diff --git a/webui/src/features/templates/TemplatesPage.tsx b/webui/src/features/templates/TemplatesPage.tsx
index 5e97cba..4bb7424 100644
--- a/webui/src/features/templates/TemplatesPage.tsx
+++ b/webui/src/features/templates/TemplatesPage.tsx
@@ -3,14 +3,13 @@ import {
Eye,
FileCheck2,
Plus,
- RefreshCw,
Save,
Send,
Trash2,
X
} from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react";
-import { DialogSection, ToolbarGroup, ActionToolbar,
+import { DialogSection, ActionToolbar,
ApiError,
ActionBlockerHint,
Button,
@@ -30,6 +29,7 @@ import { DialogSection, ToolbarGroup, ActionToolbar,
StatePanel,
StatusBadge,
ToggleSwitch,
+ WorkspaceActionBar,
WorkspaceFrame,
WorkspaceLayout,
formatDateTime,
@@ -312,10 +312,14 @@ export default function TemplatesPage({ settings, auth }: Props) {
contentLabel="Template workspace"
contentClassName="templates-workspace"
primary={<>
-
- Template library
- } variant="primary" disabled={!canWrite} disabledReason={!canWrite ? TEMPLATES_I18N.writeReason : undefined} onClick={() => requestDiscard(() => setCreateOpen(true))} />
-
+ void reload(selectedId), loading: loading || busy }}
+ contextActions={Template library}
+ createAction={} variant="primary" disabled={!canWrite} disabledReason={!canWrite ? TEMPLATES_I18N.writeReason : undefined} onClick={() => requestDiscard(() => setCreateOpen(true))} />}
+ />
setSearch(event.target.value)} placeholder="Search templates" />
{visibleItems.map((item) => (
@@ -338,25 +342,34 @@ export default function TemplatesPage({ settings, auth }: Props) {
>}
>
-
-
+
{selected?.name ?? "Select a template"}
{selected ? `${typeLabel(selected.template_type)} ยท ${selected.revision.locale}` : ""}
-
-
-
- } disabled={loading || busy} disabledReason={loading ? TEMPLATES_I18N.loading : busy ? TEMPLATES_I18N.busy : undefined} onClick={() => requestDiscard(() => void reload(selectedId))} />
-
+ }
+ helpAction={}
+ primaryActions={<>
- } variant="danger" disabled={!selected || readOnly} disabledReason={!selected ? TEMPLATES_I18N.noSelection : readOnly ? (canWrite ? TEMPLATES_I18N.readOnlyReason : TEMPLATES_I18N.writeReason) : undefined} onClick={() => setDeleteOpen(true)} />
-
-
+ >}
+ destructiveActions={} variant="danger" disabled={!selected || readOnly} disabledReason={!selected ? TEMPLATES_I18N.noSelection : readOnly ? (canWrite ? TEMPLATES_I18N.readOnlyReason : TEMPLATES_I18N.writeReason) : undefined} onClick={() => setDeleteOpen(true)} />}
+ discardAction={{ label: "Discard and reload", onClick: () => requestDiscard(() => void reload(selectedId)), disabled: !selected }}
+ saveAction={{
+ label: <> Save revision>,
+ disabled: !selected || readOnly || busy,
+ disabledReason: busy ? TEMPLATES_I18N.busy : !selected ? TEMPLATES_I18N.noSelection : readOnly ? (canWrite ? TEMPLATES_I18N.readOnlyReason : TEMPLATES_I18N.writeReason) : undefined,
+ onClick: () => void save()
+ }}
+ />
{error && {error}}