Skip to content

intent: a call action's dialog says what it acts on - description with the record, submit label, multiselect input, defaults and help (#8296) - #8305

Merged
iliyan-velichkov merged 1 commit into
masterfrom
issue-8296-call-action-dialog
Oct 28, 2026
Merged

iliyan-velichkov merged 1 commit into
masterfrom
issue-8296-call-action-dialog

Conversation

@iliyan-velichkov

Copy link
Copy Markdown
Contributor

Cause

The call: action dialog (#8090) was generic. It never named the record it acted on, and its button always said Run. A choice of several values had to be one boolean per value, with "at least one" unenforceable. No input could open with a value, and none could explain itself.

Change

Implements decisions 1-6 of the issue as written.

DSL (engine-intent)

  • ActionIntent gains description: and submit:. ActionPromptIntent gains default:, help:, options: and the multiselect type. A new ActionPromptOptionIntent holds { value, label?, help? }; a bare string is its own value and label.
  • IntentParser.normalizeActionPrompts expands bare options on the raw tree. It also keeps an unquoted date default as ISO text; SnakeYAML would otherwise hand Gson a java.util.Date.
  • Validation in validateActionCall. Every message names the action and the key. The parser refuses:
    • an unknown {property} in description, confirm or a record default. Fields, to-one relations and the Name a label: generates are properties, resolved by the new ActionPlaceholders;
    • any placeholder on scope: page;
    • options on a non-multiselect, and a multiselect without them;
    • blank or duplicate option values;
    • a literal default that does not fit its type or names no option;
    • description or submit on a page action.
  • The descriptor carries description, submit and recordFields. Each recordFields entry is {property, lookup?}, where lookup reads a to-one's display text. PromptColumns.toOneLookup was extracted from the create-from prompt's column code and is shared by both. PromptColumns.declared emits the MULTISELECT widget with its options, help and default. Every key is emitted only when declared, so a model without them generates byte-identical descriptors.

Shell

  • customActions.js:
    • openPrompt fills literal defaults at once and record defaults when they resolve, but only into an input still empty.
    • describe fills dialogDescription and confirmText from the clicked record. A to-one is fetched for its display text; a property the record lacks renders empty.
    • typedInput sends a MULTISELECT as a JSON array in options order, [] when nothing is ticked.
    • promptRun treats an empty array as a missing required input.
  • The prompt and confirm dialogs are updated in all five copies: the generated index.html.template and the application, admin, partner and personal shells.
    • The description is an x-h-dialog-description under the title.
    • The run button reads submit (default "Run").
    • help is an x-h-field-description line.
    • A MULTISELECT is an x-h-fieldset of horizontal x-h-fields, each option's label beside its box with its help under it.
    • A CHECKBOX's label now sits beside the box and toggles it (for). This applies to the dialog only; generated forms are unchanged.

Docs

  • intent-assistant-guide.md § call: and .claude/docs/intent-dsl-features.md.

Verification

  • engine-intent unit suite: 1892 tests, all green. New cases:
    • CallActionIntentTest: aMultiselectNeedsOptionsAndAKnownDefault, optionsOnAnotherTypeAreRefused, aDescriptionPlaceholderMustNameAPropertyOfTheEntity, aDefaultMustFitItsType, plus bare options, ISO date defaults, label Name, and page-action refusal.
    • CallActionDescriptorTest: the description, submit and inputs, recordFields with the to-one lookup, and that the existing actions emit none of the new keys.
  • Integration tests, run locally by name, all green:
    • CustomActionsCallIT (the shipped store in GraalJS): "{roles}" sent as ["Member","Lead"] in options order and [] when nothing is ticked; a required multiselect refused before any request; literal and {property} defaults fill the dialog; the description and confirm text resolved against the record, a to-one by its display text.
    • IntentCallActionSampleIT (browser): the issue's Invite example on a Team. The description names the team, the help lines show and Member is pre-ticked. Clicking the caption Lead ticks it, the button reads Invite, and the controller receives roles: ["Member", "Lead"].
    • GeneratesPromptHarmoniaIT and ShellRuntimeVintageIT: the shared prompt dialog and store, including an older generated page against the new runtime.
    • HarmoniaContractIT: every x-h-* directive and utility class used is one Harmonia 3.6.2 ships.
  • mvn -T 1C formatter:validate with the formatter cache wiped: BUILD SUCCESS.
  • Release-profile javadoc build of engine-intent: BUILD SUCCESS.

Not run locally: the full IT suite, and the PostgreSQL leg. The change touches no SQL.

Fixes #8296

🤖 Generated with Claude Code

…h the record, submit label, multiselect input, defaults and help (#8296)

The #8090 dialog was generic: it never named the record it acted on, its
button always said Run, a choice of several values had to be one boolean
per value, no input could open with a value, and none could explain itself.

- ActionIntent gains description: and submit:; ActionPromptIntent gains
  default:, help: and options:, and the multiselect type (options as
  { value, label?, help? } or a bare string).
- The parser normalises bare options and unquoted date defaults on the raw
  tree, and refuses: an unknown {property} in description/confirm/default
  (fields, to-one relations and a label:'s Name are properties), any
  placeholder on scope: page, options on another type, a multiselect
  without options, a literal default that does not fit its type or names
  no option, and description/submit on a page action.
- The descriptor carries description, submit and recordFields (property
  plus, for a to-one, the lookup of its display text, shared with the
  create-from prompt via PromptColumns.toOneLookup); PromptColumns.declared
  emits the MULTISELECT widget with options, help and default. Every key
  only when declared, so existing models generate byte-identical
  descriptors.
- customActions.js fills literal and record defaults, resolves the
  description and confirm placeholders against the clicked record, sends a
  MULTISELECT as a JSON array in options order ([] when nothing ticked)
  and refuses a required one left empty.
- The dialogs in all five shells (generated index.html.template,
  application, admin, partner, personal) show the description, the submit
  caption, help lines, the multiselect group, and a checkbox whose caption
  sits beside it and toggles it.

Verified: engine-intent unit suite (1892 green, incl. new
CallActionIntentTest / CallActionDescriptorTest cases);
CustomActionsCallIT, IntentCallActionSampleIT (browser, the issue's
Invite example end to end), GeneratesPromptHarmoniaIT,
ShellRuntimeVintageIT, HarmoniaContractIT; formatter:validate with the
cache wiped; release-profile javadoc on engine-intent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@iliyan-velichkov
iliyan-velichkov merged commit f9bd730 into master Oct 28, 2026
16 checks passed
@iliyan-velichkov
iliyan-velichkov deleted the issue-8296-call-action-dialog branch October 28, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

intent: a call action's dialog says what it acts on - description with the record, submit label, multiselect input, defaults and help

1 participant