@burdenoff/microfe-bigconsole 2026.730.4 → 2026.730.6
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/assistant/attachmentExtract.js +50 -0
- package/dist/bigconsole/assistant/attachmentExtract.js.map +1 -0
- package/dist/bigconsole/assistant/createSandboxAssistantTransport.js +174 -173
- package/dist/bigconsole/assistant/createSandboxAssistantTransport.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js +44 -43
- package/dist/bigconsole/components/dashboard/DashboardCanvas.js.map +1 -1
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js +93 -81
- package/dist/bigconsole/components/dashboard/DashboardToolbar.js.map +1 -1
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js +165 -0
- package/dist/bigconsole/components/dashboard/PublishToStoreDialog.js.map +1 -0
- package/dist/bigconsole/components/dashboard/index.js +1 -0
- package/dist/bigconsole/graphql/storeTemplates.js +19 -1
- package/dist/bigconsole/graphql/storeTemplates.js.map +1 -1
- package/dist/bigconsole/hooks/useStoreDashboardTemplates.js +123 -55
- package/dist/bigconsole/hooks/useStoreDashboardTemplates.js.map +1 -1
- package/dist/bigconsole/pages/DashboardViewPage.js +197 -184
- package/dist/bigconsole/pages/DashboardViewPage.js.map +1 -1
- package/dist/generated/global-operations.js +19 -2
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/node_modules/pdfjs-dist/build/pdf.js +12493 -0
- package/dist/node_modules/pdfjs-dist/build/pdf.js.map +1 -0
- package/dist/node_modules/xlsx/xlsx.js +16412 -0
- package/dist/node_modules/xlsx/xlsx.js.map +1 -0
- package/package.json +4 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { BrowseDashboardTemplatesDocument as e,
|
|
2
|
-
import { IMPORT_DASHBOARD_TEMPLATE as
|
|
3
|
-
import { useCallback as
|
|
4
|
-
import { useApolloClient as
|
|
5
|
-
import { useGatewayClient as
|
|
1
|
+
import { BrowseDashboardTemplatesDocument as e, CreateDashboardTemplateAppDocument as t, CreateDashboardTemplateVersionDocument as n, GetDashboardTemplateDetailDocument as r } from "../../generated/global-operations.js";
|
|
2
|
+
import { BUILD_DASHBOARD_TEMPLATE_CONTENT as i, IMPORT_DASHBOARD_TEMPLATE as a } from "../graphql/storeTemplates.js";
|
|
3
|
+
import { useCallback as o, useEffect as s, useMemo as c, useState as l } from "react";
|
|
4
|
+
import { useApolloClient as u } from "@apollo/client/react";
|
|
5
|
+
import { useGatewayClient as d } from "@burdenoff/fe-libs/shared/graphql";
|
|
6
6
|
//#region src/bigconsole/hooks/useStoreDashboardTemplates.ts
|
|
7
|
-
function
|
|
7
|
+
function f(e) {
|
|
8
8
|
let t = e.pricingModel ?? "FREE";
|
|
9
9
|
return {
|
|
10
10
|
id: e.id,
|
|
@@ -22,20 +22,20 @@ function l(e) {
|
|
|
22
22
|
requiresPurchase: t !== "FREE" && (e.price ?? 0) > 0
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
function
|
|
26
|
-
let { search:
|
|
27
|
-
if (
|
|
28
|
-
|
|
25
|
+
function p(p = {}) {
|
|
26
|
+
let { search: m, category: h, autoLoad: g = !0 } = p, _ = d("global"), v = u(), [y, b] = l([]), [x, S] = l(0), [C, w] = l(!1), [T, E] = l(null), D = o(async (t) => {
|
|
27
|
+
if (_) {
|
|
28
|
+
w(!0), E(null);
|
|
29
29
|
try {
|
|
30
|
-
let n = await
|
|
30
|
+
let n = await _.query({
|
|
31
31
|
query: e,
|
|
32
32
|
variables: { input: {
|
|
33
33
|
filter: {
|
|
34
34
|
type: "DASHBOARD",
|
|
35
35
|
status: "PUBLISHED",
|
|
36
36
|
compatibleWith: "bigconsole",
|
|
37
|
-
...t ??
|
|
38
|
-
...
|
|
37
|
+
...t ?? m ? { search: t ?? m } : {},
|
|
38
|
+
...h && h !== "ALL" ? { category: h } : {}
|
|
39
39
|
},
|
|
40
40
|
sortBy: "RELEVANCE",
|
|
41
41
|
pagination: {
|
|
@@ -45,47 +45,47 @@ function u(u = {}) {
|
|
|
45
45
|
} },
|
|
46
46
|
fetchPolicy: "network-only"
|
|
47
47
|
});
|
|
48
|
-
|
|
48
|
+
b((n.data?.browseStore?.products ?? []).map(f)), S(n.data?.browseStore?.totalCount ?? 0);
|
|
49
49
|
} catch (e) {
|
|
50
|
-
|
|
50
|
+
E(e instanceof Error ? e.message : "Failed to load templates from the store"), b([]), S(0);
|
|
51
51
|
} finally {
|
|
52
|
-
|
|
52
|
+
w(!1);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}, [
|
|
56
|
+
_,
|
|
56
57
|
m,
|
|
57
|
-
|
|
58
|
-
f
|
|
58
|
+
h
|
|
59
59
|
]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}, [
|
|
63
|
-
let
|
|
64
|
-
if (!
|
|
60
|
+
s(() => {
|
|
61
|
+
g && D();
|
|
62
|
+
}, [g, D]);
|
|
63
|
+
let O = o(async (e) => {
|
|
64
|
+
if (!_) return null;
|
|
65
65
|
try {
|
|
66
|
-
let
|
|
67
|
-
query:
|
|
66
|
+
let t = (await _.query({
|
|
67
|
+
query: r,
|
|
68
68
|
variables: { id: e },
|
|
69
69
|
fetchPolicy: "network-only"
|
|
70
70
|
})).data?.product?.content;
|
|
71
|
-
if (!
|
|
72
|
-
let
|
|
73
|
-
return
|
|
74
|
-
definition:
|
|
75
|
-
requiredDataSinks:
|
|
76
|
-
requiredWidgetTypes:
|
|
77
|
-
requiredInputs:
|
|
78
|
-
defaultDashboardName:
|
|
79
|
-
defaultCategory:
|
|
80
|
-
defaultTags:
|
|
81
|
-
difficultyLevel:
|
|
71
|
+
if (!t || typeof t != "object") return null;
|
|
72
|
+
let n = t;
|
|
73
|
+
return n.definition ? {
|
|
74
|
+
definition: n.definition,
|
|
75
|
+
requiredDataSinks: n.requiredDataSinks ?? [],
|
|
76
|
+
requiredWidgetTypes: n.requiredWidgetTypes ?? [],
|
|
77
|
+
requiredInputs: n.requiredInputs ?? [],
|
|
78
|
+
defaultDashboardName: n.defaultDashboardName,
|
|
79
|
+
defaultCategory: n.defaultCategory ?? null,
|
|
80
|
+
defaultTags: n.defaultTags ?? [],
|
|
81
|
+
difficultyLevel: n.difficultyLevel ?? "medium"
|
|
82
82
|
} : null;
|
|
83
83
|
} catch {
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
-
}, [
|
|
87
|
-
let t = (await
|
|
88
|
-
mutation:
|
|
86
|
+
}, [_]), k = o(async (e) => {
|
|
87
|
+
let t = (await v.mutate({
|
|
88
|
+
mutation: a,
|
|
89
89
|
variables: { input: {
|
|
90
90
|
content: e.content,
|
|
91
91
|
sourceTemplateId: e.templateId,
|
|
@@ -112,26 +112,94 @@ function u(u = {}) {
|
|
|
112
112
|
widgetsNeedingData: 0,
|
|
113
113
|
warnings: []
|
|
114
114
|
};
|
|
115
|
-
}, [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
}, [v]), A = o(async (e) => {
|
|
116
|
+
let r = (e) => ({
|
|
117
|
+
success: !1,
|
|
118
|
+
errorMessage: e,
|
|
119
|
+
sinkCount: 0,
|
|
120
|
+
unknownSinkIds: []
|
|
121
|
+
});
|
|
122
|
+
if (!_) return r("Store is unavailable right now.");
|
|
123
|
+
let a, o = 0, s = [];
|
|
124
|
+
try {
|
|
125
|
+
let t = (await v.query({
|
|
126
|
+
query: i,
|
|
127
|
+
variables: {
|
|
128
|
+
dashboardId: e.dashboardId,
|
|
129
|
+
defaultDashboardName: e.name,
|
|
130
|
+
defaultCategory: e.category ?? null,
|
|
131
|
+
defaultTags: e.tags ?? []
|
|
132
|
+
},
|
|
133
|
+
fetchPolicy: "network-only"
|
|
134
|
+
})).data?.buildDashboardTemplateContent;
|
|
135
|
+
if (!t?.content) return r("Could not build a template from this dashboard.");
|
|
136
|
+
a = t.content, o = t.sinkCount, s = t.unknownSinkIds ?? [];
|
|
137
|
+
} catch (e) {
|
|
138
|
+
return r(e instanceof Error ? e.message : "Failed to build the template.");
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
let i = (await _.mutate({
|
|
142
|
+
mutation: t,
|
|
143
|
+
variables: { input: {
|
|
144
|
+
appType: "DASHBOARD",
|
|
145
|
+
name: e.name,
|
|
146
|
+
slug: e.slug,
|
|
147
|
+
shortDescription: e.description.slice(0, 200),
|
|
148
|
+
description: e.description,
|
|
149
|
+
...e.category ? { category: e.category } : {},
|
|
150
|
+
tags: e.tags ?? [],
|
|
151
|
+
compatibleProducts: ["bigconsole"]
|
|
152
|
+
} }
|
|
153
|
+
})).data?.createApplication;
|
|
154
|
+
return i ? (await _.mutate({
|
|
155
|
+
mutation: n,
|
|
156
|
+
variables: {
|
|
157
|
+
applicationId: i.id,
|
|
158
|
+
input: {
|
|
159
|
+
version: "1.0.0",
|
|
160
|
+
manifest: a
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}), {
|
|
164
|
+
success: !0,
|
|
165
|
+
applicationId: i.id,
|
|
166
|
+
status: i.status,
|
|
167
|
+
sinkCount: o,
|
|
168
|
+
unknownSinkIds: s
|
|
169
|
+
}) : {
|
|
170
|
+
...r("The developer portal did not create the app."),
|
|
171
|
+
sinkCount: o,
|
|
172
|
+
unknownSinkIds: s
|
|
173
|
+
};
|
|
174
|
+
} catch (e) {
|
|
175
|
+
return {
|
|
176
|
+
...r(e instanceof Error ? e.message : "Failed to publish to the developer portal."),
|
|
177
|
+
sinkCount: o,
|
|
178
|
+
unknownSinkIds: s
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}, [_, v]);
|
|
182
|
+
return c(() => ({
|
|
183
|
+
templates: y,
|
|
184
|
+
loading: C,
|
|
185
|
+
error: T,
|
|
186
|
+
totalCount: x,
|
|
187
|
+
refetch: D,
|
|
188
|
+
fetchTemplateContent: O,
|
|
189
|
+
installTemplate: k,
|
|
190
|
+
publishToStore: A
|
|
124
191
|
}), [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
S,
|
|
128
|
-
v,
|
|
129
|
-
w,
|
|
192
|
+
y,
|
|
193
|
+
C,
|
|
130
194
|
T,
|
|
131
|
-
|
|
195
|
+
x,
|
|
196
|
+
D,
|
|
197
|
+
O,
|
|
198
|
+
k,
|
|
199
|
+
A
|
|
132
200
|
]);
|
|
133
201
|
}
|
|
134
202
|
//#endregion
|
|
135
|
-
export {
|
|
203
|
+
export { p as default };
|
|
136
204
|
|
|
137
205
|
//# sourceMappingURL=useStoreDashboardTemplates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStoreDashboardTemplates.js","names":[],"sources":["../../../src/bigconsole/hooks/useStoreDashboardTemplates.ts"],"sourcesContent":["/**\n * Store-distributed dashboard templates.\n *\n * Dashboard templates live in the global store as `StoreProduct` rows of type\n * `DASHBOARD` whose `content` column holds a `DashboardTemplateContent`\n * document. This mirrors how FluidGrids sources its workflow templates\n * (`browseStore(type: WORKFLOW)` → `content.definitionJson` →\n * `importWorkflowTemplate`).\n *\n * Two gateways are involved: the catalog is read from the **global** gateway,\n * and the install mutation runs against the **workspace** gateway, which is\n * where the dashboard is created.\n *\n * @module bigconsole/hooks/useStoreDashboardTemplates\n */\nimport { useApolloClient } from '@apollo/client/react';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport {\n BROWSE_DASHBOARD_TEMPLATES,\n GET_DASHBOARD_TEMPLATE_DETAIL,\n IMPORT_DASHBOARD_TEMPLATE,\n} from '../graphql/storeTemplates';\n\n/** A column a widget expects from the sink bound to its slot. */\nexport interface TemplateExpectedField {\n name: string;\n role?: string;\n}\n\n/** A data-binding slot the template needs filled. */\nexport interface TemplateRequiredDataSink {\n slot: string;\n label: string;\n description?: string | null;\n expectedFields: TemplateExpectedField[];\n widgetTitles: string[];\n}\n\nexport interface TemplateRequiredWidgetType {\n widgetType: string;\n widgetTypeKey?: string | null;\n publishType: 'BUILTIN' | 'STORE' | 'CUSTOM';\n displayName?: string;\n requiresPurchase?: boolean;\n}\n\nexport interface TemplateRequiredInput {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'select' | 'secret';\n label: string;\n placeholder?: string;\n required: boolean;\n defaultValue?: string | number | boolean | null;\n options?: { label: string; value: string }[];\n helpText?: string;\n}\n\nexport interface DashboardTemplateContent {\n definition: unknown;\n requiredDataSinks: TemplateRequiredDataSink[];\n requiredWidgetTypes: TemplateRequiredWidgetType[];\n requiredInputs: TemplateRequiredInput[];\n defaultDashboardName?: string;\n defaultCategory?: string | null;\n defaultTags?: string[];\n difficultyLevel?: 'easy' | 'medium' | 'hard';\n}\n\n/** A store product presented as a template card. */\nexport interface StoreDashboardTemplate {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n icon?: string | null;\n category?: string | null;\n tags: string[];\n featured: boolean;\n downloads: number;\n rating?: number | null;\n pricingModel: string;\n price: number;\n /** True for anything the workspace has to buy before it can be installed. */\n requiresPurchase: boolean;\n}\n\ninterface RawStoreProduct {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n icon?: string | null;\n category?: string | null;\n tags?: string[] | null;\n featured?: boolean | null;\n downloads?: number | null;\n rating?: number | null;\n pricingModel?: string | null;\n price?: number | null;\n}\n\nexport interface InstallTemplateArgs {\n templateId: string;\n templateName: string;\n content: DashboardTemplateContent;\n name?: string;\n visibility?: string;\n dataSinkBindings?: { slot: string; dataSinkId: string }[];\n inputValues?: Record<string, unknown>;\n}\n\nexport interface InstallTemplateResult {\n success: boolean;\n dashboardId?: string;\n errorMessage?: string;\n unresolvedSlots: string[];\n resolvedSlots: string[];\n widgetsNeedingData: number;\n warnings: string[];\n}\n\nfunction normalizeProduct(raw: RawStoreProduct): StoreDashboardTemplate {\n const pricingModel = raw.pricingModel ?? 'FREE';\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n description: raw.description ?? null,\n icon: raw.icon ?? null,\n category: raw.category ?? null,\n tags: raw.tags ?? [],\n featured: raw.featured ?? false,\n downloads: raw.downloads ?? 0,\n rating: raw.rating ?? null,\n pricingModel,\n price: raw.price ?? 0,\n requiresPurchase: pricingModel !== 'FREE' && (raw.price ?? 0) > 0,\n };\n}\n\nexport interface UseStoreDashboardTemplatesResult {\n templates: StoreDashboardTemplate[];\n loading: boolean;\n error: string | null;\n totalCount: number;\n refetch: (search?: string) => Promise<void>;\n /** Fetch the full template document. Kept lazy: content is large. */\n fetchTemplateContent: (templateId: string) => Promise<DashboardTemplateContent | null>;\n installTemplate: (args: InstallTemplateArgs) => Promise<InstallTemplateResult>;\n}\n\nexport function useStoreDashboardTemplates(\n options: { search?: string; category?: string; autoLoad?: boolean } = {}\n): UseStoreDashboardTemplatesResult {\n const { search, category, autoLoad = true } = options;\n\n const globalClient = useGatewayClient('global');\n const workspaceClient = useApolloClient();\n\n const [templates, setTemplates] = useState<StoreDashboardTemplate[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const refetch = useCallback(\n async (overrideSearch?: string): Promise<void> => {\n if (!globalClient) return;\n setLoading(true);\n setError(null);\n try {\n const result = await globalClient.query<{\n browseStore?: { products?: RawStoreProduct[]; totalCount?: number };\n }>({\n query: BROWSE_DASHBOARD_TEMPLATES,\n variables: {\n input: {\n filter: {\n type: 'DASHBOARD',\n status: 'PUBLISHED',\n // Without this a template published from another product's\n // devportal listing would show up in BigConsole's gallery.\n compatibleWith: 'bigconsole',\n ...((overrideSearch ?? search) ? { search: overrideSearch ?? search } : {}),\n ...(category && category !== 'ALL' ? { category } : {}),\n },\n sortBy: 'RELEVANCE',\n pagination: { limit: 50, offset: 0 },\n },\n },\n fetchPolicy: 'network-only',\n });\n\n setTemplates((result.data?.browseStore?.products ?? []).map(normalizeProduct));\n setTotalCount(result.data?.browseStore?.totalCount ?? 0);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load templates from the store');\n setTemplates([]);\n setTotalCount(0);\n } finally {\n setLoading(false);\n }\n },\n [globalClient, search, category]\n );\n\n useEffect(() => {\n if (autoLoad) void refetch();\n }, [autoLoad, refetch]);\n\n const fetchTemplateContent = useCallback(\n async (templateId: string): Promise<DashboardTemplateContent | null> => {\n if (!globalClient) return null;\n try {\n const result = await globalClient.query<{ product?: { content?: unknown } }>({\n query: GET_DASHBOARD_TEMPLATE_DETAIL,\n variables: { id: templateId },\n fetchPolicy: 'network-only',\n });\n const content = result.data?.product?.content;\n if (!content || typeof content !== 'object') return null;\n const doc = content as Partial<DashboardTemplateContent>;\n if (!doc.definition) return null;\n return {\n definition: doc.definition,\n requiredDataSinks: doc.requiredDataSinks ?? [],\n requiredWidgetTypes: doc.requiredWidgetTypes ?? [],\n requiredInputs: doc.requiredInputs ?? [],\n defaultDashboardName: doc.defaultDashboardName,\n defaultCategory: doc.defaultCategory ?? null,\n defaultTags: doc.defaultTags ?? [],\n difficultyLevel: doc.difficultyLevel ?? 'medium',\n };\n } catch {\n return null;\n }\n },\n [globalClient]\n );\n\n const installTemplate = useCallback(\n async (args: InstallTemplateArgs): Promise<InstallTemplateResult> => {\n const result = await workspaceClient.mutate<{\n importDashboardTemplate?: InstallTemplateResult & { dashboard?: { id: string } | null };\n }>({\n mutation: IMPORT_DASHBOARD_TEMPLATE,\n variables: {\n input: {\n content: args.content,\n sourceTemplateId: args.templateId,\n sourceTemplateName: args.templateName,\n ...(args.name ? { name: args.name } : {}),\n ...(args.visibility ? { visibility: args.visibility } : {}),\n ...(args.dataSinkBindings?.length ? { dataSinkBindings: args.dataSinkBindings } : {}),\n ...(args.inputValues && Object.keys(args.inputValues).length ? { inputValues: args.inputValues } : {}),\n },\n },\n });\n\n const payload = result.data?.importDashboardTemplate;\n if (!payload) {\n return {\n success: false,\n errorMessage: 'No response from the server',\n unresolvedSlots: [],\n resolvedSlots: [],\n widgetsNeedingData: 0,\n warnings: [],\n };\n }\n\n return {\n success: payload.success,\n dashboardId: payload.dashboard?.id,\n errorMessage: payload.errorMessage,\n unresolvedSlots: payload.unresolvedSlots ?? [],\n resolvedSlots: payload.resolvedSlots ?? [],\n widgetsNeedingData: payload.widgetsNeedingData ?? 0,\n warnings: payload.warnings ?? [],\n };\n },\n [workspaceClient]\n );\n\n return useMemo(\n () => ({\n templates,\n loading,\n error,\n totalCount,\n refetch,\n fetchTemplateContent,\n installTemplate,\n }),\n [templates, loading, error, totalCount, refetch, fetchTemplateContent, installTemplate]\n );\n}\n\nexport default useStoreDashboardTemplates;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useStoreDashboardTemplates.js","names":[],"sources":["../../../src/bigconsole/hooks/useStoreDashboardTemplates.ts"],"sourcesContent":["/**\n * Store-distributed dashboard templates.\n *\n * Dashboard templates live in the global store as `StoreProduct` rows of type\n * `DASHBOARD` whose `content` column holds a `DashboardTemplateContent`\n * document. This mirrors how FluidGrids sources its workflow templates\n * (`browseStore(type: WORKFLOW)` → `content.definitionJson` →\n * `importWorkflowTemplate`).\n *\n * Two gateways are involved: the catalog is read from the **global** gateway,\n * and the install mutation runs against the **workspace** gateway, which is\n * where the dashboard is created.\n *\n * @module bigconsole/hooks/useStoreDashboardTemplates\n */\nimport { useApolloClient } from '@apollo/client/react';\nimport { useGatewayClient } from '@burdenoff/fe-libs/shared/graphql';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport {\n BROWSE_DASHBOARD_TEMPLATES,\n BUILD_DASHBOARD_TEMPLATE_CONTENT,\n CREATE_TEMPLATE_APP,\n CREATE_TEMPLATE_VERSION,\n GET_DASHBOARD_TEMPLATE_DETAIL,\n IMPORT_DASHBOARD_TEMPLATE,\n} from '../graphql/storeTemplates';\n\n/** A column a widget expects from the sink bound to its slot. */\nexport interface TemplateExpectedField {\n name: string;\n role?: string;\n}\n\n/** A data-binding slot the template needs filled. */\nexport interface TemplateRequiredDataSink {\n slot: string;\n label: string;\n description?: string | null;\n expectedFields: TemplateExpectedField[];\n widgetTitles: string[];\n}\n\nexport interface TemplateRequiredWidgetType {\n widgetType: string;\n widgetTypeKey?: string | null;\n publishType: 'BUILTIN' | 'STORE' | 'CUSTOM';\n displayName?: string;\n requiresPurchase?: boolean;\n}\n\nexport interface TemplateRequiredInput {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'select' | 'secret';\n label: string;\n placeholder?: string;\n required: boolean;\n defaultValue?: string | number | boolean | null;\n options?: { label: string; value: string }[];\n helpText?: string;\n}\n\nexport interface DashboardTemplateContent {\n definition: unknown;\n requiredDataSinks: TemplateRequiredDataSink[];\n requiredWidgetTypes: TemplateRequiredWidgetType[];\n requiredInputs: TemplateRequiredInput[];\n defaultDashboardName?: string;\n defaultCategory?: string | null;\n defaultTags?: string[];\n difficultyLevel?: 'easy' | 'medium' | 'hard';\n}\n\n/** A store product presented as a template card. */\nexport interface StoreDashboardTemplate {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n icon?: string | null;\n category?: string | null;\n tags: string[];\n featured: boolean;\n downloads: number;\n rating?: number | null;\n pricingModel: string;\n price: number;\n /** True for anything the workspace has to buy before it can be installed. */\n requiresPurchase: boolean;\n}\n\ninterface RawStoreProduct {\n id: string;\n name: string;\n slug: string;\n description?: string | null;\n icon?: string | null;\n category?: string | null;\n tags?: string[] | null;\n featured?: boolean | null;\n downloads?: number | null;\n rating?: number | null;\n pricingModel?: string | null;\n price?: number | null;\n}\n\nexport interface InstallTemplateArgs {\n templateId: string;\n templateName: string;\n content: DashboardTemplateContent;\n name?: string;\n visibility?: string;\n dataSinkBindings?: { slot: string; dataSinkId: string }[];\n inputValues?: Record<string, unknown>;\n}\n\nexport interface InstallTemplateResult {\n success: boolean;\n dashboardId?: string;\n errorMessage?: string;\n unresolvedSlots: string[];\n resolvedSlots: string[];\n widgetsNeedingData: number;\n warnings: string[];\n}\n\nfunction normalizeProduct(raw: RawStoreProduct): StoreDashboardTemplate {\n const pricingModel = raw.pricingModel ?? 'FREE';\n return {\n id: raw.id,\n name: raw.name,\n slug: raw.slug,\n description: raw.description ?? null,\n icon: raw.icon ?? null,\n category: raw.category ?? null,\n tags: raw.tags ?? [],\n featured: raw.featured ?? false,\n downloads: raw.downloads ?? 0,\n rating: raw.rating ?? null,\n pricingModel,\n price: raw.price ?? 0,\n requiresPurchase: pricingModel !== 'FREE' && (raw.price ?? 0) > 0,\n };\n}\n\nexport interface PublishToStoreArgs {\n dashboardId: string;\n name: string;\n slug: string;\n description: string;\n category?: string;\n tags?: string[];\n}\n\nexport interface PublishToStoreResult {\n success: boolean;\n /** The DRAFT devportal application created for this template. */\n applicationId?: string;\n status?: string;\n errorMessage?: string;\n /** Distinct data sinks the dashboard referenced, all tokenised into slots. */\n sinkCount: number;\n /** Sinks that could not be resolved; their slots fall back to positional names. */\n unknownSinkIds: string[];\n}\n\nexport interface UseStoreDashboardTemplatesResult {\n templates: StoreDashboardTemplate[];\n loading: boolean;\n error: string | null;\n totalCount: number;\n refetch: (search?: string) => Promise<void>;\n /** Fetch the full template document. Kept lazy: content is large. */\n fetchTemplateContent: (templateId: string) => Promise<DashboardTemplateContent | null>;\n installTemplate: (args: InstallTemplateArgs) => Promise<InstallTemplateResult>;\n publishToStore: (args: PublishToStoreArgs) => Promise<PublishToStoreResult>;\n}\n\nexport function useStoreDashboardTemplates(\n options: { search?: string; category?: string; autoLoad?: boolean } = {}\n): UseStoreDashboardTemplatesResult {\n const { search, category, autoLoad = true } = options;\n\n const globalClient = useGatewayClient('global');\n const workspaceClient = useApolloClient();\n\n const [templates, setTemplates] = useState<StoreDashboardTemplate[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const refetch = useCallback(\n async (overrideSearch?: string): Promise<void> => {\n if (!globalClient) return;\n setLoading(true);\n setError(null);\n try {\n const result = await globalClient.query<{\n browseStore?: { products?: RawStoreProduct[]; totalCount?: number };\n }>({\n query: BROWSE_DASHBOARD_TEMPLATES,\n variables: {\n input: {\n filter: {\n type: 'DASHBOARD',\n status: 'PUBLISHED',\n // Without this a template published from another product's\n // devportal listing would show up in BigConsole's gallery.\n compatibleWith: 'bigconsole',\n ...((overrideSearch ?? search) ? { search: overrideSearch ?? search } : {}),\n ...(category && category !== 'ALL' ? { category } : {}),\n },\n sortBy: 'RELEVANCE',\n pagination: { limit: 50, offset: 0 },\n },\n },\n fetchPolicy: 'network-only',\n });\n\n setTemplates((result.data?.browseStore?.products ?? []).map(normalizeProduct));\n setTotalCount(result.data?.browseStore?.totalCount ?? 0);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load templates from the store');\n setTemplates([]);\n setTotalCount(0);\n } finally {\n setLoading(false);\n }\n },\n [globalClient, search, category]\n );\n\n useEffect(() => {\n if (autoLoad) void refetch();\n }, [autoLoad, refetch]);\n\n const fetchTemplateContent = useCallback(\n async (templateId: string): Promise<DashboardTemplateContent | null> => {\n if (!globalClient) return null;\n try {\n const result = await globalClient.query<{ product?: { content?: unknown } }>({\n query: GET_DASHBOARD_TEMPLATE_DETAIL,\n variables: { id: templateId },\n fetchPolicy: 'network-only',\n });\n const content = result.data?.product?.content;\n if (!content || typeof content !== 'object') return null;\n const doc = content as Partial<DashboardTemplateContent>;\n if (!doc.definition) return null;\n return {\n definition: doc.definition,\n requiredDataSinks: doc.requiredDataSinks ?? [],\n requiredWidgetTypes: doc.requiredWidgetTypes ?? [],\n requiredInputs: doc.requiredInputs ?? [],\n defaultDashboardName: doc.defaultDashboardName,\n defaultCategory: doc.defaultCategory ?? null,\n defaultTags: doc.defaultTags ?? [],\n difficultyLevel: doc.difficultyLevel ?? 'medium',\n };\n } catch {\n return null;\n }\n },\n [globalClient]\n );\n\n const installTemplate = useCallback(\n async (args: InstallTemplateArgs): Promise<InstallTemplateResult> => {\n const result = await workspaceClient.mutate<{\n importDashboardTemplate?: InstallTemplateResult & { dashboard?: { id: string } | null };\n }>({\n mutation: IMPORT_DASHBOARD_TEMPLATE,\n variables: {\n input: {\n content: args.content,\n sourceTemplateId: args.templateId,\n sourceTemplateName: args.templateName,\n ...(args.name ? { name: args.name } : {}),\n ...(args.visibility ? { visibility: args.visibility } : {}),\n ...(args.dataSinkBindings?.length ? { dataSinkBindings: args.dataSinkBindings } : {}),\n ...(args.inputValues && Object.keys(args.inputValues).length ? { inputValues: args.inputValues } : {}),\n },\n },\n });\n\n const payload = result.data?.importDashboardTemplate;\n if (!payload) {\n return {\n success: false,\n errorMessage: 'No response from the server',\n unresolvedSlots: [],\n resolvedSlots: [],\n widgetsNeedingData: 0,\n warnings: [],\n };\n }\n\n return {\n success: payload.success,\n dashboardId: payload.dashboard?.id,\n errorMessage: payload.errorMessage,\n unresolvedSlots: payload.unresolvedSlots ?? [],\n resolvedSlots: payload.resolvedSlots ?? [],\n widgetsNeedingData: payload.widgetsNeedingData ?? 0,\n warnings: payload.warnings ?? [],\n };\n },\n [workspaceClient]\n );\n\n /**\n * Turn a live dashboard into a Dashboard Template application in the\n * developer portal.\n *\n * It deliberately does NOT create a StoreProduct directly. devportal already\n * owns dashboard-template publishing end to end — versioning, submit/review,\n * publisher identity, and the `metadata.sourceApplicationId` the store uses\n * for ownership on later updates. Writing a product straight to the store\n * would fork that pipeline and orphan the listing: a later devportal publish\n * of the same slug would hit the store's slug-collision guard and refuse.\n *\n * So this fills in the one thing devportal cannot do — produce the template\n * document from a live dashboard — and hands off to the existing flow. The\n * app is left in DRAFT so the author reviews the listing and submits it\n * themselves.\n *\n * Two hops: the workspace gateway tokenises the dashboard (it owns the data\n * sinks), the global gateway owns devportal. Brokering through the client\n * keeps both directions free of cross-layer M2M, exactly like install.\n */\n const publishToStore = useCallback(\n async (args: PublishToStoreArgs): Promise<PublishToStoreResult> => {\n const failure = (errorMessage: string): PublishToStoreResult => ({\n success: false,\n errorMessage,\n sinkCount: 0,\n unknownSinkIds: [],\n });\n\n if (!globalClient) return failure('Store is unavailable right now.');\n\n let content: unknown;\n let sinkCount = 0;\n let unknownSinkIds: string[] = [];\n try {\n const built = await workspaceClient.query<{\n buildDashboardTemplateContent?: {\n content: unknown;\n sinkCount: number;\n unknownSinkIds: string[];\n };\n }>({\n query: BUILD_DASHBOARD_TEMPLATE_CONTENT,\n variables: {\n dashboardId: args.dashboardId,\n defaultDashboardName: args.name,\n defaultCategory: args.category ?? null,\n defaultTags: args.tags ?? [],\n },\n fetchPolicy: 'network-only',\n });\n const payload = built.data?.buildDashboardTemplateContent;\n if (!payload?.content) return failure('Could not build a template from this dashboard.');\n content = payload.content;\n sinkCount = payload.sinkCount;\n unknownSinkIds = payload.unknownSinkIds ?? [];\n } catch (err) {\n return failure(err instanceof Error ? err.message : 'Failed to build the template.');\n }\n\n try {\n const app = await globalClient.mutate<{\n createApplication?: { id: string; status: string };\n }>({\n mutation: CREATE_TEMPLATE_APP,\n variables: {\n input: {\n appType: 'DASHBOARD',\n name: args.name,\n slug: args.slug,\n shortDescription: args.description.slice(0, 200),\n description: args.description,\n ...(args.category ? { category: args.category } : {}),\n tags: args.tags ?? [],\n compatibleProducts: ['bigconsole'],\n },\n },\n });\n\n const application = app.data?.createApplication;\n if (!application) {\n return { ...failure('The developer portal did not create the app.'), sinkCount, unknownSinkIds };\n }\n\n // The version manifest is what devportal maps onto StoreProduct.content\n // when the app is submitted and approved.\n await globalClient.mutate({\n mutation: CREATE_TEMPLATE_VERSION,\n variables: {\n applicationId: application.id,\n input: { version: '1.0.0', manifest: content },\n },\n });\n\n return {\n success: true,\n applicationId: application.id,\n status: application.status,\n sinkCount,\n unknownSinkIds,\n };\n } catch (err) {\n return {\n ...failure(err instanceof Error ? err.message : 'Failed to publish to the developer portal.'),\n sinkCount,\n unknownSinkIds,\n };\n }\n },\n [globalClient, workspaceClient]\n );\n\n return useMemo(\n () => ({\n templates,\n loading,\n error,\n totalCount,\n refetch,\n fetchTemplateContent,\n installTemplate,\n publishToStore,\n }),\n [templates, loading, error, totalCount, refetch, fetchTemplateContent, installTemplate, publishToStore]\n );\n}\n\nexport default useStoreDashboardTemplates;\n"],"mappings":"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"}
|