fix(housekeeping): serialize workspace client props
This commit is contained in:
1 parent
8a31556d51
commit
cb77b2d3b9
7 files changed
+59
-15
No files matched your search
@@ -3,7 +3,6 @@
|
|||||||
import type {
|
import type {
|
||||||
HousekeepingRouteDefinition,
|
HousekeepingRouteDefinition,
|
||||||
HousekeepingSurface,
|
HousekeepingSurface,
|
||||||
HousekeepingWidgetDefinition,
|
|
||||||
} from "../../../foundation/contracts";
|
} from "../../../foundation/contracts";
|
||||||
import type { HousekeepingPreferences } from "../../../foundation/preferences/schema";
|
import type { HousekeepingPreferences } from "../../../foundation/preferences/schema";
|
||||||
import type { HousekeepingWidgetLoadResult } from "../../../foundation/registry";
|
import type { HousekeepingWidgetLoadResult } from "../../../foundation/registry";
|
||||||
@@ -13,6 +12,7 @@ import {
|
|||||||
type HousekeepingPreferenceSaver,
|
type HousekeepingPreferenceSaver,
|
||||||
WidgetSettings,
|
WidgetSettings,
|
||||||
} from "../../../foundation/shell/widget-settings";
|
} from "../../../foundation/shell/widget-settings";
|
||||||
|
import type { OperationsWidgetOption } from "../personalization-model";
|
||||||
|
|
||||||
export interface OperationsPersonalizationLabels {
|
export interface OperationsPersonalizationLabels {
|
||||||
readonly favorites: {
|
readonly favorites: {
|
||||||
@@ -55,7 +55,7 @@ export function OperationsPersonalization({
|
|||||||
}: {
|
}: {
|
||||||
readonly preferences: HousekeepingPreferences;
|
readonly preferences: HousekeepingPreferences;
|
||||||
readonly routes: readonly HousekeepingRouteDefinition[];
|
readonly routes: readonly HousekeepingRouteDefinition[];
|
||||||
readonly widgets: readonly HousekeepingWidgetDefinition[];
|
readonly widgets: readonly OperationsWidgetOption[];
|
||||||
readonly widgetResult: HousekeepingWidgetLoadResult;
|
readonly widgetResult: HousekeepingWidgetLoadResult;
|
||||||
readonly surface: HousekeepingSurface;
|
readonly surface: HousekeepingSurface;
|
||||||
readonly labels: OperationsPersonalizationLabels;
|
readonly labels: OperationsPersonalizationLabels;
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { PERMS } from "@/lib/permission-slugs";
|
|||||||
import {
|
import {
|
||||||
anyCapability,
|
anyCapability,
|
||||||
type HousekeepingRouteDefinition,
|
type HousekeepingRouteDefinition,
|
||||||
type HousekeepingWidgetDefinition,
|
|
||||||
ok,
|
ok,
|
||||||
} from "../../../foundation/contracts";
|
} from "../../../foundation/contracts";
|
||||||
import { defaultHousekeepingPreferences } from "../../../foundation/preferences/schema";
|
import { defaultHousekeepingPreferences } from "../../../foundation/preferences/schema";
|
||||||
|
import type { OperationsWidgetOption } from "../personalization-model";
|
||||||
import type { OperationsWorkspaceLoadResult } from "../queries";
|
import type { OperationsWorkspaceLoadResult } from "../queries";
|
||||||
import { OperationsWorkspacePage } from "./workspace";
|
import { OperationsWorkspacePage } from "./workspace";
|
||||||
|
|
||||||
@@ -20,13 +20,10 @@ const routes: readonly HousekeepingRouteDefinition[] = [
|
|||||||
capability,
|
capability,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const widgets: readonly HousekeepingWidgetDefinition[] = [
|
const widgets: readonly OperationsWidgetOption[] = [
|
||||||
{
|
{
|
||||||
id: "people.queue",
|
id: "people.queue",
|
||||||
owner: "people",
|
|
||||||
capability,
|
|
||||||
kind: "mandatory",
|
kind: "mandatory",
|
||||||
load: async () => ok({}, "widget"),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const preferences = {
|
const preferences = {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type {
|
import type {
|
||||||
HousekeepingRouteDefinition,
|
HousekeepingRouteDefinition,
|
||||||
HousekeepingSurface,
|
HousekeepingSurface,
|
||||||
HousekeepingWidgetDefinition,
|
|
||||||
} from "../../../foundation/contracts";
|
} from "../../../foundation/contracts";
|
||||||
import { HousekeepingPageShell } from "../../../foundation/page/housekeeping-page-shell";
|
import { HousekeepingPageShell } from "../../../foundation/page/housekeeping-page-shell";
|
||||||
import { OperationalInbox } from "../../../foundation/shell/operational-inbox";
|
import { OperationalInbox } from "../../../foundation/shell/operational-inbox";
|
||||||
import { RecentWork } from "../../../foundation/shell/recent-work";
|
import { RecentWork } from "../../../foundation/shell/recent-work";
|
||||||
import type { HousekeepingPreferenceSaver } from "../../../foundation/shell/widget-settings";
|
import type { HousekeepingPreferenceSaver } from "../../../foundation/shell/widget-settings";
|
||||||
|
import type { OperationsWidgetOption } from "../personalization-model";
|
||||||
import type { OperationsWorkspaceLoadResult } from "../queries";
|
import type { OperationsWorkspaceLoadResult } from "../queries";
|
||||||
import {
|
import {
|
||||||
OperationsPersonalization,
|
OperationsPersonalization,
|
||||||
@@ -50,7 +50,7 @@ export function OperationsWorkspacePage({
|
|||||||
}: {
|
}: {
|
||||||
readonly result: OperationsWorkspaceLoadResult;
|
readonly result: OperationsWorkspaceLoadResult;
|
||||||
readonly routes: readonly HousekeepingRouteDefinition[];
|
readonly routes: readonly HousekeepingRouteDefinition[];
|
||||||
readonly widgetDefinitions: readonly HousekeepingWidgetDefinition[];
|
readonly widgetDefinitions: readonly OperationsWidgetOption[];
|
||||||
readonly surface: HousekeepingSurface;
|
readonly surface: HousekeepingSurface;
|
||||||
readonly labels: OperationsWorkspaceLabels;
|
readonly labels: OperationsWorkspaceLabels;
|
||||||
readonly routeTitles: Readonly<Record<string, string>>;
|
readonly routeTitles: Readonly<Record<string, string>>;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { describe, expect, it, vi } from "vitest";
|
||||||
|
import {
|
||||||
|
anyCapability,
|
||||||
|
type HousekeepingWidgetDefinition,
|
||||||
|
ok,
|
||||||
|
} from "../../foundation/contracts";
|
||||||
|
import { toOperationsWidgetOptions } from "./personalization-model";
|
||||||
|
|
||||||
|
describe("toOperationsWidgetOptions", () => {
|
||||||
|
it("projects provider definitions to a serializable client view model", () => {
|
||||||
|
const load = vi.fn(async () => ok({ count: 1 }, "widget"));
|
||||||
|
const definitions: readonly HousekeepingWidgetDefinition[] = [
|
||||||
|
{
|
||||||
|
id: "people.queue",
|
||||||
|
owner: "people",
|
||||||
|
capability: anyCapability("admin.users.view"),
|
||||||
|
kind: "mandatory",
|
||||||
|
load,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const options = toOperationsWidgetOptions(definitions);
|
||||||
|
|
||||||
|
expect(options).toEqual([{ id: "people.queue", kind: "mandatory" }]);
|
||||||
|
expect(structuredClone(options)).toEqual(options);
|
||||||
|
expect(options[0]).not.toHaveProperty("load");
|
||||||
|
expect(load).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import type {
|
||||||
|
HousekeepingWidgetDefinition,
|
||||||
|
HousekeepingWidgetKind,
|
||||||
|
} from "../../foundation/contracts";
|
||||||
|
|
||||||
|
export interface OperationsWidgetOption {
|
||||||
|
readonly id: string;
|
||||||
|
readonly kind: HousekeepingWidgetKind;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toOperationsWidgetOptions(
|
||||||
|
definitions: readonly HousekeepingWidgetDefinition[],
|
||||||
|
): readonly OperationsWidgetOption[] {
|
||||||
|
return definitions.map(({ id, kind }) => ({ id, kind }));
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
type OperationsWorkspaceLabels,
|
type OperationsWorkspaceLabels,
|
||||||
OperationsWorkspacePage,
|
OperationsWorkspacePage,
|
||||||
} from "./pages/workspace";
|
} from "./pages/workspace";
|
||||||
|
import { toOperationsWidgetOptions } from "./personalization-model";
|
||||||
import { operationsWorkspaceQuery } from "./queries";
|
import { operationsWorkspaceQuery } from "./queries";
|
||||||
|
|
||||||
export async function renderOperationsWorkspacePage(
|
export async function renderOperationsWorkspacePage(
|
||||||
@@ -138,7 +139,7 @@ export async function renderOperationsWorkspacePage(
|
|||||||
return createElement(OperationsWorkspacePage, {
|
return createElement(OperationsWorkspacePage, {
|
||||||
result: workspaceResult,
|
result: workspaceResult,
|
||||||
routes,
|
routes,
|
||||||
widgetDefinitions,
|
widgetDefinitions: toOperationsWidgetOptions(widgetDefinitions),
|
||||||
surface: input.surface ?? "preview",
|
surface: input.surface ?? "preview",
|
||||||
labels,
|
labels,
|
||||||
routeTitles,
|
routeTitles,
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import type {
|
import type { HousekeepingResult, HousekeepingWidgetKind } from "../contracts";
|
||||||
HousekeepingResult,
|
|
||||||
HousekeepingWidgetDefinition,
|
|
||||||
} from "../contracts";
|
|
||||||
import type { HousekeepingPreferences } from "../preferences/schema";
|
import type { HousekeepingPreferences } from "../preferences/schema";
|
||||||
|
|
||||||
export type HousekeepingPreferenceSaver = (
|
export type HousekeepingPreferenceSaver = (
|
||||||
@@ -44,6 +41,11 @@ export interface WidgetSettingsLabels {
|
|||||||
readonly error: string;
|
readonly error: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HousekeepingWidgetOption {
|
||||||
|
readonly id: string;
|
||||||
|
readonly kind: HousekeepingWidgetKind;
|
||||||
|
}
|
||||||
|
|
||||||
export function WidgetSettings({
|
export function WidgetSettings({
|
||||||
preferences: initialPreferences,
|
preferences: initialPreferences,
|
||||||
widgets,
|
widgets,
|
||||||
@@ -52,7 +54,7 @@ export function WidgetSettings({
|
|||||||
titles = {},
|
titles = {},
|
||||||
}: {
|
}: {
|
||||||
readonly preferences: HousekeepingPreferences;
|
readonly preferences: HousekeepingPreferences;
|
||||||
readonly widgets: readonly HousekeepingWidgetDefinition[];
|
readonly widgets: readonly HousekeepingWidgetOption[];
|
||||||
readonly savePreferences: HousekeepingPreferenceSaver;
|
readonly savePreferences: HousekeepingPreferenceSaver;
|
||||||
readonly labels: WidgetSettingsLabels;
|
readonly labels: WidgetSettingsLabels;
|
||||||
readonly titles?: Readonly<Record<string, string>>;
|
readonly titles?: Readonly<Record<string, string>>;
|
||||||
|
|||||||
Reference in new issue
Block a user