From 852a219e0b47135c12d76029407493bb0b03cbbc Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma Date: Wed, 15 Jul 2026 18:35:11 +0530 Subject: [PATCH] feat(automations): narrow condition options for delayed rules instead of warning When a delay is on, the condition attribute dropdown for conversation-level events offers only Status, and attribute_changed is dropped from the operator list for any delayed rule. Toggling the delay on resets conditions the delayed rule can't use. This makes unsupported delayed rules unconstructable, so the inline restriction warning (and its i18n strings) are removed. --- .../dashboard/i18n/locale/en/automation.json | 6 +--- .../automation/AutomationRuleForm.vue | 33 +++++++++---------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/app/javascript/dashboard/i18n/locale/en/automation.json b/app/javascript/dashboard/i18n/locale/en/automation.json index 7faf5d71f..805674eba 100644 --- a/app/javascript/dashboard/i18n/locale/en/automation.json +++ b/app/javascript/dashboard/i18n/locale/en/automation.json @@ -38,11 +38,7 @@ "DAYS": "Days" }, "ERROR": "Delay must be between 10 minutes and 30 days", - "HELP_TEXT": "Delayed rules run only if the conditions still hold when the delay ends, and apply to conversations with activity after the rule is created.", - "RESTRICTED": { - "ATTRIBUTE_CHANGED": "A delay can't be used with an \"attribute changed\" condition, because the change can't be re-checked when the delay ends.", - "CONVERSATION_NON_STATUS": "For conversation events, a delay is only available when every condition uses the Status attribute." - } + "HELP_TEXT": "Delayed rules run only if the conditions still hold when the delay ends, and apply to conversations with activity after the rule is created." }, "CONDITIONS": { "LABEL": "Conditions" diff --git a/app/javascript/dashboard/routes/dashboard/settings/automation/AutomationRuleForm.vue b/app/javascript/dashboard/routes/dashboard/settings/automation/AutomationRuleForm.vue index c80c6447d..2d7c37dc5 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/automation/AutomationRuleForm.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/automation/AutomationRuleForm.vue @@ -128,7 +128,11 @@ const filterTypes = computed(() => { const event = eventName.value; if (!event || !props.automationTypes[event]) return []; - const attributes = getTranslatedAttributes(props.automationTypes, event); + let attributes = getTranslatedAttributes(props.automationTypes, event); + // A delayed conversation-level rule can only key its episode on status, so offer status alone. + if (isDelayed.value && event !== 'message_created') { + attributes = attributes.filter(attr => attr.key === 'status'); + } return attributes.map(attr => { if (attr.disabled) { @@ -138,7 +142,11 @@ const filterTypes = computed(() => { const mappedInputType = INPUT_TYPE_MAP[attr.inputType] || 'plainText'; const options = props.getConditionDropdownValues(attr.key) || []; - const filterOperators = (attr.filterOperators || []).map(op => { + // attribute_changed can't be re-evaluated at fire time, so hide it for delayed rules. + const availableOperators = (attr.filterOperators || []).filter( + op => !isDelayed.value || op.value !== 'attribute_changed' + ); + const filterOperators = availableOperators.map(op => { const enriched = operators.value[op.value]; if (enriched) return enriched; return { @@ -271,12 +279,15 @@ watch([isDelayed, delayInMinutes], () => { : null; }); -// Turning on a delay narrows the event list; snap an unsupported event to a supported one. +// Turning on a delay narrows the event + condition options; snap an unsupported event and reset +// conditions the delayed rule can't use. Valid selections (incl. an edited rule) are left intact. watch(isDelayed, delayed => { if (!delayed || !automation.value) return; if (!DELAYED_EVENT_KEYS.includes(automation.value.event_name)) { automation.value.event_name = 'conversation_updated'; props.onEventChange(); + } else if (!isDelaySupported.value) { + props.onEventChange(); } }); @@ -327,11 +338,7 @@ const emitSaveAutomation = () => { syncCustomAttributeTypes(); const conditionsValid = isConditionsValid(); errors.value = validateAutomation(automation.value); - if ( - allowsDelayedExecution.value && - isDelayed.value && - (executionDelayInvalid.value || !isDelaySupported.value) - ) { + if (allowsDelayedExecution.value && executionDelayInvalid.value) { errors.value.execution_delay = true; } if (Object.keys(errors.value).length === 0 && conditionsValid) { @@ -405,16 +412,6 @@ defineExpose({ open, close }); > {{ $t('AUTOMATION.ADD.FORM.EXECUTE.ERROR') }} -

- {{ - $t( - `AUTOMATION.ADD.FORM.EXECUTE.RESTRICTED.${delayRestrictionReason}` - ) - }} -

{{ $t('AUTOMATION.ADD.FORM.EXECUTE.HELP_TEXT') }}