@burdenoff/fluidgrids-fe-sdk 2026.1111.17 → 2026.1111.19
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-kJHSsIcj.js → AiStudioPage-htYcXz43.js} +2 -2
- package/dist/{MissingNodesInstallModal-CMybsI8h.js → MissingNodesInstallModal-Dly7T2_7.js} +1 -1
- package/dist/{SettingsPage-CgkRlCM5.js → SettingsPage-CJLZvv4J.js} +1485 -1484
- package/dist/{TemplateCard-DsC0KNH1.js → TemplateCard-BdB087SP.js} +47 -11
- package/dist/{TemplateConfigurationModal-BhGWIzpm.js → TemplateConfigurationModal-CPVcTDSi.js} +1 -1
- package/dist/{TemplateDetailPanel-D4cUVr-m.js → TemplateDetailPanel-DruadMkg.js} +1 -1
- package/dist/{TemplatePreview-GthzCOSo.js → TemplatePreview-CNrYJXw2.js} +2 -2
- package/dist/{TemplatesPage-CsDNT54N.js → TemplatesPage-BU4tSqOo.js} +1 -1
- package/dist/{WorkflowBuilder-DEi_9YOb.js → WorkflowBuilder-BSPGcOfA.js} +2 -2
- package/dist/{WorkflowBuilder-iPqXgbYr.js → WorkflowBuilder-DMonxuoY.js} +4 -4
- package/dist/WorkflowShareDialog-mbIwRQUY.js +168 -0
- package/dist/{WorkflowsList-CA20dVIl.js → WorkflowsList-DiiGyZkT.js} +2 -1
- package/dist/{agentTools-CkRJB7r5.js → agentTools-C7pdNJqE.js} +2 -2
- package/dist/{canvasNoteTools-CQIc7Oxg.js → canvasNoteTools-CqiPTBa1.js} +1 -1
- package/dist/code-editor-field-9-GdVE_8.js +111 -0
- package/dist/{flow-builder-y2Y1iG4Y.js → flow-builder-CV5Zu_Hq.js} +246 -8639
- package/dist/{index-W2o__Nm6.d.ts → index-6JR2vD9J.d.ts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -13
- package/dist/{node-detail-view-B91kXzIy.js → node-detail-view-ttMp6H6K.js} +4 -2
- package/dist/node-editor-tab-body-Bqb--pZy.js +174 -0
- package/dist/observability.d.ts +1 -1
- package/dist/popover-BbVOHsfO.js +472 -0
- package/dist/{quick-config-panel-DggPl1vY.js → quick-config-panel-Da4uOVSs.js} +2 -1
- package/dist/schedule-panel-DnFN933b.js +7542 -0
- package/dist/settings.js +1 -1
- package/dist/sidebar-node-editor-lcnIZxdR.js +177 -0
- package/dist/templates.js +2 -2
- package/dist/{useAgentDefinitions-Dpz0HDTq.js → useAgentDefinitions-B0dam3_o.js} +1 -396
- package/dist/useConnections-Cs7LCWEM.js +401 -0
- package/dist/{WorkflowShareDialog-B_gn968c.js → useWorkflowCodeExport-Bu2QYJzA.js} +4 -161
- package/dist/workflow-builder.js +2 -2
- package/dist/workflow-pages.d.ts +1 -1
- package/dist/workflow-pages.js +6 -6
- package/dist/workflows-list.js +1 -1
- package/package.json +1 -1
|
@@ -1052,8 +1052,34 @@ function buildNodeCheck(requiredNodeTypes, installedAppIds) {
|
|
|
1052
1052
|
};
|
|
1053
1053
|
}
|
|
1054
1054
|
|
|
1055
|
+
// src/utils/dismiss-toast.ts
|
|
1056
|
+
/** Resolves on the next zero-delay timer. */
|
|
1057
|
+
function nextTimer() {
|
|
1058
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Dismiss a toast that may have been created a moment ago.
|
|
1062
|
+
*
|
|
1063
|
+
* sonner adds a toast to the screen on a zero-delay timer, but delivers a
|
|
1064
|
+
* dismissal on animation frames. A dismissal sent while the add is still
|
|
1065
|
+
* queued (the work finished fast, or the main thread was busy rendering) is
|
|
1066
|
+
* applied first, finds nothing to remove, and the toast then appears and
|
|
1067
|
+
* stays: "Loading template..." stuck on the template preview page
|
|
1068
|
+
* (BOFF-11153). Timers of equal delay fire in the order they were set, so
|
|
1069
|
+
* waiting one zero-delay timer runs after the queued add, and the dismissal
|
|
1070
|
+
* then lands on the toast.
|
|
1071
|
+
*
|
|
1072
|
+
* Where a toast is followed by another message, replace it through the same
|
|
1073
|
+
* `id` instead (`toast.success(…, { id })`); that goes through the same
|
|
1074
|
+
* queue as the add and needs no dismissal.
|
|
1075
|
+
*/
|
|
1076
|
+
async function dismissToastWhenShown(id) {
|
|
1077
|
+
await nextTimer();
|
|
1078
|
+
toast.dismiss(id);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1055
1081
|
// src/hooks/store/useTemplateImportFlow.tsx
|
|
1056
|
-
const LazyTemplateConfigurationModal = lazy(() => import("./TemplateConfigurationModal-
|
|
1082
|
+
const LazyTemplateConfigurationModal = lazy(() => import("./TemplateConfigurationModal-CPVcTDSi.js").then((m) => ({ default: m.TemplateConfigurationModal })));
|
|
1057
1083
|
/**
|
|
1058
1084
|
* "Use this template", the same everywhere it is offered: the builder's
|
|
1059
1085
|
* template panel, the Templates page and the template preview page
|
|
@@ -1109,9 +1135,11 @@ function useTemplateImportFlow({ onImported, onQuotaExhausted }) {
|
|
|
1109
1135
|
name: overrides?.name,
|
|
1110
1136
|
templateInputs: overrides?.templateInputs
|
|
1111
1137
|
});
|
|
1112
|
-
toast.dismiss("template-import");
|
|
1113
1138
|
if (result.success && result.workflow) {
|
|
1114
|
-
toast.success(tr("fluidgrids.builder.desktopSidebar.workflowCreatedToast", "Workflow created from template!"), {
|
|
1139
|
+
toast.success(tr("fluidgrids.builder.desktopSidebar.workflowCreatedToast", "Workflow created from template!"), {
|
|
1140
|
+
id: "template-import",
|
|
1141
|
+
description: `"${result.workflow.name}" is ready to edit`
|
|
1142
|
+
});
|
|
1115
1143
|
if ((content.requiredCredentialTypes?.length ?? 0) > 0) toast.info(tr("fluidgrids.builder.desktopSidebar.credentialsNeededToast", "Credentials needed"), {
|
|
1116
1144
|
description: `Configure ${content.requiredCredentialTypes?.join(", ")} in the Credentials page`,
|
|
1117
1145
|
duration: 6e3
|
|
@@ -1120,14 +1148,20 @@ function useTemplateImportFlow({ onImported, onQuotaExhausted }) {
|
|
|
1120
1148
|
return true;
|
|
1121
1149
|
}
|
|
1122
1150
|
if (onQuotaExhausted && isQuotaExhaustedFailure(result.error?.cause ?? result.error)) {
|
|
1151
|
+
dismissToastWhenShown("template-import");
|
|
1123
1152
|
onQuotaExhausted();
|
|
1124
1153
|
return false;
|
|
1125
1154
|
}
|
|
1126
|
-
toast.error(tr("fluidgrids.builder.desktopSidebar.importTemplateErrorToast", "Failed to import template"), {
|
|
1155
|
+
toast.error(tr("fluidgrids.builder.desktopSidebar.importTemplateErrorToast", "Failed to import template"), {
|
|
1156
|
+
id: "template-import",
|
|
1157
|
+
description: result.message || tr("fluidgrids.builder.desktopSidebar.importTemplateErrorFallback", "Unknown error during import")
|
|
1158
|
+
});
|
|
1127
1159
|
return false;
|
|
1128
1160
|
} catch (err) {
|
|
1129
|
-
toast.
|
|
1130
|
-
|
|
1161
|
+
toast.error(tr("fluidgrids.builder.desktopSidebar.importFailedToast", "Import failed"), {
|
|
1162
|
+
id: "template-import",
|
|
1163
|
+
description: err instanceof Error ? err.message : tr("fluidgrids.builder.desktopSidebar.importFailedFallback", "Unknown error")
|
|
1164
|
+
});
|
|
1131
1165
|
return false;
|
|
1132
1166
|
} finally {
|
|
1133
1167
|
setInstallProgress(null);
|
|
@@ -1145,16 +1179,16 @@ function useTemplateImportFlow({ onImported, onQuotaExhausted }) {
|
|
|
1145
1179
|
toast.loading(tr("fluidgrids.builder.desktopSidebar.loadingTemplateToast", "Loading template..."), { id: "template-load" });
|
|
1146
1180
|
try {
|
|
1147
1181
|
const full = await getTemplateDetail(template.id);
|
|
1148
|
-
toast.dismiss("template-load");
|
|
1149
1182
|
if (!full) {
|
|
1150
|
-
toast.error(tr("fluidgrids.builder.desktopSidebar.templateDetailsErrorToast", "Failed to load template details"));
|
|
1183
|
+
toast.error(tr("fluidgrids.builder.desktopSidebar.templateDetailsErrorToast", "Failed to load template details"), { id: "template-load" });
|
|
1151
1184
|
return;
|
|
1152
1185
|
}
|
|
1153
1186
|
const content = await resolveTemplateContent(full, buildRequiredNodeTypes);
|
|
1154
1187
|
if (!content) {
|
|
1155
|
-
toast.error(tr("fluidgrids.builder.desktopSidebar.invalidTemplateDataToast", "Template does not contain valid workflow data"));
|
|
1188
|
+
toast.error(tr("fluidgrids.builder.desktopSidebar.invalidTemplateDataToast", "Template does not contain valid workflow data"), { id: "template-load" });
|
|
1156
1189
|
return;
|
|
1157
1190
|
}
|
|
1191
|
+
await dismissToastWhenShown("template-load");
|
|
1158
1192
|
const nodeCheck = buildNodeCheck(content.requiredNodeTypes ?? [], installedAppIds);
|
|
1159
1193
|
if (needsTemplateConfiguration(content, nodeCheck)) {
|
|
1160
1194
|
setPending({
|
|
@@ -1166,8 +1200,10 @@ function useTemplateImportFlow({ onImported, onQuotaExhausted }) {
|
|
|
1166
1200
|
}
|
|
1167
1201
|
await createCopy(full, content, nodeCheck);
|
|
1168
1202
|
} catch (err) {
|
|
1169
|
-
toast.
|
|
1170
|
-
|
|
1203
|
+
toast.error(tr("fluidgrids.builder.desktopSidebar.genericErrorToast", "Something went wrong"), {
|
|
1204
|
+
id: "template-load",
|
|
1205
|
+
description: err instanceof Error ? err.message : tr("fluidgrids.builder.desktopSidebar.genericErrorFallback", "Failed to process template")
|
|
1206
|
+
});
|
|
1171
1207
|
} finally {
|
|
1172
1208
|
setBusy(false);
|
|
1173
1209
|
}
|
package/dist/{TemplateConfigurationModal-BhGWIzpm.js → TemplateConfigurationModal-CPVcTDSi.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { a as DialogFooter, d as Input, i as DialogDescription, l as DialogTitle, o as DialogHeader, r as DialogContent, t as Dialog } from "./dialog-Cjb4lB4D.js";
|
|
3
3
|
import { t as Button } from "./button-DG7y_FVJ.js";
|
|
4
|
-
import { r as Badge } from "./TemplateCard-
|
|
4
|
+
import { r as Badge } from "./TemplateCard-BdB087SP.js";
|
|
5
5
|
import { t as Label } from "./label-CDy86rIZ.js";
|
|
6
6
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
7
7
|
import { useEffect, useMemo, useState } from "react";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as Button } from "./button-DG7y_FVJ.js";
|
|
3
|
-
import { n as templatePreview, r as Badge } from "./TemplateCard-
|
|
3
|
+
import { n as templatePreview, r as Badge } from "./TemplateCard-BdB087SP.js";
|
|
4
4
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
5
5
|
import { i as SdkPermissionButton, t as FLUIDGRIDS_PERMISSIONS } from "./constants-B2lhWNoN.js";
|
|
6
6
|
import { Icon } from "@iconify/react";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
3
|
import { t as ThemeProvider } from "./theme-provider-B3mIuz2d.js";
|
|
4
|
-
import { t as FlowBuilderPage } from "./flow-builder-
|
|
5
|
-
import { a as useTemplateImportFlow, l as useImportWorkflowTemplate } from "./TemplateCard-
|
|
4
|
+
import { t as FlowBuilderPage } from "./flow-builder-CV5Zu_Hq.js";
|
|
5
|
+
import { a as useTemplateImportFlow, l as useImportWorkflowTemplate } from "./TemplateCard-BdB087SP.js";
|
|
6
6
|
import { t as QuotaExhaustedDialog } from "./QuotaExhaustedDialog-7IFSaLyi.js";
|
|
7
7
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
8
8
|
import { i as SdkPermissionButton, t as FLUIDGRIDS_PERMISSIONS } from "./constants-B2lhWNoN.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
3
|
import { h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, s as useDuplicateWorkflow } from "./useWorkflows-BlVVu8NM.js";
|
|
4
|
-
import { a as useTemplateImportFlow, t as TemplateCard, u as useWorkflowTemplates, y as useGlobalStoreClient } from "./TemplateCard-
|
|
4
|
+
import { a as useTemplateImportFlow, t as TemplateCard, u as useWorkflowTemplates, y as useGlobalStoreClient } from "./TemplateCard-BdB087SP.js";
|
|
5
5
|
import { YF as WorkflowStatus } from "./graphql-types-CDKVWH2R.js";
|
|
6
6
|
import { i as SdkPermissionButton, t as FLUIDGRIDS_PERMISSIONS } from "./constants-B2lhWNoN.js";
|
|
7
7
|
import { t as QuotaExhaustedDialog } from "./QuotaExhaustedDialog-7IFSaLyi.js";
|
|
@@ -3,10 +3,10 @@ import { hn as useCanvasEdges, n as FluidGridsProvider } from "./FluidGridsProvi
|
|
|
3
3
|
import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
4
4
|
import { t as Button } from "./button-DG7y_FVJ.js";
|
|
5
5
|
import { d as Input } from "./dialog-Cjb4lB4D.js";
|
|
6
|
-
import { b as Card } from "./TemplateCard-
|
|
6
|
+
import { b as Card } from "./TemplateCard-BdB087SP.js";
|
|
7
7
|
import { t as cn } from "./cn-QqidFIgr.js";
|
|
8
8
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
9
|
-
import {
|
|
9
|
+
import { S as FluidGridsMark, x as useNodeSelectedEvent } from "./flow-builder-CV5Zu_Hq.js";
|
|
10
10
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
11
11
|
import { Background, Controls, Handle, MarkerType, MiniMap, Position, ReactFlow, ReactFlowProvider, useReactFlow } from "@xyflow/react";
|
|
12
12
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
|
-
import {
|
|
3
|
+
import { g as useWorkflowReloadStore, h as releaseLeaseKeptForReload, t as FlowBuilderPage } from "./flow-builder-CV5Zu_Hq.js";
|
|
4
4
|
import { n as registerLiveCanvasHandler } from "./liveCanvas-D5ytXDp8.js";
|
|
5
5
|
import { _ as throwIfResultError, n as getFluidGridsClient, x as getFluidGridsConfig } from "./client-C9XSzSXr.js";
|
|
6
6
|
import { Er as WorkflowDefinitionDocument } from "./graphql-operation-types-kX-MMjgW.js";
|
|
@@ -9,10 +9,10 @@ import { At as useSaveStatusStore, Et as classifyCreateRefusal, J as paramsFromO
|
|
|
9
9
|
import { F as mergeStickyNotes, H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
10
10
|
import { t as canvasFromDefinition } from "./definition-canvas--3MPHoP-.js";
|
|
11
11
|
import { l as useLazyWorkflowDefinition, n as useCreateWorkflow } from "./useWorkflows-BlVVu8NM.js";
|
|
12
|
-
import { c as getWorkflowNodeTypes, o as buildNodeCheck, s as buildRequiredNodeTypes, v as useInstalledNodes } from "./TemplateCard-
|
|
12
|
+
import { c as getWorkflowNodeTypes, o as buildNodeCheck, s as buildRequiredNodeTypes, v as useInstalledNodes } from "./TemplateCard-BdB087SP.js";
|
|
13
13
|
import { c as withoutGuidedTourIntent, l as decideMissingWorkflow, o as isGuidedTourIntent, s as pickGuidedTour, u as isCreateIntent } from "./firstWorkflow-C_h0KMB2.js";
|
|
14
14
|
import { f as BILLING_PLANS_PATH } from "./fluidgridsEvents-CNdcrUNN.js";
|
|
15
|
-
import {
|
|
15
|
+
import { T as CreateWorkflowRefusalDialog } from "./useWorkflowCodeExport-Bu2QYJzA.js";
|
|
16
16
|
import { Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
17
|
import { useLocation, useNavigate, useParams } from "react-router";
|
|
18
18
|
import { Icon } from "@iconify/react";
|
|
@@ -1088,7 +1088,7 @@ function GuidedTourStarter({ ready }) {
|
|
|
1088
1088
|
}
|
|
1089
1089
|
|
|
1090
1090
|
// src/builder/app/workflow/work/page.tsx
|
|
1091
|
-
const LazyMissingNodesInstallModal = lazy(() => import("./MissingNodesInstallModal-
|
|
1091
|
+
const LazyMissingNodesInstallModal = lazy(() => import("./MissingNodesInstallModal-Dly7T2_7.js").then((m) => ({ default: m.MissingNodesInstallModal })));
|
|
1092
1092
|
function WorkflowItem({ readonly = false }) {
|
|
1093
1093
|
if (readonly) {
|
|
1094
1094
|
const queryParams = new URLSearchParams(window.location.search);
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
|
+
import { n as getFluidGridsClient } from "./client-C9XSzSXr.js";
|
|
4
|
+
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
5
|
+
import { JF as WorkflowShareRole, hF as WorkflowAccess, nI as WorkflowVisibility, qF as WorkflowSharePrincipalType } from "./graphql-types-CDKVWH2R.js";
|
|
6
|
+
import { Mn as ShareWorkflowDocument, li as WorkflowSharingDocument } from "./graphql-operation-types-kX-MMjgW.js";
|
|
7
|
+
import { useMemo } from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
import { ResourceShareDialog, createSharePrincipalLister } from "@burdenoff/fe-libs/connections";
|
|
10
|
+
|
|
11
|
+
// src/utils/workflow-sharing.ts
|
|
12
|
+
/** Whether someone reaching a workflow this way may change who it is shared with. */
|
|
13
|
+
function canShareWorkflow(access) {
|
|
14
|
+
return access === "OWNER" || access === "EDITOR" || access === "ADMINISTRATOR";
|
|
15
|
+
}
|
|
16
|
+
/** Whether someone reaching a workflow this way may change or run it. */
|
|
17
|
+
function canEditWorkflow(access) {
|
|
18
|
+
return access !== "VIEWER";
|
|
19
|
+
}
|
|
20
|
+
const VISIBILITY_OUT = {
|
|
21
|
+
WORKSPACE: "WORKSPACE",
|
|
22
|
+
RESTRICTED: "RESTRICTED"
|
|
23
|
+
};
|
|
24
|
+
const VISIBILITY_IN = {
|
|
25
|
+
["WORKSPACE"]: "WORKSPACE",
|
|
26
|
+
["RESTRICTED"]: "RESTRICTED"
|
|
27
|
+
};
|
|
28
|
+
const PRINCIPAL_OUT = {
|
|
29
|
+
USER: "USER",
|
|
30
|
+
GROUP: "GROUP",
|
|
31
|
+
PROJECT: "PROJECT"
|
|
32
|
+
};
|
|
33
|
+
const PRINCIPAL_IN = {
|
|
34
|
+
["USER"]: "USER",
|
|
35
|
+
["GROUP"]: "GROUP",
|
|
36
|
+
["PROJECT"]: "PROJECT"
|
|
37
|
+
};
|
|
38
|
+
const ROLE_OUT = {
|
|
39
|
+
VIEWER: "VIEWER",
|
|
40
|
+
EDITOR: "EDITOR"
|
|
41
|
+
};
|
|
42
|
+
const ROLE_IN = {
|
|
43
|
+
["VIEWER"]: "VIEWER",
|
|
44
|
+
["EDITOR"]: "EDITOR"
|
|
45
|
+
};
|
|
46
|
+
/** The service's answer as the dialog sees it; `name` is what the title shows. */
|
|
47
|
+
function toResourceSharing(sharing, name = sharing.workflowKey) {
|
|
48
|
+
const shares = sharing.shares.map((share) => ({
|
|
49
|
+
principalType: PRINCIPAL_IN[share.principalType],
|
|
50
|
+
principalId: share.principalId,
|
|
51
|
+
role: ROLE_IN[share.role]
|
|
52
|
+
}));
|
|
53
|
+
return {
|
|
54
|
+
id: sharing.workflowKey,
|
|
55
|
+
name,
|
|
56
|
+
ownerId: sharing.ownerId ?? "",
|
|
57
|
+
visibility: VISIBILITY_IN[sharing.visibility],
|
|
58
|
+
canManage: canShareWorkflow(sharing.myAccess),
|
|
59
|
+
administrator: sharing.canTransferOwnership,
|
|
60
|
+
shares
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** The workflow service behind the generic Share dialog. */
|
|
64
|
+
function workflowSharingApi(client, listPrincipals) {
|
|
65
|
+
return {
|
|
66
|
+
async getSharing(workflowKey) {
|
|
67
|
+
const result = await client.query({
|
|
68
|
+
query: WorkflowSharingDocument,
|
|
69
|
+
variables: { workflowKey },
|
|
70
|
+
fetchPolicy: "network-only"
|
|
71
|
+
});
|
|
72
|
+
if (!result.data) throw new Error("Workflow not found");
|
|
73
|
+
return toResourceSharing(result.data.workflowSharing);
|
|
74
|
+
},
|
|
75
|
+
listPrincipals,
|
|
76
|
+
async share(input) {
|
|
77
|
+
const result = await client.mutate({
|
|
78
|
+
mutation: ShareWorkflowDocument,
|
|
79
|
+
variables: { input: {
|
|
80
|
+
workflowKey: input.resourceId,
|
|
81
|
+
visibility: VISIBILITY_OUT[input.visibility],
|
|
82
|
+
shares: input.shares.map((share) => ({
|
|
83
|
+
principalType: PRINCIPAL_OUT[share.principalType],
|
|
84
|
+
principalId: share.principalId,
|
|
85
|
+
role: ROLE_OUT[share.role]
|
|
86
|
+
})),
|
|
87
|
+
...input.ownerId ? { ownerId: input.ownerId } : {}
|
|
88
|
+
} }
|
|
89
|
+
});
|
|
90
|
+
if (!result.data) throw new Error("Workflow not found");
|
|
91
|
+
return toResourceSharing(result.data.shareWorkflow);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/components/WorkflowShareDialog.tsx
|
|
97
|
+
/**
|
|
98
|
+
* WorkflowShareDialog — who can reach a workflow (BOFF-9726).
|
|
99
|
+
*
|
|
100
|
+
* The workflow version of fe-libs' ResourceShareDialog: a workflow is shared
|
|
101
|
+
* with people, groups or workspace projects as "Can view" or "Can edit", or
|
|
102
|
+
* left to the whole workspace. The workflow service decides who may change
|
|
103
|
+
* the sharing (its owner, an editor it is shared with, or a workspace admin)
|
|
104
|
+
* and answers NOT_FOUND to anyone else; this dialog only shows what the
|
|
105
|
+
* caller may do and sends the complete new sharing back.
|
|
106
|
+
*/
|
|
107
|
+
var WorkflowShareDialog_exports = /* @__PURE__ */ __exportAll({ WorkflowShareDialog: () => WorkflowShareDialog });
|
|
108
|
+
function workflowShareCopy(tr, name) {
|
|
109
|
+
return {
|
|
110
|
+
title: (loaded) => tr("fluidgrids.sharing.title", "Share {{name}}", { name: name || loaded }),
|
|
111
|
+
titleLoading: tr("fluidgrids.sharing.titleLoading", "Share workflow"),
|
|
112
|
+
loading: tr("fluidgrids.sharing.loading", "Loading sharing…"),
|
|
113
|
+
readOnly: tr("fluidgrids.sharing.readOnly", "Only the owner, editors and workspace admins can change who can open this workflow."),
|
|
114
|
+
save: tr("fluidgrids.sharing.save", "Save"),
|
|
115
|
+
cancel: tr("fluidgrids.sharing.cancel", "Cancel"),
|
|
116
|
+
close: tr("fluidgrids.sharing.close", "Close"),
|
|
117
|
+
owner: tr("fluidgrids.sharing.owner", "Owner"),
|
|
118
|
+
add: tr("fluidgrids.sharing.add", "Share with people, groups or projects"),
|
|
119
|
+
addPlaceholder: tr("fluidgrids.sharing.addPlaceholder", "Search by name or email"),
|
|
120
|
+
sharedWith: tr("fluidgrids.sharing.sharedWith", "Shared with"),
|
|
121
|
+
onlyOwner: tr("fluidgrids.sharing.onlyOwner", "No one else yet. Only the owner and workspace admins can open it."),
|
|
122
|
+
none: tr("fluidgrids.sharing.none", "No one in particular."),
|
|
123
|
+
principalType: {
|
|
124
|
+
USER: tr("fluidgrids.sharing.type.user", "Person"),
|
|
125
|
+
GROUP: tr("fluidgrids.sharing.type.group", "Group"),
|
|
126
|
+
PROJECT: tr("fluidgrids.sharing.type.project", "Project")
|
|
127
|
+
},
|
|
128
|
+
roleFor: (grantee) => tr("fluidgrids.sharing.roleFor", "Access for {{name}}", { name: grantee }),
|
|
129
|
+
remove: (grantee) => tr("fluidgrids.sharing.remove", "Stop sharing with {{name}}", { name: grantee }),
|
|
130
|
+
visibility: {
|
|
131
|
+
legend: tr("fluidgrids.sharing.visibility.label", "Who can open this workflow"),
|
|
132
|
+
restricted: tr("fluidgrids.sharing.visibility.restricted", "Only people I choose"),
|
|
133
|
+
restrictedHint: tr("fluidgrids.sharing.visibility.restrictedHint", "You, the people, groups or projects you share it with, and workspace admins. Everyone else cannot find it."),
|
|
134
|
+
workspace: tr("fluidgrids.sharing.visibility.workspace", "Everyone in this workspace"),
|
|
135
|
+
workspaceHint: tr("fluidgrids.sharing.visibility.workspaceHint", "Anyone in the workspace can open it, as their workspace role allows.")
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function WorkflowShareDialog({ open, onClose, workflowKey, workflowName, workspaceId, client, onShared, api: apiOverride }) {
|
|
140
|
+
const tr = useTr();
|
|
141
|
+
const api = useMemo(() => {
|
|
142
|
+
if (apiOverride) return apiOverride;
|
|
143
|
+
const apollo = client ?? getFluidGridsClient();
|
|
144
|
+
return workflowSharingApi(apollo, createSharePrincipalLister(apollo));
|
|
145
|
+
}, [apiOverride, client]);
|
|
146
|
+
const copy = useMemo(() => workflowShareCopy(tr, workflowName), [tr, workflowName]);
|
|
147
|
+
const roles = useMemo(() => [{
|
|
148
|
+
value: "VIEWER",
|
|
149
|
+
label: tr("fluidgrids.sharing.role.viewer", "Can view")
|
|
150
|
+
}, {
|
|
151
|
+
value: "EDITOR",
|
|
152
|
+
label: tr("fluidgrids.sharing.role.editor", "Can edit")
|
|
153
|
+
}], [tr]);
|
|
154
|
+
return /* @__PURE__ */ jsx(ResourceShareDialog, {
|
|
155
|
+
open,
|
|
156
|
+
onClose,
|
|
157
|
+
api,
|
|
158
|
+
resourceId: workflowKey,
|
|
159
|
+
workspaceId,
|
|
160
|
+
roles,
|
|
161
|
+
copy,
|
|
162
|
+
testIdPrefix: "share-workflow",
|
|
163
|
+
translate: tr,
|
|
164
|
+
onShared: onShared ? () => onShared() : void 0
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export { canShareWorkflow as i, WorkflowShareDialog_exports as n, canEditWorkflow as r, WorkflowShareDialog as t };
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
3
|
import { c as useImportWorkflow, h as useWorkflowDefinitions, l as useLazyWorkflowDefinition, n as useCreateWorkflow, o as useDeleteWorkflow, s as useDuplicateWorkflow, u as usePreviewN8nImport } from "./useWorkflows-BlVVu8NM.js";
|
|
4
4
|
import { Dt as createThenOpen, t as FluidGridsContext } from "./FluidGridsProvider-dvZSNtSW.js";
|
|
5
|
-
import { C as
|
|
5
|
+
import { C as typeScriptModuleFile, S as typeScriptImportSource, T as CreateWorkflowRefusalDialog, a as parseWorkflowImport, b as readProjectArchive, c as MAX_IMPORT_ARCHIVE_BYTES, d as checkTypeScriptImport, i as downloadWorkflowExport, l as MAX_IMPORT_SOURCE_BYTES, m as importFileKind, n as useExportWorkflowAs, o as CODE_EXPORT_FORMATS, p as importAcceptAttribute, s as ImportSourceError, u as assertImportByteSize, w as workflowNameFromFile, y as primaryImportModule } from "./useWorkflowCodeExport-Bu2QYJzA.js";
|
|
6
6
|
import { f as BILLING_PLANS_PATH, y as isQuotaExhaustedFailure } from "./fluidgridsEvents-CNdcrUNN.js";
|
|
7
7
|
import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
8
8
|
import { a as SdkPermissionGate, i as SdkPermissionButton, s as useFluidGridsPermission, t as FLUIDGRIDS_PERMISSIONS } from "./constants-B2lhWNoN.js";
|
|
9
9
|
import { t as QuotaExhaustedDialog } from "./QuotaExhaustedDialog-7IFSaLyi.js";
|
|
10
10
|
import { r as useTr } from "./TranslationBridge-Da-TPgQm.js";
|
|
11
11
|
import { CF as WorkflowExportFormat, gF as WorkflowAccessFilter } from "./graphql-types-CDKVWH2R.js";
|
|
12
|
+
import { i as canShareWorkflow, r as canEditWorkflow, t as WorkflowShareDialog } from "./WorkflowShareDialog-mbIwRQUY.js";
|
|
12
13
|
import { l as useFluidGridsFlag, t as FLUIDGRIDS_FLAGS } from "./feature-flags-DM5myWaD.js";
|
|
13
14
|
import { _ as throwIfResultError, m as describeOperationError, n as getFluidGridsClient } from "./client-C9XSzSXr.js";
|
|
14
15
|
import { $t as RenameWorkflowProjectDocument, G as DeleteWorkflowFolderDocument, Hr as WorkflowProjectsDocument, K as DeleteWorkflowProjectDocument, M as CreateWorkflowProjectDocument, Nr as WorkflowFoldersDocument, Qt as RenameWorkflowFolderDocument, Tt as MoveWorkflowFolderDocument, g as BulkMoveWorkflowsToFolderDocument, h as BulkDeleteWorkflowsDocument, j as CreateWorkflowFolderDocument, m as BulkAssignWorkflowsToProjectDocument } from "./graphql-operation-types-kX-MMjgW.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { At as useSaveStatusStore, J as paramsFromOperation, K as nodeTitle, L as createConfiguredNode, W as fixedParameterState, Y as selectedOperationOf, _ as registryNodeData, f as isNodeConfigsInitialized, o as NODE_CONFIGS, pt as autosaveAllowedFor, xt as isFlowComplete } from "./FluidGridsProvider-dvZSNtSW.js";
|
|
3
3
|
import { E as resolveOutputHandles, H as useFlowStore, T as resolveInputHandles } from "./node-operation-selection--oy-yEq_.js";
|
|
4
|
-
import { j as isNodeTypeHiddenFromPalette } from "./TemplateCard-
|
|
5
|
-
import {
|
|
4
|
+
import { j as isNodeTypeHiddenFromPalette } from "./TemplateCard-BdB087SP.js";
|
|
5
|
+
import { b as computeAttachPosition } from "./flow-builder-CV5Zu_Hq.js";
|
|
6
6
|
import { AgentToolError, defineAgentTool } from "@burdenoff/fe-libs/shared/agent-tools";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { n as useAgentMarksStore, r as toPlainText } from "./marksStore-DGCXjTmZ.js";
|
|
3
3
|
import { J as paramsFromOperation, K as nodeTitle, Y as selectedOperationOf } from "./FluidGridsProvider-dvZSNtSW.js";
|
|
4
4
|
import { H as useFlowStore } from "./node-operation-selection--oy-yEq_.js";
|
|
5
|
-
import {
|
|
5
|
+
import { _ as notesKeyOf } from "./flow-builder-CV5Zu_Hq.js";
|
|
6
6
|
import { AgentToolError, defineAgentTool } from "@burdenoff/fe-libs/shared/agent-tools";
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-hDbaFkMy.js";
|
|
3
|
+
import { g as toCodeMirrorDiagnostics } from "./node-operation-selection--oy-yEq_.js";
|
|
4
|
+
import { Fn as useBuilderReadOnly } from "./FluidGridsProvider-dvZSNtSW.js";
|
|
5
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { cn } from "@burdenoff/fe-libs/utils";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
import CodeMirror, { EditorView } from "@uiw/react-codemirror";
|
|
9
|
+
import { lintGutter, setDiagnostics } from "@codemirror/lint";
|
|
10
|
+
|
|
11
|
+
// src/builder/components/ndv/code-editor-field.tsx
|
|
12
|
+
var code_editor_field_exports = /* @__PURE__ */ __exportAll({ CodeEditorField: () => CodeEditorField });
|
|
13
|
+
/**
|
|
14
|
+
* Loads the grammar for the selected language on demand (BOFF-6695). The
|
|
15
|
+
* lezer parsers are heavy and only one language is ever shown per editor, so
|
|
16
|
+
* each language pack is a separate chunk that loads when an editor for it
|
|
17
|
+
* mounts. `null` until the pack resolves: the editor renders as plain text
|
|
18
|
+
* for that first moment and reconfigures once highlighting arrives.
|
|
19
|
+
*/
|
|
20
|
+
function useLanguageExtension(language) {
|
|
21
|
+
const [extension, setExtension] = useState(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
let cancelled = false;
|
|
24
|
+
(language === "python" ? import("@codemirror/lang-python").then((m) => m.python()) : import("@codemirror/lang-javascript").then((m) => m.javascript({ typescript: language === "typescript" }))).then((ext) => {
|
|
25
|
+
if (!cancelled) setExtension(ext);
|
|
26
|
+
});
|
|
27
|
+
return () => {
|
|
28
|
+
cancelled = true;
|
|
29
|
+
};
|
|
30
|
+
}, [language]);
|
|
31
|
+
return extension;
|
|
32
|
+
}
|
|
33
|
+
function normalizeCodeLanguage(value) {
|
|
34
|
+
return typeof value === "string" && value.toLowerCase().startsWith("py") ? "python" : "javascript";
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Follows the app shell's `.dark` class on <html> so the editor theme matches
|
|
38
|
+
* the surrounding UI (fe-libs toggles that class; there is no context to read).
|
|
39
|
+
*/
|
|
40
|
+
function useIsDarkTheme() {
|
|
41
|
+
const [dark, setDark] = useState(() => typeof document !== "undefined" && document.documentElement.classList.contains("dark"));
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const root = document.documentElement;
|
|
44
|
+
const observer = new MutationObserver(() => setDark(root.classList.contains("dark")));
|
|
45
|
+
observer.observe(root, {
|
|
46
|
+
attributes: true,
|
|
47
|
+
attributeFilter: ["class"]
|
|
48
|
+
});
|
|
49
|
+
return () => observer.disconnect();
|
|
50
|
+
}, []);
|
|
51
|
+
return dark;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* CodeMirror-backed editor for `code`-typed NDV parameters (n8n-style Code
|
|
55
|
+
* node). Purely presentational — the stored value stays a plain string in
|
|
56
|
+
* `args.state`, exactly like the single-line input it replaces.
|
|
57
|
+
*/
|
|
58
|
+
function CodeEditorField({ value, language, placeholder, label, onChange, readOnly: readOnlyProp = false, diagnostics, minHeight = "180px", maxHeight = "420px", className, "data-testid": testId }) {
|
|
59
|
+
const dark = useIsDarkTheme();
|
|
60
|
+
const withLint = diagnostics !== void 0;
|
|
61
|
+
const builderReadOnly = useBuilderReadOnly();
|
|
62
|
+
const readOnly = readOnlyProp || builderReadOnly;
|
|
63
|
+
const languageExtension = useLanguageExtension(language);
|
|
64
|
+
const extensions = useMemo(() => [
|
|
65
|
+
...languageExtension ? [languageExtension] : [],
|
|
66
|
+
...label ? [EditorView.contentAttributes.of({ "aria-label": label })] : [],
|
|
67
|
+
...withLint ? [lintGutter()] : []
|
|
68
|
+
], [
|
|
69
|
+
languageExtension,
|
|
70
|
+
label,
|
|
71
|
+
withLint
|
|
72
|
+
]);
|
|
73
|
+
const viewRef = useRef(null);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
const view = viewRef.current;
|
|
76
|
+
if (!view || diagnostics === void 0) return;
|
|
77
|
+
view.dispatch(setDiagnostics(view.state, toCodeMirrorDiagnostics(view.state.doc.toString(), diagnostics)));
|
|
78
|
+
}, [diagnostics]);
|
|
79
|
+
return /* @__PURE__ */ jsx("div", {
|
|
80
|
+
"data-testid": testId,
|
|
81
|
+
className: cn("overflow-hidden rounded-md border border-input text-sm transition-colors focus-within:border-primary", className),
|
|
82
|
+
onKeyDown: (e) => e.stopPropagation(),
|
|
83
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
84
|
+
children: /* @__PURE__ */ jsx(CodeMirror, {
|
|
85
|
+
value,
|
|
86
|
+
onChange: readOnly ? void 0 : onChange,
|
|
87
|
+
extensions,
|
|
88
|
+
theme: dark ? "dark" : "light",
|
|
89
|
+
placeholder,
|
|
90
|
+
minHeight,
|
|
91
|
+
maxHeight,
|
|
92
|
+
editable: !readOnly,
|
|
93
|
+
readOnly,
|
|
94
|
+
onCreateEditor: (view) => {
|
|
95
|
+
viewRef.current = view;
|
|
96
|
+
if (diagnostics?.length) view.dispatch(setDiagnostics(view.state, toCodeMirrorDiagnostics(view.state.doc.toString(), diagnostics)));
|
|
97
|
+
},
|
|
98
|
+
basicSetup: {
|
|
99
|
+
lineNumbers: true,
|
|
100
|
+
foldGutter: true,
|
|
101
|
+
highlightActiveLine: !readOnly,
|
|
102
|
+
autocompletion: !readOnly,
|
|
103
|
+
bracketMatching: true,
|
|
104
|
+
closeBrackets: !readOnly,
|
|
105
|
+
indentOnInput: !readOnly
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { code_editor_field_exports as n, normalizeCodeLanguage as r, CodeEditorField as t };
|