enhancement
major
minor
major
minor
major
#29619
TL Views: a warning-level configuration constraint is dropped, so the model editor shows nothing
Problem
A configuration property may declare a constraint that reports a problem without blocking, @Constraint(value = …, asWarning = true). Such a constraint is evaluated in a form of the React view layer and then thrown away: ConfigValidation.collectConstraintFailures keeps only the failures that are not warnings, because what it collects becomes a Violation blocking ConfigFormModel.apply().
{{{#!java for (ConstraintFailure failure : checker.getFailures()) {
if (!failure.isWarning()) {
violations.add(
new Violation(failure.getItem(), failure.getContextProperty(), failure.getConstraintName()));
}
} }}}
The result is that a warning a property declares is reported in the boot log, where the configuration is read, but is invisible to the person editing that very property in the application. Found on ColorSpec#getToken() (#29606): a design token no theme emits is reported when it stands in a *.model.xml, while the same token shown in the model editor is accepted without a word - which is the silence #29606 set out to remove.
Solution
A warning-level failure is reported beside the field instead of being dropped, without blocking the form from being applied.
The transport existed: ReactFormFieldControl carries a hasWarnings state to the client and reads it from the FieldModel; FieldModel.setModelValidationWarnings is the step that was missing next to the path turning a non-warning failure into a Violation.
The change affects every constraint declared asWarning, not only the one that exposed it.
Design
- ConfigValidation.check collects both kinds of finding as Findings: a Warning record beside the blocking Violation, each carrying item, property and the constraint's own message. report places a warning on its field through FieldModel.setModelValidationWarnings (all warnings about one field in one call) and reveals the field, as it does for a violation. refusalFor places the warnings whether or not it ends in a refusal; the Refusal lists violations only.
- ConfigFieldIndex.clearFindings (formerly clearModelErrors) takes placed warnings back before each re-check, and ConfigFieldModel.setValue drops the warnings of a value the field no longer holds, as it does for the error.
- ConfigValidation.recheck is the check-and-place step without the refusals over unconfirmed entries and unreadable input; refusalFor reuses it. The standalone ConfigFormControl (the <config-form> element) runs it on every field value change while in edit mode, so warnings and errors are visible while editing, not only after Apply; nothing is checked when edit mode is entered, so a form opened over empty mandatory values does not turn red before it has been touched. Apply still refuses only on violations. The ConfigFieldPush helper that drives this moved from com.top_logic.layout.view into com.top_logic.layout.configedit, shared by the standalone form and the annotations editor of the view layer.
- The React demo's configuration editor (DemoEditorConfig) declares @Constraint(value = Positive.class, asWarning = true) on its count, so the demo shows a warning beside the violation of its mandatory owner.
Verification
- Unit tests in TestConfigValidation and TestConfigFormControl (tl-layout-configedit): a warning is found as a warning and never blocks Apply, both kinds reach their own field in one report, every warning about one property is shown, a warning is taken back on re-check and on a value change, a warning and a violation appear while editing without Apply, the other end of a cross-item constraint is cleared on the live re-check, entering edit mode flags nothing, a live re-check does not mark an unconfirmed entry.
- Browser, tl-demo-react: in the configuration editor demo a count of -1 shows "Der Wert muss positiv sein." under the count field and an empty owner shows its error at the same time; Apply is refused over the owner alone and proceeds once it is filled, with the warning still standing. In the model editor, a <color> annotation on a classifier whose design token no theme emits shows the token warning under the "Design token" field as soon as the entry is confirmed, with no error on the surrounding annotations field; choosing an emitted token clears it.
Note on the model editor: the design-token field offers the emitted tokens as a closed selection (@Options(fun = ColorTokenOptions.class)), so a token no theme emits cannot be typed there; the warning appears for a token that is already stored (from a *.model.xml, or after a theme change) when the annotation is edited.