diff --git a/ui/src/pages/Alerts/RuleEditor/TriggerStep.tsx b/ui/src/pages/Alerts/RuleEditor/TriggerStep.tsx index 61572e9a..9cb874d9 100644 --- a/ui/src/pages/Alerts/RuleEditor/TriggerStep.tsx +++ b/ui/src/pages/Alerts/RuleEditor/TriggerStep.tsx @@ -17,6 +17,13 @@ export function TriggerStep({ const { toast } = useToast(); const [lastResult, setLastResult] = useState(null); + // PER_EXCHANGE fires exactly once per exchange (Task 3.3 server validator + // rejects non-zero reNotifyMinutes / forDurationSeconds for this mode). + // Gate the two inputs here so users can't type values the server will reject. + const isPerExchange = + form.conditionKind === 'EXCHANGE_MATCH' && + (form.condition as Record).fireMode === 'PER_EXCHANGE'; + const onTest = async () => { if (!ruleId) { toast({ title: 'Save rule first to run test evaluate', variant: 'error' }); @@ -40,20 +47,28 @@ export function TriggerStep({ onChange={(e) => setForm({ ...form, evaluationIntervalSeconds: Number(e.target.value) })} /> - - setForm({ ...form, forDurationSeconds: Number(e.target.value) })} - /> - + {!isPerExchange && ( + + setForm({ ...form, forDurationSeconds: Number(e.target.value) })} + /> + + )} setForm({ ...form, reNotifyMinutes: Number(e.target.value) })} + disabled={isPerExchange} + title={ + isPerExchange + ? 'Per-exchange rules fire exactly once per exchange — re-notify does not apply.' + : undefined + } />