Render computed fields read-only and seed server prefill
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) <noreply@anthropic.com>
This commit is contained in:
parent
5ea627b064
commit
e750eb8287
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
<label key={f.uid} className={'af__field' + (f.data_type === 'longtext' ? ' af__field--wide' : '')}>
|
||||
<span>{f.name}{f.mandatory ? <em className="af__req">required</em> : null}</span>
|
||||
|
||||
{f.data_type === 'select' ? (
|
||||
{f.data_type === 'id_gen' ? (
|
||||
<div className="af__auto">
|
||||
{v || 'Issued on submit'}
|
||||
<span>auto</span>
|
||||
</div>
|
||||
) : f.data_type === 'select' ? (
|
||||
<select value={v} onChange={(e) => set(f.id, e.target.value)}>
|
||||
<option value="">—</option>
|
||||
{opts.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user