@burdenoff/microfe-workspaces 2026.531.2 → 2026.531.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/WorkspacesRoutes.js +36 -17
- package/dist/WorkspacesRoutes.js.map +1 -1
- package/dist/components/InviteMemberDialog.js +204 -117
- package/dist/components/InviteMemberDialog.js.map +1 -1
- package/dist/components/MemberListItem.js +2 -1
- package/dist/components/MemberListItem.js.map +1 -1
- package/dist/components/ProjectMemberPickerDialog.js +211 -0
- package/dist/components/ProjectMemberPickerDialog.js.map +1 -0
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useMemberMutations.js +13 -13
- package/dist/hooks/useMemberMutations.js.map +1 -1
- package/dist/hooks/useProjectMemberMutations.js +104 -0
- package/dist/hooks/useProjectMemberMutations.js.map +1 -0
- package/dist/hooks/useProjectMembers.js +42 -0
- package/dist/hooks/useProjectMembers.js.map +1 -0
- package/dist/hooks/useWorkspaceMembers.js +60 -24
- package/dist/hooks/useWorkspaceMembers.js.map +1 -1
- package/dist/hooks/useWorkspacePermissions.js +4 -0
- package/dist/hooks/useWorkspacePermissions.js.map +1 -1
- package/dist/hooks/useWorkspacesEventEmitter.js.map +1 -1
- package/dist/index.js +16 -15
- package/dist/pages/ActivityListPage.js +5 -5
- package/dist/pages/InviteAcceptancePage.js +211 -207
- package/dist/pages/InviteAcceptancePage.js.map +1 -1
- package/dist/pages/MembersListPage.js +210 -208
- package/dist/pages/MembersListPage.js.map +1 -1
- package/dist/pages/PendingInvitesPage.js +124 -120
- package/dist/pages/PendingInvitesPage.js.map +1 -1
- package/dist/pages/ProjectDetailPage.js +249 -213
- package/dist/pages/ProjectDetailPage.js.map +1 -1
- package/dist/pages/ProjectMembersPage.js +265 -0
- package/dist/pages/ProjectMembersPage.js.map +1 -0
- package/dist/pages/ProjectsListPage.js +9 -9
- package/dist/pages/WorkspaceDetailPage.js +119 -111
- package/dist/pages/WorkspaceDetailPage.js.map +1 -1
- package/dist/pages/WorkspaceInvitePage.js +790 -0
- package/dist/pages/WorkspaceInvitePage.js.map +1 -0
- package/dist/pages/WorkspacesListPage.js +115 -100
- package/dist/pages/WorkspacesListPage.js.map +1 -1
- package/dist/utils/invitationDisplay.js +25 -0
- package/dist/utils/invitationDisplay.js.map +1 -0
- package/dist/utils/workspaceBulkInviteCsv.js +42 -0
- package/dist/utils/workspaceBulkInviteCsv.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
|
|
2
|
+
import { useInfiniteQuery as t } from "@tanstack/react-query";
|
|
3
|
+
import { graphqlFetch as n } from "@burdenoff/fe-libs/shared/graphql";
|
|
4
|
+
//#region src/hooks/useProjectMembers.ts
|
|
5
|
+
var r = "\n query GetProjectMembers($projectId: ID!, $pagination: PaginationInput) {\n projectMembers(filter: { projectId: $projectId }, pagination: $pagination) {\n items {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n total\n hasMore\n }\n }\n", i = (i, a, o = 100, s = !0) => {
|
|
6
|
+
let { authToken: c, workspaceId: l } = e(), u = a || l;
|
|
7
|
+
return t({
|
|
8
|
+
queryKey: [
|
|
9
|
+
"projectMembersInfinite",
|
|
10
|
+
u,
|
|
11
|
+
i,
|
|
12
|
+
o
|
|
13
|
+
],
|
|
14
|
+
initialPageParam: 0,
|
|
15
|
+
queryFn: async ({ pageParam: e }) => {
|
|
16
|
+
let t = await n({
|
|
17
|
+
gateway: "workspace",
|
|
18
|
+
authToken: c || void 0,
|
|
19
|
+
query: r,
|
|
20
|
+
variables: {
|
|
21
|
+
projectId: i,
|
|
22
|
+
pagination: {
|
|
23
|
+
limit: o,
|
|
24
|
+
offset: e
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
workspaceId: u || void 0,
|
|
28
|
+
workspaceToken: !0
|
|
29
|
+
});
|
|
30
|
+
if (t.errors?.length) throw Error(t.errors[0]?.message || "GraphQL error");
|
|
31
|
+
if (!t.data?.projectMembers) throw Error("Project members query returned no data");
|
|
32
|
+
return t.data.projectMembers;
|
|
33
|
+
},
|
|
34
|
+
getNextPageParam: (e, t, n) => e.hasMore ? Number(n) + o : void 0,
|
|
35
|
+
enabled: s && !!i && !!u,
|
|
36
|
+
staleTime: 60 * 1e3
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
export { i as useInfiniteProjectMembers };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=useProjectMembers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProjectMembers.js","names":[],"sources":["../../src/hooks/useProjectMembers.ts"],"sourcesContent":["import { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport type { PaginationInput, ProjectMember, ProjectMemberList } from '../types';\n\nconst GET_PROJECT_MEMBERS_QUERY = `\n query GetProjectMembers($projectId: ID!, $pagination: PaginationInput) {\n projectMembers(filter: { projectId: $projectId }, pagination: $pagination) {\n items {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n total\n hasMore\n }\n }\n`;\n\nconst GET_PROJECT_MEMBER_QUERY = `\n query GetProjectMember($id: ID!) {\n projectMember(id: $id) {\n id\n projectId\n userId\n createdAt\n updatedAt\n deletedAt\n }\n }\n`;\n\nexport const useProjectMembers = (\n projectId: string,\n workspaceIdOverride?: string,\n pagination?: PaginationInput,\n enabled = true\n) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useQuery({\n queryKey: ['projectMembers', effectiveWorkspaceId, projectId, pagination],\n queryFn: async (): Promise<ProjectMemberList> => {\n const result = await graphqlFetch<{ projectMembers: ProjectMemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBERS_QUERY,\n variables: { projectId, pagination },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMembers) {\n throw new Error('Project members query returned no data');\n }\n\n return result.data.projectMembers;\n },\n enabled: enabled && !!projectId && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n\nexport const useInfiniteProjectMembers = (\n projectId: string,\n workspaceIdOverride?: string,\n pageSize = 100,\n enabled = true\n) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useInfiniteQuery({\n queryKey: ['projectMembersInfinite', effectiveWorkspaceId, projectId, pageSize],\n initialPageParam: 0,\n queryFn: async ({ pageParam }): Promise<ProjectMemberList> => {\n const result = await graphqlFetch<{ projectMembers: ProjectMemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBERS_QUERY,\n variables: {\n projectId,\n pagination: {\n limit: pageSize,\n offset: pageParam,\n },\n },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMembers) {\n throw new Error('Project members query returned no data');\n }\n\n return result.data.projectMembers;\n },\n getNextPageParam: (lastPage, _pages, lastPageParam) =>\n lastPage.hasMore ? Number(lastPageParam) + pageSize : undefined,\n enabled: enabled && !!projectId && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n\nexport const useProjectMember = (id: string, workspaceIdOverride?: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n const effectiveWorkspaceId = workspaceIdOverride || workspaceId;\n\n return useQuery({\n queryKey: ['projectMember', effectiveWorkspaceId, id],\n queryFn: async (): Promise<ProjectMember> => {\n const result = await graphqlFetch<{ projectMember: ProjectMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: GET_PROJECT_MEMBER_QUERY,\n variables: { id },\n workspaceId: effectiveWorkspaceId || undefined,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.projectMember) {\n throw new Error('Project member query returned no data');\n }\n\n return result.data.projectMember;\n },\n enabled: !!id && !!effectiveWorkspaceId,\n staleTime: 60 * 1000,\n });\n};\n"],"mappings":";;;;AAKA,IAAM,IAA4B,4UAkErB,KACX,GACA,GACA,IAAW,KACX,IAAU,OACP;CACH,IAAM,EAAE,cAAW,mBAAgB,GAAsB,EACnD,IAAuB,KAAuB;AAEpD,QAAO,EAAiB;EACtB,UAAU;GAAC;GAA0B;GAAsB;GAAW;GAAS;EAC/E,kBAAkB;EAClB,SAAS,OAAO,EAAE,mBAA4C;GAC5D,IAAM,IAAS,MAAM,EAAoD;IACvE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO;IACP,WAAW;KACT;KACA,YAAY;MACV,OAAO;MACP,QAAQ;MACT;KACF;IACD,aAAa,KAAwB,KAAA;IACrC,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,OAAI,CAAC,EAAO,MAAM,eAChB,OAAU,MAAM,yCAAyC;AAG3D,UAAO,EAAO,KAAK;;EAErB,mBAAmB,GAAU,GAAQ,MACnC,EAAS,UAAU,OAAO,EAAc,GAAG,IAAW,KAAA;EACxD,SAAS,KAAW,CAAC,CAAC,KAAa,CAAC,CAAC;EACrC,WAAW,KAAK;EACjB,CAAC"}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { useWorkspacesContext as e } from "../providers/WorkspacesProvider.js";
|
|
2
2
|
import { GetInvitationDocument as t, GetUserWorkspacesDocument as n, GetWorkspaceInvitationsDocument as r, GetWorkspaceMemberDocument as i, GetWorkspaceMembersDocument as a } from "../generated/wspace-operations.js";
|
|
3
|
-
import {
|
|
4
|
-
import { print as
|
|
5
|
-
import { graphqlFetch as
|
|
3
|
+
import { useInfiniteQuery as o, useQuery as s } from "@tanstack/react-query";
|
|
4
|
+
import { print as c } from "graphql";
|
|
5
|
+
import { graphqlFetch as l } from "@burdenoff/fe-libs/shared/graphql";
|
|
6
6
|
//#region src/hooks/useWorkspaceMembers.ts
|
|
7
|
-
var
|
|
7
|
+
var u = (t, n) => {
|
|
8
8
|
let { authToken: r } = e();
|
|
9
|
-
return
|
|
9
|
+
return s({
|
|
10
10
|
queryKey: [
|
|
11
11
|
"workspaceMembers",
|
|
12
12
|
t,
|
|
13
13
|
n
|
|
14
14
|
],
|
|
15
15
|
queryFn: async () => {
|
|
16
|
-
let e = await
|
|
16
|
+
let e = await l({
|
|
17
17
|
gateway: "workspace",
|
|
18
18
|
authToken: r || void 0,
|
|
19
|
-
query:
|
|
19
|
+
query: c(a),
|
|
20
20
|
variables: {
|
|
21
21
|
workspaceId: t,
|
|
22
22
|
pagination: n
|
|
@@ -25,47 +25,81 @@ var l = (t, n) => {
|
|
|
25
25
|
workspaceToken: !0
|
|
26
26
|
});
|
|
27
27
|
if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
|
|
28
|
+
if (!e.data?.workspaceMembers) throw Error("Workspace members query returned no data");
|
|
28
29
|
return e.data.workspaceMembers;
|
|
29
30
|
},
|
|
30
31
|
enabled: !!t,
|
|
31
32
|
staleTime: 300 * 1e3
|
|
32
33
|
});
|
|
33
|
-
},
|
|
34
|
-
let { authToken:
|
|
34
|
+
}, d = (t, n = 100, r = !0) => {
|
|
35
|
+
let { authToken: i } = e();
|
|
35
36
|
return o({
|
|
37
|
+
queryKey: [
|
|
38
|
+
"workspaceMembersInfinite",
|
|
39
|
+
t,
|
|
40
|
+
n
|
|
41
|
+
],
|
|
42
|
+
initialPageParam: 0,
|
|
43
|
+
queryFn: async ({ pageParam: e }) => {
|
|
44
|
+
let r = await l({
|
|
45
|
+
gateway: "workspace",
|
|
46
|
+
authToken: i || void 0,
|
|
47
|
+
query: c(a),
|
|
48
|
+
variables: {
|
|
49
|
+
workspaceId: t,
|
|
50
|
+
pagination: {
|
|
51
|
+
limit: n,
|
|
52
|
+
offset: e
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
workspaceId: t,
|
|
56
|
+
workspaceToken: !0
|
|
57
|
+
});
|
|
58
|
+
if (r.errors?.length) throw Error(r.errors[0]?.message || "GraphQL error");
|
|
59
|
+
if (!r.data?.workspaceMembers) throw Error("Workspace members query returned no data");
|
|
60
|
+
return r.data.workspaceMembers;
|
|
61
|
+
},
|
|
62
|
+
getNextPageParam: (e, t, r) => e.hasMore ? Number(r) + n : void 0,
|
|
63
|
+
enabled: r && !!t,
|
|
64
|
+
staleTime: 300 * 1e3
|
|
65
|
+
});
|
|
66
|
+
}, f = (t) => {
|
|
67
|
+
let { authToken: n, workspaceId: r } = e();
|
|
68
|
+
return s({
|
|
36
69
|
queryKey: [
|
|
37
70
|
"workspaceMember",
|
|
38
71
|
r,
|
|
39
72
|
t
|
|
40
73
|
],
|
|
41
74
|
queryFn: async () => {
|
|
42
|
-
let e = await
|
|
75
|
+
let e = await l({
|
|
43
76
|
gateway: "workspace",
|
|
44
77
|
authToken: n || void 0,
|
|
45
|
-
query:
|
|
78
|
+
query: c(i),
|
|
46
79
|
variables: { id: t },
|
|
47
80
|
workspaceId: r || void 0,
|
|
48
81
|
workspaceToken: !0
|
|
49
82
|
});
|
|
50
83
|
if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
|
|
84
|
+
if (!e.data?.workspaceMember) throw Error("Workspace member query returned no data");
|
|
51
85
|
return e.data.workspaceMember;
|
|
52
86
|
},
|
|
53
87
|
enabled: !!t,
|
|
54
88
|
staleTime: 300 * 1e3
|
|
55
89
|
});
|
|
56
|
-
},
|
|
90
|
+
}, p = (t, r) => {
|
|
57
91
|
let { authToken: i, workspaceId: a } = e();
|
|
58
|
-
return
|
|
92
|
+
return s({
|
|
59
93
|
queryKey: [
|
|
60
94
|
"userWorkspaces",
|
|
61
95
|
t,
|
|
62
96
|
r
|
|
63
97
|
],
|
|
64
98
|
queryFn: async () => {
|
|
65
|
-
let e = await
|
|
99
|
+
let e = await l({
|
|
66
100
|
gateway: "workspace",
|
|
67
101
|
authToken: i || void 0,
|
|
68
|
-
query:
|
|
102
|
+
query: c(n),
|
|
69
103
|
variables: {
|
|
70
104
|
userId: t,
|
|
71
105
|
pagination: r
|
|
@@ -74,14 +108,15 @@ var l = (t, n) => {
|
|
|
74
108
|
workspaceToken: !0
|
|
75
109
|
});
|
|
76
110
|
if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
|
|
111
|
+
if (!e.data?.userWorkspaces) throw Error("User workspaces query returned no data");
|
|
77
112
|
return e.data.userWorkspaces;
|
|
78
113
|
},
|
|
79
114
|
enabled: !!t,
|
|
80
115
|
staleTime: 300 * 1e3
|
|
81
116
|
});
|
|
82
|
-
},
|
|
117
|
+
}, m = (t, n, i) => {
|
|
83
118
|
let { authToken: a } = e();
|
|
84
|
-
return
|
|
119
|
+
return s({
|
|
85
120
|
queryKey: [
|
|
86
121
|
"workspaceInvitations",
|
|
87
122
|
t,
|
|
@@ -89,10 +124,10 @@ var l = (t, n) => {
|
|
|
89
124
|
i
|
|
90
125
|
],
|
|
91
126
|
queryFn: async () => {
|
|
92
|
-
let e = await
|
|
127
|
+
let e = await l({
|
|
93
128
|
gateway: "workspace",
|
|
94
129
|
authToken: a || void 0,
|
|
95
|
-
query:
|
|
130
|
+
query: c(r),
|
|
96
131
|
variables: {
|
|
97
132
|
status: n,
|
|
98
133
|
pagination: i
|
|
@@ -101,20 +136,21 @@ var l = (t, n) => {
|
|
|
101
136
|
workspaceToken: !0
|
|
102
137
|
});
|
|
103
138
|
if (e.errors?.length) throw Error(e.errors[0]?.message || "GraphQL error");
|
|
139
|
+
if (!e.data?.workspaceInvitations) throw Error("Workspace invitations query returned no data");
|
|
104
140
|
return e.data.workspaceInvitations;
|
|
105
141
|
},
|
|
106
142
|
enabled: !!t,
|
|
107
143
|
staleTime: 300 * 1e3
|
|
108
144
|
});
|
|
109
|
-
},
|
|
145
|
+
}, h = (n, r = !0) => {
|
|
110
146
|
let { authToken: i } = e();
|
|
111
|
-
return
|
|
147
|
+
return s({
|
|
112
148
|
queryKey: ["invitation", n],
|
|
113
149
|
queryFn: async () => {
|
|
114
|
-
let e = await
|
|
150
|
+
let e = await l({
|
|
115
151
|
gateway: "workspace",
|
|
116
152
|
authToken: i || void 0,
|
|
117
|
-
query:
|
|
153
|
+
query: c(t),
|
|
118
154
|
variables: { id: n }
|
|
119
155
|
});
|
|
120
156
|
if (e.errors?.length) throw Error(e.errors[0]?.message || "Failed to fetch invitation");
|
|
@@ -127,6 +163,6 @@ var l = (t, n) => {
|
|
|
127
163
|
});
|
|
128
164
|
};
|
|
129
165
|
//#endregion
|
|
130
|
-
export {
|
|
166
|
+
export { d as useInfiniteWorkspaceMembers, h as useInvitation, p as useUserWorkspaces, m as useWorkspaceInvitations, f as useWorkspaceMember, u as useWorkspaceMembers };
|
|
131
167
|
|
|
132
168
|
//# sourceMappingURL=useWorkspaceMembers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWorkspaceMembers.js","names":[],"sources":["../../src/hooks/useWorkspaceMembers.ts"],"sourcesContent":["import { useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n GetWorkspaceMembersDocument,\n GetWorkspaceMemberDocument,\n GetUserWorkspacesDocument,\n GetWorkspaceInvitationsDocument,\n GetInvitationDocument,\n} from '../generated/wspace-operations';\nimport type {\n MemberList,\n WorkspaceMember,\n WorkspaceInvitation,\n InvitationList,\n PaginationInput,\n InvitationStatus,\n} from '../types';\n\n/**\n * Hook to fetch all members of the current workspace\n */\nexport const useWorkspaceMembers = (workspaceId: string, pagination?: PaginationInput) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMembers', workspaceId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: { workspaceId, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header (required by gateway RBAC)\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceMembers;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch a single workspace member by ID\n */\nexport const useWorkspaceMember = (id: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMember', workspaceId, id],\n queryFn: async (): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ workspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMemberDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceMember;\n },\n enabled: !!id,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch all workspaces a user is a member of\n */\nexport const useUserWorkspaces = (userId: string, pagination?: PaginationInput) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['userWorkspaces', userId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ userWorkspaces: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetUserWorkspacesDocument),\n variables: { userId, pagination },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.userWorkspaces;\n },\n enabled: !!userId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch workspace invitations\n * Requires x-workspace-id header for workspace context\n */\nexport const useWorkspaceInvitations = (\n workspaceId: string,\n status?: InvitationStatus,\n pagination?: PaginationInput\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceInvitations', workspaceId, status, pagination],\n queryFn: async (): Promise<InvitationList> => {\n const result = await graphqlFetch<{ workspaceInvitations: InvitationList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceInvitationsDocument),\n variables: { status, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n return result.data!.workspaceInvitations;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to get a single invitation by ID (for acceptance page)\n */\nexport const useInvitation = (id: string, enabled = true) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['invitation', id],\n queryFn: async (): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ invitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetInvitationDocument),\n variables: { id },\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'Failed to fetch invitation');\n }\n\n if (!result.data?.invitation) {\n throw new Error('Invitation not found');\n }\n\n return result.data.invitation;\n },\n enabled: !!id && enabled,\n retry: 1,\n staleTime: 5 * 60 * 1000,\n });\n};\n"],"mappings":";;;;;;AAuBA,IAAa,KAAuB,GAAqB,MAAiC;CACxF,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAoB;GAAa;GAAW;EACvD,SAAS,YAAiC;GACxC,IAAM,IAAS,MAAM,EAA+C;IAClE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA4B;IACzC,WAAW;KAAE;KAAa;KAAY;IACtC;IACA,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAsB,MAAe;CAChD,IAAM,EAAE,cAAW,mBAAgB,GAAsB;AAEzD,QAAO,EAAS;EACd,UAAU;GAAC;GAAmB;GAAa;GAAG;EAC9C,SAAS,YAAsC;GAC7C,IAAM,IAAS,MAAM,EAAmD;IACtE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA2B;IACxC,WAAW,EAAE,OAAI;IACjB,aAAa,KAAe,KAAA;IAC5B,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAqB,GAAgB,MAAiC;CACjF,IAAM,EAAE,cAAW,mBAAgB,GAAsB;AAEzD,QAAO,EAAS;EACd,UAAU;GAAC;GAAkB;GAAQ;GAAW;EAChD,SAAS,YAAiC;GACxC,IAAM,IAAS,MAAM,EAA6C;IAChE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAA0B;IACvC,WAAW;KAAE;KAAQ;KAAY;IACjC,aAAa,KAAe,KAAA;IAC5B,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAOS,KACX,GACA,GACA,MACG;CACH,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU;GAAC;GAAwB;GAAa;GAAQ;GAAW;EACnE,SAAS,YAAqC;GAC5C,IAAM,IAAS,MAAM,EAAuD;IAC1E,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAAgC;IAC7C,WAAW;KAAE;KAAQ;KAAY;IACjC;IACA,gBAAgB;IACjB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,gBAAgB;AAG/D,UAAO,EAAO,KAAM;;EAEtB,SAAS,CAAC,CAAC;EACX,WAAW,MAAS;EACrB,CAAC;GAMS,KAAiB,GAAY,IAAU,OAAS;CAC3D,IAAM,EAAE,iBAAc,GAAsB;AAE5C,QAAO,EAAS;EACd,UAAU,CAAC,cAAc,EAAG;EAC5B,SAAS,YAA0C;GACjD,IAAM,IAAS,MAAM,EAAkD;IACrE,SAAS;IACT,WAAW,KAAa,KAAA;IACxB,OAAO,EAAM,EAAsB;IACnC,WAAW,EAAE,OAAI;IAClB,CAAC;AAEF,OAAI,EAAO,QAAQ,OACjB,OAAU,MAAM,EAAO,OAAO,IAAI,WAAW,6BAA6B;AAG5E,OAAI,CAAC,EAAO,MAAM,WAChB,OAAU,MAAM,uBAAuB;AAGzC,UAAO,EAAO,KAAK;;EAErB,SAAS,CAAC,CAAC,KAAM;EACjB,OAAO;EACP,WAAW,MAAS;EACrB,CAAC"}
|
|
1
|
+
{"version":3,"file":"useWorkspaceMembers.js","names":[],"sources":["../../src/hooks/useWorkspaceMembers.ts"],"sourcesContent":["import { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport { print } from 'graphql';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useWorkspacesContext } from '../providers/WorkspacesProvider';\nimport {\n GetWorkspaceMembersDocument,\n GetWorkspaceMemberDocument,\n GetUserWorkspacesDocument,\n GetWorkspaceInvitationsDocument,\n GetInvitationDocument,\n} from '../generated/wspace-operations';\nimport type {\n MemberList,\n WorkspaceMember,\n WorkspaceInvitation,\n InvitationList,\n PaginationInput,\n InvitationStatus,\n} from '../types';\n\n/**\n * Hook to fetch all members of the current workspace\n */\nexport const useWorkspaceMembers = (workspaceId: string, pagination?: PaginationInput) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMembers', workspaceId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: { workspaceId, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header (required by gateway RBAC)\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMembers) {\n throw new Error('Workspace members query returned no data');\n }\n\n return result.data.workspaceMembers;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\nexport const useInfiniteWorkspaceMembers = (\n workspaceId: string,\n pageSize = 100,\n enabled = true\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useInfiniteQuery({\n queryKey: ['workspaceMembersInfinite', workspaceId, pageSize],\n initialPageParam: 0,\n queryFn: async ({ pageParam }): Promise<MemberList> => {\n const result = await graphqlFetch<{ workspaceMembers: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMembersDocument),\n variables: {\n workspaceId,\n pagination: {\n limit: pageSize,\n offset: pageParam,\n },\n },\n workspaceId,\n workspaceToken: true,\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMembers) {\n throw new Error('Workspace members query returned no data');\n }\n\n return result.data.workspaceMembers;\n },\n getNextPageParam: (lastPage, _pages, lastPageParam) =>\n lastPage.hasMore ? Number(lastPageParam) + pageSize : undefined,\n enabled: enabled && !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch a single workspace member by ID\n */\nexport const useWorkspaceMember = (id: string) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceMember', workspaceId, id],\n queryFn: async (): Promise<WorkspaceMember> => {\n const result = await graphqlFetch<{ workspaceMember: WorkspaceMember }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceMemberDocument),\n variables: { id },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceMember) {\n throw new Error('Workspace member query returned no data');\n }\n\n return result.data.workspaceMember;\n },\n enabled: !!id,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch all workspaces a user is a member of\n */\nexport const useUserWorkspaces = (userId: string, pagination?: PaginationInput) => {\n const { authToken, workspaceId } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['userWorkspaces', userId, pagination],\n queryFn: async (): Promise<MemberList> => {\n const result = await graphqlFetch<{ userWorkspaces: MemberList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetUserWorkspacesDocument),\n variables: { userId, pagination },\n workspaceId: workspaceId || undefined,\n workspaceToken: true, // Required by gateway RBAC for wspace-scoped operations\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.userWorkspaces) {\n throw new Error('User workspaces query returned no data');\n }\n\n return result.data.userWorkspaces;\n },\n enabled: !!userId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to fetch workspace invitations\n * Requires x-workspace-id header for workspace context\n */\nexport const useWorkspaceInvitations = (\n workspaceId: string,\n status?: InvitationStatus,\n pagination?: PaginationInput\n) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['workspaceInvitations', workspaceId, status, pagination],\n queryFn: async (): Promise<InvitationList> => {\n const result = await graphqlFetch<{ workspaceInvitations: InvitationList }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetWorkspaceInvitationsDocument),\n variables: { status, pagination },\n workspaceId,\n workspaceToken: true, // Auto-read from profile context for x-workspace-id header\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'GraphQL error');\n }\n\n if (!result.data?.workspaceInvitations) {\n throw new Error('Workspace invitations query returned no data');\n }\n\n return result.data.workspaceInvitations;\n },\n enabled: !!workspaceId,\n staleTime: 5 * 60 * 1000,\n });\n};\n\n/**\n * Hook to get a single invitation by ID (for acceptance page)\n */\nexport const useInvitation = (id: string, enabled = true) => {\n const { authToken } = useWorkspacesContext();\n\n return useQuery({\n queryKey: ['invitation', id],\n queryFn: async (): Promise<WorkspaceInvitation> => {\n const result = await graphqlFetch<{ invitation: WorkspaceInvitation }>({\n gateway: 'workspace',\n authToken: authToken || undefined,\n query: print(GetInvitationDocument),\n variables: { id },\n });\n\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message || 'Failed to fetch invitation');\n }\n\n if (!result.data?.invitation) {\n throw new Error('Invitation not found');\n }\n\n return result.data.invitation;\n },\n enabled: !!id && enabled,\n retry: 1,\n staleTime: 5 * 60 * 1000,\n });\n};\n"],"mappings":"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"}
|
|
@@ -22,6 +22,10 @@ function n() {
|
|
|
22
22
|
canUpdateProject: n(e.PROJECT_UPDATE),
|
|
23
23
|
canDeleteProject: n(e.PROJECT_DELETE),
|
|
24
24
|
canArchiveProject: n(e.PROJECT_ARCHIVE),
|
|
25
|
+
canListProjectMembers: n(e.PROJECT_MEMBER_LIST),
|
|
26
|
+
canViewProjectMember: n(e.PROJECT_MEMBER_READ),
|
|
27
|
+
canAddProjectMember: n(e.PROJECT_MEMBER_CREATE),
|
|
28
|
+
canRemoveProjectMember: n(e.PROJECT_MEMBER_DELETE),
|
|
25
29
|
canViewSettings: n(e.SETTINGS_READ),
|
|
26
30
|
canUpdateSettings: n(e.SETTINGS_WRITE),
|
|
27
31
|
canViewActivity: n(e.ACTIVITY_READ)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWorkspacePermissions.js","names":[],"sources":["../../src/hooks/useWorkspacePermissions.ts"],"sourcesContent":["/**\n * Workspace MFE - Permission Hook\n *\n * Wraps usePermissions() with typed permission flags for all workspace resources.\n */\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\n\nexport function useWorkspacePermissions() {\n const { hasPermission, isLoading } = usePermissions();\n\n return {\n isLoading,\n\n // Workspace\n canListWorkspaces: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_LIST),\n canViewWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_READ),\n canCreateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_CREATE),\n canUpdateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE),\n canDeleteWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_DELETE),\n canArchiveWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_ARCHIVE),\n\n // Members\n canListMembers: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_LIST),\n canViewMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_READ),\n canInviteMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_CREATE),\n canUpdateMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_UPDATE),\n canRemoveMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_DELETE),\n\n // Projects\n canListProjects: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_LIST),\n canViewProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_READ),\n canCreateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_CREATE),\n canUpdateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_UPDATE),\n canDeleteProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_DELETE),\n canArchiveProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_ARCHIVE),\n\n // Settings\n canViewSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_READ),\n canUpdateSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_WRITE),\n\n // Activity\n canViewActivity: hasPermission(WORKSPACE_PERMISSIONS.ACTIVITY_READ),\n };\n}\n"],"mappings":";;;AASA,SAAgB,IAA0B;CACxC,IAAM,EAAE,kBAAe,iBAAc,GAAgB;AAErD,QAAO;EACL;EAGA,mBAAmB,EAAc,EAAsB,eAAe;EACtE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,qBAAqB,EAAc,EAAsB,kBAAkB;EAG3E,gBAAgB,EAAc,EAAsB,YAAY;EAChE,eAAe,EAAc,EAAsB,YAAY;EAC/D,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EAGnE,iBAAiB,EAAc,EAAsB,aAAa;EAClE,gBAAgB,EAAc,EAAsB,aAAa;EACjE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,mBAAmB,EAAc,EAAsB,gBAAgB;EAGvE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,mBAAmB,EAAc,EAAsB,eAAe;EAGtE,iBAAiB,EAAc,EAAsB,cAAc;EACpE"}
|
|
1
|
+
{"version":3,"file":"useWorkspacePermissions.js","names":[],"sources":["../../src/hooks/useWorkspacePermissions.ts"],"sourcesContent":["/**\n * Workspace MFE - Permission Hook\n *\n * Wraps usePermissions() with typed permission flags for all workspace resources.\n */\n\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { WORKSPACE_PERMISSIONS } from '../constants/permissions';\n\nexport function useWorkspacePermissions() {\n const { hasPermission, isLoading } = usePermissions();\n\n return {\n isLoading,\n\n // Workspace\n canListWorkspaces: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_LIST),\n canViewWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_READ),\n canCreateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_CREATE),\n canUpdateWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_UPDATE),\n canDeleteWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_DELETE),\n canArchiveWorkspace: hasPermission(WORKSPACE_PERMISSIONS.WORKSPACE_ARCHIVE),\n\n // Members\n canListMembers: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_LIST),\n canViewMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_READ),\n canInviteMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_CREATE),\n canUpdateMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_UPDATE),\n canRemoveMember: hasPermission(WORKSPACE_PERMISSIONS.MEMBER_DELETE),\n\n // Projects\n canListProjects: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_LIST),\n canViewProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_READ),\n canCreateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_CREATE),\n canUpdateProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_UPDATE),\n canDeleteProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_DELETE),\n canArchiveProject: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_ARCHIVE),\n\n // Project members\n canListProjectMembers: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_LIST),\n canViewProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_READ),\n canAddProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_CREATE),\n canRemoveProjectMember: hasPermission(WORKSPACE_PERMISSIONS.PROJECT_MEMBER_DELETE),\n\n // Settings\n canViewSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_READ),\n canUpdateSettings: hasPermission(WORKSPACE_PERMISSIONS.SETTINGS_WRITE),\n\n // Activity\n canViewActivity: hasPermission(WORKSPACE_PERMISSIONS.ACTIVITY_READ),\n };\n}\n"],"mappings":";;;AASA,SAAgB,IAA0B;CACxC,IAAM,EAAE,kBAAe,iBAAc,GAAgB;AAErD,QAAO;EACL;EAGA,mBAAmB,EAAc,EAAsB,eAAe;EACtE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,oBAAoB,EAAc,EAAsB,iBAAiB;EACzE,qBAAqB,EAAc,EAAsB,kBAAkB;EAG3E,gBAAgB,EAAc,EAAsB,YAAY;EAChE,eAAe,EAAc,EAAsB,YAAY;EAC/D,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EACnE,iBAAiB,EAAc,EAAsB,cAAc;EAGnE,iBAAiB,EAAc,EAAsB,aAAa;EAClE,gBAAgB,EAAc,EAAsB,aAAa;EACjE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,kBAAkB,EAAc,EAAsB,eAAe;EACrE,mBAAmB,EAAc,EAAsB,gBAAgB;EAGvE,uBAAuB,EAAc,EAAsB,oBAAoB;EAC/E,sBAAsB,EAAc,EAAsB,oBAAoB;EAC9E,qBAAqB,EAAc,EAAsB,sBAAsB;EAC/E,wBAAwB,EAAc,EAAsB,sBAAsB;EAGlF,iBAAiB,EAAc,EAAsB,cAAc;EACnE,mBAAmB,EAAc,EAAsB,eAAe;EAGtE,iBAAiB,EAAc,EAAsB,cAAc;EACpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useWorkspacesEventEmitter.js","names":[],"sources":["../../src/hooks/useWorkspacesEventEmitter.ts"],"sourcesContent":["/**\n * Workspaces-domain event emitter. Emits lifecycle events to the host shell's\n * event bus per `~/products/infra/infra-specs/microfrontends/47-FRONTEND-EVENT-BUS.md`.\n *\n * The MFE never sinks directly to Rybbit/audit — it goes through the bus.\n *\n * The fe-libs `EventBus.emit` is statically typed against `BurdenoffEventName`\n * which doesn't list our workspaces-domain names. The runtime bus is dynamic,\n * so the cast loses autocomplete but is sound.\n */\nimport { useCallback } from 'react';\n\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport type WorkspacesDomainEvent =\n // Lifecycle (success)\n | 'workspace.created'\n | 'workspace.updated'\n | 'workspace.deleted'\n | 'workspace.archived'\n | 'workspace.reactivated'\n | 'project.created'\n | 'project.updated'\n | 'project.deleted'\n | 'project.archived'\n | 'project.unarchived'\n | 'workspace-member.added'\n | 'workspace-member.removed'\n | 'workspace-member.role-updated'\n | 'workspace-invitation.created'\n | 'workspace-invitation.updated'\n | 'workspace-invitation.accepted'\n | 'workspace-invitation.rejected'\n | 'workspace-invitation.cancelled'\n | 'workspace-invitation.resent'\n | 'workspace-invitation.deleted'\n | 'workspace-activity.appended'\n // Failure / observability — forwarded to OtelBrowserSink + audit sink\n | 'workspace.create_failed'\n | 'workspace.update_failed'\n | 'workspace.delete_failed'\n | 'workspace.archive_failed'\n | 'workspace.reactivate_failed'\n | 'project.create_failed'\n | 'project.update_failed'\n | 'project.delete_failed'\n | 'project.archive_failed'\n | 'project.unarchive_failed'\n | 'workspace-member.add_failed'\n | 'workspace-member.remove_failed'\n | 'workspace-member.role-update_failed'\n | 'workspace-invitation.create_failed'\n | 'workspace-invitation.update_failed'\n | 'workspace-invitation.accept_failed'\n | 'workspace-invitation.reject_failed'\n | 'workspace-invitation.cancel_failed'\n | 'workspace-invitation.resend_failed'\n | 'workspace-invitation.delete_failed'\n // Module-scoped (plural) — describes a navigation event into the module,\n // not an action on a single resource.\n | 'workspaces.page.viewed';\n\nexport interface WorkspacesEventPayload {\n workspaceId?: string;\n projectId?: string;\n memberId?: string;\n invitationId?: string;\n userId?: string;\n email?: string;\n source?: string;\n // Observability fields (no PII per SRE guide §7)\n page?: string;\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport function useWorkspacesEventEmitter(): {\n emit: (event: WorkspacesDomainEvent, payload?: WorkspacesEventPayload) => void;\n} {\n const bus = useEventBus();\n // Memoize the emit callback so consumers (notably `useWorkspacesPageView`)\n // can put it in effect dep arrays without firing on every render.\n const emit = useCallback(\n (event: WorkspacesDomainEvent, payload: WorkspacesEventPayload = {}) => {\n try {\n type DynamicEmit = (e: string, p: unknown) => void;\n (bus as unknown as { emit: DynamicEmit }).emit(event, payload);\n } catch (err) {\n // Bus failures must not break workspace operations — but in dev we\n // surface the error so a wrong event shape doesn't disappear silently.\n if (import.meta.env?.DEV) {\n console.warn('[useWorkspacesEventEmitter] event bus emit failed', {\n event,\n payload,\n err,\n });\n }\n }\n },\n [bus]\n );\n return { emit };\n}\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"useWorkspacesEventEmitter.js","names":[],"sources":["../../src/hooks/useWorkspacesEventEmitter.ts"],"sourcesContent":["/**\n * Workspaces-domain event emitter. Emits lifecycle events to the host shell's\n * event bus per `~/products/infra/infra-specs/microfrontends/47-FRONTEND-EVENT-BUS.md`.\n *\n * The MFE never sinks directly to Rybbit/audit — it goes through the bus.\n *\n * The fe-libs `EventBus.emit` is statically typed against `BurdenoffEventName`\n * which doesn't list our workspaces-domain names. The runtime bus is dynamic,\n * so the cast loses autocomplete but is sound.\n */\nimport { useCallback } from 'react';\n\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport type WorkspacesDomainEvent =\n // Lifecycle (success)\n | 'workspace.created'\n | 'workspace.updated'\n | 'workspace.deleted'\n | 'workspace.archived'\n | 'workspace.reactivated'\n | 'project.created'\n | 'project.updated'\n | 'project.deleted'\n | 'project.archived'\n | 'project.unarchived'\n | 'project-member.added'\n | 'project-member.removed'\n | 'workspace-member.added'\n | 'workspace-member.removed'\n | 'workspace-member.role-updated'\n | 'workspace-invitation.created'\n | 'workspace-invitation.updated'\n | 'workspace-invitation.accepted'\n | 'workspace-invitation.rejected'\n | 'workspace-invitation.cancelled'\n | 'workspace-invitation.resent'\n | 'workspace-invitation.deleted'\n | 'workspace-activity.appended'\n // Failure / observability — forwarded to OtelBrowserSink + audit sink\n | 'workspace.create_failed'\n | 'workspace.update_failed'\n | 'workspace.delete_failed'\n | 'workspace.archive_failed'\n | 'workspace.reactivate_failed'\n | 'project.create_failed'\n | 'project.update_failed'\n | 'project.delete_failed'\n | 'project.archive_failed'\n | 'project.unarchive_failed'\n | 'project-member.add_failed'\n | 'project-member.remove_failed'\n | 'workspace-member.add_failed'\n | 'workspace-member.remove_failed'\n | 'workspace-member.role-update_failed'\n | 'workspace-invitation.create_failed'\n | 'workspace-invitation.update_failed'\n | 'workspace-invitation.accept_failed'\n | 'workspace-invitation.reject_failed'\n | 'workspace-invitation.cancel_failed'\n | 'workspace-invitation.resend_failed'\n | 'workspace-invitation.delete_failed'\n // Module-scoped (plural) — describes a navigation event into the module,\n // not an action on a single resource.\n | 'workspaces.page.viewed';\n\nexport interface WorkspacesEventPayload {\n workspaceId?: string;\n projectId?: string;\n memberId?: string;\n invitationId?: string;\n userId?: string;\n email?: string;\n source?: string;\n // Observability fields (no PII per SRE guide §7)\n page?: string;\n durationMs?: number;\n errorCode?: string;\n errorMessage?: string;\n}\n\nexport function useWorkspacesEventEmitter(): {\n emit: (event: WorkspacesDomainEvent, payload?: WorkspacesEventPayload) => void;\n} {\n const bus = useEventBus();\n // Memoize the emit callback so consumers (notably `useWorkspacesPageView`)\n // can put it in effect dep arrays without firing on every render.\n const emit = useCallback(\n (event: WorkspacesDomainEvent, payload: WorkspacesEventPayload = {}) => {\n try {\n type DynamicEmit = (e: string, p: unknown) => void;\n (bus as unknown as { emit: DynamicEmit }).emit(event, payload);\n } catch (err) {\n // Bus failures must not break workspace operations — but in dev we\n // surface the error so a wrong event shape doesn't disappear silently.\n if (import.meta.env?.DEV) {\n console.warn('[useWorkspacesEventEmitter] event bus emit failed', {\n event,\n payload,\n err,\n });\n }\n }\n },\n [bus]\n );\n return { emit };\n}\n"],"mappings":";;;AAiFA,SAAgB,IAEd;CACA,IAAM,IAAM,GAAa;AAsBzB,QAAO,EAAE,MAnBI,GACV,GAA8B,IAAkC,EAAE,KAAK;AACtE,MAAI;AAED,KAAyC,KAAK,GAAO,EAAQ;UAClD;IAYhB,CAAC,EAAI,CACN,EACc"}
|
package/dist/index.js
CHANGED
|
@@ -7,20 +7,21 @@ import { getMemberRoleClasses as c, getMemberRoleLabel as l, getProjectStatusCla
|
|
|
7
7
|
import { WorkspaceCard as _ } from "./components/WorkspaceCard.js";
|
|
8
8
|
import { WorkspacesRoot as v } from "./WorkspacesRoot.js";
|
|
9
9
|
import { DashboardPage as y } from "./pages/dashboard/DashboardPage.js";
|
|
10
|
-
import {
|
|
11
|
-
import { useAcceptInvitation as
|
|
12
|
-
import { InviteAcceptancePage as
|
|
13
|
-
import { PendingInvitesPage as
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
10
|
+
import { useInfiniteWorkspaceMembers as b, useInvitation as x, useUserWorkspaces as S, useWorkspaceInvitations as C, useWorkspaceMember as w, useWorkspaceMembers as T } from "./hooks/useWorkspaceMembers.js";
|
|
11
|
+
import { useAcceptInvitation as E, useAddWorkspaceMember as D, useBulkCreateInvitations as O, useCancelInvitation as k, useCreateInvitation as A, useDeleteInvitation as j, useRejectInvitation as M, useRemoveUserFromWorkspace as N, useRemoveWorkspaceMember as P, useResendInvitation as F, useUpdateInvitation as I } from "./hooks/useMemberMutations.js";
|
|
12
|
+
import { InviteAcceptancePage as L } from "./pages/InviteAcceptancePage.js";
|
|
13
|
+
import { PendingInvitesPage as R } from "./pages/PendingInvitesPage.js";
|
|
14
|
+
import { useMyProjects as z, useProject as B, useProjectMembersCount as V, useProjects as H } from "./hooks/useProjects.js";
|
|
15
|
+
import { WorkspaceInvitePage as U } from "./pages/WorkspaceInvitePage.js";
|
|
16
|
+
import { useArchiveWorkspace as W, useCreateWorkspace as G, useDeleteWorkspace as K, useReactivateWorkspace as q, useUpdateWorkspace as J } from "./hooks/useWorkspaceMutations.js";
|
|
17
|
+
import { useArchiveProject as Y, useCreateProject as X, useDeleteProject as Z, useTagProject as Q, useUnarchiveProject as $, useUntagProject as ee, useUpdateProject as te } from "./hooks/useProjectMutations.js";
|
|
18
|
+
import { useMyOrganizations as ne, useMyTenants as re } from "./hooks/useTenants.js";
|
|
18
19
|
import "./hooks/index.js";
|
|
19
|
-
import { CreateWorkspaceDialog as
|
|
20
|
-
import { formatDate as
|
|
21
|
-
import { ProjectCard as
|
|
22
|
-
import { CreateProjectDialog as
|
|
23
|
-
import { MemberListItem as
|
|
24
|
-
import { InviteMemberDialog as
|
|
20
|
+
import { CreateWorkspaceDialog as ie } from "./components/CreateWorkspaceDialog.js";
|
|
21
|
+
import { formatDate as ae, formatDateTime as oe, formatFileSize as se, formatProjectStatus as ce, formatRelativeTime as le, formatWorkspaceStatus as ue, getInitials as de, toTitleCase as fe, truncate as pe } from "./utils/formatters.js";
|
|
22
|
+
import { ProjectCard as me } from "./components/ProjectCard.js";
|
|
23
|
+
import { CreateProjectDialog as he } from "./components/CreateProjectDialog.js";
|
|
24
|
+
import { MemberListItem as ge } from "./components/MemberListItem.js";
|
|
25
|
+
import { InviteMemberDialog as _e } from "./components/InviteMemberDialog.js";
|
|
25
26
|
import "./components/index.js";
|
|
26
|
-
export {
|
|
27
|
+
export { he as CreateProjectDialog, ie as CreateWorkspaceDialog, y as DashboardPage, L as InviteAcceptancePage, _e as InviteMemberDialog, ge as MemberListItem, R as PendingInvitesPage, me as ProjectCard, _ as WorkspaceCard, U as WorkspaceInvitePage, n as WorkspacesErrorBoundary, e as WorkspacesProvider, v as WorkspacesRoot, ae as formatDate, oe as formatDateTime, se as formatFileSize, ce as formatProjectStatus, le as formatRelativeTime, ue as formatWorkspaceStatus, de as getInitials, c as getMemberRoleClasses, l as getMemberRoleLabel, u as getProjectStatusClasses, d as getProjectStatusIconClass, f as getProjectStatusLabel, p as getWorkspaceStatusBgClass, m as getWorkspaceStatusClasses, h as getWorkspaceStatusIconClass, g as getWorkspaceStatusLabel, fe as toTitleCase, pe as truncate, E as useAcceptInvitation, D as useAddWorkspaceMember, Y as useArchiveProject, W as useArchiveWorkspace, O as useBulkCreateInvitations, k as useCancelInvitation, A as useCreateInvitation, X as useCreateProject, G as useCreateWorkspace, j as useDeleteInvitation, Z as useDeleteProject, K as useDeleteWorkspace, b as useInfiniteWorkspaceMembers, x as useInvitation, ne as useMyOrganizations, s as useMyPendingInvitations, z as useMyProjects, re as useMyTenants, i as useMyWorkspaces, B as useProject, V as useProjectMembersCount, H as useProjects, q as useReactivateWorkspace, M as useRejectInvitation, N as useRemoveUserFromWorkspace, P as useRemoveWorkspaceMember, F as useResendInvitation, Q as useTagProject, $ as useUnarchiveProject, ee as useUntagProject, I as useUpdateInvitation, te as useUpdateProject, J as useUpdateWorkspace, S as useUserWorkspaces, a as useWorkspace, C as useWorkspaceInvitations, w as useWorkspaceMember, T as useWorkspaceMembers, o as useWorkspaces, t as useWorkspacesContext, r as useWorkspacesStore };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { tWithFallback as e } from "../utils/i18n.js";
|
|
2
2
|
import { useWorkspacesPageView as t } from "../hooks/useWorkspacesPageView.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { useWorkspacePermissions as n } from "../hooks/useWorkspacePermissions.js";
|
|
4
|
+
import { formatDate as r } from "../utils/formatters.js";
|
|
5
|
+
import { useWorkspaceActivity as i } from "../hooks/useWorkspaceActivity.js";
|
|
6
6
|
import { Activity as a } from "lucide-react";
|
|
7
7
|
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
8
8
|
import { Card as c, CardContent as l, CardHeader as u, CardTitle as d, Skeleton as f } from "@burdenoff/fe-libs/ui";
|
|
@@ -15,7 +15,7 @@ function h() {
|
|
|
15
15
|
workspaceId: g,
|
|
16
16
|
requireParams: !0
|
|
17
17
|
});
|
|
18
|
-
let { data: _, isLoading: v, error: y } =
|
|
18
|
+
let { data: _, isLoading: v, error: y } = i(g), { canViewActivity: b, isLoading: x } = n();
|
|
19
19
|
return x ? /* @__PURE__ */ s("div", {
|
|
20
20
|
className: "space-y-4 p-6",
|
|
21
21
|
children: [/* @__PURE__ */ o(f, { className: "h-10 w-1/3" }), /* @__PURE__ */ o(f, { className: "h-64" })]
|
|
@@ -87,7 +87,7 @@ function h() {
|
|
|
87
87
|
" ",
|
|
88
88
|
/* @__PURE__ */ o("span", {
|
|
89
89
|
className: "text-foreground",
|
|
90
|
-
children:
|
|
90
|
+
children: r(t.timestamp)
|
|
91
91
|
})
|
|
92
92
|
] }),
|
|
93
93
|
/* @__PURE__ */ s("p", { children: [
|