diff --git a/webapp/src/components/Params.tsx b/webapp/src/components/Params.tsx index 5ffcce1..ebb5c6c 100644 --- a/webapp/src/components/Params.tsx +++ b/webapp/src/components/Params.tsx @@ -43,6 +43,11 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD const [submitError, setSubmitError] = useState(null) const [submitting, setSubmitting] = useState(false) const [collapsed, setCollapsed] = useSectionCollapsed('params') + // Name of the declaration currently loaded into the form for editing, or `null` when the form is + // declaring a brand-new param. The name field is locked while editing — `declareParam` overwrites + // in place by name, so changing it here would silently create a second param and orphan the + // original (and anything referencing it by name) rather than renaming it. + const [editingName, setEditingName] = useState(null) const isBoolean = kind === 'boolean' const isElapsedSinceLast = source === 'elapsed_since_last' @@ -63,6 +68,30 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD if (next === 'elapsed_since_last') setKind('duration') } + function resetForm() { + setEditingName(null) + setName('') + setRegex('') + setCaptureGroup('') + setJsonFieldPath('') + setSource('regex') + setKind(EMPTY_KIND) + setSubmitError(null) + } + + // Loads `param`'s current values into the declaration form for editing — a click handler for a + // declared-param badge. + function editParam(param: ParamDeclaration) { + setEditingName(param.name) + setName(param.name) + setRegex(param.message_match_regex) + setCaptureGroup(param.capture_group) + setJsonFieldPath(param.json_field_path ?? '') + setSource(param.elapsed_since_last ? 'elapsed_since_last' : param.json_field_path ? 'json_field' : 'regex') + setKind(param.kind) + setSubmitError(null) + } + async function handleSubmit(e: React.FormEvent) { e.preventDefault() setSubmitError(null) @@ -79,15 +108,10 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD kind: effectiveSource === 'elapsed_since_last' ? 'duration' : kind, elapsed_since_last: effectiveSource === 'elapsed_since_last', }) - setName('') - setRegex('') - setCaptureGroup('') - setJsonFieldPath('') - setSource('regex') - setKind(EMPTY_KIND) + resetForm() onDeclared() } catch (err) { - setSubmitError(err instanceof ApiError ? err.message : 'Failed to declare param') + setSubmitError(err instanceof ApiError ? err.message : `Failed to ${editingName ? 'update' : 'declare'} param`) } finally { setSubmitting(false) } @@ -115,13 +139,16 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD )} + {editingName && ( +
+ Editing "{editingName}" +
+ )} {submitError &&
{submitError}
} - +
+ + {editingName && ( + + )} +
@@ -222,9 +266,15 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD
{params.length === 0 && No params declared yet.} {params.map((p) => ( - editParam(p)} + className={`rounded border px-2 py-1 text-xs ${ + editingName === p.name + ? 'border-accent bg-accent/10 text-accent-text' + : 'border-border-soft text-text-secondary hover:bg-surface-2' + }`} title={p.elapsed_since_last ? undefined : p.message_match_regex} > {p.name} ({p.kind} @@ -234,7 +284,7 @@ export function Params({ params, onDeclared }: { params: ParamDeclaration[]; onD ? '' : `, ${p.json_field_path ? `json field ${p.json_field_path}` : `group ${p.capture_group}`}`} ) - + ))}