@burdenoff/microfe-bigconsole 2026.716.2 → 2026.716.3

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.
@@ -1,8 +1,9 @@
1
1
  import { CreateDashboardViewDocument as e, DeleteDashboardViewDocument as t, GetDashboardViewDocument as n, GetDefaultDashboardViewDocument as r, ListDashboardViewsDocument as i, SetDefaultViewDocument as a, UpdateDashboardViewDocument as o } from "../../generated/wspace-operations.js";
2
- import { useCallback as s, useState as c } from "react";
3
- import { useApolloClient as l } from "@apollo/client/react";
2
+ import { createBigConsoleQuotaError as s, isBigConsoleQuotaError as c } from "../utils/quota.js";
3
+ import { useCallback as l, useState as u } from "react";
4
+ import { useApolloClient as d } from "@apollo/client/react";
4
5
  //#region src/bigconsole/hooks/useDashboardViews.ts
5
- function u(e) {
6
+ function f(e) {
6
7
  return {
7
8
  id: e.id,
8
9
  dashboardId: e.dashboardId,
@@ -20,151 +21,153 @@ function u(e) {
20
21
  updatedBy: e.updatedBy
21
22
  };
22
23
  }
23
- function d() {
24
- let [d, f] = c([]), [p, m] = c(null), [h, g] = c(null), [_, v] = c(!1), [y, b] = c(null), x = l();
24
+ function p() {
25
+ let [p, m] = u([]), [h, g] = u(null), [_, v] = u(null), [y, b] = u(!1), [x, S] = u(null), C = d();
25
26
  return {
26
- views: d,
27
- defaultView: p,
28
- currentView: h,
29
- loading: _,
30
- error: y,
31
- fetchViews: s(async (e) => {
27
+ views: p,
28
+ defaultView: h,
29
+ currentView: _,
30
+ loading: y,
31
+ error: x,
32
+ fetchViews: l(async (e) => {
32
33
  try {
33
- v(!0), b(null);
34
- let t = ((await x.query({
34
+ b(!0), S(null);
35
+ let t = ((await C.query({
35
36
  query: i,
36
37
  variables: {
37
38
  dashboardId: e,
38
39
  first: 100
39
40
  },
40
41
  fetchPolicy: "network-only"
41
- })).data?.listDashboardViews?.edges || []).map((e) => u(e.node));
42
- f(t);
42
+ })).data?.listDashboardViews?.edges || []).map((e) => f(e.node));
43
+ m(t);
43
44
  let n = t.find((e) => e.isDefault);
44
- return n && m(n), t;
45
+ return n && g(n), t;
45
46
  } catch (e) {
46
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch views")), [];
47
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch views")), [];
47
48
  } finally {
48
- v(!1);
49
+ b(!1);
49
50
  }
50
- }, [x]),
51
- fetchDefaultView: s(async (e) => {
51
+ }, [C]),
52
+ fetchDefaultView: l(async (e) => {
52
53
  try {
53
- v(!0), b(null);
54
- let t = await x.query({
54
+ b(!0), S(null);
55
+ let t = await C.query({
55
56
  query: r,
56
57
  variables: { dashboardId: e },
57
58
  fetchPolicy: "network-only"
58
59
  });
59
60
  if (t.data?.getDefaultDashboardView) {
60
- let e = u(t.data.getDefaultDashboardView);
61
- return m(e), e;
61
+ let e = f(t.data.getDefaultDashboardView);
62
+ return g(e), e;
62
63
  }
63
64
  return null;
64
65
  } catch (e) {
65
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch default view")), null;
66
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to fetch default view")), null;
66
67
  } finally {
67
- v(!1);
68
+ b(!1);
68
69
  }
69
- }, [x]),
70
- getView: s(async (e) => {
70
+ }, [C]),
71
+ getView: l(async (e) => {
71
72
  try {
72
- v(!0), b(null);
73
- let t = await x.query({
73
+ b(!0), S(null);
74
+ let t = await C.query({
74
75
  query: n,
75
76
  variables: { id: e },
76
77
  fetchPolicy: "network-only"
77
78
  });
78
- return t.data?.getDashboardView ? u(t.data.getDashboardView) : null;
79
+ return t.data?.getDashboardView ? f(t.data.getDashboardView) : null;
79
80
  } catch (e) {
80
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to get view")), null;
81
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to get view")), null;
81
82
  } finally {
82
- v(!1);
83
+ b(!1);
83
84
  }
84
- }, [x]),
85
- saveCurrentView: s(async (t) => {
85
+ }, [C]),
86
+ saveCurrentView: l(async (t) => {
86
87
  try {
87
- v(!0), b(null);
88
- let n = await x.mutate({
88
+ b(!0), S(null);
89
+ let n = await C.mutate({
89
90
  mutation: e,
90
91
  variables: { input: t }
91
92
  });
93
+ if (c(n)) throw s(n);
92
94
  if (n.data?.createDashboardView) {
93
- let e = u(n.data.createDashboardView);
94
- return f((t) => [...t, e]), e.isDefault && m(e), e;
95
+ let e = f(n.data.createDashboardView);
96
+ return m((t) => [...t, e]), e.isDefault && g(e), e;
95
97
  }
96
98
  return null;
97
99
  } catch (e) {
98
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to save view")), null;
100
+ if (c(e)) throw e;
101
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to save view")), null;
99
102
  } finally {
100
- v(!1);
103
+ b(!1);
101
104
  }
102
- }, [x]),
103
- loadView: s((e) => {
104
- let t = d.find((t) => t.id === e);
105
- t && g(t);
106
- }, [d]),
107
- updateView: s(async (e) => {
105
+ }, [C]),
106
+ loadView: l((e) => {
107
+ let t = p.find((t) => t.id === e);
108
+ t && v(t);
109
+ }, [p]),
110
+ updateView: l(async (e) => {
108
111
  try {
109
- v(!0), b(null);
110
- let t = await x.mutate({
112
+ b(!0), S(null);
113
+ let t = await C.mutate({
111
114
  mutation: o,
112
115
  variables: { input: e }
113
116
  });
114
117
  if (t.data?.updateDashboardView) {
115
- let e = u(t.data.updateDashboardView);
116
- return f((t) => t.map((t) => t.id === e.id ? e : t)), e.isDefault && m(e), h?.id === e.id && g(e), e;
118
+ let e = f(t.data.updateDashboardView);
119
+ return m((t) => t.map((t) => t.id === e.id ? e : t)), e.isDefault && g(e), _?.id === e.id && v(e), e;
117
120
  }
118
121
  return null;
119
122
  } catch (e) {
120
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update view")), null;
123
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update view")), null;
121
124
  } finally {
122
- v(!1);
125
+ b(!1);
123
126
  }
124
- }, [x, h?.id]),
125
- deleteView: s(async (e) => {
127
+ }, [C, _?.id]),
128
+ deleteView: l(async (e) => {
126
129
  try {
127
- return v(!0), b(null), (await x.mutate({
130
+ return b(!0), S(null), (await C.mutate({
128
131
  mutation: t,
129
132
  variables: { id: e }
130
- })).data?.deleteDashboardView ? (f((t) => t.filter((t) => t.id !== e)), p?.id === e && m(null), h?.id === e && g(null), !0) : !1;
133
+ })).data?.deleteDashboardView ? (m((t) => t.filter((t) => t.id !== e)), h?.id === e && g(null), _?.id === e && v(null), !0) : !1;
131
134
  } catch (e) {
132
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to delete view")), !1;
135
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to delete view")), !1;
133
136
  } finally {
134
- v(!1);
137
+ b(!1);
135
138
  }
136
139
  }, [
137
- x,
138
- p?.id,
139
- h?.id
140
+ C,
141
+ h?.id,
142
+ _?.id
140
143
  ]),
141
- setAsDefault: s(async (e) => {
144
+ setAsDefault: l(async (e) => {
142
145
  try {
143
- v(!0), b(null);
144
- let t = await x.mutate({
146
+ b(!0), S(null);
147
+ let t = await C.mutate({
145
148
  mutation: a,
146
149
  variables: { viewId: e }
147
150
  });
148
151
  if (t.data?.setDefaultView) {
149
- let e = u(t.data.setDefaultView);
150
- return f((t) => t.map((t) => ({
152
+ let e = f(t.data.setDefaultView);
153
+ return m((t) => t.map((t) => ({
151
154
  ...t,
152
155
  isDefault: t.id === e.id
153
- }))), m(e), e;
156
+ }))), g(e), e;
154
157
  }
155
158
  return null;
156
159
  } catch (e) {
157
- return b(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to set default view")), null;
160
+ return S(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to set default view")), null;
158
161
  } finally {
159
- v(!1);
162
+ b(!1);
160
163
  }
161
- }, [x]),
162
- clearCurrentView: s(() => {
163
- g(null);
164
+ }, [C]),
165
+ clearCurrentView: l(() => {
166
+ v(null);
164
167
  }, [])
165
168
  };
166
169
  }
167
170
  //#endregion
168
- export { d as default };
171
+ export { p as default };
169
172
 
170
173
  //# sourceMappingURL=useDashboardViews.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useDashboardViews.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardViews.ts"],"sourcesContent":["/**\n * useDashboardViews Hook\n *\n * Provides operations for managing dashboard saved views.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n GetDashboardViewDocument,\n ListDashboardViewsDocument,\n GetDefaultDashboardViewDocument,\n CreateDashboardViewDocument,\n UpdateDashboardViewDocument,\n DeleteDashboardViewDocument,\n SetDefaultViewDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardView {\n id: string;\n dashboardId: string;\n workspaceId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault: boolean;\n version: number;\n metadata?: Record<string, unknown>;\n createdAt: string;\n createdBy?: string;\n updatedAt: string;\n updatedBy?: string;\n}\n\nexport interface CreateDashboardViewInput {\n dashboardId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateDashboardViewInput {\n id: string;\n name?: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UseDashboardViewsResult {\n views: DashboardView[];\n defaultView: DashboardView | null;\n currentView: DashboardView | null;\n loading: boolean;\n error: Error | null;\n\n // Operations\n fetchViews: (dashboardId: string) => Promise<DashboardView[]>;\n fetchDefaultView: (dashboardId: string) => Promise<DashboardView | null>;\n getView: (id: string) => Promise<DashboardView | null>;\n saveCurrentView: (input: CreateDashboardViewInput) => Promise<DashboardView | null>;\n loadView: (viewId: string) => void;\n updateView: (input: UpdateDashboardViewInput) => Promise<DashboardView | null>;\n deleteView: (id: string) => Promise<boolean>;\n setAsDefault: (viewId: string) => Promise<DashboardView | null>;\n clearCurrentView: () => void;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\ninterface RawViewData {\n id: string;\n dashboardId: string;\n workspaceId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n version?: number;\n metadata?: Record<string, unknown>;\n createdAt?: string;\n createdBy?: string;\n updatedAt?: string;\n updatedBy?: string;\n}\n\nfunction normalizeView(data: RawViewData): DashboardView {\n return {\n id: data.id,\n dashboardId: data.dashboardId,\n workspaceId: data.workspaceId,\n name: data.name,\n description: data.description,\n filters: data.filters,\n layout: data.layout,\n isDefault: data.isDefault || false,\n version: data.version || 1,\n metadata: data.metadata,\n createdAt: data.createdAt || new Date().toISOString(),\n createdBy: data.createdBy,\n updatedAt: data.updatedAt || new Date().toISOString(),\n updatedBy: data.updatedBy,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardViews(): UseDashboardViewsResult {\n const [views, setViews] = useState<DashboardView[]>([]);\n const [defaultView, setDefaultView] = useState<DashboardView | null>(null);\n const [currentView, setCurrentView] = useState<DashboardView | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const apolloClient = useApolloClient();\n\n // Fetch all views for a dashboard\n const fetchViews = useCallback(\n async (dashboardId: string): Promise<DashboardView[]> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboardViews?: { edges?: Array<{ node: RawViewData }> } }>({\n query: ListDashboardViewsDocument,\n variables: { dashboardId, first: 100 },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboardViews?.edges || [];\n const normalizedViews = edges.map((edge) => normalizeView(edge.node));\n setViews(normalizedViews);\n\n // Find and set default view\n const defaultV = normalizedViews.find((v: DashboardView) => v.isDefault);\n if (defaultV) {\n setDefaultView(defaultV);\n }\n\n return normalizedViews;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch views');\n setError(error);\n return [];\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch default view for a dashboard\n const fetchDefaultView = useCallback(\n async (dashboardId: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDefaultDashboardView?: RawViewData }>({\n query: GetDefaultDashboardViewDocument,\n variables: { dashboardId },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDefaultDashboardView) {\n const view = normalizeView(result.data.getDefaultDashboardView);\n setDefaultView(view);\n return view;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch default view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Get a specific view\n const getView = useCallback(\n async (id: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDashboardView?: RawViewData }>({\n query: GetDashboardViewDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboardView) {\n return normalizeView(result.data.getDashboardView);\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to get view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Save current state as a view\n const saveCurrentView = useCallback(\n async (input: CreateDashboardViewInput): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ createDashboardView?: RawViewData }>({\n mutation: CreateDashboardViewDocument,\n variables: { input },\n });\n\n if (result.data?.createDashboardView) {\n const newView = normalizeView(result.data.createDashboardView);\n setViews((prev) => [...prev, newView]);\n\n if (newView.isDefault) {\n setDefaultView(newView);\n }\n\n return newView;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to save view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Load a view (set as current)\n const loadView = useCallback(\n (viewId: string) => {\n const view = views.find((v) => v.id === viewId);\n if (view) {\n setCurrentView(view);\n }\n },\n [views]\n );\n\n // Update a view\n const updateView = useCallback(\n async (input: UpdateDashboardViewInput): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateDashboardView?: RawViewData }>({\n mutation: UpdateDashboardViewDocument,\n variables: { input },\n });\n\n if (result.data?.updateDashboardView) {\n const updatedView = normalizeView(result.data.updateDashboardView);\n setViews((prev) => prev.map((v) => (v.id === updatedView.id ? updatedView : v)));\n\n if (updatedView.isDefault) {\n setDefaultView(updatedView);\n }\n\n if (currentView?.id === updatedView.id) {\n setCurrentView(updatedView);\n }\n\n return updatedView;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentView?.id]\n );\n\n // Delete a view\n const deleteView = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteDashboardView?: boolean }>({\n mutation: DeleteDashboardViewDocument,\n variables: { id },\n });\n\n if (result.data?.deleteDashboardView) {\n setViews((prev) => prev.filter((v) => v.id !== id));\n\n if (defaultView?.id === id) {\n setDefaultView(null);\n }\n\n if (currentView?.id === id) {\n setCurrentView(null);\n }\n\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete view');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, defaultView?.id, currentView?.id]\n );\n\n // Set a view as the default\n const setAsDefault = useCallback(\n async (viewId: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ setDefaultView?: RawViewData }>({\n mutation: SetDefaultViewDocument,\n variables: { viewId },\n });\n\n if (result.data?.setDefaultView) {\n const newDefaultView = normalizeView(result.data.setDefaultView);\n\n // Update the views list - remove isDefault from old, add to new\n setViews((prev) =>\n prev.map((v) => ({\n ...v,\n isDefault: v.id === newDefaultView.id,\n }))\n );\n\n setDefaultView(newDefaultView);\n return newDefaultView;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to set default view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Clear current view\n const clearCurrentView = useCallback(() => {\n setCurrentView(null);\n }, []);\n\n return {\n views,\n defaultView,\n currentView,\n loading,\n error,\n fetchViews,\n fetchDefaultView,\n getView,\n saveCurrentView,\n loadView,\n updateView,\n deleteView,\n setAsDefault,\n clearCurrentView,\n };\n}\n\nexport default useDashboardViews;\n"],"mappings":"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"}
1
+ {"version":3,"file":"useDashboardViews.js","names":[],"sources":["../../../src/bigconsole/hooks/useDashboardViews.ts"],"sourcesContent":["/**\n * useDashboardViews Hook\n *\n * Provides operations for managing dashboard saved views.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport { createBigConsoleQuotaError, isBigConsoleQuotaError } from '../utils/quota';\nimport {\n GetDashboardViewDocument,\n ListDashboardViewsDocument,\n GetDefaultDashboardViewDocument,\n CreateDashboardViewDocument,\n UpdateDashboardViewDocument,\n DeleteDashboardViewDocument,\n SetDefaultViewDocument,\n} from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DashboardView {\n id: string;\n dashboardId: string;\n workspaceId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault: boolean;\n version: number;\n metadata?: Record<string, unknown>;\n createdAt: string;\n createdBy?: string;\n updatedAt: string;\n updatedBy?: string;\n}\n\nexport interface CreateDashboardViewInput {\n dashboardId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UpdateDashboardViewInput {\n id: string;\n name?: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface UseDashboardViewsResult {\n views: DashboardView[];\n defaultView: DashboardView | null;\n currentView: DashboardView | null;\n loading: boolean;\n error: Error | null;\n\n // Operations\n fetchViews: (dashboardId: string) => Promise<DashboardView[]>;\n fetchDefaultView: (dashboardId: string) => Promise<DashboardView | null>;\n getView: (id: string) => Promise<DashboardView | null>;\n saveCurrentView: (input: CreateDashboardViewInput) => Promise<DashboardView | null>;\n loadView: (viewId: string) => void;\n updateView: (input: UpdateDashboardViewInput) => Promise<DashboardView | null>;\n deleteView: (id: string) => Promise<boolean>;\n setAsDefault: (viewId: string) => Promise<DashboardView | null>;\n clearCurrentView: () => void;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\ninterface RawViewData {\n id: string;\n dashboardId: string;\n workspaceId: string;\n name: string;\n description?: string;\n filters?: Record<string, unknown>;\n layout?: Record<string, unknown>;\n isDefault?: boolean;\n version?: number;\n metadata?: Record<string, unknown>;\n createdAt?: string;\n createdBy?: string;\n updatedAt?: string;\n updatedBy?: string;\n}\n\nfunction normalizeView(data: RawViewData): DashboardView {\n return {\n id: data.id,\n dashboardId: data.dashboardId,\n workspaceId: data.workspaceId,\n name: data.name,\n description: data.description,\n filters: data.filters,\n layout: data.layout,\n isDefault: data.isDefault || false,\n version: data.version || 1,\n metadata: data.metadata,\n createdAt: data.createdAt || new Date().toISOString(),\n createdBy: data.createdBy,\n updatedAt: data.updatedAt || new Date().toISOString(),\n updatedBy: data.updatedBy,\n };\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useDashboardViews(): UseDashboardViewsResult {\n const [views, setViews] = useState<DashboardView[]>([]);\n const [defaultView, setDefaultView] = useState<DashboardView | null>(null);\n const [currentView, setCurrentView] = useState<DashboardView | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const apolloClient = useApolloClient();\n\n // Fetch all views for a dashboard\n const fetchViews = useCallback(\n async (dashboardId: string): Promise<DashboardView[]> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ listDashboardViews?: { edges?: Array<{ node: RawViewData }> } }>({\n query: ListDashboardViewsDocument,\n variables: { dashboardId, first: 100 },\n fetchPolicy: 'network-only',\n });\n\n const edges = result.data?.listDashboardViews?.edges || [];\n const normalizedViews = edges.map((edge) => normalizeView(edge.node));\n setViews(normalizedViews);\n\n // Find and set default view\n const defaultV = normalizedViews.find((v: DashboardView) => v.isDefault);\n if (defaultV) {\n setDefaultView(defaultV);\n }\n\n return normalizedViews;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch views');\n setError(error);\n return [];\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Fetch default view for a dashboard\n const fetchDefaultView = useCallback(\n async (dashboardId: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDefaultDashboardView?: RawViewData }>({\n query: GetDefaultDashboardViewDocument,\n variables: { dashboardId },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDefaultDashboardView) {\n const view = normalizeView(result.data.getDefaultDashboardView);\n setDefaultView(view);\n return view;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to fetch default view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Get a specific view\n const getView = useCallback(\n async (id: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<{ getDashboardView?: RawViewData }>({\n query: GetDashboardViewDocument,\n variables: { id },\n fetchPolicy: 'network-only',\n });\n\n if (result.data?.getDashboardView) {\n return normalizeView(result.data.getDashboardView);\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to get view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Save current state as a view\n const saveCurrentView = useCallback(\n async (input: CreateDashboardViewInput): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ createDashboardView?: RawViewData }>({\n mutation: CreateDashboardViewDocument,\n variables: { input },\n });\n\n if (isBigConsoleQuotaError(result)) {\n throw createBigConsoleQuotaError(result);\n }\n\n if (result.data?.createDashboardView) {\n const newView = normalizeView(result.data.createDashboardView);\n setViews((prev) => [...prev, newView]);\n\n if (newView.isDefault) {\n setDefaultView(newView);\n }\n\n return newView;\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 save view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Load a view (set as current)\n const loadView = useCallback(\n (viewId: string) => {\n const view = views.find((v) => v.id === viewId);\n if (view) {\n setCurrentView(view);\n }\n },\n [views]\n );\n\n // Update a view\n const updateView = useCallback(\n async (input: UpdateDashboardViewInput): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ updateDashboardView?: RawViewData }>({\n mutation: UpdateDashboardViewDocument,\n variables: { input },\n });\n\n if (result.data?.updateDashboardView) {\n const updatedView = normalizeView(result.data.updateDashboardView);\n setViews((prev) => prev.map((v) => (v.id === updatedView.id ? updatedView : v)));\n\n if (updatedView.isDefault) {\n setDefaultView(updatedView);\n }\n\n if (currentView?.id === updatedView.id) {\n setCurrentView(updatedView);\n }\n\n return updatedView;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to update view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, currentView?.id]\n );\n\n // Delete a view\n const deleteView = useCallback(\n async (id: string): Promise<boolean> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ deleteDashboardView?: boolean }>({\n mutation: DeleteDashboardViewDocument,\n variables: { id },\n });\n\n if (result.data?.deleteDashboardView) {\n setViews((prev) => prev.filter((v) => v.id !== id));\n\n if (defaultView?.id === id) {\n setDefaultView(null);\n }\n\n if (currentView?.id === id) {\n setCurrentView(null);\n }\n\n return true;\n }\n\n return false;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to delete view');\n setError(error);\n return false;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient, defaultView?.id, currentView?.id]\n );\n\n // Set a view as the default\n const setAsDefault = useCallback(\n async (viewId: string): Promise<DashboardView | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.mutate<{ setDefaultView?: RawViewData }>({\n mutation: SetDefaultViewDocument,\n variables: { viewId },\n });\n\n if (result.data?.setDefaultView) {\n const newDefaultView = normalizeView(result.data.setDefaultView);\n\n // Update the views list - remove isDefault from old, add to new\n setViews((prev) =>\n prev.map((v) => ({\n ...v,\n isDefault: v.id === newDefaultView.id,\n }))\n );\n\n setDefaultView(newDefaultView);\n return newDefaultView;\n }\n\n return null;\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to set default view');\n setError(error);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Clear current view\n const clearCurrentView = useCallback(() => {\n setCurrentView(null);\n }, []);\n\n return {\n views,\n defaultView,\n currentView,\n loading,\n error,\n fetchViews,\n fetchDefaultView,\n getView,\n saveCurrentView,\n loadView,\n updateView,\n deleteView,\n setAsDefault,\n clearCurrentView,\n };\n}\n\nexport default useDashboardViews;\n"],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { GetDashboardDocument as e, ImportDashboardDocument as t, UpdateDashboardDocument as n, ValidateDashboardImportDocument as r } from "../../generated/wspace-operations.js";
2
- import { useCallback as i, useState as a } from "react";
3
- import { useApolloClient as o } from "@apollo/client/react";
2
+ import { createBigConsoleQuotaError as i, isBigConsoleQuotaError as a } from "../utils/quota.js";
3
+ import { useCallback as o, useState as s } from "react";
4
+ import { useApolloClient as c } from "@apollo/client/react";
4
5
  //#region src/bigconsole/hooks/useImportDashboard.ts
5
- function s(e) {
6
+ function l(e) {
6
7
  return new Promise((t, n) => {
7
8
  let r = new FileReader();
8
9
  r.onload = (e) => {
@@ -11,17 +12,17 @@ function s(e) {
11
12
  }, r.onerror = () => n(/* @__PURE__ */ Error("Failed to read file")), r.readAsText(e);
12
13
  });
13
14
  }
14
- function c(e) {
15
+ function u(e) {
15
16
  if (e == null) return e;
16
- if (Array.isArray(e)) return e.map((e) => c(e));
17
+ if (Array.isArray(e)) return e.map((e) => u(e));
17
18
  if (typeof e == "object") {
18
19
  let t = {};
19
- for (let [n, r] of Object.entries(e)) n !== "__typename" && (t[n] = c(r));
20
+ for (let [n, r] of Object.entries(e)) n !== "__typename" && (t[n] = u(r));
20
21
  return t;
21
22
  }
22
23
  return e;
23
24
  }
24
- function l(e) {
25
+ function d(e) {
25
26
  try {
26
27
  let t = JSON.parse(e);
27
28
  return t.exportedFrom?.dashboardId || t.dashboard?.id || null;
@@ -29,129 +30,132 @@ function l(e) {
29
30
  return null;
30
31
  }
31
32
  }
32
- function u() {
33
- let [u, d] = a(!1), [f, p] = a(null), [m, h] = a(null), [g, _] = a(null), v = o(), y = i(async (e) => {
33
+ function f() {
34
+ let [f, p] = s(!1), [m, h] = s(null), [g, _] = s(null), [v, y] = s(null), b = c(), x = o(async (e) => {
34
35
  try {
35
- d(!0), p(null);
36
- let t = (await v.query({
36
+ p(!0), h(null);
37
+ let t = (await b.query({
37
38
  query: r,
38
39
  variables: { content: e },
39
40
  fetchPolicy: "network-only"
40
41
  })).data?.validateDashboardImport;
41
- if (t) return h(t), t;
42
+ if (t) return _(t), t;
42
43
  throw Error("Validation returned empty result");
43
44
  } catch (e) {
44
- return p(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to validate import")), null;
45
+ return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to validate import")), null;
45
46
  } finally {
46
- d(!1);
47
+ p(!1);
47
48
  }
48
- }, [v]), b = i(async (r, i = {}) => {
49
+ }, [b]), S = o(async (r, o = {}) => {
49
50
  try {
50
- d(!0), p(null);
51
- let a = JSON.parse(r).dashboard, o = l(r), s = !1, u;
52
- if (o) try {
53
- let t = (await v.query({
51
+ p(!0), h(null);
52
+ let s = JSON.parse(r).dashboard, c = d(r), l = !1, f;
53
+ if (c) try {
54
+ let t = (await b.query({
54
55
  query: e,
55
- variables: { id: o },
56
+ variables: { id: c },
56
57
  fetchPolicy: "network-only"
57
58
  })).data?.getDashboard;
58
59
  if (t) {
59
- if ((t.description || "") !== (a.description || "") || t.category !== a.category || t.visibility !== a.visibility || JSON.stringify(t.layout) !== JSON.stringify(a.layout) || JSON.stringify(t.metadata) !== JSON.stringify(a.metadata) || JSON.stringify(t.context) !== JSON.stringify(a.context)) {
60
+ if ((t.description || "") !== (s.description || "") || t.category !== s.category || t.visibility !== s.visibility || JSON.stringify(t.layout) !== JSON.stringify(s.layout) || JSON.stringify(t.metadata) !== JSON.stringify(s.metadata) || JSON.stringify(t.context) !== JSON.stringify(s.context)) {
60
61
  let e = {
61
- id: o,
62
+ id: c,
62
63
  name: t.name,
63
- description: a.description || void 0,
64
- category: a.category || void 0,
65
- layout: c(a.layout) || void 0,
66
- visibility: a.visibility || void 0,
67
- metadata: c(a.metadata) || void 0,
68
- context: c(a.context) || void 0,
69
- translations: c(a.translations) || void 0
70
- }, r = (await v.mutate({
64
+ description: s.description || void 0,
65
+ category: s.category || void 0,
66
+ layout: u(s.layout) || void 0,
67
+ visibility: s.visibility || void 0,
68
+ metadata: u(s.metadata) || void 0,
69
+ context: u(s.context) || void 0,
70
+ translations: u(s.translations) || void 0
71
+ }, r = (await b.mutate({
71
72
  mutation: n,
72
73
  variables: { input: e }
73
74
  })).data?.updateBigConsoleDashboard;
74
- r && (s = !0, u = {
75
+ r && (l = !0, f = {
75
76
  id: r.id,
76
77
  name: r.name
77
78
  });
78
79
  } else {
79
- u = {
80
+ f = {
80
81
  id: t.id,
81
82
  name: t.name
82
83
  };
83
84
  let e = {
84
85
  success: !0,
85
- dashboard: u,
86
+ dashboard: f,
86
87
  originalUpdated: !1,
87
- originalDashboard: u,
88
+ originalDashboard: f,
88
89
  alreadyExists: !0
89
90
  };
90
- return _(e), e;
91
+ return y(e), e;
91
92
  }
92
93
  let e = {
93
94
  success: !0,
94
- dashboard: u,
95
- originalUpdated: s,
96
- originalDashboard: u,
95
+ dashboard: f,
96
+ originalUpdated: l,
97
+ originalDashboard: f,
97
98
  alreadyExists: !1
98
99
  };
99
- return _(e), e;
100
+ return y(e), e;
100
101
  }
101
102
  } catch (e) {
102
103
  console.warn("Could not fetch original dashboard:", e);
103
104
  }
104
- let f = (await v.mutate({
105
+ let m = await b.mutate({
105
106
  mutation: t,
106
107
  variables: { input: {
107
108
  content: r,
108
- name: i.name,
109
- visibility: i.visibility,
110
- skipWarnings: i.skipWarnings ?? !1
109
+ name: o.name,
110
+ visibility: o.visibility,
111
+ skipWarnings: o.skipWarnings ?? !1
111
112
  } }
112
- })).data?.importBigConsoleDashboard;
113
- if (f) {
113
+ });
114
+ if (a(m)) throw i(m);
115
+ let g = m.data?.importBigConsoleDashboard;
116
+ if (g) {
114
117
  let e = {
115
- ...f,
118
+ ...g,
116
119
  originalUpdated: !1,
117
120
  originalDashboard: void 0
118
121
  };
119
- return _(e), e;
122
+ return y(e), e;
120
123
  }
121
124
  throw Error("Import returned empty result");
122
125
  } catch (e) {
123
- return p(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import dashboard")), null;
126
+ if (a(e)) throw e;
127
+ return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import dashboard")), null;
124
128
  } finally {
125
- d(!1);
129
+ p(!1);
126
130
  }
127
- }, [v]);
131
+ }, [b]);
128
132
  return {
129
- loading: u,
130
- error: f,
131
- validationResult: m,
132
- importResult: g,
133
- validateImport: y,
134
- importDashboard: b,
135
- importFromFile: i(async (e, t = {}) => {
133
+ loading: f,
134
+ error: m,
135
+ validationResult: g,
136
+ importResult: v,
137
+ validateImport: x,
138
+ importDashboard: S,
139
+ importFromFile: o(async (e, t = {}) => {
136
140
  try {
137
141
  if (!e.name.endsWith(".json")) throw Error("Invalid file type. Please select a JSON file.");
138
- let n = await s(e);
142
+ let n = await l(e);
139
143
  try {
140
144
  JSON.parse(n);
141
145
  } catch {
142
146
  throw Error("Invalid JSON format. Please select a valid export file.");
143
147
  }
144
- return await b(n, t);
148
+ return await S(n, t);
145
149
  } catch (e) {
146
- return p(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import from file")), null;
150
+ return h(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import from file")), null;
147
151
  }
148
- }, [b]),
149
- clearState: i(() => {
150
- p(null), h(null), _(null);
152
+ }, [S]),
153
+ clearState: o(() => {
154
+ h(null), _(null), y(null);
151
155
  }, [])
152
156
  };
153
157
  }
154
158
  //#endregion
155
- export { u as default };
159
+ export { f as default };
156
160
 
157
161
  //# sourceMappingURL=useImportDashboard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useImportDashboard.js","names":[],"sources":["../../../src/bigconsole/hooks/useImportDashboard.ts"],"sourcesContent":["/**\n * useImportDashboard Hook\n *\n * Provides dashboard import functionality with validation and conflict resolution.\n * Supports both creating new dashboards and updating existing ones on re-import.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n ValidateDashboardImportDocument,\n ImportDashboardDocument,\n UpdateDashboardDocument,\n GetDashboardDocument,\n} from '../../generated/wspace-operations';\nimport type { DashboardFullFieldsFragment } from '../../generated/wspace-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDashboardInfo {\n name: string;\n description?: string;\n pageCount: number;\n widgetCount: number;\n exportedAt?: string;\n exportedFrom?: string;\n schemaVersion: string;\n}\n\nexport interface ImportValidationError {\n code: string;\n message: string;\n path?: string;\n}\n\nexport interface ImportValidationWarning {\n code: string;\n message: string;\n path?: string;\n suggestion?: string;\n}\n\nexport interface ImportValidationResult {\n isValid: boolean;\n dashboardInfo: ImportDashboardInfo;\n errors: ImportValidationError[];\n warnings: ImportValidationWarning[];\n}\n\nexport interface ImportStats {\n pagesCreated: number;\n widgetsCreated: number;\n actionsCreated: number;\n filtersCreated: number;\n translationsCreated: number;\n dataSourcesSkipped: number;\n webhooksSkipped: number;\n}\n\nexport interface ImportDashboardResult {\n success: boolean;\n dashboard?: {\n id: string;\n name: string;\n };\n errorMessage?: string;\n stats?: ImportStats;\n /** Whether the original dashboard was also updated */\n originalUpdated?: boolean;\n /** The original dashboard that was updated (if any) */\n originalDashboard?: {\n id: string;\n name: string;\n };\n /** Whether the entity already exists with no changes (show \"already exists\" popup) */\n alreadyExists?: boolean;\n}\n\nexport interface ImportDashboardOptions {\n /** Override dashboard name (optional) */\n name?: string;\n /** Target visibility (optional, defaults to PRIVATE) */\n visibility?: 'PRIVATE' | 'TEAM' | 'PUBLIC';\n /** Skip validation warnings (default: false) */\n skipWarnings?: boolean;\n}\n\nexport interface UseImportDashboardResult {\n /** Loading state */\n loading: boolean;\n /** Error state */\n error: Error | null;\n /** Last validation result */\n validationResult: ImportValidationResult | null;\n /** Last import result */\n importResult: ImportDashboardResult | null;\n /** Validate import content without importing */\n validateImport: (content: string) => Promise<ImportValidationResult | null>;\n /** Import dashboard from JSON content */\n importDashboard: (content: string, options?: ImportDashboardOptions) => Promise<ImportDashboardResult | null>;\n /** Import dashboard from file */\n importFromFile: (file: File, options?: ImportDashboardOptions) => Promise<ImportDashboardResult | null>;\n /** Clear state */\n clearState: () => void;\n}\n\n// ============================================================================\n// Helper: Read file as text\n// ============================================================================\n\nfunction readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => {\n const result = e.target?.result;\n if (typeof result === 'string') {\n resolve(result);\n } else {\n reject(new Error('Failed to read file as text'));\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n}\n\n/**\n * Recursively remove __typename fields from an object\n * This is necessary because exported data contains __typename fields\n * which are not accepted by GraphQL input types\n */\nfunction stripTypename<T>(obj: T): T {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripTypename(item)) as T;\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (key !== '__typename') {\n cleaned[key] = stripTypename(value);\n }\n }\n return cleaned as T;\n }\n\n return obj;\n}\n\n/**\n * Extract dashboard ID from imported JSON content\n * The ID is injected during export for re-import update support\n */\nfunction extractDashboardIdFromContent(content: string): string | null {\n try {\n const parsed = JSON.parse(content);\n // Check both locations where ID might be stored\n return parsed.exportedFrom?.dashboardId || parsed.dashboard?.id || null;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useImportDashboard(): UseImportDashboardResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [validationResult, setValidationResult] = useState<ImportValidationResult | null>(null);\n const [importResult, setImportResult] = useState<ImportDashboardResult | null>(null);\n\n const apolloClient = useApolloClient();\n\n // Validate import content\n const validateImport = useCallback(\n async (content: string): Promise<ImportValidationResult | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<Record<string, unknown>>({\n query: ValidateDashboardImportDocument,\n variables: { content },\n fetchPolicy: 'network-only',\n });\n\n const validation = result.data?.validateDashboardImport as ImportValidationResult | undefined;\n\n if (validation) {\n setValidationResult(validation);\n return validation;\n }\n\n throw new Error('Validation returned empty result');\n } catch (err) {\n const validationError = err instanceof Error ? err : new Error('Failed to validate import');\n setError(validationError);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Import dashboard from JSON content\n // Logic (DECLARATIVE - idempotent re-import):\n // 1. If original dashboard ID exists in JSON, check if original still exists\n // 2. If original exists → UPDATE it with the JSON data (no new copy created)\n // 3. If original doesn't exist → CREATE a new dashboard via ImportDashboard mutation\n // This ensures re-importing the same JSON is idempotent and updates the existing entity\n const importDashboard = useCallback(\n async (content: string, options: ImportDashboardOptions = {}): Promise<ImportDashboardResult | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Parse the content to get dashboard data\n const parsed = JSON.parse(content);\n const dashboardData = parsed.dashboard;\n\n // Extract original dashboard ID from the JSON (if it was exported from an existing dashboard)\n const originalDashboardId = extractDashboardIdFromContent(content);\n let originalUpdated = false;\n let originalDashboardInfo: { id: string; name: string } | undefined;\n\n // Step 1: Check if original dashboard exists and update it\n if (originalDashboardId) {\n try {\n const getDashboardResult = await apolloClient.query<{ getDashboard?: DashboardFullFieldsFragment }>({\n query: GetDashboardDocument,\n variables: { id: originalDashboardId },\n fetchPolicy: 'network-only',\n });\n\n const existingDashboard = getDashboardResult.data?.getDashboard;\n\n if (existingDashboard) {\n // Compare to detect changes (excluding name - we don't update the original's name)\n const hasChanges =\n (existingDashboard.description || '') !== (dashboardData.description || '') ||\n existingDashboard.category !== dashboardData.category ||\n existingDashboard.visibility !== dashboardData.visibility ||\n JSON.stringify(existingDashboard.layout) !== JSON.stringify(dashboardData.layout) ||\n JSON.stringify(existingDashboard.metadata) !== JSON.stringify(dashboardData.metadata) ||\n JSON.stringify(existingDashboard.context) !== JSON.stringify(dashboardData.context);\n\n // Update original if there are changes\n // Note: We intentionally do NOT update the name - the original keeps its name\n // Use stripTypename to remove __typename fields from nested objects\n if (hasChanges) {\n const updateInput = {\n id: originalDashboardId,\n name: existingDashboard.name, // Keep original name\n description: dashboardData.description || undefined,\n category: dashboardData.category || undefined,\n layout: stripTypename(dashboardData.layout) || undefined,\n visibility: dashboardData.visibility || undefined,\n metadata: stripTypename(dashboardData.metadata) || undefined,\n context: stripTypename(dashboardData.context) || undefined,\n translations: stripTypename(dashboardData.translations) || undefined,\n };\n\n const updateResult = await apolloClient.mutate<{\n updateBigConsoleDashboard?: DashboardFullFieldsFragment;\n }>({\n mutation: UpdateDashboardDocument,\n variables: { input: updateInput },\n });\n\n const updatedDashboard = updateResult.data?.updateBigConsoleDashboard;\n if (updatedDashboard) {\n originalUpdated = true;\n originalDashboardInfo = {\n id: updatedDashboard.id,\n name: updatedDashboard.name,\n };\n }\n } else {\n // No changes - entity already exists with same data\n // Return with alreadyExists flag so UI can show \"already exists\" popup\n originalDashboardInfo = {\n id: existingDashboard.id,\n name: existingDashboard.name,\n };\n const alreadyExistsResult: ImportDashboardResult = {\n success: true,\n dashboard: originalDashboardInfo,\n originalUpdated: false,\n originalDashboard: originalDashboardInfo,\n alreadyExists: true,\n };\n setImportResult(alreadyExistsResult);\n return alreadyExistsResult;\n }\n\n // If original was updated, return success with the updated dashboard info\n const finalResult: ImportDashboardResult = {\n success: true,\n dashboard: originalDashboardInfo,\n originalUpdated,\n originalDashboard: originalDashboardInfo,\n alreadyExists: false,\n };\n setImportResult(finalResult);\n return finalResult;\n }\n // If original doesn't exist, continue to create a new dashboard\n } catch (fetchErr) {\n // Original dashboard fetch failed (might not exist), continue with import\n console.warn('Could not fetch original dashboard:', fetchErr);\n }\n }\n\n // Step 2: Create a NEW dashboard only if original doesn't exist\n // (This happens when importing for the first time, or if original was deleted)\n const result = await apolloClient.mutate<Record<string, unknown>>({\n mutation: ImportDashboardDocument,\n variables: {\n input: {\n content,\n name: options.name,\n visibility: options.visibility,\n skipWarnings: options.skipWarnings ?? false,\n },\n },\n });\n\n const importRes = result.data?.importBigConsoleDashboard as ImportDashboardResult | undefined;\n\n if (importRes) {\n const finalResult: ImportDashboardResult = {\n ...importRes,\n originalUpdated: false,\n originalDashboard: undefined,\n };\n setImportResult(finalResult);\n return finalResult;\n }\n\n throw new Error('Import returned empty result');\n } catch (err) {\n const importError = err instanceof Error ? err : new Error('Failed to import dashboard');\n setError(importError);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Import dashboard from file\n const importFromFile = useCallback(\n async (file: File, options: ImportDashboardOptions = {}): Promise<ImportDashboardResult | null> => {\n try {\n // Validate file type\n if (!file.name.endsWith('.json')) {\n throw new Error('Invalid file type. Please select a JSON file.');\n }\n\n // Read file content\n const content = await readFileAsText(file);\n\n // Validate JSON format\n try {\n JSON.parse(content);\n } catch {\n throw new Error('Invalid JSON format. Please select a valid export file.');\n }\n\n // Perform import\n return await importDashboard(content, options);\n } catch (err) {\n const fileError = err instanceof Error ? err : new Error('Failed to import from file');\n setError(fileError);\n return null;\n }\n },\n [importDashboard]\n );\n\n // Clear state\n const clearState = useCallback(() => {\n setError(null);\n setValidationResult(null);\n setImportResult(null);\n }, []);\n\n return {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDashboard,\n importFromFile,\n clearState,\n };\n}\n\nexport default useImportDashboard;\n"],"mappings":"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"}
1
+ {"version":3,"file":"useImportDashboard.js","names":[],"sources":["../../../src/bigconsole/hooks/useImportDashboard.ts"],"sourcesContent":["/**\n * useImportDashboard Hook\n *\n * Provides dashboard import functionality with validation and conflict resolution.\n * Supports both creating new dashboards and updating existing ones on re-import.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n ValidateDashboardImportDocument,\n ImportDashboardDocument,\n UpdateDashboardDocument,\n GetDashboardDocument,\n} from '../../generated/wspace-operations';\nimport type { DashboardFullFieldsFragment } from '../../generated/wspace-operations';\nimport { createBigConsoleQuotaError, isBigConsoleQuotaError } from '../utils/quota';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ImportDashboardInfo {\n name: string;\n description?: string;\n pageCount: number;\n widgetCount: number;\n exportedAt?: string;\n exportedFrom?: string;\n schemaVersion: string;\n}\n\nexport interface ImportValidationError {\n code: string;\n message: string;\n path?: string;\n}\n\nexport interface ImportValidationWarning {\n code: string;\n message: string;\n path?: string;\n suggestion?: string;\n}\n\nexport interface ImportValidationResult {\n isValid: boolean;\n dashboardInfo: ImportDashboardInfo;\n errors: ImportValidationError[];\n warnings: ImportValidationWarning[];\n}\n\nexport interface ImportStats {\n pagesCreated: number;\n widgetsCreated: number;\n actionsCreated: number;\n filtersCreated: number;\n translationsCreated: number;\n dataSourcesSkipped: number;\n webhooksSkipped: number;\n}\n\nexport interface ImportDashboardResult {\n success: boolean;\n dashboard?: {\n id: string;\n name: string;\n };\n errorMessage?: string;\n stats?: ImportStats;\n /** Whether the original dashboard was also updated */\n originalUpdated?: boolean;\n /** The original dashboard that was updated (if any) */\n originalDashboard?: {\n id: string;\n name: string;\n };\n /** Whether the entity already exists with no changes (show \"already exists\" popup) */\n alreadyExists?: boolean;\n}\n\nexport interface ImportDashboardOptions {\n /** Override dashboard name (optional) */\n name?: string;\n /** Target visibility (optional, defaults to PRIVATE) */\n visibility?: 'PRIVATE' | 'TEAM' | 'PUBLIC';\n /** Skip validation warnings (default: false) */\n skipWarnings?: boolean;\n}\n\nexport interface UseImportDashboardResult {\n /** Loading state */\n loading: boolean;\n /** Error state */\n error: Error | null;\n /** Last validation result */\n validationResult: ImportValidationResult | null;\n /** Last import result */\n importResult: ImportDashboardResult | null;\n /** Validate import content without importing */\n validateImport: (content: string) => Promise<ImportValidationResult | null>;\n /** Import dashboard from JSON content */\n importDashboard: (content: string, options?: ImportDashboardOptions) => Promise<ImportDashboardResult | null>;\n /** Import dashboard from file */\n importFromFile: (file: File, options?: ImportDashboardOptions) => Promise<ImportDashboardResult | null>;\n /** Clear state */\n clearState: () => void;\n}\n\n// ============================================================================\n// Helper: Read file as text\n// ============================================================================\n\nfunction readFileAsText(file: File): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (e) => {\n const result = e.target?.result;\n if (typeof result === 'string') {\n resolve(result);\n } else {\n reject(new Error('Failed to read file as text'));\n }\n };\n reader.onerror = () => reject(new Error('Failed to read file'));\n reader.readAsText(file);\n });\n}\n\n/**\n * Recursively remove __typename fields from an object\n * This is necessary because exported data contains __typename fields\n * which are not accepted by GraphQL input types\n */\nfunction stripTypename<T>(obj: T): T {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => stripTypename(item)) as T;\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if (key !== '__typename') {\n cleaned[key] = stripTypename(value);\n }\n }\n return cleaned as T;\n }\n\n return obj;\n}\n\n/**\n * Extract dashboard ID from imported JSON content\n * The ID is injected during export for re-import update support\n */\nfunction extractDashboardIdFromContent(content: string): string | null {\n try {\n const parsed = JSON.parse(content);\n // Check both locations where ID might be stored\n return parsed.exportedFrom?.dashboardId || parsed.dashboard?.id || null;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\nexport function useImportDashboard(): UseImportDashboardResult {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [validationResult, setValidationResult] = useState<ImportValidationResult | null>(null);\n const [importResult, setImportResult] = useState<ImportDashboardResult | null>(null);\n\n const apolloClient = useApolloClient();\n\n // Validate import content\n const validateImport = useCallback(\n async (content: string): Promise<ImportValidationResult | null> => {\n try {\n setLoading(true);\n setError(null);\n\n const result = await apolloClient.query<Record<string, unknown>>({\n query: ValidateDashboardImportDocument,\n variables: { content },\n fetchPolicy: 'network-only',\n });\n\n const validation = result.data?.validateDashboardImport as ImportValidationResult | undefined;\n\n if (validation) {\n setValidationResult(validation);\n return validation;\n }\n\n throw new Error('Validation returned empty result');\n } catch (err) {\n const validationError = err instanceof Error ? err : new Error('Failed to validate import');\n setError(validationError);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Import dashboard from JSON content\n // Logic (DECLARATIVE - idempotent re-import):\n // 1. If original dashboard ID exists in JSON, check if original still exists\n // 2. If original exists → UPDATE it with the JSON data (no new copy created)\n // 3. If original doesn't exist → CREATE a new dashboard via ImportDashboard mutation\n // This ensures re-importing the same JSON is idempotent and updates the existing entity\n const importDashboard = useCallback(\n async (content: string, options: ImportDashboardOptions = {}): Promise<ImportDashboardResult | null> => {\n try {\n setLoading(true);\n setError(null);\n\n // Parse the content to get dashboard data\n const parsed = JSON.parse(content);\n const dashboardData = parsed.dashboard;\n\n // Extract original dashboard ID from the JSON (if it was exported from an existing dashboard)\n const originalDashboardId = extractDashboardIdFromContent(content);\n let originalUpdated = false;\n let originalDashboardInfo: { id: string; name: string } | undefined;\n\n // Step 1: Check if original dashboard exists and update it\n if (originalDashboardId) {\n try {\n const getDashboardResult = await apolloClient.query<{ getDashboard?: DashboardFullFieldsFragment }>({\n query: GetDashboardDocument,\n variables: { id: originalDashboardId },\n fetchPolicy: 'network-only',\n });\n\n const existingDashboard = getDashboardResult.data?.getDashboard;\n\n if (existingDashboard) {\n // Compare to detect changes (excluding name - we don't update the original's name)\n const hasChanges =\n (existingDashboard.description || '') !== (dashboardData.description || '') ||\n existingDashboard.category !== dashboardData.category ||\n existingDashboard.visibility !== dashboardData.visibility ||\n JSON.stringify(existingDashboard.layout) !== JSON.stringify(dashboardData.layout) ||\n JSON.stringify(existingDashboard.metadata) !== JSON.stringify(dashboardData.metadata) ||\n JSON.stringify(existingDashboard.context) !== JSON.stringify(dashboardData.context);\n\n // Update original if there are changes\n // Note: We intentionally do NOT update the name - the original keeps its name\n // Use stripTypename to remove __typename fields from nested objects\n if (hasChanges) {\n const updateInput = {\n id: originalDashboardId,\n name: existingDashboard.name, // Keep original name\n description: dashboardData.description || undefined,\n category: dashboardData.category || undefined,\n layout: stripTypename(dashboardData.layout) || undefined,\n visibility: dashboardData.visibility || undefined,\n metadata: stripTypename(dashboardData.metadata) || undefined,\n context: stripTypename(dashboardData.context) || undefined,\n translations: stripTypename(dashboardData.translations) || undefined,\n };\n\n const updateResult = await apolloClient.mutate<{\n updateBigConsoleDashboard?: DashboardFullFieldsFragment;\n }>({\n mutation: UpdateDashboardDocument,\n variables: { input: updateInput },\n });\n\n const updatedDashboard = updateResult.data?.updateBigConsoleDashboard;\n if (updatedDashboard) {\n originalUpdated = true;\n originalDashboardInfo = {\n id: updatedDashboard.id,\n name: updatedDashboard.name,\n };\n }\n } else {\n // No changes - entity already exists with same data\n // Return with alreadyExists flag so UI can show \"already exists\" popup\n originalDashboardInfo = {\n id: existingDashboard.id,\n name: existingDashboard.name,\n };\n const alreadyExistsResult: ImportDashboardResult = {\n success: true,\n dashboard: originalDashboardInfo,\n originalUpdated: false,\n originalDashboard: originalDashboardInfo,\n alreadyExists: true,\n };\n setImportResult(alreadyExistsResult);\n return alreadyExistsResult;\n }\n\n // If original was updated, return success with the updated dashboard info\n const finalResult: ImportDashboardResult = {\n success: true,\n dashboard: originalDashboardInfo,\n originalUpdated,\n originalDashboard: originalDashboardInfo,\n alreadyExists: false,\n };\n setImportResult(finalResult);\n return finalResult;\n }\n // If original doesn't exist, continue to create a new dashboard\n } catch (fetchErr) {\n // Original dashboard fetch failed (might not exist), continue with import\n console.warn('Could not fetch original dashboard:', fetchErr);\n }\n }\n\n // Step 2: Create a NEW dashboard only if original doesn't exist\n // (This happens when importing for the first time, or if original was deleted)\n const result = await apolloClient.mutate<Record<string, unknown>>({\n mutation: ImportDashboardDocument,\n variables: {\n input: {\n content,\n name: options.name,\n visibility: options.visibility,\n skipWarnings: options.skipWarnings ?? false,\n },\n },\n });\n\n if (isBigConsoleQuotaError(result)) {\n throw createBigConsoleQuotaError(result);\n }\n\n const importRes = result.data?.importBigConsoleDashboard as ImportDashboardResult | undefined;\n\n if (importRes) {\n const finalResult: ImportDashboardResult = {\n ...importRes,\n originalUpdated: false,\n originalDashboard: undefined,\n };\n setImportResult(finalResult);\n return finalResult;\n }\n\n throw new Error('Import returned empty result');\n } catch (err) {\n if (isBigConsoleQuotaError(err)) {\n throw err;\n }\n const importError = err instanceof Error ? err : new Error('Failed to import dashboard');\n setError(importError);\n return null;\n } finally {\n setLoading(false);\n }\n },\n [apolloClient]\n );\n\n // Import dashboard from file\n const importFromFile = useCallback(\n async (file: File, options: ImportDashboardOptions = {}): Promise<ImportDashboardResult | null> => {\n try {\n // Validate file type\n if (!file.name.endsWith('.json')) {\n throw new Error('Invalid file type. Please select a JSON file.');\n }\n\n // Read file content\n const content = await readFileAsText(file);\n\n // Validate JSON format\n try {\n JSON.parse(content);\n } catch {\n throw new Error('Invalid JSON format. Please select a valid export file.');\n }\n\n // Perform import\n return await importDashboard(content, options);\n } catch (err) {\n const fileError = err instanceof Error ? err : new Error('Failed to import from file');\n setError(fileError);\n return null;\n }\n },\n [importDashboard]\n );\n\n // Clear state\n const clearState = useCallback(() => {\n setError(null);\n setValidationResult(null);\n setImportResult(null);\n }, []);\n\n return {\n loading,\n error,\n validationResult,\n importResult,\n validateImport,\n importDashboard,\n importFromFile,\n clearState,\n };\n}\n\nexport default useImportDashboard;\n"],"mappings":"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"}