feat(automations): parallel branch canvas, simple/advanced level per org, rules list UX
This commit is contained in:
@@ -114,6 +114,7 @@ export type OrgModuleKey =
|
||||
| "activities"
|
||||
| "tickets"
|
||||
| "workflow_automations"
|
||||
| "workflow_automations_advanced"
|
||||
| "message_automations"
|
||||
| "lead_forms"
|
||||
| "project_boards"
|
||||
@@ -153,6 +154,7 @@ export const ORG_MODULE_KEYS: OrgModuleKey[] = [
|
||||
"activities",
|
||||
"tickets",
|
||||
"workflow_automations",
|
||||
"workflow_automations_advanced",
|
||||
"message_automations",
|
||||
"lead_forms",
|
||||
"leads",
|
||||
@@ -193,6 +195,7 @@ export const ORG_MODULE_LABELS: Record<OrgModuleKey, string> = {
|
||||
activities: "فعالیتها",
|
||||
tickets: "تیکتها",
|
||||
workflow_automations: "اتوماسیون گردش کار",
|
||||
workflow_automations_advanced: "اتوماسیون گردش کار حرفهای (چندشاخه)",
|
||||
message_automations: "اتوماسیون پیامک",
|
||||
lead_forms: "فرمساز سرنخ",
|
||||
leads: "مدیریت لیدها",
|
||||
@@ -283,8 +286,11 @@ export function isOrgModuleKey(value: string): value is OrgModuleKey {
|
||||
return (ORG_MODULE_KEYS as readonly string[]).includes(value);
|
||||
}
|
||||
|
||||
/** ماژولهایی که باید صراحتاً توسط سوپرادمین فعال شوند */
|
||||
export const OPT_IN_ORG_MODULES: OrgModuleKey[] = ["workflow_automations_advanced"];
|
||||
|
||||
export function defaultEnabledModules(): OrgModuleKey[] {
|
||||
return [...ORG_MODULE_KEYS];
|
||||
return ORG_MODULE_KEYS.filter((k) => !OPT_IN_ORG_MODULES.includes(k));
|
||||
}
|
||||
|
||||
export interface SubscriptionSummaryDto {
|
||||
@@ -3105,7 +3111,7 @@ export const AUTOMATION_ACTION_LABELS: Record<AutomationAction, string> = {
|
||||
add_loyalty_points: "افزودن امتیاز باشگاه",
|
||||
};
|
||||
|
||||
export const MAX_AUTOMATION_STEPS = 12;
|
||||
export const MAX_AUTOMATION_STEPS = 20;
|
||||
|
||||
export const AUTOMATION_ACTIONS = [
|
||||
"create_activity",
|
||||
@@ -3464,6 +3470,45 @@ export function planAutomationActions(
|
||||
return out;
|
||||
}
|
||||
|
||||
export interface AutomationBranchRange {
|
||||
/** اندیس اولین شرط شاخه */
|
||||
start: number;
|
||||
/** اندیس بعد از آخرین گام شاخه */
|
||||
end: number;
|
||||
}
|
||||
|
||||
/** گامهای بدون شرط ابتدای زنجیره و بازهٔ هر شاخه (در حالت branches) */
|
||||
export function splitAutomationBranches(steps: AutomationStep[]): {
|
||||
prefixEnd: number;
|
||||
branches: AutomationBranchRange[];
|
||||
} {
|
||||
const branches: AutomationBranchRange[] = [];
|
||||
let prefixEnd = steps.length;
|
||||
steps.forEach((step, i) => {
|
||||
if (!isAutomationCondition(step)) return;
|
||||
const prev = steps[i - 1];
|
||||
if (prev && isAutomationCondition(prev)) return;
|
||||
if (!branches.length) prefixEnd = i;
|
||||
else branches[branches.length - 1].end = i;
|
||||
branches.push({ start: i, end: steps.length });
|
||||
});
|
||||
return { prefixEnd, branches };
|
||||
}
|
||||
|
||||
/** قانون از امکانات اتوماسیون حرفهای (شاخه، شرط فرم، تخصیص نوبتی) استفاده میکند */
|
||||
export function automationUsesAdvanced(
|
||||
steps: AutomationStep[],
|
||||
chainMode: AutomationChainMode | undefined,
|
||||
): boolean {
|
||||
if (chainMode === "branches") return true;
|
||||
return steps.some(
|
||||
(s) =>
|
||||
(isAutomationCondition(s) && s.conditionField === "form_field") ||
|
||||
s.assignMode === "team_round_robin" ||
|
||||
s.assignMode === "users_round_robin",
|
||||
);
|
||||
}
|
||||
|
||||
/** مقدار پاسخ فرم را به گزینهها میشکند (چندانتخابی با کاما ذخیره میشود) */
|
||||
export function splitFormAnswer(raw: unknown): string[] {
|
||||
if (raw == null) return [];
|
||||
|
||||
Reference in New Issue
Block a user