diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index f26d8848be..d863b7e839 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1044,6 +1044,14 @@ "using_additional_inputs_as_variables": "How to use additional inputs as variables?", "download_desktop_app": "Download desktop app", "set_ping_link": "Set Ping link", + "when_something_happens": "When something happens", + "action_is_performed": "An action is performed", + "test_action": "Test action", + "notification_sent": "Notification sent", + "no_input": "No input", + "test_workflow_action": "Test workflow action", + "send_sms": "Send SMS", + "send_sms_to_number": "Are you sure you want to send a SMS to {{number}}?", "missing_connected_calendar": "No default calendar connected", "connect_your_calendar_and_link": "You can connect your calendar from <1>here.", "default_calendar_selected": "Default calendar", diff --git a/packages/features/ee/workflows/components/WorkflowDetailsPage.tsx b/packages/features/ee/workflows/components/WorkflowDetailsPage.tsx index 44ec1edca4..182d9e97b1 100644 --- a/packages/features/ee/workflows/components/WorkflowDetailsPage.tsx +++ b/packages/features/ee/workflows/components/WorkflowDetailsPage.tsx @@ -1,3 +1,4 @@ +import { ArrowDownIcon } from "@heroicons/react/outline"; import { WorkflowActions, WorkflowTemplates } from "@prisma/client"; import { useRouter } from "next/router"; import { Dispatch, SetStateAction, useMemo, useState } from "react"; @@ -168,7 +169,7 @@ export default function WorkflowDetailsPage(props: Props) { )}
-
+
@@ -310,15 +338,21 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { @@ -482,8 +517,6 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { type="button" color="primary" onClick={async () => { - const reminderBody = form.getValues(`steps.${step.stepNumber - 1}.reminderBody`); - const emailSubject = form.getValues(`steps.${step.stepNumber - 1}.emailSubject`); let isEmpty = false; let errorMessage = ""; @@ -507,6 +540,9 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { if (!isEmpty) { setEditEmailBodyMode(false); setEditCounter(editCounter - 1); + if (!editNumberMode) { + setIsTestActionDisabled(false); + } } setErrorMessageCustomInput(errorMessage); }}> @@ -515,6 +551,29 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) { )} )} + {form.getValues(`steps.${step.stepNumber - 1}.action`) !== WorkflowActions.SMS_ATTENDEE && ( + + )}
@@ -552,6 +611,25 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
+ + { + e.preventDefault(); + testActionMutation.mutate({ + action: step.action, + emailSubject: step.emailSubject || "", + reminderBody: step.reminderBody || "", + template: step.template, + sendTo: step.sendTo || "", + }); + setConfirmationDialogOpen(false); + }}> + {t("send_sms_to_number", { number: sendTo })} + + ); } diff --git a/packages/features/ee/workflows/pages/workflow.tsx b/packages/features/ee/workflows/pages/workflow.tsx index 2c6afd2d73..7123bad0c5 100644 --- a/packages/features/ee/workflows/pages/workflow.tsx +++ b/packages/features/ee/workflows/pages/workflow.tsx @@ -88,7 +88,7 @@ function WorkflowPage() { }); useEffect(() => { - if (workflow) { + if (workflow && !form.getValues("name")) { setSelectedEventTypes( workflow.activeOn.map((active) => ({ value: String(active.eventType.id), diff --git a/packages/trpc/server/routers/viewer/workflows.tsx b/packages/trpc/server/routers/viewer/workflows.tsx index 9864475749..75215972b7 100644 --- a/packages/trpc/server/routers/viewer/workflows.tsx +++ b/packages/trpc/server/routers/viewer/workflows.tsx @@ -9,6 +9,7 @@ import { } from "@prisma/client"; import { z } from "zod"; +import dayjs from "@calcom/dayjs"; import { WORKFLOW_TEMPLATES, WORKFLOW_TRIGGER_EVENTS, @@ -20,9 +21,11 @@ import { scheduleEmailReminder, } from "@calcom/features/ee/workflows/lib/reminders/emailReminderManager"; import { + BookingInfo, deleteScheduledSMSReminder, scheduleSMSReminder, } from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager"; +import { getErrorFromUnknown } from "@calcom/lib/errors"; import { TRPCError } from "@trpc/server"; @@ -709,4 +712,112 @@ export const workflowsRouter = createProtectedRouter() workflow, }; }, + }) + .mutation("testAction", { + input: z.object({ + action: z.enum(WORKFLOW_ACTIONS), + emailSubject: z.string(), + reminderBody: z.string(), + template: z.enum(WORKFLOW_TEMPLATES), + sendTo: z.string().optional(), + }), + async resolve({ ctx, input }) { + const { action, emailSubject, reminderBody, template, sendTo } = input; + try { + const booking = await ctx.prisma.booking.findFirst({ + orderBy: { + createdAt: "desc", + }, + where: { + userId: ctx.user.id, + }, + include: { + attendees: true, + user: true, + }, + }); + + let evt: BookingInfo; + if (booking) { + evt = { + uid: booking?.uid, + attendees: + booking?.attendees.map((attendee) => { + return { name: attendee.name, email: attendee.email, timeZone: attendee.timeZone }; + }) || [], + organizer: { + language: { + locale: booking?.user?.locale || "", + }, + name: booking?.user?.name || "", + email: booking?.user?.email || "", + timeZone: booking?.user?.timeZone || "", + }, + startTime: booking?.startTime.toISOString() || "", + endTime: booking?.endTime.toISOString() || "", + title: booking?.title || "", + location: booking?.location || null, + additionalNotes: booking?.description || null, + customInputs: booking?.customInputs, + }; + } else { + //if no booking exists create an example booking + evt = { + attendees: [{ name: "John Doe", email: "john.doe@example.com", timeZone: "Europe/London" }], + organizer: { + language: { + locale: ctx.user.locale, + }, + name: ctx.user.name || "", + email: ctx.user.email, + timeZone: ctx.user.timeZone, + }, + startTime: dayjs().add(10, "hour").toISOString(), + endTime: dayjs().add(11, "hour").toISOString(), + title: "Example Booking", + location: "Office", + additionalNotes: "These are additional notes", + }; + } + + if (action === WorkflowActions.EMAIL_ATTENDEE || action === WorkflowActions.EMAIL_HOST) { + scheduleEmailReminder( + evt, + WorkflowTriggerEvents.NEW_EVENT, + action, + { time: null, timeUnit: null }, + ctx.user.email, + emailSubject, + reminderBody, + 0, + template + ); + return { message: "Notification sent" }; + } else if (action === WorkflowActions.SMS_NUMBER && sendTo) { + scheduleSMSReminder( + evt, + sendTo, + WorkflowTriggerEvents.NEW_EVENT, + action, + { time: null, timeUnit: null }, + reminderBody, + 0, + template + ); + return { message: "Notification sent" }; + } + return { + ok: false, + status: 500, + message: "Notification could not be sent", + }; + } catch (_err) { + const error = getErrorFromUnknown(_err); + return { + ok: false, + status: 500, + message: error.message, + }; + } + }, });