The workflow card title hint read "Preview Workflow", which names the action but does not tell that the title itself is clickable. It now reads "Click to preview workflow", matching the wording history cards used for their title.
Clickable card titles (workflow cards) are cut off after two lines, and their tooltip only named the click action, so a long name could not be read anywhere. When the title is cut off, the tooltip now shows the click hint first and the full name below it, with a gap between them; titles that fit keep the hint alone.
The tooltip moves from v-g-tooltip to GTooltip, which takes slot content for the two blocks and only describes the link. v-g-tooltip also set the hint as the link's aria-label, so screen readers announced "Preview Workflow" instead of the workflow name; the link text is now its accessible name and the tooltip its description, shown on hover and on keyboard focus.
The title link of an owned history set it as current, which the "Set as Current" button on the same card already does. A plain-text title gets the shared GCard behaviour instead: the full name in a tooltip only when the title is cut off after two lines. The HistoryCard titleClick listener was never fired by GCard, so it goes too.
The Selenium helper that selects history cards by name now reads the plain-text title.
The tool step's GLink and ToolLinkPopover pair becomes ToolDetailsButton with the step's tool icon in its slot. The popover now targets the button through its ref instead of looking up its id, and the button keeps its per-instance id, so the rendered markup only loses the display's unused scoped-style attribute on the button and popover host.
Mount the real ToolLinkPopover instead of shallow stubs and assert the markup users get: the button before the step title, its id, classes and tool icon, the dialog it controls, the popover host beside it and that keyboard focus opens it. The checks pass on the current markup, so moving the button into a shared component has to keep it as is.
Both elements carried the same GLink, info icon and ToolLinkPopover block. The rendered button, its name and the dialog it controls are unchanged, as the element tests check.
Mount the real ToolLinkPopover instead of a stub and assert the markup users get: the button's place after the title, its classes and icon, the dialog it controls, the popover host beside it and that keyboard focus opens it. The checks pass on the current markup, so moving the button into a shared component has to keep it as is.
JobMetrics, JobParameters and WorkflowDisplay each render the same GLink trigger and interactive ToolLinkPopover pair. ToolDetailsButton renders that pair once, with the localized "Tool details" name, an info icon the caller can replace, and an optional id for the button.
With the computed owner filter, the tab showed "No workflows found" until the user arrived. It now keeps its loading state instead.
(cherry picked from commit 8488c0dbf7)
Keep the fetched page and filter it by owner in a computed instead of awaiting the shared user load, so the list updates whenever the user arrives and no longer waits on App's history load. This replaces the await and the rejection handling from the previous two commits.
(cherry picked from commit 1e795c75e1)
The shared promise also loads histories, and either can fail independently of the user already being set (e.g. only histories fail after the user resolved). Swallow that rejection: App.vue already reports it, so re-throwing here would only drop an otherwise-loadable list and duplicate the toast.
(cherry picked from commit 2192376e02)
On a fresh page load, App.vue starts loading the current user while WorkflowList requests /api/workflows. When the workflows response arrives first, the "My workflows" owner filter runs with no user and drops every workflow, so the list shows "No workflows found" until the user navigates away and back. Await the shared user load promise before filtering.
(cherry picked from commit 0909e80648)
The old test only read the listInFlow and inline props of the stubbed tag editor. Mount the real dialog and tag editor instead, open the editor and assert that the suggestion list is in the dialog body, before Cancel and Ok. Teleport is unstubbed so the list lands where the app puts it; with the list teleported to the dialog element the test fails.
The old class check on the tag editor passed with and without the in-flow list, so it proved nothing. Assert instead that the suggestion list is inside the dialog body, after the tag input; with the list teleported to the dialog element the test fails.
With the suggestions in the page flow the options already follow the close button in the DOM, so the browser's Tab order is right and the manual focus move is not needed. Return early like the option Tab handler does.
When one dataset feeds a parameter that accepts it as is and another
that needs an implicit conversion, the request names the same id for
both. runtimeify now passes each parameter's extensions to the
adapters, and the lookup picks the input whose datatype the parameter
accepts, checking the dataset itself before its conversions as the
tool action does.
When a job input needs an implicit conversion, the job runs on the
converted dataset while the validated tool request still names the
dataset the user picked. setup_for_runtimeify only indexed the job's
input datasets, so adapt_dataset failed with "Could not find HDA for
dataset id ...". Index each input under the dataset it was converted
from as well.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>