refactor(webui): adopt semantic page actions
This commit is contained in:
@@ -6,8 +6,7 @@ import {
|
||||
useState,
|
||||
type FormEvent
|
||||
} from "react";
|
||||
import { ActionToolbar,
|
||||
ActionBlockerHint,
|
||||
import { ActionBlockerHint,
|
||||
CountBadge,
|
||||
DismissibleAlert,
|
||||
Button,
|
||||
@@ -19,6 +18,7 @@ import { ActionToolbar,
|
||||
StatusBadge,
|
||||
ToggleSwitch,
|
||||
useGuardedNavigate,
|
||||
WorkspaceActionBar,
|
||||
WorkspaceFrame,
|
||||
type PlatformRouteContext
|
||||
} from "@govoplan/core-webui";
|
||||
@@ -41,6 +41,7 @@ export default function PortalPage({ settings }: PlatformRouteContext) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
const [launchingId, setLaunchingId] = useState("");
|
||||
const [reloadKey, setReloadKey] = useState(0);
|
||||
const launchAttempts = useRef(new Map<string, {
|
||||
idempotencyKey: string;
|
||||
requestedAt: string;
|
||||
@@ -67,7 +68,7 @@ export default function PortalPage({ settings }: PlatformRouteContext) {
|
||||
}).
|
||||
finally(() => setLoading(false));
|
||||
return () => controller.abort();
|
||||
}, [includeUnavailable, settings, submittedQuery]);
|
||||
}, [includeUnavailable, reloadKey, settings, submittedQuery]);
|
||||
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
@@ -79,7 +80,7 @@ export default function PortalPage({ settings }: PlatformRouteContext) {
|
||||
}
|
||||
});
|
||||
return () => controller.abort();
|
||||
}, [settings]);
|
||||
}, [reloadKey, settings]);
|
||||
|
||||
const counts = useMemo(() => ({
|
||||
available: services.filter((entry) => entry.state === "available").length,
|
||||
@@ -131,8 +132,14 @@ export default function PortalPage({ settings }: PlatformRouteContext) {
|
||||
return (
|
||||
<main className="portal-page">
|
||||
<WorkspaceFrame className="portal-shell" label="Service directory" interfaceId="portal.service-directory" helpContextId="portal.page.directory" helpModuleId="portal">
|
||||
<ActionToolbar surface="panel-header" className="portal-toolbar">
|
||||
<FilterBar as="form" surface="control" wrap="never" width="wide" className="portal-search" onSubmit={submit}>
|
||||
<WorkspaceActionBar
|
||||
scope="workspace"
|
||||
variant="collection"
|
||||
refreshable
|
||||
reloadAction={{ onReload: () => setReloadKey((value) => value + 1), loading }}
|
||||
className="portal-toolbar"
|
||||
contextActions={<>
|
||||
<FilterBar as="form" surface="control" wrap="never" width="wide" className="portal-search" onSubmit={submit}>
|
||||
<Search size={17} aria-hidden="true" />
|
||||
<input
|
||||
value={query}
|
||||
@@ -141,17 +148,18 @@ export default function PortalPage({ settings }: PlatformRouteContext) {
|
||||
placeholder="Search services"
|
||||
/>
|
||||
<Button type="submit" variant="primary">Search</Button>
|
||||
</FilterBar>
|
||||
<DocumentationHelpLink
|
||||
</FilterBar>
|
||||
<ToggleSwitch
|
||||
label="Show unavailable services"
|
||||
checked={includeUnavailable}
|
||||
onChange={setIncludeUnavailable}
|
||||
/>
|
||||
</>}
|
||||
helpAction={<DocumentationHelpLink
|
||||
reference={{ topicId: "portal.service-directory", documentationType: "user" }}
|
||||
label="Open service directory documentation"
|
||||
/>
|
||||
<ToggleSwitch
|
||||
label="Show unavailable services"
|
||||
checked={includeUnavailable}
|
||||
onChange={setIncludeUnavailable}
|
||||
/>
|
||||
</ActionToolbar>
|
||||
/>}
|
||||
/>
|
||||
|
||||
<div className="portal-result-summary" aria-live="polite">
|
||||
<strong>{counts.available}</strong> available
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Clock3, LogIn, RefreshCw, Send } from "lucide-react";
|
||||
import { Clock3, LogIn, Send } from "lucide-react";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useParams, useSearchParams } from "react-router";
|
||||
import {
|
||||
ActionToolbar,
|
||||
Button,
|
||||
Card,
|
||||
DescriptionItem,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
LoadingIndicator,
|
||||
PageScrollViewport,
|
||||
StatusBadge,
|
||||
WorkspaceActionBar,
|
||||
WorkspaceFrame,
|
||||
type PlatformRouteContext
|
||||
} from "@govoplan/core-webui";
|
||||
@@ -101,13 +101,14 @@ export default function PortalStatusPage({ settings }: PlatformRouteContext) {
|
||||
helpModuleId="portal"
|
||||
helpTopicId="portal.application-status"
|
||||
helpContextId="portal.application-status">
|
||||
<ActionToolbar surface="workspace" className="portal-status-toolbar">
|
||||
<strong>Application status</strong>
|
||||
<Button onClick={() => void load()} disabled={loading}>
|
||||
<RefreshCw size={16} aria-hidden="true" />
|
||||
Reload
|
||||
</Button>
|
||||
</ActionToolbar>
|
||||
<WorkspaceActionBar
|
||||
scope="workspace"
|
||||
variant="detail"
|
||||
refreshable
|
||||
reloadAction={{ onReload: () => void load(), loading }}
|
||||
className="portal-status-toolbar"
|
||||
contextActions={<strong>Application status</strong>}
|
||||
/>
|
||||
<PageScrollViewport className="portal-status-viewport">
|
||||
{error && <DismissibleAlert tone="danger" resetKey={error}>{error}</DismissibleAlert>}
|
||||
{notice && <DismissibleAlert tone="info" resetKey={notice}>{notice}</DismissibleAlert>}
|
||||
|
||||
Reference in New Issue
Block a user