refactor(webui): adopt semantic workspace actions

This commit is contained in:
2026-08-19 18:47:45 +02:00
parent da0960967d
commit f9f7ab75d3
@@ -1,9 +1,8 @@
import { useEffect, useMemo, useState } from "react"; import { useEffect, useMemo, useState } from "react";
import { Bell, Check, ExternalLink, RefreshCw, Send, XCircle } from "lucide-react"; import { Bell, Check, ExternalLink, Send, XCircle } from "lucide-react";
import { import {
ActionBlockerHint, ActionBlockerHint,
ActionToolbar, ActionToolbar,
AdminIconButton,
Button, Button,
ConfirmDialog, ConfirmDialog,
CountBadge, CountBadge,
@@ -14,6 +13,7 @@ import {
SelectionListItem, SelectionListItem,
StatePanel, StatePanel,
StatusBadge, StatusBadge,
WorkspaceActionBar,
WorkspaceFrame, WorkspaceFrame,
WorkspaceLayout, WorkspaceLayout,
hasScope, hasScope,
@@ -192,20 +192,18 @@ export default function NotificationCenterPage({ settings, auth }: { settings: A
helpContextId="notifications.page.center" helpContextId="notifications.page.center"
helpModuleId="notifications" helpModuleId="notifications"
primary={<> primary={<>
<ActionToolbar surface="panel-header" className="notifications-sidebar-bar"> <WorkspaceActionBar
<div className="notifications-title"> scope="collection-pane"
variant="collection"
refreshable
reloadAction={{ onReload: () => void load(), loading: loading || busy, label: "i18n:govoplan-notifications.refresh" }}
className="notifications-sidebar-bar"
contextActions={<div className="notifications-title">
<Bell size={17} /> <Bell size={17} />
<strong>i18n:govoplan-notifications.notifications</strong> <strong>i18n:govoplan-notifications.notifications</strong>
{unreadCount > 0 ? <CountBadge>{unreadCount}</CountBadge> : null} {unreadCount > 0 ? <CountBadge>{unreadCount}</CountBadge> : null}
</div> </div>}
<AdminIconButton
label="i18n:govoplan-notifications.refresh"
icon={<RefreshCw size={16} aria-hidden="true" />}
onClick={() => void load()}
disabled={loading || busy}
disabledReason={loading ? NOTIFICATIONS_I18N.loading : busy ? NOTIFICATIONS_I18N.actionActive : undefined}
/> />
</ActionToolbar>
<SegmentedControl <SegmentedControl
className="notifications-status-filter" className="notifications-status-filter"
options={statusFilters.map((status) => ({ id: status, label: statusLabel(status) }))} options={statusFilters.map((status) => ({ id: status, label: statusLabel(status) }))}
@@ -241,27 +239,30 @@ export default function NotificationCenterPage({ settings, auth }: { settings: A
</div> </div>
</>} </>}
> >
<ActionToolbar surface="panel-header" className="notifications-topbar"> <WorkspaceActionBar
<div className="notifications-title-line"> scope="detail-pane"
variant="detail"
className="notifications-topbar"
contextActions={<div className="notifications-title-line">
<Bell size={18} /> <Bell size={18} />
<strong>{selected?.subject || selected?.event_kind || "i18n:govoplan-notifications.surface.center"}</strong> <strong>{selected?.subject || selected?.event_kind || "i18n:govoplan-notifications.surface.center"}</strong>
</div> </div>}
<div className="notifications-actions"> helpAction={<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} />}
<DocumentationHelpLink reference={NOTIFICATIONS_DOCUMENTATION} /> primaryActions={<div className="notifications-actions">
<Button onClick={() => void markSelected("read")} disabled={Boolean(markReadDisabledReason)} disabledReason={markReadDisabledReason}> <Button onClick={() => void markSelected("read")} disabled={Boolean(markReadDisabledReason)} disabledReason={markReadDisabledReason}>
<Check size={16} /> i18n:govoplan-notifications.mark_read <Check size={16} /> i18n:govoplan-notifications.mark_read
</Button> </Button>
<Button onClick={() => void markSelected("acknowledged")} disabled={Boolean(acknowledgeDisabledReason)} disabledReason={acknowledgeDisabledReason}> <Button onClick={() => void markSelected("acknowledged")} disabled={Boolean(acknowledgeDisabledReason)} disabledReason={acknowledgeDisabledReason}>
<Check size={16} /> i18n:govoplan-notifications.acknowledge <Check size={16} /> i18n:govoplan-notifications.acknowledge
</Button> </Button>
<Button variant="danger" onClick={() => setConfirmingAction("cancel")} disabled={Boolean(cancelDisabledReason)} disabledReason={cancelDisabledReason}>
<XCircle size={16} /> i18n:govoplan-notifications.cancel_delivery
</Button>
<Button onClick={() => setConfirmingAction("dispatch")} disabled={Boolean(dispatchDisabledReason)} disabledReason={dispatchDisabledReason}> <Button onClick={() => setConfirmingAction("dispatch")} disabled={Boolean(dispatchDisabledReason)} disabledReason={dispatchDisabledReason}>
<Send size={16} /> i18n:govoplan-notifications.dispatch_pending <Send size={16} /> i18n:govoplan-notifications.dispatch_pending
</Button> </Button>
</div> </div>}
</ActionToolbar> destructiveActions={<Button variant="danger" onClick={() => setConfirmingAction("cancel")} disabled={Boolean(cancelDisabledReason)} disabledReason={cancelDisabledReason}>
<XCircle size={16} /> i18n:govoplan-notifications.cancel_delivery
</Button>}
/>
{error ? <DismissibleAlert tone="danger" compact resetKey={error}>{error}</DismissibleAlert> : null} {error ? <DismissibleAlert tone="danger" compact resetKey={error}>{error}</DismissibleAlert> : null}