enhancement
major
minor
major
minor
minor
#29611
TL Views: `<notify>` action shows a translated notice in a generic-command chain (snackbar or OK dialog, optionally stopping the chain); `<throw-error>` removed
Problem
A <generic-command> chain that refuses an input has no action that merely tells the user why. Two cases from the issue tracker tl-dev:
- The app-bar ticket search (#29542 <value-input> with <on-submit>): a term naming no ticket. The <else> branch of the <if> (#29543) should show "No ticket TL-999999." and end the chain.
- A drop of several tickets on the Done lane (#29545), whose Resolve dialog is per ticket: the chain refuses with "Drop one ticket at a time to resolve it."
What exists: <throw-error message="…"> takes a fixed String - no ResKey, no i18n literal, no argument from the chain value - and its JavaDoc calls it a test aid; <confirm expr="…"> takes an i18n function of the chain value but always renders a Yes/No dialog (ConfirmDialogControl builds both buttons), which asks a question the user cannot answer. The apps therefore either abuse <confirm> as a notice or call the TL-Script throw(#('…'@en, '…'@de).fill($term)), which raises ScriptAbort and happens to surface as the window's snackbar with one INFO line in the log.
Solution
One action, <notify> (NotifyAction), tells the user something from inside a command chain:
<if test="ticket -> $ticket != null">
<then>…</then>
<else>
<notify kind="warning" stop="true" expr="term -> #('No ticket {0}.'@en, 'Kein Ticket {0}.'@de).fill($term)"/>
</else>
</if>
- expr (with <inputs>, evaluated like <confirm>: input channel values first, the chain's value last) computes the message - an i18n literal, a resource key or a text. null or an empty text means there is nothing to say: the chain continues unchanged.
- kind="info|warning|error" (default info) is the severity: the snackbar variant, or the title of the dialog.
- display="snackbar|dialog" (default snackbar). The snackbar notice is shown in passing and is synchronous (usable inside <with-transaction>). The dialog shows the message with a single OK button and suspends the chain until it is closed (OK, Escape, X or backdrop), like <confirm> does; a context without a dialog manager falls back to the snackbar.
- stop="true" (default false) ends the chain after the notice: no further action runs, the compensations of the executed actions run, and nothing is logged or reported as a failure - a refused input is the command working as intended. Without stop the value passes on unchanged, so a notice can also close a chain ("Saved.") or stand in the middle of one.
- title (resource key) names the dialog; by default the title follows the kind.
The dialog is built by a reusable MessageDialogControl in the React control layer beside ConfirmDialogControl.
<throw-error> is removed: a notice with stop="true" covers its only use, and a genuine failure is raised by the TL-Script function throw(#('…'@en).fill(…)) inside <execute-script>, which carries an i18n message and is reported through CommandErrors like every other failure. The error-handling demo of tl-demo-react uses that instead and shows the notice variants.
Documentation in docs/faq/react-view-layer.md beside <confirm>.
Migration
<throw-error message="…"/> in a .view.xml is replaced by <notify kind="error" stop="true" expr="x -> #('…'@en)"/> when the chain should merely end with the message, or by <execute-script function="x -> throw(#('…'@en))"/> when the command should fail.