Merge branch 'main' into minimum-booking-notice-will-allow-hours-and-days
This commit is contained in:
commit
ab42cfd4bd
|
@ -27,6 +27,12 @@ interface IAddActionDialog {
|
|||
isOpenDialog: boolean;
|
||||
setIsOpenDialog: Dispatch<SetStateAction<boolean>>;
|
||||
addAction: (action: WorkflowActions, sendTo?: string, numberRequired?: boolean) => void;
|
||||
isFreeUser: boolean;
|
||||
}
|
||||
|
||||
interface ISelectActionOption {
|
||||
label: string;
|
||||
value: WorkflowActions;
|
||||
}
|
||||
|
||||
type AddActionFormValues = {
|
||||
|
@ -35,12 +41,19 @@ type AddActionFormValues = {
|
|||
numberRequired?: boolean;
|
||||
};
|
||||
|
||||
const cleanUpActionsForFreeUser = (actions: ISelectActionOption[]) => {
|
||||
return actions.filter(
|
||||
(item) => item.value !== WorkflowActions.SMS_ATTENDEE && item.value !== WorkflowActions.SMS_NUMBER
|
||||
);
|
||||
};
|
||||
|
||||
export const AddActionDialog = (props: IAddActionDialog) => {
|
||||
const { t } = useLocale();
|
||||
const { isOpenDialog, setIsOpenDialog, addAction } = props;
|
||||
const { isOpenDialog, setIsOpenDialog, addAction, isFreeUser } = props;
|
||||
const [isPhoneNumberNeeded, setIsPhoneNumberNeeded] = useState(false);
|
||||
const [isEmailAddressNeeded, setIsEmailAddressNeeded] = useState(false);
|
||||
const actionOptions = getWorkflowActionOptions(t);
|
||||
const workflowActions = getWorkflowActionOptions(t);
|
||||
const actionOptions = isFreeUser ? cleanUpActionsForFreeUser(workflowActions) : workflowActions;
|
||||
|
||||
const formSchema = z.object({
|
||||
action: z.enum(WORKFLOW_ACTIONS),
|
||||
|
@ -59,6 +72,26 @@ export const AddActionDialog = (props: IAddActionDialog) => {
|
|||
resolver: zodResolver(formSchema),
|
||||
});
|
||||
|
||||
const handleSelectAction = (newValue: ISelectActionOption | null) => {
|
||||
if (newValue) {
|
||||
form.setValue("action", newValue.value);
|
||||
if (newValue.value === WorkflowActions.SMS_NUMBER) {
|
||||
setIsPhoneNumberNeeded(true);
|
||||
setIsEmailAddressNeeded(false);
|
||||
} else if (newValue.value === WorkflowActions.EMAIL_ADDRESS) {
|
||||
setIsEmailAddressNeeded(true);
|
||||
setIsPhoneNumberNeeded(false);
|
||||
} else {
|
||||
setIsEmailAddressNeeded(false);
|
||||
setIsPhoneNumberNeeded(false);
|
||||
}
|
||||
form.unregister("sendTo");
|
||||
form.unregister("numberRequired");
|
||||
form.clearErrors("action");
|
||||
form.clearErrors("sendTo");
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpenDialog} onOpenChange={setIsOpenDialog}>
|
||||
<DialogContent type="creation" useOwnActionButtons={true} title={t("add_action")}>
|
||||
|
@ -86,25 +119,7 @@ export const AddActionDialog = (props: IAddActionDialog) => {
|
|||
isSearchable={false}
|
||||
className="text-sm"
|
||||
defaultValue={actionOptions[0]}
|
||||
onChange={(val) => {
|
||||
if (val) {
|
||||
form.setValue("action", val.value);
|
||||
if (val.value === WorkflowActions.SMS_NUMBER) {
|
||||
setIsPhoneNumberNeeded(true);
|
||||
setIsEmailAddressNeeded(false);
|
||||
} else if (val.value === WorkflowActions.EMAIL_ADDRESS) {
|
||||
setIsEmailAddressNeeded(true);
|
||||
setIsPhoneNumberNeeded(false);
|
||||
} else {
|
||||
setIsEmailAddressNeeded(false);
|
||||
setIsPhoneNumberNeeded(false);
|
||||
}
|
||||
form.unregister("sendTo");
|
||||
form.unregister("numberRequired");
|
||||
form.clearErrors("action");
|
||||
form.clearErrors("sendTo");
|
||||
}
|
||||
}}
|
||||
onChange={handleSelectAction}
|
||||
options={actionOptions}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@ import { Controller, UseFormReturn } from "react-hook-form";
|
|||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
import { Button } from "@calcom/ui/v2";
|
||||
import { Label, TextField } from "@calcom/ui/v2";
|
||||
|
@ -28,6 +29,9 @@ export default function WorkflowDetailsPage(props: Props) {
|
|||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
|
||||
const me = useMeQuery();
|
||||
const isFreeUser = me.data?.plan === "FREE";
|
||||
|
||||
const [isAddActionDialogOpen, setIsAddActionDialogOpen] = useState(false);
|
||||
const [reload, setReload] = useState(false);
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
|
@ -120,7 +124,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
|||
<div className="w-full rounded-md border border-gray-200 bg-gray-50 p-3 py-5 md:ml-3 md:p-8">
|
||||
{form.getValues("trigger") && (
|
||||
<div>
|
||||
<WorkflowStepContainer form={form} />
|
||||
<WorkflowStepContainer form={form} isFreeUser={isFreeUser} />
|
||||
</div>
|
||||
)}
|
||||
{form.getValues("steps") && (
|
||||
|
@ -133,6 +137,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
|||
step={step}
|
||||
reload={reload}
|
||||
setReload={setReload}
|
||||
isFreeUser={isFreeUser}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@ -152,6 +157,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
|||
isOpenDialog={isAddActionDialogOpen}
|
||||
setIsOpenDialog={setIsAddActionDialogOpen}
|
||||
addAction={addAction}
|
||||
isFreeUser={isFreeUser}
|
||||
/>
|
||||
<DeleteDialog
|
||||
isOpenDialog={deleteDialogOpen}
|
||||
|
|
|
@ -38,11 +38,12 @@ type WorkflowStepProps = {
|
|||
form: UseFormReturn<FormValues>;
|
||||
reload?: boolean;
|
||||
setReload?: Dispatch<SetStateAction<boolean>>;
|
||||
isFreeUser: boolean;
|
||||
};
|
||||
|
||||
export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
const { t, i18n } = useLocale();
|
||||
const { step, form, reload, setReload } = props;
|
||||
const { step, form, reload, setReload, isFreeUser } = props;
|
||||
const [isAdditionalInputsDialogOpen, setIsAdditionalInputsDialogOpen] = useState(false);
|
||||
const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
|
||||
|
||||
|
@ -300,7 +301,15 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
|||
}
|
||||
}}
|
||||
defaultValue={selectedAction}
|
||||
options={actionOptions}
|
||||
options={
|
||||
isFreeUser
|
||||
? actionOptions.filter(
|
||||
(actionOption) =>
|
||||
actionOption.value !== WorkflowActions.SMS_ATTENDEE &&
|
||||
actionOption.value !== WorkflowActions.SMS_NUMBER
|
||||
)
|
||||
: actionOptions
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -27,12 +27,17 @@ import {
|
|||
scheduleSMSReminder,
|
||||
} from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
import { getTranslation } from "@calcom/lib/server/i18n";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { createProtectedRouter } from "../../createRouter";
|
||||
|
||||
function isSMSAction(action: WorkflowActions) {
|
||||
if (action === WorkflowActions.SMS_ATTENDEE || action === WorkflowActions.SMS_NUMBER) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export const workflowsRouter = createProtectedRouter()
|
||||
.query("list", {
|
||||
async resolve({ ctx }) {
|
||||
|
@ -515,6 +520,9 @@ export const workflowsRouter = createProtectedRouter()
|
|||
});
|
||||
//step was edited
|
||||
} else if (JSON.stringify(oldStep) !== JSON.stringify(newStep)) {
|
||||
if (user.plan === "FREE" && !isSMSAction(oldStep.action) && isSMSAction(newStep.action)) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
await ctx.prisma.workflowStep.update({
|
||||
where: {
|
||||
id: oldStep.id,
|
||||
|
@ -652,6 +660,9 @@ export const workflowsRouter = createProtectedRouter()
|
|||
//added steps
|
||||
const addedSteps = steps.map((s) => {
|
||||
if (s.id <= 0) {
|
||||
if (user.plan === "FREE" && isSMSAction(s.action)) {
|
||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||
}
|
||||
const { id: stepId, ...stepToAdd } = s;
|
||||
return stepToAdd;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user