feat(forms): request-form builder #486
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-731-admin-form-builder"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Second slice of the client-request frontend, after the public page in #485: the admin surface that defines what a client is asked for.
/admin/formslists the tenant's request forms and edits one in a single modal covering the definition, its ordered field set, and its conditional rules.Why one editor, not the parent-then-children split
sla.rscreates a policy and then edits its targets in a second modal. That shape does not fit here, for two server-side reasons:fieldsREPLACES the whole set rather than merging, because field identity is the payload key and a merge cannot express a rename unambiguously.A whole-form editor matches both facts exactly. It also opens with one empty field row rather than an empty list the operator has to discover the "Add field" button to escape.
Details worth reviewing
Position is the sort order. Fields are reordered by moving rows, and
sort_orderis assigned from the index on save, so an operator never types numbers that can collide.Three checks run client-side purely to save a round trip, with the server still the authority: a duplicate reference name, a choice list with no options, and a rule missing either of its fields. Each is something the server also rejects. Per
docs/form-conventions.mdevery check runs and every slot is set before bailing once, so one problem never masks another.Server field errors land in the banner on purpose. The server keys them
fields[3].optionsandrules[0].field, which have no inline slot in a dynamic row editor, so routing them by key would drop them. They surface in the form-level banner where they stay readable.The slug follows the name until touched, then stops, and is read-only once the definition exists. It is the link-stable identifier, and links already emailed to clients have to keep resolving. The client-side
slugifymirrors the server's slug shape rather than approximating it, and is unit-tested against it.An unknown rule kind blocks the save rather than silently dropping it.
FormRuledecodes an unrecognised kind toOtherso a definition authored by a newer server still loads and lists, but saving would write the loss back, so the editor refuses and says why. Unit-tested.A typed PATCH was missing. Only the
String-errorpatch_authedexisted, which discards theerror.errors[]envelope the editor needs. Added alongsideput_authed_typed.Verification
cargo check --target wasm32-unknown-unknown,cargo fmt --all --check,cargo test(258 passed, 0 failed, including 3 new unit tests), and both guard scripts (check-theme-tokens,check-runner-labels).just check-clippystill reports the two pre-existing failures insrc/pages/projects.rs(manual_div_ceil) andsrc/pages/time.rs(unnecessary_sort_by). Both reproduce on unmodifiedmainwith a local clippy newer than CI's, so they are not from this branch; nothing in the new code trips a lint. Flagged in #485 too, and worth its own fix before whoever upgrades the runner hits it.Next slices
The send-a-link action (issue a request link to a client from the company or contact screen), then the measured-duration readout on the KB article page.