refactor(webui): adopt semantic workspace actions
This commit is contained in:
@@ -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={<>
|
||||
<ActionToolbar surface="panel-header">
|
||||
<strong>Template library</strong>
|
||||
<IconButton label="Add template" icon={<Plus size={17} />} variant="primary" disabled={!canWrite} disabledReason={!canWrite ? TEMPLATES_I18N.writeReason : undefined} onClick={() => requestDiscard(() => setCreateOpen(true))} />
|
||||
</ActionToolbar>
|
||||
<WorkspaceActionBar
|
||||
scope="collection-pane"
|
||||
variant="collection"
|
||||
refreshable
|
||||
reloadAction={{ onReload: () => void reload(selectedId), loading: loading || busy }}
|
||||
contextActions={<strong>Template library</strong>}
|
||||
createAction={<IconButton label="Add template" icon={<Plus size={17} />} variant="primary" disabled={!canWrite} disabledReason={!canWrite ? TEMPLATES_I18N.writeReason : undefined} onClick={() => requestDiscard(() => setCreateOpen(true))} />}
|
||||
/>
|
||||
<FilterBar surface="panel"><input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="Search templates" /></FilterBar>
|
||||
<SelectionList variant="navigation" label="Templates">
|
||||
{visibleItems.map((item) => (
|
||||
@@ -338,25 +342,34 @@ export default function TemplatesPage({ settings, auth }: Props) {
|
||||
</SelectionList>
|
||||
</>}
|
||||
>
|
||||
<ActionToolbar surface="panel-header" className="templates-workspace-toolbar">
|
||||
<span className="templates-current-title">
|
||||
<WorkspaceActionBar
|
||||
scope="editor-pane"
|
||||
variant="editor"
|
||||
state={busy ? "saving" : dirty ? "dirty" : "clean"}
|
||||
className="templates-workspace-toolbar"
|
||||
contextActions={<span className="templates-current-title">
|
||||
<strong>{selected?.name ?? "Select a template"}</strong>
|
||||
<small>{selected ? `${typeLabel(selected.template_type)} · ${selected.revision.locale}` : ""}</small>
|
||||
</span>
|
||||
<ToolbarGroup align="end" className="templates-toolbar-actions">
|
||||
<DocumentationHelpLink reference={TEMPLATES_DOCUMENTATION} />
|
||||
<IconButton label="Discard and reload" icon={<RefreshCw size={17} />} disabled={loading || busy} disabledReason={loading ? TEMPLATES_I18N.loading : busy ? TEMPLATES_I18N.busy : undefined} onClick={() => requestDiscard(() => void reload(selectedId))} />
|
||||
<Button variant="primary" disabled={!selected || readOnly || !dirty || busy} disabledReason={busy ? TEMPLATES_I18N.busy : !selected ? TEMPLATES_I18N.noSelection : readOnly ? (canWrite ? TEMPLATES_I18N.readOnlyReason : TEMPLATES_I18N.writeReason) : !dirty ? TEMPLATES_I18N.noChanges : undefined} onClick={() => void save()}><Save size={16} /> Save revision</Button>
|
||||
</span>}
|
||||
helpAction={<DocumentationHelpLink reference={TEMPLATES_DOCUMENTATION} />}
|
||||
primaryActions={<>
|
||||
<Button disabled={!selected || !canPublish || dirty || busy} disabledReason={busy ? TEMPLATES_I18N.busy : !selected ? TEMPLATES_I18N.noSelection : !canPublish ? TEMPLATES_I18N.publishReason : dirty ? TEMPLATES_I18N.saveBeforeAction : undefined} onClick={() => setPublishOpen(true)}><FileCheck2 size={16} /> Publish</Button>
|
||||
<IconButton label="Delete template" icon={<Trash2 size={17} />} variant="danger" disabled={!selected || readOnly} disabledReason={!selected ? TEMPLATES_I18N.noSelection : readOnly ? (canWrite ? TEMPLATES_I18N.readOnlyReason : TEMPLATES_I18N.writeReason) : undefined} onClick={() => setDeleteOpen(true)} />
|
||||
<SegmentedControl
|
||||
value={view}
|
||||
onChange={setView}
|
||||
options={[{ id: "definition", label: "Definition" }, { id: "preview", label: "Preview" }]}
|
||||
ariaLabel="Template workspace"
|
||||
/>
|
||||
</ToolbarGroup>
|
||||
</ActionToolbar>
|
||||
</>}
|
||||
destructiveActions={<IconButton label="Delete template" icon={<Trash2 size={17} />} 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 size={16} /> 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()
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="templates-alerts">
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
||||
|
||||
Reference in New Issue
Block a user