feat: disable form workflows for free plan, add upgrade badge, make reminder template free (#24839)
This commit is contained in:
@@ -40,6 +40,7 @@ interface IAddActionDialog {
|
||||
needsCredits: boolean;
|
||||
creditsTeamId?: number;
|
||||
isOrganization?: boolean;
|
||||
needsTeamsUpgrade?: boolean;
|
||||
}[];
|
||||
}
|
||||
|
||||
@@ -170,7 +171,16 @@ export const AddActionDialog = (props: IAddActionDialog) => {
|
||||
menuPlacement="bottom"
|
||||
defaultValue={actionOptions[0]}
|
||||
onChange={handleSelectAction}
|
||||
options={actionOptions}
|
||||
options={actionOptions.map((option) => ({
|
||||
label: option.label,
|
||||
value: option.value,
|
||||
needsTeamsUpgrade: option.needsTeamsUpgrade,
|
||||
}))}
|
||||
isOptionDisabled={(option: {
|
||||
label: string;
|
||||
value: WorkflowActions;
|
||||
needsTeamsUpgrade?: boolean;
|
||||
}) => !!option.needsTeamsUpgrade}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Dispatch, SetStateAction } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import type { UseFormReturn } from "react-hook-form";
|
||||
|
||||
import { useHasActiveTeamPlan } from "@calcom/features/billing/hooks/useHasPaidPlan";
|
||||
import type { WorkflowPermissions } from "@calcom/features/workflows/repositories/WorkflowPermissionsRepository";
|
||||
import { SENDER_ID, SENDER_NAME, SCANNING_WORKFLOW_STEPS } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
@@ -43,6 +44,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
||||
const { form, workflowId, selectedOptions, setSelectedOptions, teamId, isOrg, allOptions, permissions } =
|
||||
props;
|
||||
const { t, i18n } = useLocale();
|
||||
const { hasActiveTeamPlan } = useHasActiveTeamPlan();
|
||||
|
||||
const [isAddActionDialogOpen, setIsAddActionDialogOpen] = useState(false);
|
||||
const [isDeleteStepDialogOpen, setIsDeleteStepDialogOpen] = useState(false);
|
||||
@@ -84,12 +86,15 @@ export default function WorkflowDetailsPage(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
const needsTeamsUpgrade = isFormTrigger(form.getValues("trigger")) && !hasActiveTeamPlan;
|
||||
|
||||
return {
|
||||
...option,
|
||||
label,
|
||||
creditsTeamId: teamId,
|
||||
isOrganization: isOrg,
|
||||
isCalAi: isCalAIAction(option.value),
|
||||
needsTeamsUpgrade,
|
||||
};
|
||||
})
|
||||
: [];
|
||||
|
||||
@@ -101,6 +101,7 @@ type WorkflowStepProps = {
|
||||
creditsTeamId?: number;
|
||||
isOrganization: boolean;
|
||||
isCalAi: boolean;
|
||||
needsTeamsUpgrade?: boolean;
|
||||
}[];
|
||||
updateTemplate: boolean;
|
||||
setUpdateTemplate: Dispatch<SetStateAction<boolean>>;
|
||||
@@ -371,7 +372,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
handleCreateAgent,
|
||||
]);
|
||||
|
||||
const triggerOptions = getWorkflowTriggerOptions(t);
|
||||
const triggerOptions = getWorkflowTriggerOptions(t, hasActiveTeamPlan);
|
||||
const templateOptions = getWorkflowTemplateOptions(t, step?.action, hasActiveTeamPlan, trigger);
|
||||
|
||||
const steps = useWatch({
|
||||
@@ -379,6 +380,11 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
name: "steps",
|
||||
});
|
||||
|
||||
// Extract current step template from watched steps array
|
||||
const currentStepTemplate = step ? steps?.[step.stepNumber - 1]?.template : null;
|
||||
|
||||
const isReminderTemplate = currentStepTemplate === WorkflowTemplates.REMINDER;
|
||||
|
||||
const hasAiAction = hasCalAIAction(steps);
|
||||
const hasEmailToHostAction = steps.some((s) => s.action === WorkflowActions.EMAIL_HOST);
|
||||
const hasWhatsappAction = steps.some((s) => isWhatsappAction(s.action));
|
||||
@@ -531,11 +537,12 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
isDisabled={props.readOnly}
|
||||
onChange={(val) => {
|
||||
if (val) {
|
||||
const currentTrigger = form.getValues("trigger");
|
||||
const triggerValue = val.value as WorkflowTriggerEvents;
|
||||
const currentTrigger = form.getValues("trigger") as WorkflowTriggerEvents;
|
||||
const isCurrentFormTrigger = isFormTrigger(currentTrigger);
|
||||
const isNewFormTrigger = isFormTrigger(val.value);
|
||||
const isNewFormTrigger = isFormTrigger(triggerValue);
|
||||
|
||||
form.setValue("trigger", val.value);
|
||||
form.setValue("trigger", triggerValue);
|
||||
|
||||
// Reset activeOn when switching between form and non-form triggers
|
||||
if (isCurrentFormTrigger !== isNewFormTrigger) {
|
||||
@@ -546,12 +553,12 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
form.setValue("selectAll", false);
|
||||
}
|
||||
|
||||
const newTimeSectionText = getTimeSectionText(val.value, t);
|
||||
const newTimeSectionText = getTimeSectionText(triggerValue, t);
|
||||
if (newTimeSectionText) {
|
||||
setTimeSectionText(newTimeSectionText);
|
||||
if (
|
||||
val.value === WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW ||
|
||||
val.value === WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW
|
||||
triggerValue === WorkflowTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW ||
|
||||
triggerValue === WorkflowTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW
|
||||
) {
|
||||
form.setValue("time", 5);
|
||||
form.setValue("timeUnit", TimeUnit.MINUTE);
|
||||
@@ -564,7 +571,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
form.unregister("time");
|
||||
form.unregister("timeUnit");
|
||||
}
|
||||
if (isFormTrigger(val.value)) {
|
||||
if (isFormTrigger(triggerValue)) {
|
||||
const steps = form.getValues("steps");
|
||||
if (steps?.length) {
|
||||
const updatedSteps = steps.map((step) =>
|
||||
@@ -584,7 +591,14 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
}
|
||||
}}
|
||||
defaultValue={selectedTrigger}
|
||||
options={filteredTriggerOptions}
|
||||
options={filteredTriggerOptions.map((option) => ({
|
||||
label: option.label,
|
||||
value: option.value,
|
||||
needsTeamsUpgrade: option.needsTeamsUpgrade,
|
||||
}))}
|
||||
isOptionDisabled={(option: { label: string; value: string; needsTeamsUpgrade?: boolean }) =>
|
||||
!!option.needsTeamsUpgrade
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
@@ -1321,7 +1335,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
refEmailSubject.current = e;
|
||||
}}
|
||||
rows={2}
|
||||
disabled={props.readOnly || !hasActiveTeamPlan}
|
||||
disabled={props.readOnly || (!hasActiveTeamPlan && !isReminderTemplate)}
|
||||
className="my-0 focus:ring-transparent"
|
||||
required
|
||||
{...restEmailSubjectForm}
|
||||
@@ -1354,7 +1368,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
||||
editable={
|
||||
!props.readOnly &&
|
||||
!isWhatsappAction(step.action) &&
|
||||
(hasActiveTeamPlan || isSMSAction(step.action))
|
||||
(hasActiveTeamPlan || isSMSAction(step.action) || isReminderTemplate)
|
||||
}
|
||||
excludedToolbarItems={
|
||||
!isSMSAction(step.action) ? [] : ["blockType", "bold", "italic", "link"]
|
||||
|
||||
@@ -31,7 +31,7 @@ export function getWorkflowActionOptions(t: TFunction, isOrgsPlan?: boolean) {
|
||||
});
|
||||
}
|
||||
|
||||
export function getWorkflowTriggerOptions(t: TFunction) {
|
||||
export function getWorkflowTriggerOptions(t: TFunction, hasPaidPlan: boolean = false) {
|
||||
// TODO: remove this after workflows are supported
|
||||
const filterdWorkflowTriggerEvents = WORKFLOW_TRIGGER_EVENTS.filter(
|
||||
(event) =>
|
||||
@@ -41,8 +41,15 @@ export function getWorkflowTriggerOptions(t: TFunction) {
|
||||
|
||||
return filterdWorkflowTriggerEvents.map((triggerEvent) => {
|
||||
const triggerString = t(`${triggerEvent.toLowerCase()}_trigger`);
|
||||
const isFormSubmittedTrigger =
|
||||
triggerEvent === WorkflowTriggerEvents.FORM_SUBMITTED ||
|
||||
triggerEvent === WorkflowTriggerEvents.FORM_SUBMITTED_NO_EVENT;
|
||||
|
||||
return { label: triggerString.charAt(0).toUpperCase() + triggerString.slice(1), value: triggerEvent };
|
||||
return {
|
||||
label: triggerString.charAt(0).toUpperCase() + triggerString.slice(1),
|
||||
value: triggerEvent,
|
||||
needsTeamsUpgrade: !hasPaidPlan && isFormSubmittedTrigger,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,7 +62,7 @@ function convertToTemplateOptions(
|
||||
return {
|
||||
label: t(`${template.toLowerCase()}`),
|
||||
value: template,
|
||||
needsTeamsUpgrade: !hasPaidPlan,
|
||||
needsTeamsUpgrade: !hasPaidPlan && template !== WorkflowTemplates.REMINDER,
|
||||
} as { label: string; value: any; needsTeamsUpgrade: boolean };
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user