@burdenoff/fluidgrids-fe-sdk 2026.1112.7 → 2026.1112.9
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/{AiStudioPage-QGTFaVpx.js → AiStudioPage-DfoV1Olc.js} +5 -5
- package/dist/ApprovalInboxPage-Bb8H9ruw.js +1317 -0
- package/dist/{DataSinkDashboardPage-kyzcjpzL.js → DataSinkDashboardPage-Dt3xTBb8.js} +1 -1
- package/dist/{DataTablesPage-0U89KNBt.js → DataTablesPage-Zz23QZQp.js} +6 -4
- package/dist/Disclosure-DQiUKrqd.js +41 -0
- package/dist/{EntityTagPicker-dxfzv8aO.js → EntityTagPicker-CuZAMby_.js} +1 -1
- package/dist/{ExecutionDetailPage-D4Mdbzb2.js → ExecutionDetailPage-CcUxFexZ.js} +15 -14
- package/dist/{ExecutionsListPage-g_SPxAGX.js → ExecutionsListPage-JpByw6nA.js} +11 -9
- package/dist/{FailureTriagePanel-D4lJ4zqQ.js → FailureTriagePanel-BjatYyAa.js} +1 -1
- package/dist/{FluidGridsProvider-B1hgCbxG.js → FluidGridsProvider-TQ-aDPtn.js} +3 -3
- package/dist/{HistoryPage-C7NwkVNC.js → HistoryPage-s9pl5gyl.js} +2 -2
- package/dist/{InsightsPage-D9B_qW8e.js → InsightsPage-CtjJCky-.js} +4 -4
- package/dist/{MissingNodesInstallModal-BkkgeFeN.js → MissingNodesInstallModal-olEc52p2.js} +1 -1
- package/dist/{NodesPage-BEeUbIts.js → NodesPage-BSNpOUMX.js} +2 -2
- package/dist/OpenTemplateAsCodeButton-Dh3ee2OR.js +94 -0
- package/dist/PaidTemplateConfirm-DjmVi_m-.js +28 -0
- package/dist/{RunActionsMenu-DmO14hEE.js → RunActionsMenu-BE_1r3bF.js} +1 -50
- package/dist/{RunnersPage-CvAPHdfU.js → RunnersPage-CAt4YDhB.js} +2 -1
- package/dist/{SettingsPage-k21044-Z.js → SettingsPage-ywyjIAL8.js} +6 -6
- package/dist/{TagFilterSelect-CqhxcDjh.js → TagFilterSelect-DcusTt1p.js} +1 -1
- package/dist/{TaskQueuesPage-B86p51gH.js → TaskQueuesPage-C2dkenVF.js} +2 -2
- package/dist/TechnicalDetails-D4xGy201.js +19 -0
- package/dist/{TemplateCard-DanOe65C.js → TemplateCard--WYJZlA_.js} +293 -36
- package/dist/{TemplateConfigurationModal-CeMpPEhT.js → TemplateConfigurationModal-cd0-QVMZ.js} +20 -11
- package/dist/{TemplateDetailPanel-DnoA6mC3.js → TemplateDetailPanel-C-2JuXg6.js} +1 -1
- package/dist/TemplatePreview-BCnGjMuN.js +646 -0
- package/dist/{TemplatesPage-C7f2xq12.js → TemplatesPage-u7bXJYfv.js} +377 -138
- package/dist/{VariablesPage-BtoLjmUA.js → VariablesPage-CPL34WBc.js} +2 -358
- package/dist/{VersionDiffDialog-pLpG_I1r.js → VersionDiffDialog-c27yet_-.js} +1 -1
- package/dist/{WorkflowBuilder-Aslfa2vj.js → WorkflowBuilder-BWxBmBoP.js} +3 -3
- package/dist/{WorkflowBuilder-DY1_KJiV.js → WorkflowBuilder-DxAAPHsn.js} +8 -8
- package/dist/{WorkflowProposalCard-BjYAZH3q.js → WorkflowProposalCard-BvmJ5ea8.js} +1 -1
- package/dist/{WorkflowSearchRedirect-iPQBL6WO.js → WorkflowSearchRedirect-BGKduhfZ.js} +1 -1
- package/dist/{WorkflowShareDialog-DB-qJLB2.js → WorkflowShareDialog-BRwTF9QB.js} +1 -1
- package/dist/{WorkflowsList-rOxlI49U.js → WorkflowsList-Bocag4TX.js} +9 -8
- package/dist/{agentTools-B8gnHFVM.js → agentTools-JHtYGgd7.js} +3 -3
- package/dist/{api-JpNuowX4.js → api-Dw8nfVRD.js} +1 -1
- package/dist/{api-Dvitj1aT.js → api-m8hX_l2k.js} +1 -1
- package/dist/{canvasNoteTools-Cj7MvVDH.js → canvasNoteTools-B2ouyIbj.js} +2 -2
- package/dist/{HumanRequestCard-lbWDpWd7.js → channel-CZ70oI81.js} +5 -228
- package/dist/{code-editor-field-yJZEDJBi.js → code-editor-field-CWGZyNGM.js} +1 -1
- package/dist/executions.js +2 -2
- package/dist/{feature-flags-DM5myWaD.js → feature-flags-B_b8PJ6Z.js} +63 -3
- package/dist/flags.d.ts +1 -1
- package/dist/flags.js +1 -1
- package/dist/{flow-builder-dvqpKs8d.js → flow-builder-DzKPrW2r.js} +535 -313
- package/dist/{graphql-operation-types-z2oXfQvM.js → graphql-operation-types-DZVhCBEi.js} +250 -1
- package/dist/history.js +1 -1
- package/dist/{index-BcdtKBM-.d.ts → index-B4g88tCa.d.ts} +15 -1
- package/dist/{index-DNo9aFUT.d.ts → index-CGCAcRKo.d.ts} +32 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +38 -38
- package/dist/{node-detail-view-ZnJ3Hvvo.js → node-detail-view-DNilUGcx.js} +9 -9
- package/dist/{node-editor-tab-body-BuiIr7VD.js → node-editor-tab-body-XBedxkpN.js} +3 -3
- package/dist/{node-endpoint-configs-typvqw2c.js → node-endpoint-configs-BI7zc8eM.js} +1 -1
- package/dist/nodes.js +1 -1
- package/dist/observability.d.ts +1 -1
- package/dist/observability.js +2 -2
- package/dist/{popover-mexhIFP3.js → popover-BC4r84K0.js} +3 -3
- package/dist/{quick-config-panel-EV66lJOM.js → quick-config-panel-BPmrhIOb.js} +3 -3
- package/dist/{schedule-panel-BeLfDNFh.js → schedule-panel-DJN1TDQH.js} +8 -8
- package/dist/settings.js +1 -1
- package/dist/{sidebar-node-editor-D85Moj5d.js → sidebar-node-editor-DKdfcd2r.js} +3 -3
- package/dist/templates.js +2 -2
- package/dist/{useAgentDefinitions-Uy6nhpKN.js → useAgentDefinitions-B4sw7bLw.js} +1 -1
- package/dist/{useDurableParity-04-5PTk2.js → useDurableParity-B3h8jqP0.js} +2 -2
- package/dist/{useEntityTags-D5C0tdLs.js → useEntityTags-BpDeLhzV.js} +1 -1
- package/dist/{useExecutions-DJXtbA15.js → useExecutions-BbkBSYpS.js} +2 -2
- package/dist/{useObservability-Dfgh4yjv.js → useObservability-BASo2sA3.js} +1 -1
- package/dist/{useRunHistory-BZQ3t68Q.js → useRunHistory-C3Pv_SJW.js} +2 -2
- package/dist/useVariables-cI8uLwye.js +361 -0
- package/dist/useWorkflowCodeExport-k5Emm4ZS.js +226 -0
- package/dist/{useWorkflows-CP-d3ygY.js → useWorkflows-CRUlQBd3.js} +2 -2
- package/dist/workflow-builder.js +4 -4
- package/dist/workflow-code-transfer-Cshsgf2H.js +375 -0
- package/dist/workflow-host.d.ts +1 -1
- package/dist/workflow-host.js +1 -1
- package/dist/workflow-pages.d.ts +1 -1
- package/dist/workflow-pages.js +19 -19
- package/dist/workflow-transfer-CQnQC-ke.js +104 -0
- package/dist/workflows-list.js +1 -1
- package/package.json +1 -1
- package/dist/ApprovalInboxPage-QAJim81n.js +0 -559
- package/dist/QuotaExhaustedDialog-Bj7AG_0y.js +0 -55
- package/dist/TemplatePreview-DY4GxnfC.js +0 -231
- package/dist/useWorkflowCodeExport-D0zapXXm.js +0 -643
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
|
+
import { t as ThemeProvider } from "./theme-provider-B3mIuz2d.js";
|
|
4
|
+
import { t as FlowBuilderPage } from "./flow-builder-DzKPrW2r.js";
|
|
5
|
+
import { S as useInstalledNodes, c as buildNodeCheck, d as useImportWorkflowTemplate, l as buildRequiredNodeTypes, n as formatTemplatePrice, r as isPaidTemplate, s as useTemplateImportFlow } from "./TemplateCard--WYJZlA_.js";
|
|
6
|
+
import { S as QuotaExhaustedDialog } from "./workflow-code-transfer-Cshsgf2H.js";
|
|
7
|
+
import { n as WithOpenTemplateAsCode } from "./OpenTemplateAsCodeButton-Dh3ee2OR.js";
|
|
8
|
+
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
9
|
+
import { i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-dcxg6zG6.js";
|
|
10
|
+
import { t as BILLING_PLANS_PATH } from "./quota-Cdt8yz7N.js";
|
|
11
|
+
import { n as useNavigationV2 } from "./useNavigationV2-C2WeqN7d.js";
|
|
12
|
+
import { m as describeOperationError } from "./client-C9XSzSXr.js";
|
|
13
|
+
import { t as Disclosure } from "./Disclosure-DQiUKrqd.js";
|
|
14
|
+
import { c as useVariables, t as useCreateVariable } from "./useVariables-cI8uLwye.js";
|
|
15
|
+
import { t as PaidTemplateConfirm } from "./PaidTemplateConfirm-DjmVi_m-.js";
|
|
16
|
+
import { useEffect, useMemo, useState } from "react";
|
|
17
|
+
import { useLocation, useNavigate, useParams } from "react-router";
|
|
18
|
+
import { Icon } from "@iconify/react";
|
|
19
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
import { toast } from "sonner";
|
|
21
|
+
import { Input } from "@burdenoff/fe-libs/ui";
|
|
22
|
+
import { ErrorBoundary } from "@burdenoff/fe-libs/shared/components";
|
|
23
|
+
import { Button as Button$1 } from "@burdenoff/fe-libs/button";
|
|
24
|
+
import "@xyflow/react/dist/style.css";
|
|
25
|
+
|
|
26
|
+
// src/utils/template-needs.ts
|
|
27
|
+
/** "slack_oauth2" → "Slack oauth2", "google-sheets" → "Google sheets". */
|
|
28
|
+
function humanizeIdentifier(identifier) {
|
|
29
|
+
const text = identifier.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_\-.:/]+/g, " ").replace(/\s+/g, " ").trim().toLowerCase();
|
|
30
|
+
return text ? text.charAt(0).toUpperCase() + text.slice(1) : identifier;
|
|
31
|
+
}
|
|
32
|
+
function appName(node) {
|
|
33
|
+
return node.displayName?.trim() || humanizeIdentifier(node.nodeType);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The store apps the template uses (built-in steps are always there, so they
|
|
37
|
+
* are not listed), each with its status: ready (installed), installed for
|
|
38
|
+
* you when you use the template, to buy first, or not in the store.
|
|
39
|
+
*/
|
|
40
|
+
function templateApps(check) {
|
|
41
|
+
const entry = (status) => (node) => ({
|
|
42
|
+
nodeType: node.nodeType,
|
|
43
|
+
name: appName(node),
|
|
44
|
+
status
|
|
45
|
+
});
|
|
46
|
+
return [
|
|
47
|
+
...check.installed.filter((node) => node.publishType !== "BUILTIN").map(entry("ready")),
|
|
48
|
+
...check.missing.map(entry("install")),
|
|
49
|
+
...check.missingPaid.map(entry("purchase")),
|
|
50
|
+
...(check.unavailable ?? []).map(entry("unavailable"))
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
/** `{{ $vars.API_URL }}` (expressions) and `${vars.API_URL}` (legacy). */
|
|
54
|
+
const VARIABLE_PATTERNS = [/\$vars\.([A-Za-z_][A-Za-z0-9_]*)/g, /\$\{vars\.([A-Za-z_][A-Za-z0-9_]*)\}/g];
|
|
55
|
+
/** The workspace values (`$vars`) a template's definition reads, sorted. */
|
|
56
|
+
function templateVariableNames(definition) {
|
|
57
|
+
let text;
|
|
58
|
+
try {
|
|
59
|
+
text = JSON.stringify(definition ?? null);
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const names = /* @__PURE__ */ new Set();
|
|
64
|
+
for (const pattern of VARIABLE_PATTERNS) for (const match of text.matchAll(pattern)) if (match[1]) names.add(match[1]);
|
|
65
|
+
return [...names].sort();
|
|
66
|
+
}
|
|
67
|
+
/** Canvas-only nodes that are not steps (they never run). */
|
|
68
|
+
const NOT_A_STEP = /* @__PURE__ */ new Set(["sticky-note"]);
|
|
69
|
+
/** The template's steps by name, in canvas order. */
|
|
70
|
+
function templateSteps(nodes) {
|
|
71
|
+
const steps = [];
|
|
72
|
+
for (const node of nodes) {
|
|
73
|
+
const type = typeof node.type === "string" ? node.type : "";
|
|
74
|
+
if (NOT_A_STEP.has(type)) continue;
|
|
75
|
+
const id = typeof node.id === "string" ? node.id : String(steps.length);
|
|
76
|
+
const label = node.data?.label;
|
|
77
|
+
steps.push({
|
|
78
|
+
id,
|
|
79
|
+
name: typeof label === "string" && label.trim() ? label.trim() : humanizeIdentifier(type.replace(/^store\//, "")) || id
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return steps;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/modules/templates/components/TemplateNeedsPanel.tsx
|
|
86
|
+
/**
|
|
87
|
+
* "What you'll need" beside a template's preview (Navigation v2,
|
|
88
|
+
* BOFF-11848): before "Use this template", the apps it uses and whether each
|
|
89
|
+
* is ready, the accounts to connect, the values it will ask for, the
|
|
90
|
+
* workspace values it reads (with a way to add a missing one right here),
|
|
91
|
+
* and the price, author, step count and how often it was used.
|
|
92
|
+
*/
|
|
93
|
+
/** Download and view counts, written for the reader's locale. */
|
|
94
|
+
const COUNT_FORMAT = new Intl.NumberFormat(void 0, {
|
|
95
|
+
notation: "compact",
|
|
96
|
+
maximumFractionDigits: 1
|
|
97
|
+
});
|
|
98
|
+
const APP_STATUS_ICON = {
|
|
99
|
+
ready: "mdi:check-circle-outline",
|
|
100
|
+
install: "mdi:download-outline",
|
|
101
|
+
purchase: "mdi:cart-outline",
|
|
102
|
+
unavailable: "mdi:alert-circle-outline"
|
|
103
|
+
};
|
|
104
|
+
function Section({ title, children, testId }) {
|
|
105
|
+
return /* @__PURE__ */ jsxs("section", {
|
|
106
|
+
className: "space-y-1.5",
|
|
107
|
+
"data-testid": testId,
|
|
108
|
+
children: [/* @__PURE__ */ jsx("h3", {
|
|
109
|
+
className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground",
|
|
110
|
+
children: title
|
|
111
|
+
}), children]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function AddWorkspaceValue({ name, onAdded }) {
|
|
115
|
+
const tr = useTr();
|
|
116
|
+
const { createVariable, loading } = useCreateVariable();
|
|
117
|
+
const [value, setValue] = useState("");
|
|
118
|
+
const save = async () => {
|
|
119
|
+
try {
|
|
120
|
+
await createVariable({
|
|
121
|
+
key: name,
|
|
122
|
+
value
|
|
123
|
+
});
|
|
124
|
+
toast.success(tr("fluidgrids.pages.templatePreview.addValueSaved", "Saved {{name}}", { name }));
|
|
125
|
+
onAdded();
|
|
126
|
+
} catch (err) {
|
|
127
|
+
const failed = tr("fluidgrids.pages.templatePreview.addValueFailed", "Could not save {{name}}", { name });
|
|
128
|
+
toast.error(failed, { description: describeOperationError(err, failed) });
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
132
|
+
className: "flex items-center gap-2",
|
|
133
|
+
children: [/* @__PURE__ */ jsx(Input, {
|
|
134
|
+
value,
|
|
135
|
+
onChange: (event) => setValue(event.target.value),
|
|
136
|
+
placeholder: tr("fluidgrids.pages.templatePreview.addValuePlaceholder", "Value for {{name}}", { name }),
|
|
137
|
+
"aria-label": tr("fluidgrids.pages.templatePreview.addValuePlaceholder", "Value for {{name}}", { name }),
|
|
138
|
+
className: "h-8 text-xs",
|
|
139
|
+
"data-testid": `template-value-input-${name}`
|
|
140
|
+
}), /* @__PURE__ */ jsx(SdkPermissionButton, {
|
|
141
|
+
permission: FLUIDGRIDS_PERMISSIONS.VARIABLE_CREATE,
|
|
142
|
+
deniedBehavior: "hide",
|
|
143
|
+
children: /* @__PURE__ */ jsx(Button$1, {
|
|
144
|
+
"data-agent": "confirm",
|
|
145
|
+
size: "sm",
|
|
146
|
+
variant: "outline",
|
|
147
|
+
disabled: loading || !value.trim(),
|
|
148
|
+
onClick: () => void save(),
|
|
149
|
+
"data-testid": `template-value-save-${name}`,
|
|
150
|
+
children: tr("fluidgrids.pages.templatePreview.addValueSave", "Save")
|
|
151
|
+
})
|
|
152
|
+
})]
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/** The `$vars` the template reads, checked against the workspace's values. */
|
|
156
|
+
function WorkspaceValuesCheck({ names }) {
|
|
157
|
+
const tr = useTr();
|
|
158
|
+
const { variables, loading, refetch } = useVariables();
|
|
159
|
+
const known = new Set(variables.map((variable) => variable.key));
|
|
160
|
+
const missing = loading ? [] : names.filter((name) => !known.has(name));
|
|
161
|
+
const missingSet = new Set(missing);
|
|
162
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
163
|
+
className: "space-y-2",
|
|
164
|
+
children: [missing.length > 0 && /* @__PURE__ */ jsx("p", {
|
|
165
|
+
className: "text-xs text-text-primary",
|
|
166
|
+
"data-testid": "template-values-missing",
|
|
167
|
+
children: tr("fluidgrids.pages.templatePreview.needsValuesMissing", "This workflow needs: {{names}}", { names: missing.join(", ") })
|
|
168
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
169
|
+
className: "space-y-2",
|
|
170
|
+
children: names.map((name) => {
|
|
171
|
+
const isMissing = missingSet.has(name);
|
|
172
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
173
|
+
className: "space-y-1 text-xs",
|
|
174
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
175
|
+
className: "flex items-center justify-between gap-2",
|
|
176
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
177
|
+
className: "font-mono text-text-primary",
|
|
178
|
+
children: name
|
|
179
|
+
}), !loading && /* @__PURE__ */ jsx("span", {
|
|
180
|
+
className: isMissing ? "text-status-warning-text" : "text-text-secondary",
|
|
181
|
+
children: isMissing ? tr("fluidgrids.pages.templatePreview.valueMissing", "Missing") : tr("fluidgrids.pages.templatePreview.valueSet", "Set")
|
|
182
|
+
})]
|
|
183
|
+
}), isMissing && /* @__PURE__ */ jsx(AddWorkspaceValue, {
|
|
184
|
+
name,
|
|
185
|
+
onAdded: () => void refetch()
|
|
186
|
+
})]
|
|
187
|
+
}, name);
|
|
188
|
+
})
|
|
189
|
+
})]
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function AppsSection({ nodeCheck }) {
|
|
193
|
+
const tr = useTr();
|
|
194
|
+
const apps = nodeCheck ? templateApps(nodeCheck) : [];
|
|
195
|
+
const statusText = {
|
|
196
|
+
ready: tr("fluidgrids.pages.templatePreview.appReady", "Ready"),
|
|
197
|
+
install: tr("fluidgrids.pages.templatePreview.appWillInstall", "Added for you when you use it"),
|
|
198
|
+
purchase: tr("fluidgrids.pages.templatePreview.appNeedsPurchase", "Needs to be bought first"),
|
|
199
|
+
unavailable: tr("fluidgrids.pages.templatePreview.appUnavailable", "Not in the store")
|
|
200
|
+
};
|
|
201
|
+
const empty = nodeCheck ? tr("fluidgrids.pages.templatePreview.needsNoApps", "Only built-in steps, nothing to add") : tr("fluidgrids.pages.templatePreview.needsChecking", "Checking…");
|
|
202
|
+
return /* @__PURE__ */ jsx(Section, {
|
|
203
|
+
title: tr("fluidgrids.pages.templatePreview.needsApps", "Apps it uses"),
|
|
204
|
+
testId: "template-needs-apps",
|
|
205
|
+
children: apps.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
206
|
+
className: "space-y-1.5",
|
|
207
|
+
children: apps.map((app) => /* @__PURE__ */ jsxs("li", {
|
|
208
|
+
className: "flex items-start justify-between gap-2 text-xs",
|
|
209
|
+
"data-status": app.status,
|
|
210
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
211
|
+
className: "text-text-primary",
|
|
212
|
+
children: app.name
|
|
213
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
214
|
+
className: "flex shrink-0 items-center gap-1 text-text-secondary",
|
|
215
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
216
|
+
icon: APP_STATUS_ICON[app.status],
|
|
217
|
+
width: 14
|
|
218
|
+
}), statusText[app.status]]
|
|
219
|
+
})]
|
|
220
|
+
}, app.nodeType))
|
|
221
|
+
}) : /* @__PURE__ */ jsx("p", {
|
|
222
|
+
className: "text-xs text-text-secondary",
|
|
223
|
+
children: empty
|
|
224
|
+
})
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/** A titled list of names, or a line saying there are none. */
|
|
228
|
+
function NamesSection({ title, names, empty, testId }) {
|
|
229
|
+
if (names.length === 0 && empty === void 0) return null;
|
|
230
|
+
return /* @__PURE__ */ jsx(Section, {
|
|
231
|
+
title,
|
|
232
|
+
testId,
|
|
233
|
+
children: names.length > 0 ? /* @__PURE__ */ jsx("ul", {
|
|
234
|
+
className: "space-y-1 text-xs text-text-primary",
|
|
235
|
+
children: names.map((name) => /* @__PURE__ */ jsx("li", { children: name }, name))
|
|
236
|
+
}) : /* @__PURE__ */ jsx("p", {
|
|
237
|
+
className: "text-xs text-text-secondary",
|
|
238
|
+
children: empty
|
|
239
|
+
})
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
function ValuesSection({ names }) {
|
|
243
|
+
const tr = useTr();
|
|
244
|
+
const { allowed: canReadValues } = useFluidGridsPermission(FLUIDGRIDS_PERMISSIONS.VARIABLE_READ);
|
|
245
|
+
if (names.length === 0) return null;
|
|
246
|
+
return /* @__PURE__ */ jsx(Section, {
|
|
247
|
+
title: tr("fluidgrids.pages.templatePreview.needsValues", "Workspace values"),
|
|
248
|
+
testId: "template-needs-values",
|
|
249
|
+
children: canReadValues ? /* @__PURE__ */ jsx(WorkspaceValuesCheck, { names }) : /* @__PURE__ */ jsx("p", {
|
|
250
|
+
className: "text-xs text-text-primary",
|
|
251
|
+
children: tr("fluidgrids.pages.templatePreview.needsValuesMissing", "This workflow needs: {{names}}", { names: names.join(", ") })
|
|
252
|
+
})
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function FactsList({ template, stepCount }) {
|
|
256
|
+
const tr = useTr();
|
|
257
|
+
const author = template.authorName || template.publisher?.name || tr("fluidgrids.builder.templateCard.unknownAuthor", "Unknown");
|
|
258
|
+
const price = template.pricingModel === "FREE" ? tr("fluidgrids.builder.templateCard.freeBadge", "Free") : formatTemplatePrice(template.price, template.currency);
|
|
259
|
+
return /* @__PURE__ */ jsxs("dl", {
|
|
260
|
+
className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1.5 border-t border-card-foreground/10 pt-3 text-xs",
|
|
261
|
+
"data-testid": "template-needs-facts",
|
|
262
|
+
children: [
|
|
263
|
+
/* @__PURE__ */ jsx("dt", {
|
|
264
|
+
className: "text-text-secondary",
|
|
265
|
+
children: tr("fluidgrids.pages.templatePreview.factPrice", "Price")
|
|
266
|
+
}),
|
|
267
|
+
/* @__PURE__ */ jsx("dd", {
|
|
268
|
+
className: "text-text-primary",
|
|
269
|
+
children: price
|
|
270
|
+
}),
|
|
271
|
+
/* @__PURE__ */ jsx("dt", {
|
|
272
|
+
className: "text-text-secondary",
|
|
273
|
+
children: tr("fluidgrids.pages.templatePreview.factAuthor", "Made by")
|
|
274
|
+
}),
|
|
275
|
+
/* @__PURE__ */ jsxs("dd", {
|
|
276
|
+
className: "text-text-primary",
|
|
277
|
+
children: [author, template.publisher?.isVerified && /* @__PURE__ */ jsxs("span", {
|
|
278
|
+
className: "ml-1 text-text-secondary",
|
|
279
|
+
children: [
|
|
280
|
+
"(",
|
|
281
|
+
tr("fluidgrids.builder.templateCard.verifiedLabel", "Verified publisher"),
|
|
282
|
+
")"
|
|
283
|
+
]
|
|
284
|
+
})]
|
|
285
|
+
}),
|
|
286
|
+
/* @__PURE__ */ jsx("dt", {
|
|
287
|
+
className: "text-text-secondary",
|
|
288
|
+
children: tr("fluidgrids.pages.templatePreview.factSteps", "Steps")
|
|
289
|
+
}),
|
|
290
|
+
/* @__PURE__ */ jsx("dd", {
|
|
291
|
+
className: "text-text-primary",
|
|
292
|
+
children: stepCount
|
|
293
|
+
}),
|
|
294
|
+
/* @__PURE__ */ jsx("dt", {
|
|
295
|
+
className: "text-text-secondary",
|
|
296
|
+
children: tr("fluidgrids.pages.templatePreview.factUsage", "Used")
|
|
297
|
+
}),
|
|
298
|
+
/* @__PURE__ */ jsx("dd", {
|
|
299
|
+
className: "text-text-primary",
|
|
300
|
+
children: tr("fluidgrids.pages.templatePreview.factUsageValue", "{{downloads}} times · {{views}} views", {
|
|
301
|
+
downloads: COUNT_FORMAT.format(template.downloads ?? 0),
|
|
302
|
+
views: COUNT_FORMAT.format(template.viewCount ?? 0)
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
]
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
function StepsList({ steps }) {
|
|
309
|
+
const tr = useTr();
|
|
310
|
+
if (steps.length === 0) return null;
|
|
311
|
+
return /* @__PURE__ */ jsx(Disclosure, {
|
|
312
|
+
closedLabel: tr("fluidgrids.pages.templatePreview.showSteps", "Show the {{count}} steps", { count: steps.length }),
|
|
313
|
+
openLabel: tr("fluidgrids.pages.templatePreview.hideSteps", "Hide the steps"),
|
|
314
|
+
"data-testid": "template-needs-steps",
|
|
315
|
+
children: /* @__PURE__ */ jsx("ol", {
|
|
316
|
+
className: "list-decimal space-y-0.5 pl-5 text-xs text-text-primary",
|
|
317
|
+
children: steps.map((step) => /* @__PURE__ */ jsx("li", { children: step.name }, step.id))
|
|
318
|
+
})
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
function TemplateNeedsPanel({ template, content, nodeCheck, steps }) {
|
|
322
|
+
const tr = useTr();
|
|
323
|
+
return /* @__PURE__ */ jsxs("aside", {
|
|
324
|
+
className: "flex max-h-[40vh] w-full shrink-0 flex-col gap-4 overflow-y-auto border-b border-card-foreground/10 bg-card p-4 lg:max-h-none lg:w-80 lg:border-b-0 lg:border-l",
|
|
325
|
+
"aria-labelledby": "template-needs-title",
|
|
326
|
+
"data-testid": "template-needs-panel",
|
|
327
|
+
children: [
|
|
328
|
+
/* @__PURE__ */ jsx("h2", {
|
|
329
|
+
id: "template-needs-title",
|
|
330
|
+
className: "text-sm font-semibold text-card-foreground",
|
|
331
|
+
children: tr("fluidgrids.pages.templatePreview.needsTitle", "What you'll need")
|
|
332
|
+
}),
|
|
333
|
+
/* @__PURE__ */ jsx(AppsSection, { nodeCheck }),
|
|
334
|
+
/* @__PURE__ */ jsx(NamesSection, {
|
|
335
|
+
title: tr("fluidgrids.pages.templatePreview.needsAccounts", "Accounts to connect"),
|
|
336
|
+
names: (content?.requiredCredentialTypes ?? []).map(humanizeIdentifier),
|
|
337
|
+
empty: tr("fluidgrids.pages.templatePreview.needsNoAccounts", "No accounts needed"),
|
|
338
|
+
testId: "template-needs-accounts"
|
|
339
|
+
}),
|
|
340
|
+
/* @__PURE__ */ jsx(NamesSection, {
|
|
341
|
+
title: tr("fluidgrids.pages.templatePreview.needsInputs", "You'll be asked for"),
|
|
342
|
+
names: (content?.requiredInputs ?? []).map((input) => input.label || input.name),
|
|
343
|
+
testId: "template-needs-inputs"
|
|
344
|
+
}),
|
|
345
|
+
/* @__PURE__ */ jsx(ValuesSection, { names: templateVariableNames(content?.definitionJson) }),
|
|
346
|
+
/* @__PURE__ */ jsx(FactsList, {
|
|
347
|
+
template,
|
|
348
|
+
stepCount: steps.length
|
|
349
|
+
}),
|
|
350
|
+
/* @__PURE__ */ jsx(StepsList, { steps })
|
|
351
|
+
]
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/utils/template-graph.ts
|
|
356
|
+
/**
|
|
357
|
+
* Extract nodes/edges from a template `content` object.
|
|
358
|
+
* Returns null when the content carries no renderable graph.
|
|
359
|
+
*/
|
|
360
|
+
function extractTemplateGraph(content) {
|
|
361
|
+
const dj = content?.definitionJson;
|
|
362
|
+
if (!dj) return null;
|
|
363
|
+
const graph = dj.data ?? dj;
|
|
364
|
+
const nodes = graph?.nodes ?? [];
|
|
365
|
+
const edges = graph?.edges ?? [];
|
|
366
|
+
if (!nodes.length) return null;
|
|
367
|
+
return {
|
|
368
|
+
nodes,
|
|
369
|
+
edges
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// src/pages/useTemplatePreviewLoad.ts
|
|
374
|
+
/**
|
|
375
|
+
* Loads a store template for the preview page: the product, its content and
|
|
376
|
+
* the graph the read-only canvas draws, or a plain error. With Navigation v2
|
|
377
|
+
* (BOFF-11848) it also works out the apps the template needs, for the "What
|
|
378
|
+
* you'll need" panel: the template's own list when it has one, else from its
|
|
379
|
+
* nodes (as "Use this template" does). The canvas does not wait for that.
|
|
380
|
+
*/
|
|
381
|
+
function useTemplatePreviewLoad(productId, withRequiredNodes) {
|
|
382
|
+
const tr = useTr();
|
|
383
|
+
const { getTemplateDetail, parseTemplateContent } = useImportWorkflowTemplate();
|
|
384
|
+
const [workflow, setWorkflow] = useState(null);
|
|
385
|
+
const [template, setTemplate] = useState(null);
|
|
386
|
+
const [content, setContent] = useState(null);
|
|
387
|
+
const [loading, setLoading] = useState(true);
|
|
388
|
+
const [error, setError] = useState(null);
|
|
389
|
+
const [requiredNodes, setRequiredNodes] = useState(null);
|
|
390
|
+
useEffect(() => {
|
|
391
|
+
let mounted = true;
|
|
392
|
+
const fail = (message) => {
|
|
393
|
+
if (!mounted) return;
|
|
394
|
+
setError(message);
|
|
395
|
+
setLoading(false);
|
|
396
|
+
};
|
|
397
|
+
const loadFailed = () => tr("fluidgrids.pages.templatePreview.errorLoadFailed", "Failed to load template.");
|
|
398
|
+
const load = async () => {
|
|
399
|
+
if (!productId) {
|
|
400
|
+
fail(tr("fluidgrids.pages.templatePreview.errorNoTemplateSpecified", "No template specified."));
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
const full = await getTemplateDetail(productId);
|
|
405
|
+
if (!full) {
|
|
406
|
+
fail(loadFailed());
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const parsed = parseTemplateContent(full);
|
|
410
|
+
const graph = extractTemplateGraph(parsed);
|
|
411
|
+
const nodes = graph?.nodes ?? [];
|
|
412
|
+
const edges = graph?.edges ?? [];
|
|
413
|
+
if (!nodes.length) {
|
|
414
|
+
fail(tr("fluidgrids.pages.templatePreview.errorNoWorkflow", "This template has no workflow to preview."));
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
417
|
+
if (mounted) {
|
|
418
|
+
setTemplate(full);
|
|
419
|
+
setContent(parsed);
|
|
420
|
+
setWorkflow({
|
|
421
|
+
id: productId,
|
|
422
|
+
workflowKey: productId,
|
|
423
|
+
version: "preview",
|
|
424
|
+
name: full.name ?? tr("fluidgrids.pages.templatePreview.fallbackTemplateName", "Template"),
|
|
425
|
+
nodes,
|
|
426
|
+
edges,
|
|
427
|
+
sidebar: {
|
|
428
|
+
active: "none",
|
|
429
|
+
panels: { nodeProperties: { selectedNode: null } }
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
setLoading(false);
|
|
433
|
+
}
|
|
434
|
+
if (withRequiredNodes) {
|
|
435
|
+
const listed = parsed?.requiredNodeTypes ?? [];
|
|
436
|
+
const required = listed.length ? listed : await buildRequiredNodeTypes(nodes).catch(() => []);
|
|
437
|
+
if (mounted) setRequiredNodes(required);
|
|
438
|
+
}
|
|
439
|
+
} catch (e) {
|
|
440
|
+
fail(e instanceof Error ? e.message : loadFailed());
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
load();
|
|
444
|
+
return () => {
|
|
445
|
+
mounted = false;
|
|
446
|
+
};
|
|
447
|
+
}, [
|
|
448
|
+
productId,
|
|
449
|
+
getTemplateDetail,
|
|
450
|
+
parseTemplateContent,
|
|
451
|
+
tr,
|
|
452
|
+
withRequiredNodes
|
|
453
|
+
]);
|
|
454
|
+
return {
|
|
455
|
+
workflow,
|
|
456
|
+
template,
|
|
457
|
+
content,
|
|
458
|
+
loading,
|
|
459
|
+
error,
|
|
460
|
+
requiredNodes
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/pages/TemplatePreview.tsx
|
|
465
|
+
var TemplatePreview_exports = /* @__PURE__ */ __exportAll({ TemplatePreview: () => TemplatePreview });
|
|
466
|
+
/**
|
|
467
|
+
* TemplatePreview — a read-only, n8n-style preview of a store workflow template.
|
|
468
|
+
*
|
|
469
|
+
* It loads the template's `content.definitionJson`, seeds the builder's flow
|
|
470
|
+
* store with the graph, and renders the *real* builder canvas in read-only mode
|
|
471
|
+
* (no dragging/connecting/editing — pan + zoom only). A header shows the
|
|
472
|
+
* template name/description and a "Use this template" CTA that imports the
|
|
473
|
+
* template and opens the editable builder. Nothing is created until the user
|
|
474
|
+
* clicks "Use this template".
|
|
475
|
+
*
|
|
476
|
+
* Navigation v2 (BOFF-11848, FluidGrids only): a "What you'll need" panel
|
|
477
|
+
* beside the canvas (apps and their status, accounts, values, price, author,
|
|
478
|
+
* steps, use counts), the canvas fits the whole template on screen, the badge
|
|
479
|
+
* says nothing is created until Use, and a paid template asks first.
|
|
480
|
+
*/
|
|
481
|
+
/** The read-only badge: today's words, or (v2) why it matters. */
|
|
482
|
+
function PreviewBadge({ plain }) {
|
|
483
|
+
const text = useTr()("fluidgrids.pages.templatePreview.readOnlyBadge", plain ? "Preview — nothing is created until you click Use" : "Preview · read-only");
|
|
484
|
+
return /* @__PURE__ */ jsx("span", {
|
|
485
|
+
className: plain ? "min-w-0 truncate rounded-full bg-card-foreground/10 px-2 py-0.5 text-[11px] font-medium text-muted-foreground" : "shrink-0 rounded-full bg-card-foreground/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground",
|
|
486
|
+
title: plain ? text : void 0,
|
|
487
|
+
"data-testid": "template-preview-badge",
|
|
488
|
+
children: text
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
/** A message in place of the canvas, with the way back to Templates. */
|
|
492
|
+
function PreviewMessage({ message, onBack, icon }) {
|
|
493
|
+
const tr = useTr();
|
|
494
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
495
|
+
className: "flex h-full flex-col items-center justify-center gap-3 p-8 text-center",
|
|
496
|
+
children: [
|
|
497
|
+
icon && /* @__PURE__ */ jsx(Icon, {
|
|
498
|
+
icon,
|
|
499
|
+
className: "size-8 text-muted-foreground"
|
|
500
|
+
}),
|
|
501
|
+
/* @__PURE__ */ jsx("p", {
|
|
502
|
+
className: "text-sm text-muted-foreground",
|
|
503
|
+
children: message
|
|
504
|
+
}),
|
|
505
|
+
/* @__PURE__ */ jsx(Button$1, {
|
|
506
|
+
variant: "outline",
|
|
507
|
+
onClick: onBack,
|
|
508
|
+
children: tr("fluidgrids.pages.templatePreview.backToTemplates", "Back to templates")
|
|
509
|
+
})
|
|
510
|
+
]
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
function PreviewLoading() {
|
|
514
|
+
const tr = useTr();
|
|
515
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
516
|
+
className: "flex h-full items-center justify-center gap-2 text-sm text-muted-foreground",
|
|
517
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
518
|
+
icon: "svg-spinners:ring-resize",
|
|
519
|
+
className: "size-4"
|
|
520
|
+
}), tr("fluidgrids.pages.templatePreview.loadingPreview", "Loading preview…")]
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
function TemplatePreview() {
|
|
524
|
+
const { productId } = useParams();
|
|
525
|
+
const navigate = useNavigate();
|
|
526
|
+
const location = useLocation();
|
|
527
|
+
const tr = useTr();
|
|
528
|
+
const v2 = useNavigationV2();
|
|
529
|
+
const { installedAppIds } = useInstalledNodes();
|
|
530
|
+
const { workflow, template, content, loading, error, requiredNodes } = useTemplatePreviewLoad(productId, v2);
|
|
531
|
+
const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);
|
|
532
|
+
const [confirmPaid, setConfirmPaid] = useState(false);
|
|
533
|
+
const workflowsBase = location.pathname.replace(/\/templates(\/.*)?$/, "");
|
|
534
|
+
const nodeCheck = useMemo(() => requiredNodes ? buildNodeCheck(requiredNodes, installedAppIds) : null, [requiredNodes, installedAppIds]);
|
|
535
|
+
const steps = useMemo(() => templateSteps(workflow?.nodes ?? []), [workflow]);
|
|
536
|
+
const templateImport = useTemplateImportFlow({
|
|
537
|
+
onImported: (created) => navigate(`${workflowsBase}/workflow/${created.workflowKey}/${created.version}`),
|
|
538
|
+
onQuotaExhausted: () => setShowQuotaExhausted(true)
|
|
539
|
+
});
|
|
540
|
+
const importing = templateImport.busy;
|
|
541
|
+
const handleUse = () => {
|
|
542
|
+
if (!template) return;
|
|
543
|
+
if (v2 && isPaidTemplate(template)) {
|
|
544
|
+
setConfirmPaid(true);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
templateImport.start(template);
|
|
548
|
+
};
|
|
549
|
+
const backToTemplates = () => navigate(`${workflowsBase}/templates`);
|
|
550
|
+
return /* @__PURE__ */ jsxs(ThemeProvider, { children: [
|
|
551
|
+
/* @__PURE__ */ jsxs("div", {
|
|
552
|
+
className: "flex h-full w-full flex-col overflow-hidden",
|
|
553
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
554
|
+
className: "flex h-14 shrink-0 items-center justify-between gap-3 border-b border-card-foreground/10 bg-gradient-to-r from-primary/40 to-transparent px-3",
|
|
555
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
556
|
+
className: "flex min-w-0 items-center gap-2",
|
|
557
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
558
|
+
type: "button",
|
|
559
|
+
onClick: backToTemplates,
|
|
560
|
+
title: tr("fluidgrids.pages.templatePreview.backTooltip", "Back to templates"),
|
|
561
|
+
className: "flex size-9 shrink-0 items-center justify-center rounded-md text-card-foreground transition-colors hover:bg-card-foreground/10",
|
|
562
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
563
|
+
icon: "ion:arrow-back-outline",
|
|
564
|
+
className: "size-5"
|
|
565
|
+
})
|
|
566
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
567
|
+
className: "min-w-0",
|
|
568
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
569
|
+
className: "flex items-center gap-2",
|
|
570
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
571
|
+
className: "truncate text-sm font-semibold text-card-foreground",
|
|
572
|
+
children: workflow?.name ?? template?.name ?? tr("fluidgrids.pages.templatePreview.fallbackHeaderTitle", "Template preview")
|
|
573
|
+
}), /* @__PURE__ */ jsx(PreviewBadge, { plain: v2 })]
|
|
574
|
+
}), template?.description ? /* @__PURE__ */ jsx("span", {
|
|
575
|
+
className: "block truncate text-xs text-muted-foreground",
|
|
576
|
+
children: template.description
|
|
577
|
+
}) : null]
|
|
578
|
+
})]
|
|
579
|
+
}), /* @__PURE__ */ jsx(WithOpenTemplateAsCode, {
|
|
580
|
+
templateName: template ? template.name : null,
|
|
581
|
+
content,
|
|
582
|
+
className: "shrink-0",
|
|
583
|
+
wrapperClassName: "flex shrink-0 items-center gap-2",
|
|
584
|
+
children: /* @__PURE__ */ jsx(SdkPermissionButton, {
|
|
585
|
+
permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_CREATE,
|
|
586
|
+
deniedTooltip: tr("fluidgrids.templates.useDeniedTooltip", "You don't have permission to create workflows from templates"),
|
|
587
|
+
children: /* @__PURE__ */ jsxs(Button$1, {
|
|
588
|
+
onClick: handleUse,
|
|
589
|
+
disabled: importing || !template,
|
|
590
|
+
className: "shrink-0 gap-2",
|
|
591
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
592
|
+
icon: importing ? "svg-spinners:ring-resize" : "mdi:plus",
|
|
593
|
+
className: "size-4"
|
|
594
|
+
}), tr("fluidgrids.pages.templatePreview.useThisTemplate", "Use this template")]
|
|
595
|
+
})
|
|
596
|
+
})
|
|
597
|
+
})]
|
|
598
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
599
|
+
className: v2 ? "flex min-h-0 w-full flex-1 flex-col lg:flex-row-reverse" : "contents",
|
|
600
|
+
children: [v2 && template && workflow && /* @__PURE__ */ jsx(TemplateNeedsPanel, {
|
|
601
|
+
template,
|
|
602
|
+
content,
|
|
603
|
+
nodeCheck,
|
|
604
|
+
steps
|
|
605
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
606
|
+
className: "relative min-h-0 w-full flex-1",
|
|
607
|
+
children: /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
608
|
+
fallback: () => /* @__PURE__ */ jsx(PreviewMessage, {
|
|
609
|
+
message: tr("fluidgrids.pages.templatePreview.renderErrorMessage", "Something went wrong rendering this template preview."),
|
|
610
|
+
onBack: backToTemplates
|
|
611
|
+
}),
|
|
612
|
+
children: loading ? /* @__PURE__ */ jsx(PreviewLoading, {}) : error ? /* @__PURE__ */ jsx(PreviewMessage, {
|
|
613
|
+
icon: "mdi:alert-circle-outline",
|
|
614
|
+
message: error,
|
|
615
|
+
onBack: backToTemplates
|
|
616
|
+
}) : workflow ? /* @__PURE__ */ jsx(FlowBuilderPage, {
|
|
617
|
+
workflow,
|
|
618
|
+
readOnly: true,
|
|
619
|
+
fitToScreen: v2
|
|
620
|
+
}) : null
|
|
621
|
+
})
|
|
622
|
+
})]
|
|
623
|
+
})]
|
|
624
|
+
}),
|
|
625
|
+
templateImport.dialog,
|
|
626
|
+
/* @__PURE__ */ jsx(PaidTemplateConfirm, {
|
|
627
|
+
template: confirmPaid ? template : null,
|
|
628
|
+
onConfirm: () => {
|
|
629
|
+
setConfirmPaid(false);
|
|
630
|
+
if (template) templateImport.start(template);
|
|
631
|
+
},
|
|
632
|
+
onCancel: () => setConfirmPaid(false)
|
|
633
|
+
}),
|
|
634
|
+
/* @__PURE__ */ jsx(QuotaExhaustedDialog, {
|
|
635
|
+
surface: "template-import",
|
|
636
|
+
open: showQuotaExhausted,
|
|
637
|
+
onOpenChange: setShowQuotaExhausted,
|
|
638
|
+
onUpgrade: () => {
|
|
639
|
+
setShowQuotaExhausted(false);
|
|
640
|
+
navigate(BILLING_PLANS_PATH);
|
|
641
|
+
}
|
|
642
|
+
})
|
|
643
|
+
] });
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
export { TemplatePreview_exports as n, extractTemplateGraph as r, TemplatePreview as t };
|