@burdenoff/microfe-bigconsole 2026.1012.2 → 2026.1012.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.
- package/dist/bigconsole/components/dashboard/ExportDashboardDialog.js +123 -121
- package/dist/bigconsole/components/dashboard/ImportDashboardDialog.js +241 -267
- package/dist/bigconsole/hooks/useExportDashboard.js +62 -38
- package/dist/bigconsole/hooks/useImportDashboard.d.ts +2 -12
- package/dist/bigconsole/hooks/useImportDashboard.js +95 -126
- package/package.json +1 -1
|
@@ -1,19 +1,38 @@
|
|
|
1
1
|
import { ExportDashboardDocument as e } from "../../generated/wspace-operations.js";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { useBigConsole as t } from "../context/BigConsoleContext.js";
|
|
3
|
+
import "../context/index.js";
|
|
4
|
+
import { useCallback as n, useLayoutEffect as r, useRef as i, useState as a } from "react";
|
|
5
|
+
import { useApolloClient as o } from "@apollo/client/react";
|
|
4
6
|
//#region src/bigconsole/hooks/useExportDashboard.ts
|
|
5
|
-
function
|
|
7
|
+
function s(e, t) {
|
|
6
8
|
let n = new Blob([e], { type: "application/json" }), r = URL.createObjectURL(n), i = document.createElement("a");
|
|
7
9
|
i.href = r, i.download = t, document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(r);
|
|
8
10
|
}
|
|
9
|
-
function
|
|
11
|
+
function c(e) {
|
|
10
12
|
return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").substring(0, 50);
|
|
11
13
|
}
|
|
12
|
-
function
|
|
13
|
-
let [
|
|
14
|
+
function l() {
|
|
15
|
+
let [l, u] = a(!1), [d, f] = a(null), p = o(), { currentUser: m, workspaceId: h } = t(), g = `${m?.id ?? ""}|${h ?? ""}`, _ = i(g), v = i(0);
|
|
16
|
+
r(() => (_.current = g, v.current++, u(!1), f(null), () => {
|
|
17
|
+
_.current = "";
|
|
18
|
+
}), [g]);
|
|
19
|
+
let y = n(() => {
|
|
20
|
+
if (!h || !m?.id || _.current !== g) throw Error("Select a workspace before exporting a dashboard.");
|
|
21
|
+
return {
|
|
22
|
+
requiredWorkspaceAuth: !0,
|
|
23
|
+
requiredWorkspaceId: h,
|
|
24
|
+
queryDeduplication: !1
|
|
25
|
+
};
|
|
26
|
+
}, [
|
|
27
|
+
h,
|
|
28
|
+
m?.id,
|
|
29
|
+
g
|
|
30
|
+
]), b = n(async (t, n = {}) => {
|
|
31
|
+
let r = ++v.current, i = () => _.current === g && v.current === r;
|
|
14
32
|
try {
|
|
15
|
-
|
|
16
|
-
|
|
33
|
+
let r = y();
|
|
34
|
+
u(!0), f(null);
|
|
35
|
+
let a = await p.query({
|
|
17
36
|
query: e,
|
|
18
37
|
variables: {
|
|
19
38
|
id: t,
|
|
@@ -23,51 +42,56 @@ function o() {
|
|
|
23
42
|
prettyPrint: n.prettyPrint ?? !0
|
|
24
43
|
}
|
|
25
44
|
},
|
|
26
|
-
fetchPolicy: "
|
|
45
|
+
fetchPolicy: "no-cache",
|
|
46
|
+
errorPolicy: "none",
|
|
47
|
+
context: r
|
|
27
48
|
});
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
49
|
+
if (!i()) return null;
|
|
50
|
+
if (a.error) throw a.error;
|
|
51
|
+
let o = a.data?.exportDashboard;
|
|
52
|
+
if (o) {
|
|
53
|
+
let e = JSON.parse(o);
|
|
32
54
|
if (!e || typeof e != "object" || Array.isArray(e)) throw Error("Export returned invalid JSON");
|
|
33
|
-
|
|
34
|
-
return Object.assign(r, { exportedFrom: {
|
|
35
|
-
...a,
|
|
36
|
-
dashboardId: t
|
|
37
|
-
} }), "dashboard" in r && r.dashboard && typeof r.dashboard == "object" && (r.dashboard = {
|
|
38
|
-
...r.dashboard,
|
|
39
|
-
id: t
|
|
40
|
-
}), JSON.stringify(r, null, n.prettyPrint === !1 ? void 0 : 2);
|
|
55
|
+
return JSON.stringify(e, null, n.prettyPrint === !1 ? void 0 : 2);
|
|
41
56
|
}
|
|
42
57
|
throw Error("Export returned empty content");
|
|
43
58
|
} catch (e) {
|
|
44
|
-
return
|
|
59
|
+
return i() && f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to export dashboard")), null;
|
|
45
60
|
} finally {
|
|
46
|
-
|
|
61
|
+
i() && u(!1);
|
|
47
62
|
}
|
|
48
|
-
}, [
|
|
63
|
+
}, [
|
|
64
|
+
p,
|
|
65
|
+
g,
|
|
66
|
+
y
|
|
67
|
+
]);
|
|
49
68
|
return {
|
|
50
|
-
loading:
|
|
51
|
-
error:
|
|
52
|
-
exportDashboard:
|
|
53
|
-
downloadDashboard:
|
|
69
|
+
loading: l,
|
|
70
|
+
error: d,
|
|
71
|
+
exportDashboard: b,
|
|
72
|
+
downloadDashboard: n(async (e, t, n = {}) => {
|
|
54
73
|
try {
|
|
55
|
-
|
|
74
|
+
y();
|
|
75
|
+
let r = n.preparedContent ?? await b(e, n);
|
|
56
76
|
if (!r) return !1;
|
|
57
|
-
let
|
|
58
|
-
if (!
|
|
77
|
+
let i = t;
|
|
78
|
+
if (!i) {
|
|
59
79
|
let e = JSON.parse(r);
|
|
60
|
-
e && typeof e == "object" && "dashboard" in e && e.dashboard && typeof e.dashboard == "object" && "name" in e.dashboard && typeof e.dashboard.name == "string" && (
|
|
80
|
+
e && typeof e == "object" && "dashboard" in e && e.dashboard && typeof e.dashboard == "object" && "name" in e.dashboard && typeof e.dashboard.name == "string" && (i = e.dashboard.name);
|
|
61
81
|
}
|
|
62
|
-
return
|
|
82
|
+
return s(r, `${c(i || "dashboard")}-export-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`), !0;
|
|
63
83
|
} catch (e) {
|
|
64
|
-
return
|
|
84
|
+
return _.current === g && f(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to download dashboard")), !1;
|
|
65
85
|
}
|
|
66
|
-
}, [
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
}, [
|
|
87
|
+
b,
|
|
88
|
+
g,
|
|
89
|
+
y
|
|
90
|
+
]),
|
|
91
|
+
clearError: n(() => {
|
|
92
|
+
v.current++, u(!1), f(null);
|
|
69
93
|
}, [])
|
|
70
94
|
};
|
|
71
95
|
}
|
|
72
96
|
//#endregion
|
|
73
|
-
export {
|
|
97
|
+
export { l as default };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useImportDashboard Hook
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Supports both creating new dashboards and updating existing ones on re-import.
|
|
4
|
+
* Imports a validated new dashboard copy. Export provenance never authorizes updates to an existing dashboard.
|
|
6
5
|
*/
|
|
7
6
|
export interface ImportDashboardInfo {
|
|
8
7
|
name: string;
|
|
@@ -47,21 +46,12 @@ export interface ImportDashboardResult {
|
|
|
47
46
|
};
|
|
48
47
|
errorMessage?: string;
|
|
49
48
|
stats?: ImportStats;
|
|
50
|
-
/** Whether the original dashboard was also updated */
|
|
51
|
-
originalUpdated?: boolean;
|
|
52
|
-
/** The original dashboard that was updated (if any) */
|
|
53
|
-
originalDashboard?: {
|
|
54
|
-
id: string;
|
|
55
|
-
name: string;
|
|
56
|
-
};
|
|
57
|
-
/** Whether the entity already exists with no changes (show "already exists" popup) */
|
|
58
|
-
alreadyExists?: boolean;
|
|
59
49
|
}
|
|
60
50
|
export interface ImportDashboardOptions {
|
|
61
51
|
/** Override dashboard name (optional) */
|
|
62
52
|
name?: string;
|
|
63
53
|
/** Target visibility (optional, defaults to PRIVATE) */
|
|
64
|
-
visibility?: 'PRIVATE' | '
|
|
54
|
+
visibility?: 'PRIVATE' | 'WORKSPACE' | 'PUBLIC';
|
|
65
55
|
/** Skip validation warnings (default: false) */
|
|
66
56
|
skipWarnings?: boolean;
|
|
67
57
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { ImportDashboardDocument as e, ValidateDashboardImportDocument as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useBigConsole as n } from "../context/BigConsoleContext.js";
|
|
3
|
+
import "../context/index.js";
|
|
4
|
+
import { createBigConsoleQuotaError as r, isBigConsoleQuotaError as i } from "../utils/quota.js";
|
|
5
|
+
import { useCallback as a, useLayoutEffect as o, useRef as s, useState as c } from "react";
|
|
6
|
+
import { useApolloClient as l } from "@apollo/client/react";
|
|
5
7
|
//#region src/bigconsole/hooks/useImportDashboard.ts
|
|
6
|
-
function
|
|
8
|
+
function u(e) {
|
|
7
9
|
return new Promise((t, n) => {
|
|
8
10
|
let r = new FileReader();
|
|
9
11
|
r.onload = (e) => {
|
|
@@ -12,148 +14,115 @@ function l(e) {
|
|
|
12
14
|
}, r.onerror = () => n(/* @__PURE__ */ Error("Failed to read file")), r.readAsText(e);
|
|
13
15
|
});
|
|
14
16
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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) => {
|
|
17
|
+
function d() {
|
|
18
|
+
let [d, f] = c(!1), [p, m] = c(null), [h, g] = c(null), [_, v] = c(null), y = l(), { currentUser: b, workspaceId: x } = n(), S = `${b?.id ?? ""}|${x ?? ""}`, C = s(S), w = s(0);
|
|
19
|
+
o(() => (C.current = S, w.current++, f(!1), m(null), g(null), v(null), () => {
|
|
20
|
+
C.current = "";
|
|
21
|
+
}), [S]);
|
|
22
|
+
let T = a(() => {
|
|
23
|
+
if (!x || !b?.id || C.current !== S) throw Error("Select a workspace before importing a dashboard.");
|
|
24
|
+
return {
|
|
25
|
+
requiredWorkspaceAuth: !0,
|
|
26
|
+
requiredWorkspaceId: x,
|
|
27
|
+
queryDeduplication: !1
|
|
28
|
+
};
|
|
29
|
+
}, [
|
|
30
|
+
x,
|
|
31
|
+
b?.id,
|
|
32
|
+
S
|
|
33
|
+
]), E = a(async (e) => {
|
|
34
|
+
let n = ++w.current, r = () => C.current === S && w.current === n;
|
|
35
35
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
let n = T();
|
|
37
|
+
f(!0), m(null), g(null), v(null);
|
|
38
|
+
let i = await y.query({
|
|
39
|
+
query: t,
|
|
39
40
|
variables: { content: e },
|
|
40
|
-
fetchPolicy: "
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
fetchPolicy: "no-cache",
|
|
42
|
+
errorPolicy: "none",
|
|
43
|
+
context: n
|
|
44
|
+
});
|
|
45
|
+
if (!r()) return null;
|
|
46
|
+
if (i.error) throw i.error;
|
|
47
|
+
let a = i.data?.validateDashboardImport;
|
|
48
|
+
if (a) return g(a), a;
|
|
43
49
|
throw Error("Validation returned empty result");
|
|
44
50
|
} catch (e) {
|
|
45
|
-
return
|
|
51
|
+
return r() && m(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to validate import")), null;
|
|
46
52
|
} finally {
|
|
47
|
-
|
|
53
|
+
r() && f(!1);
|
|
48
54
|
}
|
|
49
|
-
}, [
|
|
55
|
+
}, [
|
|
56
|
+
y,
|
|
57
|
+
S,
|
|
58
|
+
T
|
|
59
|
+
]), D = a(async (t, n = {}) => {
|
|
60
|
+
let a = ++w.current, o = () => C.current === S && w.current === a;
|
|
50
61
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
query: e,
|
|
56
|
-
variables: { id: c },
|
|
57
|
-
fetchPolicy: "network-only"
|
|
58
|
-
})).data?.getDashboard;
|
|
59
|
-
if (t) {
|
|
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)) {
|
|
61
|
-
let e = {
|
|
62
|
-
id: c,
|
|
63
|
-
name: t.name,
|
|
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({
|
|
72
|
-
mutation: n,
|
|
73
|
-
variables: { input: e }
|
|
74
|
-
})).data?.updateBigConsoleDashboard;
|
|
75
|
-
r && (l = !0, f = {
|
|
76
|
-
id: r.id,
|
|
77
|
-
name: r.name
|
|
78
|
-
});
|
|
79
|
-
} else {
|
|
80
|
-
f = {
|
|
81
|
-
id: t.id,
|
|
82
|
-
name: t.name
|
|
83
|
-
};
|
|
84
|
-
let e = {
|
|
85
|
-
success: !0,
|
|
86
|
-
dashboard: f,
|
|
87
|
-
originalUpdated: !1,
|
|
88
|
-
originalDashboard: f,
|
|
89
|
-
alreadyExists: !0
|
|
90
|
-
};
|
|
91
|
-
return y(e), e;
|
|
92
|
-
}
|
|
93
|
-
let e = {
|
|
94
|
-
success: !0,
|
|
95
|
-
dashboard: f,
|
|
96
|
-
originalUpdated: l,
|
|
97
|
-
originalDashboard: f,
|
|
98
|
-
alreadyExists: !1
|
|
99
|
-
};
|
|
100
|
-
return y(e), e;
|
|
101
|
-
}
|
|
102
|
-
} catch (e) {
|
|
103
|
-
console.warn("Could not fetch original dashboard:", e);
|
|
104
|
-
}
|
|
105
|
-
let m = await b.mutate({
|
|
106
|
-
mutation: t,
|
|
62
|
+
let a = T();
|
|
63
|
+
f(!0), m(null), v(null);
|
|
64
|
+
let s = await y.mutate({
|
|
65
|
+
mutation: e,
|
|
107
66
|
variables: { input: {
|
|
108
|
-
content:
|
|
109
|
-
name:
|
|
110
|
-
visibility:
|
|
111
|
-
skipWarnings:
|
|
112
|
-
} }
|
|
67
|
+
content: t,
|
|
68
|
+
name: n.name,
|
|
69
|
+
visibility: n.visibility,
|
|
70
|
+
skipWarnings: n.skipWarnings ?? !1
|
|
71
|
+
} },
|
|
72
|
+
errorPolicy: "none",
|
|
73
|
+
context: a
|
|
113
74
|
});
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
};
|
|
122
|
-
return y(e), e;
|
|
123
|
-
}
|
|
124
|
-
throw Error("Import returned empty result");
|
|
75
|
+
if (!o()) return null;
|
|
76
|
+
if (i(s)) throw r(s);
|
|
77
|
+
if (s.error) throw s.error;
|
|
78
|
+
let c = s.data?.importBigConsoleDashboard;
|
|
79
|
+
if (!c) throw Error("Import returned empty result");
|
|
80
|
+
if (c.success && !c.dashboard?.id) throw Error("Import returned no dashboard");
|
|
81
|
+
return v(c), c;
|
|
125
82
|
} catch (e) {
|
|
126
|
-
if (
|
|
127
|
-
|
|
83
|
+
if (!o()) return null;
|
|
84
|
+
if (i(e)) throw e;
|
|
85
|
+
return m(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import dashboard")), null;
|
|
128
86
|
} finally {
|
|
129
|
-
|
|
87
|
+
o() && f(!1);
|
|
130
88
|
}
|
|
131
|
-
}, [
|
|
89
|
+
}, [
|
|
90
|
+
y,
|
|
91
|
+
S,
|
|
92
|
+
T
|
|
93
|
+
]);
|
|
132
94
|
return {
|
|
133
|
-
loading:
|
|
134
|
-
error:
|
|
135
|
-
validationResult:
|
|
136
|
-
importResult:
|
|
137
|
-
validateImport:
|
|
138
|
-
importDashboard:
|
|
139
|
-
importFromFile:
|
|
95
|
+
loading: d,
|
|
96
|
+
error: p,
|
|
97
|
+
validationResult: h,
|
|
98
|
+
importResult: _,
|
|
99
|
+
validateImport: E,
|
|
100
|
+
importDashboard: D,
|
|
101
|
+
importFromFile: a(async (e, t = {}) => {
|
|
102
|
+
let n = ++w.current, r = () => C.current === S && w.current === n, i;
|
|
140
103
|
try {
|
|
141
|
-
if (!e.name.endsWith(".json")) throw Error("Invalid file type. Please select a JSON file.");
|
|
142
|
-
|
|
104
|
+
if (T(), f(!0), m(null), g(null), v(null), !e.name.toLowerCase().endsWith(".json")) throw Error("Invalid file type. Please select a JSON file.");
|
|
105
|
+
if (i = await u(e), !r()) return null;
|
|
143
106
|
try {
|
|
144
|
-
JSON.parse(
|
|
107
|
+
JSON.parse(i);
|
|
145
108
|
} catch {
|
|
146
109
|
throw Error("Invalid JSON format. Please select a valid export file.");
|
|
147
110
|
}
|
|
148
|
-
return await S(n, t);
|
|
149
111
|
} catch (e) {
|
|
150
|
-
return
|
|
112
|
+
return r() && m(e instanceof Error ? e : /* @__PURE__ */ Error("Failed to import from file")), null;
|
|
113
|
+
} finally {
|
|
114
|
+
r() && f(!1);
|
|
151
115
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
116
|
+
return r() ? D(i, t) : null;
|
|
117
|
+
}, [
|
|
118
|
+
D,
|
|
119
|
+
S,
|
|
120
|
+
T
|
|
121
|
+
]),
|
|
122
|
+
clearState: a(() => {
|
|
123
|
+
w.current++, f(!1), m(null), g(null), v(null);
|
|
155
124
|
}, [])
|
|
156
125
|
};
|
|
157
126
|
}
|
|
158
127
|
//#endregion
|
|
159
|
-
export {
|
|
128
|
+
export { d as default };
|