From e750eb828760788ca67acfe7c98885a9ec4ae427 Mon Sep 17 00:00:00 2001 From: Yashas Date: Mon, 24 Aug 2026 16:19:15 +0530 Subject: [PATCH] Render computed fields read-only and seed server prefill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lead_ref is now an id_gen, issued server-side and stripped from the submission — so the form shows it as auto rather than as an empty box somebody is expected to type a reference code into, and never sends it. Also seeds the inputs from the prefill the form response carries. The door's channel and the signed-in agent are stamped by a prefill pipeline, so the form should show them already filled rather than ask. Co-Authored-By: Claude Opus 5 (1M context) --- src/components/ActivityForm.css | 10 ++++++++++ src/components/ActivityForm.jsx | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/components/ActivityForm.css b/src/components/ActivityForm.css index fcfa14b..4459d71 100644 --- a/src/components/ActivityForm.css +++ b/src/components/ActivityForm.css @@ -41,3 +41,13 @@ } .af__err strong { font-family: ui-monospace, monospace; margin-right: 6px; } .af__err p { margin: 6px 0 0; font-size: .8rem; color: var(--zk-muted); } + +.af__auto { + font-size: .88rem; padding: 8px 10px; border-radius: 4px; min-height: 37px; + border: 1px dashed var(--zk-line); background: var(--zk-tint); color: var(--zk-muted); + display: flex; align-items: center; justify-content: space-between; gap: 8px; +} +.af__auto span { + font-size: .6rem; letter-spacing: .07em; text-transform: uppercase; + color: var(--zk-grey); border: 1px solid var(--zk-line); border-radius: 3px; padding: 1px 5px; +} diff --git a/src/components/ActivityForm.jsx b/src/components/ActivityForm.jsx index afb235f..a200d4b 100644 --- a/src/components/ActivityForm.jsx +++ b/src/components/ActivityForm.jsx @@ -22,7 +22,19 @@ export default function ActivityForm({ activityUid, instanceId, onDone, onCancel let dead = false setSchema(null); setError(null); setValues({}) client.formSchema(activityUid, instanceId) - .then((s) => { if (!dead) setSchema(s) }) + .then((s) => { + if (dead) return + setSchema(s) + // The server resolved a prefill pipeline for this activity — it stamps + // the channel from the door and the agent from the signed-in user, so + // the form never asks for either. Seed the inputs with what it sent. + const pre = s.prefill_data || s.prefillData || s.field_defaults || {} + if (pre && typeof pre === 'object') { + const seed = {} + for (const f of s.fields) if (pre[f.id] !== undefined) seed[f.id] = pre[f.id] + if (Object.keys(seed).length) setValues(seed) + } + }) .catch((e) => { if (!dead) setError(e) }) return () => { dead = true } }, [client, activityUid, instanceId]) @@ -36,6 +48,9 @@ export default function ActivityForm({ activityUid, instanceId, onDone, onCancel // and an unknown field is fatal, so empties are dropped rather than sent. const payload = {} for (const f of schema.fields) { + // id_gen is issued server-side and stripped from the submission. Sending + // it would be forging a reference the platform owns. + if (f.data_type === 'id_gen') continue const v = values[f.id] if (v === undefined || v === '' || (Array.isArray(v) && v.length === 0)) continue payload[f.id] = f.data_type === 'number' ? Number(v) : v @@ -65,7 +80,12 @@ export default function ActivityForm({ activityUid, instanceId, onDone, onCancel