Add a per-Constraint severity control to the Schema editor - #1301
Open
alistair3149 wants to merge 1 commit into
Open
Add a per-Constraint severity control to the Schema editor#1301alistair3149 wants to merge 1 commit into
alistair3149 wants to merge 1 commit into
Conversation
alistair3149
force-pushed
the
feature/1149-severity-control
branch
from
August 17, 2026 21:57
b80194b to
761cee7
Compare
Member
Author
alistair3149
marked this pull request as ready for review
August 17, 2026 22:12
Fixes #1149. Follows-up to #1227, which made the editor round-trip the object Constraint form. Adds a per-Constraint severity control to the Schema editor, so marking a Constraint `error` ([ADR 26](https://github.com/ProfessionalWiki/NeoWiki/blob/master/docs/adr/026-validation-severity-levels.md)) no longer requires hand-editing the JSON. * `SeverityInput.vue`: a `CdxMenuButton` whose face is the current level's icon (grey `cdxIconAlert` for warning, red `cdxIconError` for error) at `size="small"` plus an x-small chevron. The menu offers Warning and Error, each with its icon in the Codex warning/error colour and a one-line meaning; the Error line depends on `$wgNeoWikiEnforceValidation` ("Flags the value as an error and blocks saving" / "Flags the value as an error"), which `FrontendModuleLoader` now exposes as `wgNeoWikiEnforceValidation`. Accessible name and tooltip name the Constraint too, since several controls can sit on one property: "Severity of "Minimum": Warning". * Placement: the end of the Constraint's label row (label at the start, input untouched below), or the end of the checkbox row for boolean Constraints. The trigger keeps Codex's 32px hit area but takes 20px in the flow through negative block margins, so label rows and checkbox rows keep their height. The two placement helper classes (`ext-neowiki-severity-field`, `ext-neowiki-severity-row`) live with the component. * Shown only once the Constraint is set: `required` checked, a bound with a value, `uniqueItems` checked, at least one option. Unticking `required` or `uniqueItems`, or removing the last option, drops the severity with it; a cleared bound keeps its severity until save (a number input reports interim text such as `1.` as empty, so pruning there would lose the choice mid-typing), and serialization drops the severity of any Constraint still absent. Changing the Property Type keeps `required` with its severity and drops the type-specific ones. * Sites: `required` (`PropertyDefinitionEditor`), `minimum` / `maximum` (Number, Date, DateTime), `minLength` / `maxLength` / `uniqueItems` (Text), `uniqueItems` (Url), `options` (Select). Display Attributes (`precision`) and shape fields (`multiple`, `relation`, `targetSchema`) get none, matching what the backend accepts. * `withConstraintSeverity( property, name, severity )` returns the `Partial` an attributes editor emits: it sets the annotation, removes it for warning (the default), and drops an emptied map, so unannotated definitions stay identical to factory-built ones. `withoutSeveritiesOfClearedConstraints` prunes the annotations of Constraints a change unticks or empties; `PropertyDefinitionEditor` applies it to every attribute change. * `NeoNestedField` gap 8px → 16px so a bound's control does not crowd the next bound's label. * New messages, `cdxIconError` in the icon allowlist, and `SeverityInput` exported through the public API for extension attributes editors. * Tests: `SeverityInput`, `withConstraintSeverity` and `withoutSeveritiesOfClearedConstraints` get their own specs; each site's spec covers reveal-once-set and the emitted `constraintSeverities`; `PropertyDefinitionEditor` covers unsetting and the type change; `FrontendModuleLoaderTest` and `NeoWikiExtension.spec.ts` cover the new config var. * A boxed `CdxSelect` per Constraint: four boxed fields on a fully constrained text property. * A collapsed per-property "Severity" section: the author would pick a severity without the rule's value in view. * Toggle buttons: the glyph could not change with the level, and Codex's pressed state reads as blue rather than error. * A help sentence on the form: the menu descriptions carry the meaning at the moment of choice. 1. On a dev wiki with demo data, open `Schema:Validation Demo` and click the edit pencil. 2. Select *Score*: each bound's label row ends with a small grey ⚠▾ and the inputs keep full width. Open the *Maximum* one: a menu with Warning (yellow) and Error (red), each with a one-line meaning. Pick Error — the trigger turns red and its tooltip reads "Severity: Error". 3. Select *Title*: the trigger ends the "Require a value" row. Untick the box and it disappears; tick it and it is back. 4. Select *Status*: the trigger ends the "Options" label row; the chip input keeps full width. 5. Save. The stored JSON has `"maximum": { "value": 100, "severity": "error" }` while the untouched Constraints stay bare. Reopen the editor: the trigger shows Error again. 6. With `$wgNeoWikiEnforceValidation = true` in `LocalSettings.php`, the Error item reads "Flags the value as an error and blocks saving"; without it, "Flags the value as an error". <sub>AI-authored — Claude Code, Fable 5; design settled with Alistair, then implemented; verified with vitest (124 files, 1351 tests), PHPUnit for the loader, vue-tsc/vite build, eslint/stylelint/phpcs/phpstan, mutation-tested new specs, an adversarial code review whose confirmed findings are addressed, and a browser round trip on a dev wiki in both enforcement settings.</sub> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
alistair3149
force-pushed
the
feature/1149-severity-control
branch
from
August 20, 2026 15:21
761cee7 to
52d177a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #1149. Follows-up to #1227, which made the editor round-trip the object Constraint form.
Adds a per-Constraint severity control to the Schema editor, so marking a Constraint
error(ADR 26) no longer requires hand-editing the JSON.The control
SeverityInput.vue: aCdxMenuButtonwhose face is the current level's icon (greycdxIconAlertfor warning, redcdxIconErrorfor error) atsize="small"plus an x-small chevron. The menu offers Warning and Error, each with its icon in the Codex warning/error colour and a one-line meaning; the Error line depends on$wgNeoWikiEnforceValidation("Flags the value as an error and blocks saving" / "Flags the value as an error"), whichFrontendModuleLoadernow exposes aswgNeoWikiEnforceValidation. Accessible name and tooltip name the Constraint too, since several controls can sit on one property: "Severity of "Minimum": Warning".ext-neowiki-severity-field,ext-neowiki-severity-row) live with the component.requiredchecked, a bound with a value,uniqueItemschecked, at least one option. UntickingrequiredoruniqueItems, or removing the last option, drops the severity with it; a cleared bound keeps its severity until save (a number input reports interim text such as1.as empty, so pruning there would lose the choice mid-typing), and serialization drops the severity of any Constraint still absent. Changing the Property Type keepsrequiredwith its severity and drops the type-specific ones.required(PropertyDefinitionEditor),minimum/maximum(Number, Date, DateTime),minLength/maxLength/uniqueItems(Text),uniqueItems(Url),options(Select). Display Attributes (precision) and shape fields (multiple,relation,targetSchema) get none, matching what the backend accepts.Wiring
withConstraintSeverity( property, name, severity )returns thePartialan attributes editor emits: it sets the annotation, removes it for warning (the default), and drops an emptied map, so unannotated definitions stay identical to factory-built ones.withoutSeveritiesOfClearedConstraintsprunes the annotations of Constraints a change unticks or empties;PropertyDefinitionEditorapplies it to every attribute change.NeoNestedFieldgap 8px → 16px so a bound's control does not crowd the next bound's label.cdxIconErrorin the icon allowlist, andSeverityInputexported through the public API for extension attributes editors.SeverityInput,withConstraintSeverityandwithoutSeveritiesOfClearedConstraintsget their own specs; each site's spec covers reveal-once-set and the emittedconstraintSeverities;PropertyDefinitionEditorcovers unsetting and the type change;FrontendModuleLoaderTestandNeoWikiExtension.spec.tscover the new config var.Considered, omitted
CdxSelectper Constraint: four boxed fields on a fully constrained text property.Manual Browser Check
Schema:Validation Demoand click the edit pencil."maximum": { "value": 100, "severity": "error" }while the untouched Constraints stay bare. Reopen the editor: the trigger shows Error again.$wgNeoWikiEnforceValidation = trueinLocalSettings.php, the Error item reads "Flags the value as an error and blocks saving"; without it, "Flags the value as an error".AI-authored — Claude Code, Fable 5; design settled with Alistair, then implemented; verified with vitest (124 files, 1351 tests), PHPUnit for the loader, vue-tsc/vite build, eslint/stylelint/phpcs/phpstan, mutation-tested new specs, an adversarial code review whose confirmed findings are addressed, and a browser round trip on a dev wiki in both enforcement settings.