Harden quick-add against review findings
Independent review of the quick-add range surfaced real holes: - The emptyLabel guard suppressed creation for any name that happened to be a substring of the label — typing "Rent" in the parent picker (a substring of "No parent (root)") silently offered nothing. The guard is gone; the exact-match rule already suppresses creates when the full label is typed. - Async creates resolved against click-time snapshots, so a checkbox toggled or chip removed during the server round trip was silently reverted. Consumers now apply functional updates or a latest-value ref. - Created names are capped at 200 characters, matching the registry forms; over-long text fails inline instead of minting a permanent multi-kilobyte name. - A create failing after the user blurred mid-flight reopens the list so the error is never invisible, and option rows are locked while a create is in flight so a race cannot override an explicit pick.
This commit is contained in:
@@ -695,6 +695,11 @@ function CorrectionEditor({
|
||||
mutate: Mutate;
|
||||
onChange: (value: CorrectionValue) => void;
|
||||
}) {
|
||||
// Async creates resolve against the freshest correction, not the snapshot
|
||||
// captured when the create row was clicked: a chip removed during the
|
||||
// server round trip must survive the create landing.
|
||||
const latest = useRef(value);
|
||||
latest.current = value;
|
||||
const addable = data.tags
|
||||
.filter((t) => !value.tag_ids.includes(t.id))
|
||||
.map((t) => ({ value: t.id, label: t.name }));
|
||||
@@ -739,7 +744,9 @@ function CorrectionEditor({
|
||||
mutate={mutate}
|
||||
value={value.category_id}
|
||||
disabled={disabled}
|
||||
onChange={(category_id) => onChange({ ...value, category_id })}
|
||||
onChange={(category_id) =>
|
||||
onChange({ ...latest.current, category_id })
|
||||
}
|
||||
/>
|
||||
</dd>
|
||||
</div>
|
||||
@@ -783,14 +790,13 @@ function CorrectionEditor({
|
||||
{
|
||||
key: "tag",
|
||||
label: `Create tag "${text}"`,
|
||||
run: async () =>
|
||||
run: async () => {
|
||||
const id = await createTag(mutate, data, text);
|
||||
onChange({
|
||||
...value,
|
||||
tag_ids: [
|
||||
...value.tag_ids,
|
||||
await createTag(mutate, data, text),
|
||||
],
|
||||
}),
|
||||
...latest.current,
|
||||
tag_ids: [...latest.current.tag_ids, id],
|
||||
});
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user