Repository navigation
Schema: conditional-visibility rule editor #20
Description
Activity
- addedparityWeb/API feature-parity workWeb/API feature-parity workP2DepthDeptharea:listsArea: listsArea: lists
on Sep 15, 2026 - added a parent issue
on Sep 15, 2026 Live-verified findings from the schema service (#17 / PR #143) — three change the design here
⚠️ 1. The non-destructivepropertiesform accepts only SIX types, not twelve400 Unknown propertyType 'textarea'. Allowed: text, number, boolean, date, url, emailpropertyTypeis also mandatory on every item (omitting it gives the same error for'undefined'/'null').Consequence: a list using
textarea,datetime,tel,select,multiselectorprioritycannot be edited non-destructively at all — every change to it has to go through the destructive DSL rebuild. That is a real, permanent constraint on #22's guard, not an edge case: the moment a user picks one of the six richer types in #18's builder, they lose safe editing on that list forever.Exposed as
ListFieldType.PropertiesEditableandListSchema.SupportsPropertiesEditso the UI can tell the user before they choose.2. "Destructive" means columns, not rows — so #22's confirmation copy must not say "rows will be deleted"
Confirmed live. The DSL rebuild:
- drops and recreates every column with a new id, losing any
validation/options/visibilitythe new DSL omits; - leaves rows intact, but values whose keys no longer exist are orphaned in
rowData— still stored, not shown, not validated.
And it renames the list:
schema.nameoverwrote the title ('ZZ Throwaway Schema Probe'→'ZZ Renamed By DSL Rebuild'), andschema.descriptionoverwrites the list description too — clearing it when omitted. #22's confirmation needs to say all three things.3. Deleting a data-bearing column requires
?force=true409 {…, "propertiesWithData": ["link"]}?force=truethen strips that key from every row. The sharedEnsureSuccessAsyncdiscards thepropertiesWithDataarray, so a dedicatedListSchemaExceptioncarriesIssues/PropertiesWithData/RequiresForce. #18 should name the affected columns in its confirmation rather than showing a bare 409.4. The server never validates conditional visibility — #20 must
An unknown operator, a missing watched key, and a forward reference all return
200and then silently never match. So there is no server-side safety net:ListSchema.Validate()does these checks client-side, and #20's editor should surface them rather than letting a rule quietly do nothing.5.
propertiesPUT definitively preserves row data — #22's guard is soundA rename + column-add on a list holding two rows returned
200and both rows came back with identical ids, identicalversion(still 1), and identicalrowData. Column ids were preserved too, and thevalidationRules/helpText/visibilityConditionthat thepropertiesshape cannot even express survived untouched.Note the envelope differs between the two directions:
GETreturns{"data":{…}}, thepropertiesPUTreturns{"properties":[…]}ordered bydisplayOrder— nodatawrapper.6. Schema-less lists are unaffected
Created without a schema they answer
{"data":{"name":"<list title>","description":…,"fields":[]}}and accept rows with arbitrary, even nested, keys. Unknown keys are accepted on a schema'd list too — nothing is stripped.fields: []cannot be PUT back (DSL must have at least one field), soListSchema.Validate()catches that locally.Also relevant to #21
Row-write validation returns
422withdetails:[{field,message}], which the current plumbing flattens — so #21 can't currently attach a message to the offending field without unpacking that itself.Separately, #144/PR #146 fixed a crash on the row-read path (
ListDataRow.ListIdwasrequiredbut absent) and modelledversion, which is the hook for optimistic concurrency on row edits.- drops and recreates every column with a new id, losing any
Scope
A column can be shown/hidden based on another column's value:
{ "key": "studentId", "type": "text", "label": "Student ID", "visibility": { "condition": { "field": "ticketType", "operator": "equals", "value": "student" } } }Operators
equals,notEquals,contains,notContains,greaterThan,lessThan,greaterThanOrEqual,lessThanOrEqual,isEmpty,isNotEmpty(the last two ignorevalue).Documented semantics to honor
requiredcolumn hidden by its condition is not enforced until the condition makes it visible.fields; visibility is evaluated indisplayOrder.and/orgrouping.Acceptance criteria