import { createElement } from "react"; import { satisfiesCapability } from "../../foundation/capability-context"; import { createHousekeepingRegistry } from "../../foundation/registry"; import { HOUSEKEEPING_MANIFESTS } from "../../manifests"; import type { HousekeepingRouteHandler } from "../../route-handlers"; import { type OperationsWorkspaceLabels, OperationsWorkspacePage, } from "./pages/workspace"; import { operationsWorkspaceQuery } from "./queries"; export async function renderOperationsWorkspacePage( input: Parameters[0], ) { const translate = input.translate ?? ((key: string) => key); const message = (key: string, fallback: string) => { const value = translate(key); return value === key ? fallback : value; }; const registry = createHousekeepingRegistry(HOUSEKEEPING_MANIFESTS); const accessibleDomains = registry.domains.filter( (domain) => domain.id !== "operations" && satisfiesCapability(input.context, domain.capability), ); const routes = accessibleDomains.flatMap((domain) => domain.routes.filter((route) => satisfiesCapability(input.context, route.capability), ), ); const widgetDefinitions = registry.domains .filter((domain) => satisfiesCapability(input.context, domain.capability)) .flatMap((domain) => domain.widgets.filter((widget) => satisfiesCapability(input.context, widget.capability), ), ); const labels: OperationsWorkspaceLabels = { title: message("workspace.title", "Operations workspace"), description: message( "workspace.description", "Inbox, recent work, favorites, and widgets for the domains you can operate.", ), noDomainsTitle: message( "workspace.noDomainsTitle", "No operational domains are available", ), noDomainsDescription: message( "workspace.noDomainsDescription", "No operational domain is authorized for your account.", ), partial: message( "workspace.partial", "Some workspace sections are unavailable", ), inbox: { title: message("workspace.inbox.title", "Operational inbox"), domainFilter: message("workspace.inbox.domainFilter", "Filter by domain"), stateFilter: message("workspace.inbox.stateFilter", "Filter by state"), priorityFilter: message( "workspace.inbox.priorityFilter", "Filter by priority", ), all: message("workspace.inbox.all", "All"), loading: message("workspace.inbox.loading", "Loading operational inbox"), empty: message("workspace.inbox.empty", "No operational work is waiting"), partial: message( "workspace.inbox.partial", "Some inbox sources are unavailable", ), open: message("workspace.inbox.open", "Open"), }, recent: { title: message("workspace.recent.title", "Recent work"), empty: message("workspace.recent.empty", "No recent Housekeeping work"), }, favorites: { title: message("workspace.favorites.title", "Favorites"), pin: message("workspace.favorites.pin", "Pin"), unpin: message("workspace.favorites.unpin", "Unpin"), error: message( "workspace.favorites.error", "Preferences could not be saved", ), reorderInstructions: message( "workspace.favorites.reorderInstructions", "Press Space, then use the arrow keys to reorder.", ), }, widgetSettings: { title: message("workspace.widgetSettings.title", "Widget settings"), mandatory: message("workspace.widgetSettings.mandatory", "Mandatory"), error: message( "workspace.widgetSettings.error", "Preferences could not be saved", ), }, widgets: { title: message("workspace.widgets.title", "Widgets"), partial: message( "workspace.widgets.partial", "Some widgets are unavailable", ), error: message( "workspace.widgets.error", "Widget order could not be saved", ), reorderInstructions: message( "workspace.widgets.reorderInstructions", "Press Space, then use the arrow keys to reorder.", ), }, }; const routeTitles = Object.fromEntries( routes.map((route) => [ route.labelKey, message(route.labelKey.slice("pages.housekeeping.".length), route.id), ]), ); const widgetTitles = Object.fromEntries( widgetDefinitions.map((widget) => [ widget.id, message(`widgets.${widget.id}`, widget.id), ]), ); const workspaceResult = await operationsWorkspaceQuery(input.context); const inboxTitles = Object.fromEntries( workspaceResult.model.inbox.items.map((item) => [ item.titleKey, item.titleKey.startsWith("pages.housekeeping.") ? message( item.titleKey.slice("pages.housekeeping.".length), item.domain, ) : item.titleKey, ]), ); return createElement(OperationsWorkspacePage, { result: workspaceResult, routes, widgetDefinitions, surface: input.surface ?? "preview", labels, routeTitles, widgetTitles, inboxTitles, ...(input.savePreferences ? { savePreferences: input.savePreferences } : {}), }); } export const OPERATIONS_ROUTE_HANDLERS: readonly HousekeepingRouteHandler[] = Object.freeze([ Object.freeze({ routeId: "operations.workspace", render: renderOperationsWorkspacePage, }), ]);