Skip to content
File

Blob: src/client/lib/affordance/workspace-page.ts

typescript91 lines
1import {
2 getPageEditEntitlements,
3 getPageStructureEntitlements,
4 type PageAccessLevel,
5 type ResolvedWorkspaceRole,
6} from "@/shared/entitlements";
7import { deriveEditorAffordance, type EditorAffordance } from "@/client/lib/affordance/editor";
8import { deriveCanvasAffordance, type CanvasAffordance } from "@/client/lib/affordance/canvas";
9import {
10 ENABLED_ACTION,
11 HIDDEN_ACTION,
12 disabledAction,
13 OFFLINE_ACTION_REASON,
14 type UiActionState,
15} from "@/client/lib/affordance/action-state";
16import { resolveArchiveAffordance } from "@/client/lib/affordance/archive";
17import type { WorkspaceAccessMode } from "@/client/stores/workspace-replica";
18import type { PageKind } from "@/shared/types";
19 
20interface WorkspacePageAffordanceBase {
21 breadcrumbMode: "normal" | "restricted";
22 shareDialog: UiActionState;
23 editPageMetadata: UiActionState;
24 archivePage: UiActionState;
25}
26 
27export type WorkspacePageAffordance =
28 | (WorkspacePageAffordanceBase & {
29 kind: "doc";
30 editor: EditorAffordance;
31 })
32 | (WorkspacePageAffordanceBase & {
33 kind: "canvas";
34 canvas: CanvasAffordance;
35 });
36 
37export function deriveWorkspacePageAffordance(input: {
38 accessMode: WorkspaceAccessMode | null;
39 workspaceRole: ResolvedWorkspaceRole;
40 pageKind: PageKind;
41 pageAccess: PageAccessLevel;
42 ownsPage: boolean;
43 workspaceId: string | undefined;
44 online: boolean;
45}): WorkspacePageAffordance {
46 const { accessMode, workspaceRole, pageKind, pageAccess, ownsPage, workspaceId, online } = input;
47 const editEntitlements = getPageEditEntitlements("canonical", pageAccess);
48 const structureEntitlements = getPageStructureEntitlements(workspaceRole, ownsPage);
49 const canManageShares = accessMode === "member" && workspaceRole !== "guest" && workspaceRole !== "none";
50 const base: WorkspacePageAffordanceBase = {
51 breadcrumbMode: accessMode === "shared" || workspaceRole === "guest" ? "restricted" : "normal",
52 shareDialog: canManageShares ? (online ? ENABLED_ACTION : disabledAction(OFFLINE_ACTION_REASON)) : HIDDEN_ACTION,
53 editPageMetadata: editEntitlements.editPageMetadata
54 ? online
55 ? ENABLED_ACTION
56 : disabledAction(OFFLINE_ACTION_REASON)
57 : HIDDEN_ACTION,
58 archivePage: resolveArchiveAffordance({
59 archiveAnyPage: structureEntitlements.archiveAnyPage,
60 archiveOwnPage: structureEntitlements.archiveOwnPage,
61 ownsPage,
62 online,
63 }),
64 };
65 
66 if (pageKind === "canvas") {
67 return {
68 ...base,
69 kind: "canvas",
70 canvas: deriveCanvasAffordance({
71 surface: "canonical",
72 pageAccess,
73 workspaceId,
74 online,
75 }),
76 };
77 }
78 
79 return {
80 ...base,
81 kind: "doc",
82 editor: deriveEditorAffordance({
83 surface: "canonical",
84 pageAccess,
85 workspaceId,
86 online,
87 workspaceRole,
88 }),
89 };
90}