@burdenoff/microfe-bigconsole 2026.716.2 → 2026.716.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/bigconsole/BigConsoleRoot.js +100 -90
- package/dist/bigconsole/BigConsoleRoot.js.map +1 -1
- package/dist/bigconsole/assistant/assistantRunStore.js +3 -1
- package/dist/bigconsole/assistant/assistantRunStore.js.map +1 -1
- package/dist/bigconsole/assistant/index.js +2 -1
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +70 -60
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js.map +1 -1
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js +187 -175
- package/dist/bigconsole/components/dashboard/SavedViewsDropdown/SavedViewsDropdown.js.map +1 -1
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js +133 -0
- package/dist/bigconsole/components/preview/AiPreviewMiniPanel.js.map +1 -0
- package/dist/bigconsole/components/preview/AiPreviewPanel.js +88 -136
- package/dist/bigconsole/components/preview/AiPreviewPanel.js.map +1 -1
- package/dist/bigconsole/components/preview/previewShared.js +61 -0
- package/dist/bigconsole/components/preview/previewShared.js.map +1 -0
- package/dist/bigconsole/hooks/useDashboardOperations.js +72 -67
- package/dist/bigconsole/hooks/useDashboardOperations.js.map +1 -1
- package/dist/bigconsole/hooks/useDashboardTemplates.js +108 -105
- package/dist/bigconsole/hooks/useDashboardTemplates.js.map +1 -1
- package/dist/bigconsole/hooks/useDashboardViews.js +77 -74
- package/dist/bigconsole/hooks/useDashboardViews.js.map +1 -1
- package/dist/bigconsole/hooks/useImportDashboard.js +68 -64
- package/dist/bigconsole/hooks/useImportDashboard.js.map +1 -1
- package/dist/bigconsole/pages/DashboardsPage.js +240 -234
- package/dist/bigconsole/pages/DashboardsPage.js.map +1 -1
- package/dist/bigconsole/pages/InsightsPage.js +161 -143
- package/dist/bigconsole/pages/InsightsPage.js.map +1 -1
- package/dist/bigconsole/providers/BigConsoleQuotaProvider.js +70 -0
- package/dist/bigconsole/providers/BigConsoleQuotaProvider.js.map +1 -0
- package/dist/bigconsole/utils/quota.js +86 -0
- package/dist/bigconsole/utils/quota.js.map +1 -0
- package/package.json +2 -2
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { useDashboardStore as e } from "../store/dashboardStore.js";
|
|
2
2
|
import "../store/index.js";
|
|
3
3
|
import { CloneDashboardDocument as t, CreateDashboardDocument as n, DeleteDashboardDocument as r, GetDashboardDocument as i, ListDashboardsDocument as a, UpdateDashboardDocument as o } from "../../generated/wspace-operations.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { createBigConsoleQuotaError as s, isBigConsoleQuotaError as c } from "../utils/quota.js";
|
|
5
|
+
import { useCallback as l, useEffect as u, useState as d } from "react";
|
|
6
|
+
import { useApolloClient as f } from "@apollo/client/react";
|
|
6
7
|
//#region src/bigconsole/hooks/useDashboardOperations.ts
|
|
7
|
-
function
|
|
8
|
+
function p(e) {
|
|
8
9
|
let t = e.pages?.edges?.map((t) => ({
|
|
9
10
|
id: t.node.id,
|
|
10
11
|
dashboardId: t.node.dashboardId || e.id,
|
|
@@ -39,7 +40,7 @@ function d(e) {
|
|
|
39
40
|
updatedAt: e.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
|
-
function
|
|
43
|
+
function m(e) {
|
|
43
44
|
return {
|
|
44
45
|
id: e.id,
|
|
45
46
|
name: e.name || "Untitled Dashboard",
|
|
@@ -53,10 +54,10 @@ function f(e) {
|
|
|
53
54
|
pageCount: e.pages?.totalCount ?? 0
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
|
-
function
|
|
57
|
-
let [
|
|
57
|
+
function h() {
|
|
58
|
+
let [h, g] = d(!1), [_, v] = d(null), [y, b] = d([]), x = f(), S = e((e) => e.currentDashboard), C = e((e) => e.setCurrentDashboard), w = l(async (e) => {
|
|
58
59
|
try {
|
|
59
|
-
|
|
60
|
+
g(!0), v(null), b(((await x.query({
|
|
60
61
|
query: a,
|
|
61
62
|
variables: {
|
|
62
63
|
first: 50,
|
|
@@ -64,34 +65,34 @@ function p() {
|
|
|
64
65
|
includeArchived: !1
|
|
65
66
|
},
|
|
66
67
|
fetchPolicy: "network-only"
|
|
67
|
-
})).data?.listDashboards?.edges || []).map((e) =>
|
|
68
|
+
})).data?.listDashboards?.edges || []).map((e) => m(e.node)));
|
|
68
69
|
} catch (e) {
|
|
69
|
-
|
|
70
|
+
v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboards"));
|
|
70
71
|
} finally {
|
|
71
|
-
|
|
72
|
+
g(!1);
|
|
72
73
|
}
|
|
73
|
-
}, [
|
|
74
|
+
}, [x]), T = l(async (e, t) => {
|
|
74
75
|
let n = t?.silent ?? !1;
|
|
75
76
|
try {
|
|
76
|
-
n || (
|
|
77
|
-
let t = await
|
|
77
|
+
n || (g(!0), v(null));
|
|
78
|
+
let t = await x.query({
|
|
78
79
|
query: i,
|
|
79
80
|
variables: { id: e },
|
|
80
81
|
fetchPolicy: "network-only"
|
|
81
82
|
});
|
|
82
83
|
if (t.data?.getDashboard) {
|
|
83
|
-
let e =
|
|
84
|
-
return
|
|
84
|
+
let e = p(t.data.getDashboard);
|
|
85
|
+
return C(e), e;
|
|
85
86
|
}
|
|
86
87
|
return null;
|
|
87
88
|
} catch (e) {
|
|
88
|
-
return n ||
|
|
89
|
+
return n || v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch dashboard")), null;
|
|
89
90
|
} finally {
|
|
90
|
-
n ||
|
|
91
|
+
n || g(!1);
|
|
91
92
|
}
|
|
92
|
-
}, [
|
|
93
|
+
}, [x, C]), E = l(async (e) => {
|
|
93
94
|
try {
|
|
94
|
-
|
|
95
|
+
g(!0), v(null);
|
|
95
96
|
let t = {
|
|
96
97
|
name: e.name,
|
|
97
98
|
description: e.description,
|
|
@@ -100,62 +101,64 @@ function p() {
|
|
|
100
101
|
createDefaultPage: !0
|
|
101
102
|
};
|
|
102
103
|
e.tags && e.tags.length > 0 && (t.metadata = { tags: e.tags });
|
|
103
|
-
let r = await
|
|
104
|
+
let r = await x.mutate({
|
|
104
105
|
mutation: n,
|
|
105
106
|
variables: { input: t }
|
|
106
107
|
});
|
|
108
|
+
if (c(r)) throw s(r);
|
|
107
109
|
if (r.data?.createBigConsoleDashboard) {
|
|
108
|
-
let e =
|
|
109
|
-
return await
|
|
110
|
+
let e = p(r.data.createBigConsoleDashboard);
|
|
111
|
+
return await w(), e;
|
|
110
112
|
}
|
|
111
113
|
return null;
|
|
112
114
|
} catch (e) {
|
|
113
|
-
|
|
115
|
+
if (c(e)) throw e;
|
|
116
|
+
return v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to create dashboard")), null;
|
|
114
117
|
} finally {
|
|
115
|
-
|
|
118
|
+
g(!1);
|
|
116
119
|
}
|
|
117
|
-
}, [
|
|
120
|
+
}, [x, w]), D = l(async (e) => {
|
|
118
121
|
try {
|
|
119
|
-
|
|
120
|
-
let t = await
|
|
122
|
+
g(!0), v(null);
|
|
123
|
+
let t = await x.mutate({
|
|
121
124
|
mutation: o,
|
|
122
125
|
variables: { input: e }
|
|
123
126
|
});
|
|
124
127
|
if (t.data?.updateBigConsoleDashboard) {
|
|
125
|
-
let n =
|
|
126
|
-
return
|
|
128
|
+
let n = p(t.data.updateBigConsoleDashboard);
|
|
129
|
+
return S?.id === e.id && C(n), await w(), n;
|
|
127
130
|
}
|
|
128
131
|
return null;
|
|
129
132
|
} catch (e) {
|
|
130
|
-
return
|
|
133
|
+
return v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update dashboard")), null;
|
|
131
134
|
} finally {
|
|
132
|
-
|
|
135
|
+
g(!1);
|
|
133
136
|
}
|
|
134
137
|
}, [
|
|
135
|
-
y,
|
|
136
|
-
b?.id,
|
|
137
138
|
x,
|
|
138
|
-
S
|
|
139
|
-
|
|
139
|
+
S?.id,
|
|
140
|
+
C,
|
|
141
|
+
w
|
|
142
|
+
]), O = l(async (e) => {
|
|
140
143
|
try {
|
|
141
|
-
return
|
|
144
|
+
return g(!0), v(null), (await x.mutate({
|
|
142
145
|
mutation: r,
|
|
143
146
|
variables: { id: e }
|
|
144
|
-
})).data?.deleteBigConsoleDashboard ? (
|
|
147
|
+
})).data?.deleteBigConsoleDashboard ? (S?.id === e && C(null), await w(), !0) : !1;
|
|
145
148
|
} catch (e) {
|
|
146
|
-
return
|
|
149
|
+
return v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to delete dashboard")), !1;
|
|
147
150
|
} finally {
|
|
148
|
-
|
|
151
|
+
g(!1);
|
|
149
152
|
}
|
|
150
153
|
}, [
|
|
151
|
-
y,
|
|
152
|
-
b?.id,
|
|
153
154
|
x,
|
|
154
|
-
S
|
|
155
|
-
|
|
155
|
+
S?.id,
|
|
156
|
+
C,
|
|
157
|
+
w
|
|
158
|
+
]), k = l(async (e, n) => {
|
|
156
159
|
try {
|
|
157
|
-
|
|
158
|
-
let r = await
|
|
160
|
+
g(!0), v(null);
|
|
161
|
+
let r = await x.mutate({
|
|
159
162
|
mutation: t,
|
|
160
163
|
variables: { input: {
|
|
161
164
|
sourceDashboardId: e,
|
|
@@ -163,36 +166,38 @@ function p() {
|
|
|
163
166
|
includeWidgets: !0
|
|
164
167
|
} }
|
|
165
168
|
});
|
|
169
|
+
if (c(r)) throw s(r);
|
|
166
170
|
if (r.data?.cloneDashboard) {
|
|
167
|
-
let e =
|
|
168
|
-
return await
|
|
171
|
+
let e = p(r.data.cloneDashboard);
|
|
172
|
+
return await w(), e;
|
|
169
173
|
}
|
|
170
174
|
return null;
|
|
171
175
|
} catch (e) {
|
|
172
|
-
|
|
176
|
+
if (c(e)) throw e;
|
|
177
|
+
return v(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to clone dashboard")), null;
|
|
173
178
|
} finally {
|
|
174
|
-
|
|
179
|
+
g(!1);
|
|
175
180
|
}
|
|
176
|
-
}, [
|
|
177
|
-
await
|
|
178
|
-
}, [
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
}, [
|
|
182
|
-
loading:
|
|
183
|
-
error:
|
|
184
|
-
dashboards:
|
|
185
|
-
currentDashboard:
|
|
186
|
-
fetchDashboards:
|
|
187
|
-
fetchDashboard:
|
|
188
|
-
createDashboard:
|
|
189
|
-
updateDashboard:
|
|
190
|
-
deleteDashboard:
|
|
191
|
-
cloneDashboard:
|
|
192
|
-
refetch:
|
|
181
|
+
}, [x, w]), A = l(async () => {
|
|
182
|
+
await w();
|
|
183
|
+
}, [w]);
|
|
184
|
+
return u(() => {
|
|
185
|
+
w();
|
|
186
|
+
}, [w]), {
|
|
187
|
+
loading: h,
|
|
188
|
+
error: _,
|
|
189
|
+
dashboards: y,
|
|
190
|
+
currentDashboard: S,
|
|
191
|
+
fetchDashboards: w,
|
|
192
|
+
fetchDashboard: T,
|
|
193
|
+
createDashboard: E,
|
|
194
|
+
updateDashboard: D,
|
|
195
|
+
deleteDashboard: O,
|
|
196
|
+
cloneDashboard: k,
|
|
197
|
+
refetch: A
|
|
193
198
|
};
|
|
194
199
|
}
|
|
195
200
|
//#endregion
|
|
196
|
-
export {
|
|
201
|
+
export { h as default };
|
|
197
202
|
|
|
198
203
|
//# sourceMappingURL=useDashboardOperations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDashboardOperations.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardOperations.ts"],"sourcesContent":["/**\n * useDashboardOperations Hook\n *\n * Provides CRUD operations for dashboards using GraphQL.\n */\n\nimport { useCallback, useState, useEffect } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport type { Dashboard, DashboardLayoutConfig } from '../types';\nimport { useDashboardStore } from '../store';\nimport {\n ListDashboardsDocument,\n GetDashboardDocument,\n CreateDashboardDocument,\n UpdateDashboardDocument,\n DeleteDashboardDocument,\n CloneDashboardDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardListItem {\n id: string;\n name: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n viewCount?: number;\n widgetCount?: number;\n createdAt: string;\n updatedAt: string;\n pageCount: number;\n}\n\ninterface CreateDashboardInput {\n name: string;\n description?: string;\n category?: string;\n layoutType?: string;\n tags?: string[];\n}\n\ninterface UpdateDashboardInput {\n id: string;\n name?: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n}\n\ninterface FetchDashboardOptions {\n /**\n * Silent refetch for live-canvas polling: do NOT toggle the global `loading`\n * flag (which would flash the page-level spinner) and do NOT surface a\n * transient fetch error (which would replace the board with the error screen).\n * The last good dashboard stays on screen if a poll fails.\n */\n silent?: boolean;\n}\n\ninterface DashboardOperationsResult {\n loading: boolean;\n error: Error | null;\n dashboards: DashboardListItem[];\n currentDashboard: Dashboard | null;\n\n // Operations\n fetchDashboards: (search?: string) => Promise<void>;\n fetchDashboard: (id: string, options?: FetchDashboardOptions) => Promise<Dashboard | null>;\n createDashboard: (input: CreateDashboardInput) => Promise<Dashboard | null>;\n updateDashboard: (input: UpdateDashboardInput) => Promise<Dashboard | null>;\n deleteDashboard: (id: string) => Promise<boolean>;\n cloneDashboard: (sourceDashboardId: string, name: string) => Promise<Dashboard | null>;\n refetch: () => Promise<void>;\n}\n\n// ============================================================================\n// Helper: Normalize dashboard from GraphQL response\n// ============================================================================\n\n// Raw GraphQL response shape for dashboard data\ninterface RawDashboardData {\n id: string;\n name?: string;\n description?: string;\n workspaceId?: string;\n isPublic?: boolean;\n isTemplate?: boolean;\n layout?: Record<string, unknown>;\n category?: string;\n viewCount?: number;\n widgetCount?: number;\n createdBy?: string;\n ownerId?: string;\n createdAt?: string;\n updatedAt?: string;\n pages?: {\n edges?: Array<{\n node: {\n id: string;\n dashboardId?: string;\n name?: string;\n order?: number;\n layout?: Record<string, unknown>;\n gridColumns?: number;\n createdAt?: string;\n updatedAt?: string;\n };\n }>;\n totalCount?: number;\n };\n}\n\nfunction normalizeDashboard(data: RawDashboardData): Dashboard {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widgets loaded separately via useWidgetOperations\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n // GetDashboard caps pages at first:10 to stay under the gateway cost-limit\n // (see DashboardFullFields fragment / BOFF-2720). Surface a warning instead of\n // silently dropping pages if a dashboard ever exceeds the cap.\n const totalPages = data.pages?.totalCount ?? pages.length;\n if (totalPages > pages.length) {\n console.warn(\n `[bigconsole] Dashboard ${data.id} has ${totalPages} pages but only ${pages.length} were loaded ` +\n `(GetDashboard pages cap). Pages beyond the cap are not shown — see BOFF-2720.`\n );\n }\n\n return {\n id: data.id,\n workspaceId: data.workspaceId || '',\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n slug: data.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n isPublished: data.isPublic || false,\n isTemplate: data.isTemplate || false,\n layoutConfig: (data.layout as unknown as DashboardLayoutConfig) || {\n columns: 12,\n rowHeight: 100,\n gap: 10,\n margin: [10, 10],\n containerPadding: [10, 10],\n },\n pages,\n translations: [],\n createdBy: data.createdBy || data.ownerId || '',\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n };\n}\n\nfunction normalizeDashboardListItem(data: RawDashboardData): DashboardListItem {\n // The list query selects only pages.totalCount (no edges) to stay under the\n // gateway Armor cost-limit — see DashboardListItem fragment / BOFF-2719.\n return {\n id: data.id,\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n category: data.category,\n isPublic: data.isPublic,\n viewCount: data.viewCount,\n widgetCount: data.widgetCount,\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n pageCount: data.pages?.totalCount ?? 0,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardOperations(): DashboardOperationsResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [dashboards, setDashboards] = useState<DashboardListItem[]>([]);\n\n // Get Apollo Client - will throw if not in ApolloProvider context\n const apolloClient = useApolloClient();\n\n // Store actions\n const currentDashboard = useDashboardStore((state) => state.currentDashboard);\n const setCurrentDashboard = useDashboardStore((state) => state.setCurrentDashboard);\n\n // Fetch dashboards list\n const fetchDashboards = useCallback(\n async (search?: string) => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboards?: { edges?: Array<{ node: RawDashboardData }> } }>({\n query: ListDashboardsDocument,\n variables: {\n first: 50,\n search,\n includeArchived: false,\n },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboards?.edges || [];\n const dashboardsList = edges.map((edge) => normalizeDashboardListItem(edge.node));\n setDashboards(dashboardsList);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboards');\n setError(error);\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch single dashboard\n const fetchDashboard = useCallback(\n async (id: string, options?: FetchDashboardOptions): Promise<Dashboard | null> => {\n const silent = options?.silent ?? false;\n try {\n if (!silent) {\n setLoading(true);\n setError(null);\n }\n\n const result = await apolloClient.query<{ getDashboard?: RawDashboardData }>({\n query: GetDashboardDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboard) {\n const dashboard = normalizeDashboard(result.data.getDashboard);\n setCurrentDashboard(dashboard);\n return dashboard;\n }\n\n return null;\n } catch (err) {\n // Silent (live-poll) failures must not wipe the board or flip the page to\n // the error screen — keep the last good dashboard on screen.\n if (!silent) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboard');\n setError(error);\n }\n return null;\n } finally {\n if (!silent) {\n setLoading(false);\n }\n }\n },\n [apolloClient, setCurrentDashboard]\n );\n\n // Create dashboard\n const createDashboard = useCallback(\n async (input: CreateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Build mutation input\n // Note: Tags require Tag IDs from the Tags service. For now, tags are stored in metadata.\n // Full tag integration would require querying/creating tags via the Tags service first.\n const mutationInput: Record<string, unknown> = {\n name: input.name,\n description: input.description,\n category: input.category || 'CUSTOM',\n layout: input.layoutType || 'GRID',\n createDefaultPage: true,\n };\n\n // Store tags in metadata until full Tags service integration\n if (input.tags && input.tags.length > 0) {\n mutationInput.metadata = {\n tags: input.tags,\n };\n }\n\n const result = await apolloClient.mutate<{ createBigConsoleDashboard?: RawDashboardData }>({\n mutation: CreateDashboardDocument,\n variables: {\n input: mutationInput,\n },\n });\n\n if (result.data?.createBigConsoleDashboard) {\n const newDashboard = normalizeDashboard(result.data.createBigConsoleDashboard);\n await fetchDashboards();\n return newDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to create dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Update dashboard\n const updateDashboard = useCallback(\n async (input: UpdateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateBigConsoleDashboard?: RawDashboardData }>({\n mutation: UpdateDashboardDocument,\n variables: { input },\n });\n\n if (result.data?.updateBigConsoleDashboard) {\n const updatedDashboard = normalizeDashboard(result.data.updateBigConsoleDashboard);\n if (currentDashboard?.id === input.id) {\n setCurrentDashboard(updatedDashboard);\n }\n await fetchDashboards();\n return updatedDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Delete dashboard\n const deleteDashboard = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteBigConsoleDashboard?: boolean }>({\n mutation: DeleteDashboardDocument,\n variables: { id },\n });\n\n if (result.data?.deleteBigConsoleDashboard) {\n if (currentDashboard?.id === id) {\n setCurrentDashboard(null);\n }\n await fetchDashboards();\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete dashboard');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Clone dashboard (duplicate including widgets)\n const cloneDashboard = useCallback(\n async (sourceDashboardId: string, name: string): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ cloneDashboard?: RawDashboardData }>({\n mutation: CloneDashboardDocument,\n variables: {\n input: { sourceDashboardId, name, includeWidgets: true },\n },\n });\n\n if (result.data?.cloneDashboard) {\n const cloned = normalizeDashboard(result.data.cloneDashboard);\n await fetchDashboards();\n return cloned;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to clone dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Refetch\n const refetch = useCallback(async () => {\n await fetchDashboards();\n }, [fetchDashboards]);\n\n // Fetch on mount\n useEffect(() => {\n fetchDashboards();\n }, [fetchDashboards]);\n\n return {\n loading,\n error,\n dashboards,\n currentDashboard,\n fetchDashboards,\n fetchDashboard,\n createDashboard,\n updateDashboard,\n deleteDashboard,\n cloneDashboard,\n refetch,\n };\n}\n\nexport default useDashboardOperations;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useDashboardOperations.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardOperations.ts"],"sourcesContent":["/**\n * useDashboardOperations Hook\n *\n * Provides CRUD operations for dashboards using GraphQL.\n */\n\nimport { useCallback, useState, useEffect } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport type { Dashboard, DashboardLayoutConfig } from '../types';\nimport { useDashboardStore } from '../store';\nimport { createBigConsoleQuotaError, isBigConsoleQuotaError } from '../utils/quota';\nimport {\n ListDashboardsDocument,\n GetDashboardDocument,\n CreateDashboardDocument,\n UpdateDashboardDocument,\n DeleteDashboardDocument,\n CloneDashboardDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardListItem {\n id: string;\n name: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n viewCount?: number;\n widgetCount?: number;\n createdAt: string;\n updatedAt: string;\n pageCount: number;\n}\n\ninterface CreateDashboardInput {\n name: string;\n description?: string;\n category?: string;\n layoutType?: string;\n tags?: string[];\n}\n\ninterface UpdateDashboardInput {\n id: string;\n name?: string;\n description?: string;\n category?: string;\n isPublic?: boolean;\n}\n\ninterface FetchDashboardOptions {\n /**\n * Silent refetch for live-canvas polling: do NOT toggle the global `loading`\n * flag (which would flash the page-level spinner) and do NOT surface a\n * transient fetch error (which would replace the board with the error screen).\n * The last good dashboard stays on screen if a poll fails.\n */\n silent?: boolean;\n}\n\ninterface DashboardOperationsResult {\n loading: boolean;\n error: Error | null;\n dashboards: DashboardListItem[];\n currentDashboard: Dashboard | null;\n\n // Operations\n fetchDashboards: (search?: string) => Promise<void>;\n fetchDashboard: (id: string, options?: FetchDashboardOptions) => Promise<Dashboard | null>;\n createDashboard: (input: CreateDashboardInput) => Promise<Dashboard | null>;\n updateDashboard: (input: UpdateDashboardInput) => Promise<Dashboard | null>;\n deleteDashboard: (id: string) => Promise<boolean>;\n cloneDashboard: (sourceDashboardId: string, name: string) => Promise<Dashboard | null>;\n refetch: () => Promise<void>;\n}\n\n// ============================================================================\n// Helper: Normalize dashboard from GraphQL response\n// ============================================================================\n\n// Raw GraphQL response shape for dashboard data\ninterface RawDashboardData {\n id: string;\n name?: string;\n description?: string;\n workspaceId?: string;\n isPublic?: boolean;\n isTemplate?: boolean;\n layout?: Record<string, unknown>;\n category?: string;\n viewCount?: number;\n widgetCount?: number;\n createdBy?: string;\n ownerId?: string;\n createdAt?: string;\n updatedAt?: string;\n pages?: {\n edges?: Array<{\n node: {\n id: string;\n dashboardId?: string;\n name?: string;\n order?: number;\n layout?: Record<string, unknown>;\n gridColumns?: number;\n createdAt?: string;\n updatedAt?: string;\n };\n }>;\n totalCount?: number;\n };\n}\n\nfunction normalizeDashboard(data: RawDashboardData): Dashboard {\n const pages =\n data.pages?.edges?.map((edge) => ({\n id: edge.node.id,\n dashboardId: edge.node.dashboardId || data.id,\n name: edge.node.name,\n slug: edge.node.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n order: edge.node.order || 0,\n layoutConfig: edge.node.layout || {},\n gridColumns: edge.node.gridColumns || 12,\n widgets: [], // Widgets loaded separately via useWidgetOperations\n createdAt: edge.node.createdAt || new Date().toISOString(),\n updatedAt: edge.node.updatedAt || new Date().toISOString(),\n })) || [];\n\n // GetDashboard caps pages at first:10 to stay under the gateway cost-limit\n // (see DashboardFullFields fragment / BOFF-2720). Surface a warning instead of\n // silently dropping pages if a dashboard ever exceeds the cap.\n const totalPages = data.pages?.totalCount ?? pages.length;\n if (totalPages > pages.length) {\n console.warn(\n `[bigconsole] Dashboard ${data.id} has ${totalPages} pages but only ${pages.length} were loaded ` +\n `(GetDashboard pages cap). Pages beyond the cap are not shown — see BOFF-2720.`\n );\n }\n\n return {\n id: data.id,\n workspaceId: data.workspaceId || '',\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n slug: data.name?.toLowerCase().replace(/\\s+/g, '-') || '',\n isPublished: data.isPublic || false,\n isTemplate: data.isTemplate || false,\n layoutConfig: (data.layout as unknown as DashboardLayoutConfig) || {\n columns: 12,\n rowHeight: 100,\n gap: 10,\n margin: [10, 10],\n containerPadding: [10, 10],\n },\n pages,\n translations: [],\n createdBy: data.createdBy || data.ownerId || '',\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n };\n}\n\nfunction normalizeDashboardListItem(data: RawDashboardData): DashboardListItem {\n // The list query selects only pages.totalCount (no edges) to stay under the\n // gateway Armor cost-limit — see DashboardListItem fragment / BOFF-2719.\n return {\n id: data.id,\n name: data.name || 'Untitled Dashboard',\n description: data.description,\n category: data.category,\n isPublic: data.isPublic,\n viewCount: data.viewCount,\n widgetCount: data.widgetCount,\n createdAt: data.createdAt || new Date().toISOString(),\n updatedAt: data.updatedAt || new Date().toISOString(),\n pageCount: data.pages?.totalCount ?? 0,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardOperations(): DashboardOperationsResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [dashboards, setDashboards] = useState<DashboardListItem[]>([]);\n\n // Get Apollo Client - will throw if not in ApolloProvider context\n const apolloClient = useApolloClient();\n\n // Store actions\n const currentDashboard = useDashboardStore((state) => state.currentDashboard);\n const setCurrentDashboard = useDashboardStore((state) => state.setCurrentDashboard);\n\n // Fetch dashboards list\n const fetchDashboards = useCallback(\n async (search?: string) => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboards?: { edges?: Array<{ node: RawDashboardData }> } }>({\n query: ListDashboardsDocument,\n variables: {\n first: 50,\n search,\n includeArchived: false,\n },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboards?.edges || [];\n const dashboardsList = edges.map((edge) => normalizeDashboardListItem(edge.node));\n setDashboards(dashboardsList);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboards');\n setError(error);\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch single dashboard\n const fetchDashboard = useCallback(\n async (id: string, options?: FetchDashboardOptions): Promise<Dashboard | null> => {\n const silent = options?.silent ?? false;\n try {\n if (!silent) {\n setLoading(true);\n setError(null);\n }\n\n const result = await apolloClient.query<{ getDashboard?: RawDashboardData }>({\n query: GetDashboardDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboard) {\n const dashboard = normalizeDashboard(result.data.getDashboard);\n setCurrentDashboard(dashboard);\n return dashboard;\n }\n\n return null;\n } catch (err) {\n // Silent (live-poll) failures must not wipe the board or flip the page to\n // the error screen — keep the last good dashboard on screen.\n if (!silent) {\n const error = err instanceof Error ? err : new Error('Failed to fetch dashboard');\n setError(error);\n }\n return null;\n } finally {\n if (!silent) {\n setLoading(false);\n }\n }\n },\n [apolloClient, setCurrentDashboard]\n );\n\n // Create dashboard\n const createDashboard = useCallback(\n async (input: CreateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Build mutation input\n // Note: Tags require Tag IDs from the Tags service. For now, tags are stored in metadata.\n // Full tag integration would require querying/creating tags via the Tags service first.\n const mutationInput: Record<string, unknown> = {\n name: input.name,\n description: input.description,\n category: input.category || 'CUSTOM',\n layout: input.layoutType || 'GRID',\n createDefaultPage: true,\n };\n\n // Store tags in metadata until full Tags service integration\n if (input.tags && input.tags.length > 0) {\n mutationInput.metadata = {\n tags: input.tags,\n };\n }\n\n const result = await apolloClient.mutate<{ createBigConsoleDashboard?: RawDashboardData }>({\n mutation: CreateDashboardDocument,\n variables: {\n input: mutationInput,\n },\n });\n\n if (isBigConsoleQuotaError(result)) {\n throw createBigConsoleQuotaError(result);\n }\n\n if (result.data?.createBigConsoleDashboard) {\n const newDashboard = normalizeDashboard(result.data.createBigConsoleDashboard);\n await fetchDashboards();\n return newDashboard;\n }\n\n return null;\n } catch (err) {\n if (isBigConsoleQuotaError(err)) {\n throw err;\n }\n const error = err instanceof Error ? err : new Error('Failed to create dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Update dashboard\n const updateDashboard = useCallback(\n async (input: UpdateDashboardInput): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateBigConsoleDashboard?: RawDashboardData }>({\n mutation: UpdateDashboardDocument,\n variables: { input },\n });\n\n if (result.data?.updateBigConsoleDashboard) {\n const updatedDashboard = normalizeDashboard(result.data.updateBigConsoleDashboard);\n if (currentDashboard?.id === input.id) {\n setCurrentDashboard(updatedDashboard);\n }\n await fetchDashboards();\n return updatedDashboard;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Delete dashboard\n const deleteDashboard = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteBigConsoleDashboard?: boolean }>({\n mutation: DeleteDashboardDocument,\n variables: { id },\n });\n\n if (result.data?.deleteBigConsoleDashboard) {\n if (currentDashboard?.id === id) {\n setCurrentDashboard(null);\n }\n await fetchDashboards();\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete dashboard');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentDashboard?.id, setCurrentDashboard, fetchDashboards]\n );\n\n // Clone dashboard (duplicate including widgets)\n const cloneDashboard = useCallback(\n async (sourceDashboardId: string, name: string): Promise<Dashboard | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ cloneDashboard?: RawDashboardData }>({\n mutation: CloneDashboardDocument,\n variables: {\n input: { sourceDashboardId, name, includeWidgets: true },\n },\n });\n\n if (isBigConsoleQuotaError(result)) {\n throw createBigConsoleQuotaError(result);\n }\n\n if (result.data?.cloneDashboard) {\n const cloned = normalizeDashboard(result.data.cloneDashboard);\n await fetchDashboards();\n return cloned;\n }\n\n return null;\n } catch (err) {\n if (isBigConsoleQuotaError(err)) {\n throw err;\n }\n const error = err instanceof Error ? err : new Error('Failed to clone dashboard');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, fetchDashboards]\n );\n\n // Refetch\n const refetch = useCallback(async () => {\n await fetchDashboards();\n }, [fetchDashboards]);\n\n // Fetch on mount\n useEffect(() => {\n fetchDashboards();\n }, [fetchDashboards]);\n\n return {\n loading,\n error,\n dashboards,\n currentDashboard,\n fetchDashboards,\n fetchDashboard,\n createDashboard,\n updateDashboard,\n deleteDashboard,\n cloneDashboard,\n refetch,\n };\n}\n\nexport default useDashboardOperations;\n"],"mappings":"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"}
|