Files
cameleer-server/ui/src/pages/Alerts/RuleEditor/ConditionStep.tsx
hsiegeln ef8c60c2b5 feat(ui/alerts): ConditionStep with 6 kind-specific forms
Each condition kind (ROUTE_METRIC, EXCHANGE_MATCH, AGENT_STATE,
DEPLOYMENT_STATE, LOG_PATTERN, JVM_METRIC) renders its own payload-shape
form. Changing the kind resets the condition payload to {kind, scope} so
stale fields from a previous kind don't leak into the save request.

Deviation: DS Select uses native event-based onChange. Plan draft showed
a value-based signature (onChange(v) => ...).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 13:59:55 +02:00

50 lines
2.4 KiB
TypeScript

import { FormField, Select } from '@cameleer/design-system';
import type { FormState } from './form-state';
import { RouteMetricForm } from './condition-forms/RouteMetricForm';
import { ExchangeMatchForm } from './condition-forms/ExchangeMatchForm';
import { AgentStateForm } from './condition-forms/AgentStateForm';
import { DeploymentStateForm } from './condition-forms/DeploymentStateForm';
import { LogPatternForm } from './condition-forms/LogPatternForm';
import { JvmMetricForm } from './condition-forms/JvmMetricForm';
const KIND_OPTIONS = [
{ value: 'ROUTE_METRIC', label: 'Route metric (error rate, latency, throughput)' },
{ value: 'EXCHANGE_MATCH', label: 'Exchange match (specific failures)' },
{ value: 'AGENT_STATE', label: 'Agent state (DEAD / STALE)' },
{ value: 'DEPLOYMENT_STATE', label: 'Deployment state (FAILED / DEGRADED)' },
{ value: 'LOG_PATTERN', label: 'Log pattern (count of matching logs)' },
{ value: 'JVM_METRIC', label: 'JVM metric (heap, GC, inflight)' },
];
export function ConditionStep({ form, setForm }: { form: FormState; setForm: (f: FormState) => void }) {
const onKindChange = (v: string) => {
const kind = v as FormState['conditionKind'];
// Reset the condition payload so stale fields from a previous kind don't leak
// into the save request. Preserve scope — it's managed on the scope step.
const prev = form.condition as Record<string, unknown>;
setForm({
...form,
conditionKind: kind,
condition: { kind, scope: prev.scope } as FormState['condition'],
});
};
return (
<div style={{ display: 'grid', gap: 16, maxWidth: 720 }}>
<FormField label="Condition kind">
<Select
value={form.conditionKind}
onChange={(e) => onKindChange(e.target.value)}
options={KIND_OPTIONS}
/>
</FormField>
{form.conditionKind === 'ROUTE_METRIC' && <RouteMetricForm form={form} setForm={setForm} />}
{form.conditionKind === 'EXCHANGE_MATCH' && <ExchangeMatchForm form={form} setForm={setForm} />}
{form.conditionKind === 'AGENT_STATE' && <AgentStateForm form={form} setForm={setForm} />}
{form.conditionKind === 'DEPLOYMENT_STATE' && <DeploymentStateForm form={form} setForm={setForm} />}
{form.conditionKind === 'LOG_PATTERN' && <LogPatternForm form={form} setForm={setForm} />}
{form.conditionKind === 'JVM_METRIC' && <JvmMetricForm form={form} setForm={setForm} />}
</div>
);
}