Adopt shared WebUI structural primitives
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { Link } from "react-router";
|
||||
import { FormGrid, ToolbarGroup,
|
||||
ActionToolbar,
|
||||
AdminIconButton,
|
||||
Button,
|
||||
DateTimeField,
|
||||
@@ -20,10 +21,14 @@ import { FormGrid, ToolbarGroup,
|
||||
DismissibleAlert,
|
||||
DocumentationHelpLink,
|
||||
FormField,
|
||||
FilterBar,
|
||||
SegmentedControl,
|
||||
SelectionList,
|
||||
SelectionListItem,
|
||||
StatePanel,
|
||||
StatusBadge,
|
||||
WorkspaceFrame,
|
||||
WorkspaceLayout,
|
||||
hasScope,
|
||||
type ApiSettings,
|
||||
type AuthInfo
|
||||
@@ -120,10 +125,22 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="tasks-page" data-help-context-id="tasks.page.inbox">
|
||||
<div className="tasks-shell">
|
||||
<aside className="tasks-sidebar">
|
||||
<div className="tasks-sidebar-bar">
|
||||
<WorkspaceFrame as="main" height="viewport" surface="plain" className="tasks-page" label="Task inbox" data-help-context-id="tasks.page.inbox">
|
||||
<WorkspaceLayout
|
||||
variant="split"
|
||||
primarySize="default"
|
||||
primaryScrollable={false}
|
||||
contentScrollable={false}
|
||||
surface="contained"
|
||||
primaryClassName="tasks-sidebar"
|
||||
contentClassName="tasks-workspace"
|
||||
primaryLabel="i18n:govoplan-tasks.work"
|
||||
contentLabel="i18n:govoplan-tasks.work_details"
|
||||
interfaceId="tasks.inbox.workspace"
|
||||
helpContextId="tasks.page.inbox"
|
||||
helpModuleId="tasks"
|
||||
primary={<>
|
||||
<ActionToolbar surface="panel-header" className="tasks-sidebar-bar">
|
||||
<span className="tasks-title"><ListChecks size={18} /><strong>i18n:govoplan-tasks.work</strong></span>
|
||||
<ToolbarGroup align="end" className="tasks-toolbar-actions">
|
||||
<AdminIconButton
|
||||
@@ -142,8 +159,8 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
/>
|
||||
) : null}
|
||||
</ToolbarGroup>
|
||||
</div>
|
||||
<form className="tasks-search" onSubmit={submitSearch} role="search">
|
||||
</ActionToolbar>
|
||||
<FilterBar as="form" surface="control" wrap="never" className="tasks-search" onSubmit={submitSearch} role="search">
|
||||
<Search size={15} aria-hidden="true" />
|
||||
<input
|
||||
value={searchDraft}
|
||||
@@ -151,7 +168,7 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
placeholder="i18n:govoplan-tasks.search_placeholder"
|
||||
aria-label="i18n:govoplan-tasks.search"
|
||||
/>
|
||||
</form>
|
||||
</FilterBar>
|
||||
<SegmentedControl
|
||||
className="tasks-status-filter"
|
||||
options={[
|
||||
@@ -168,7 +185,7 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
{loading ? <p className="tasks-note">i18n:govoplan-tasks.loading</p> : null}
|
||||
{!loading && items.length === 0 ? <p className="tasks-note">i18n:govoplan-tasks.empty</p> : null}
|
||||
{items.length ? (
|
||||
<SelectionList label="i18n:govoplan-tasks.work_items">
|
||||
<SelectionList variant="navigation" label="i18n:govoplan-tasks.work_items">
|
||||
{items.map((item) => (
|
||||
<SelectionListItem
|
||||
key={`${item.provider_id}:${item.id}`}
|
||||
@@ -183,25 +200,24 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
</SelectionList>
|
||||
) : null}
|
||||
</div>
|
||||
</aside>
|
||||
</>}
|
||||
>
|
||||
|
||||
<section className="tasks-workspace" data-help-context-id="tasks.page.detail">
|
||||
<div className="tasks-topbar">
|
||||
<ActionToolbar surface="panel-header" className="tasks-topbar" data-help-context-id="tasks.page.detail">
|
||||
<span className="tasks-detail-title"><ListChecks size={18} /><strong>{selected?.title ?? "i18n:govoplan-tasks.work_details"}</strong></span>
|
||||
<ToolbarGroup align="end" className="tasks-toolbar-actions">
|
||||
<DocumentationHelpLink reference={DOCUMENTATION} />
|
||||
{selected?.provider_id === "tasks.explicit" && canWrite ? <TaskActions item={selected} busy={busy} onAction={(action) => action === "defer" ? setDeferOpen(true) : void runAction(action)} /> : null}
|
||||
</ToolbarGroup>
|
||||
</div>
|
||||
</ActionToolbar>
|
||||
|
||||
{error ? <DismissibleAlert tone="danger" compact resetKey={error}>{error}</DismissibleAlert> : null}
|
||||
{diagnostics.map((message) => <DismissibleAlert key={message} tone="warning" compact resetKey={message}>{message}</DismissibleAlert>)}
|
||||
|
||||
{selected ? <TaskDetails item={selected} /> : (
|
||||
<div className="tasks-empty-detail"><ListChecks size={24} /><h1>i18n:govoplan-tasks.work</h1><p>i18n:govoplan-tasks.select_help</p></div>
|
||||
<StatePanel size="fill" icon={<ListChecks size={24} />} title="i18n:govoplan-tasks.work" description="i18n:govoplan-tasks.select_help" />
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
</WorkspaceLayout>
|
||||
|
||||
<CreateTaskDialog
|
||||
open={createOpen}
|
||||
@@ -230,7 +246,7 @@ export default function TasksPage({ settings, auth }: { settings: ApiSettings; a
|
||||
<DateTimeField value={deferredUntil} onChange={setDeferredUntil} min={localDateTime(new Date())} />
|
||||
</FormField>
|
||||
</Dialog>
|
||||
</main>
|
||||
</WorkspaceFrame>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user