Skip to content
File

Blob: src/client/lib/affordance/share-dialog.ts

typescript81 lines
1import {
2 canCreateLinkShare,
3 canCreateUserShareByEmail,
4 canRevokeShare,
5 type ResolvedWorkspaceRole,
6} from "@/shared/entitlements";
7import {
8 ENABLED_ACTION,
9 HIDDEN_ACTION,
10 disabledAction,
11 isActionVisible,
12 OFFLINE_ACTION_REASON,
13 type UiActionState,
14} from "@/client/lib/affordance/action-state";
15import type { PageShare } from "@/shared/types";
16 
17export interface ShareDialogAffordance {
18 showPeopleSection: boolean;
19 showLinkSection: boolean;
20 createUserShare: UiActionState;
21 createLinkShare: UiActionState;
22 /** Owners/admins may invite people who are not yet workspace members by email.
23 * Members can only share with existing members; the UI should not expose a
24 * free-form email submit for them since the worker rejects it. */
25 shareByEmail: boolean;
26}
27 
28export interface ShareDialogRowAffordance {
29 revoke: UiActionState;
30 copyLink: UiActionState;
31}
32 
33export function deriveShareDialogAffordance(input: {
34 workspaceRole: ResolvedWorkspaceRole;
35 online: boolean;
36 hasUserShares: boolean;
37 hasLinkShares: boolean;
38}): ShareDialogAffordance {
39 const { workspaceRole, online, hasUserShares, hasLinkShares } = input;
40 const canCreateUserShare = workspaceRole !== "guest" && workspaceRole !== "none";
41 const createUserShare = canCreateUserShare
42 ? online
43 ? ENABLED_ACTION
44 : disabledAction(OFFLINE_ACTION_REASON)
45 : HIDDEN_ACTION;
46 const createLinkShare = canCreateLinkShare(workspaceRole)
47 ? online
48 ? ENABLED_ACTION
49 : disabledAction(OFFLINE_ACTION_REASON)
50 : HIDDEN_ACTION;
51 
52 return {
53 showPeopleSection: canCreateUserShare || hasUserShares,
54 showLinkSection: hasLinkShares || isActionVisible(createLinkShare),
55 createUserShare,
56 createLinkShare,
57 shareByEmail: canCreateUserShareByEmail(workspaceRole),
58 };
59}
60 
61export function deriveShareDialogRowAffordance(input: {
62 workspaceRole: ResolvedWorkspaceRole;
63 online: boolean;
64 currentUserId: string | undefined;
65 share: PageShare;
66 granteeIsWorkspaceMember: boolean;
67}): ShareDialogRowAffordance {
68 const { workspaceRole, online, currentUserId, share, granteeIsWorkspaceMember } = input;
69 const canRevoke = canRevokeShare({
70 workspaceRole,
71 granteeType: share.grantee_type,
72 shareCreatedByViewer: share.created_by === currentUserId,
73 granteeIsWorkspaceMember,
74 });
75 
76 return {
77 revoke: canRevoke ? (online ? ENABLED_ACTION : disabledAction(OFFLINE_ACTION_REASON)) : HIDDEN_ACTION,
78 copyLink: share.link_token ? ENABLED_ACTION : HIDDEN_ACTION,
79 };
80}