refactor(webui): adopt semantic workspace actions

This commit is contained in:
2026-08-19 18:47:46 +02:00
parent 244c0ee4c1
commit f49ad8eff4
+46 -45
View File
@@ -14,7 +14,6 @@ import {
GitFork, GitFork,
ListChecks, ListChecks,
Plus, Plus,
RefreshCw,
RotateCcw, RotateCcw,
Save, Save,
Settings2, Settings2,
@@ -23,7 +22,7 @@ import {
} from "lucide-react"; } from "lucide-react";
import { ReactFlowProvider } from "@xyflow/react"; import { ReactFlowProvider } from "@xyflow/react";
import { useSearchParams } from "react-router"; import { useSearchParams } from "react-router";
import { ToolbarGroup, ActionToolbar, import { ActionToolbar,
Button, Button,
ConfirmDialog, ConfirmDialog,
ContentGrid, ContentGrid,
@@ -46,6 +45,7 @@ import { ToolbarGroup, ActionToolbar,
StatePanel, StatePanel,
StatusBadge, StatusBadge,
ToggleSwitch, ToggleSwitch,
WorkspaceActionBar,
WorkspaceFrame, WorkspaceFrame,
WorkspaceLayout, WorkspaceLayout,
hasScope, hasScope,
@@ -111,7 +111,7 @@ export default function WorkflowPage({
settings: ApiSettings; settings: ApiSettings;
auth: AuthInfo; auth: AuthInfo;
}) { }) {
const { requestNavigation } = useUnsavedChanges(); const { requestDiscard, requestNavigation } = useUnsavedChanges();
const [searchParams, setSearchParams] = useSearchParams(); const [searchParams, setSearchParams] = useSearchParams();
const requestedDefinitionId = searchParams.get("definition"); const requestedDefinitionId = searchParams.get("definition");
const requestedRunId = searchParams.get("run"); const requestedRunId = searchParams.get("run");
@@ -606,20 +606,13 @@ export default function WorkflowPage({
contentLabel="Workflow editor" contentLabel="Workflow editor"
contentClassName="workflow-workspace" contentClassName="workflow-workspace"
primary={<> primary={<>
<ActionToolbar surface="panel-header"> <WorkspaceActionBar
<strong>Workflows</strong> scope="collection-pane"
<ToolbarGroup align="end" className="workflow-toolbar-actions"> variant="collection"
<DocumentationHelpLink refreshable
reference={{ topicId: "workflow.editor", documentationType: "user" }} reloadAction={{ onReload: () => void reload(draft?.id), loading: loading || working }}
label="Open Workflow documentation" contextActions={<>
/> <strong>Workflows</strong>
<IconButton
label="Refresh"
icon={<RefreshCw size={16} />}
variant="ghost"
onClick={() => void reload(draft?.id)}
disabled={loading || working}
/>
{hasScope(auth, "workflow:instance:admin") ? ( {hasScope(auth, "workflow:instance:admin") ? (
<IconButton <IconButton
label="Reconcile module standards" label="Reconcile module standards"
@@ -629,16 +622,20 @@ export default function WorkflowPage({
disabled={loading || working} disabled={loading || working}
/> />
) : null} ) : null}
<IconButton </>}
helpAction={<DocumentationHelpLink
reference={{ topicId: "workflow.editor", documentationType: "user" }}
label="Open Workflow documentation"
/>}
createAction={<IconButton
label="New workflow" label="New workflow"
icon={<Plus size={17} />} icon={<Plus size={17} />}
variant="primary" variant="primary"
onClick={createNew} onClick={createNew}
disabled={!canWrite} disabled={!canWrite}
disabledReason={!canWrite ? "Workflow definition write permission is required." : undefined} disabledReason={!canWrite ? "Workflow definition write permission is required." : undefined}
/> />}
</ToolbarGroup> />
</ActionToolbar>
<FilterBar surface="panel"> <FilterBar surface="panel">
<input <input
type="search" type="search"
@@ -683,8 +680,12 @@ export default function WorkflowPage({
> >
{draft && displayedGraph ? ( {draft && displayedGraph ? (
<> <>
<ActionToolbar surface="panel-header" className="workflow-workspace-toolbar"> <WorkspaceActionBar
<span className="workflow-identity-fields"> scope="editor-pane"
variant="editor"
state={working ? "saving" : dirty && !draft.name.trim() ? "invalid" : dirty ? "dirty" : "clean"}
className="workflow-workspace-toolbar"
contextActions={<span className="workflow-identity-fields">
<input <input
className="workflow-name-input" className="workflow-name-input"
value={draft.name} value={draft.name}
@@ -706,8 +707,8 @@ export default function WorkflowPage({
placeholder="Description" placeholder="Description"
aria-label="Workflow description" aria-label="Workflow description"
/> />
</span> </span>}
<span className="workflow-command-bar"> primaryActions={<span className="workflow-command-bar">
{draft.id ? ( {draft.id ? (
<select <select
className="workflow-revision-select" className="workflow-revision-select"
@@ -851,26 +852,26 @@ export default function WorkflowPage({
<CheckCircle2 size={16} /> Activate <CheckCircle2 size={16} /> Activate
</Button> </Button>
) : null} ) : null}
<Button </span>}
variant="primary" destructiveActions={draft.id && draft.standard?.kind !== "baseline" ? (
onClick={() => void saveDraft()} <IconButton
disabled={ label="Delete workflow"
!canEdit || !dirty || working || readOnly icon={<Trash2 size={16} />}
} variant="danger"
> onClick={() => setDeleteOpen(true)}
<Save size={16} /> Save disabled={!canEdit || working}
</Button> />
{draft.id && draft.standard?.kind !== "baseline" ? ( ) : undefined}
<IconButton discardAction={{
label="Delete workflow" label: <><RotateCcw size={16} /> Discard</>,
icon={<Trash2 size={16} />} onClick: () => requestDiscard(() => void reload(draft.id))
variant="danger" }}
onClick={() => setDeleteOpen(true)} saveAction={{
disabled={!canEdit || working} label: <><Save size={16} /> Save</>,
/> onClick: () => void saveDraft(),
) : null} disabled: !canEdit || readOnly
</span> }}
</ActionToolbar> />
<div className="workflow-alerts"> <div className="workflow-alerts">
{error ? ( {error ? (
<DismissibleAlert tone="danger" resetKey={error}> <DismissibleAlert tone="danger" resetKey={error}>