@burdenoff/fluidgrids-fe-sdk 2026.1103.2 → 2026.1104.2

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.
Files changed (53) hide show
  1. package/dist/ExecutionDetailPage-ND2VMU45.js +25 -0
  2. package/dist/{ExecutionsListPage-RC342VCZ.js → ExecutionsListPage-EZ65FXER.js} +9 -9
  3. package/dist/{TemplateDetailPanel-XJ43LW3G.js → TemplateDetailPanel-7MPY5MYT.js} +1 -1
  4. package/dist/{WorkflowBuilder-TCS4JELN.js → WorkflowBuilder-4I44FWII.js} +14 -14
  5. package/dist/{WorkflowsList-6ES2EDGZ.js → WorkflowsList-YFD2RKKQ.js} +9 -9
  6. package/dist/{agentTools-4JT66UQB.js → agentTools-SZZN6TP3.js} +5 -5
  7. package/dist/{chunk-EKB3EIIC.js → chunk-4EUEKSEQ.js} +1 -1
  8. package/dist/{chunk-Y7MQ3LYB.js → chunk-4YCMMBSK.js} +2 -2
  9. package/dist/{chunk-ZUVFD5KV.js → chunk-5375NUIO.js} +2 -0
  10. package/dist/{chunk-6WPW42TX.js → chunk-5D4XS3WJ.js} +2 -2
  11. package/dist/{chunk-742OIXMP.js → chunk-5UHAB75U.js} +1 -1
  12. package/dist/{chunk-YC76QFWZ.js → chunk-AAIZ6S6E.js} +2 -2
  13. package/dist/{chunk-QXACKASD.js → chunk-AFX3EKFN.js} +22 -3
  14. package/dist/{chunk-JTQFBZTV.js → chunk-AVHBWJRY.js} +6 -3
  15. package/dist/{chunk-OBWB73Y7.js → chunk-BIB7IH26.js} +4 -4
  16. package/dist/{chunk-G2FPOWN5.js → chunk-D4WA2M2N.js} +2 -2
  17. package/dist/{chunk-LTINUSLK.js → chunk-DFIX6YWP.js} +59 -16
  18. package/dist/{chunk-PC3CICOW.js → chunk-F7LQL43U.js} +1 -1
  19. package/dist/{chunk-SHYDX2LO.js → chunk-GEY7RXRZ.js} +5 -5
  20. package/dist/{chunk-AOLY5INN.js → chunk-H4ERTSMX.js} +31 -1
  21. package/dist/{chunk-Y7BNGLRI.js → chunk-IK7IGG6T.js} +6 -6
  22. package/dist/{chunk-N6XYVO7N.js → chunk-KHXRYQYP.js} +2 -2
  23. package/dist/{chunk-UH7JKPUF.js → chunk-MF7JLSJX.js} +1 -1
  24. package/dist/{chunk-BVCMAGLJ.js → chunk-NGXJHYV5.js} +1 -1
  25. package/dist/{chunk-UW5GY6LQ.js → chunk-NIY6R42C.js} +4 -4
  26. package/dist/{chunk-BP6YPKNK.js → chunk-NJRCAE6K.js} +4 -4
  27. package/dist/{chunk-LVTOWRAM.js → chunk-NYBL5WHP.js} +2 -2
  28. package/dist/{chunk-UMULDJCK.js → chunk-OMB3WMDQ.js} +6 -6
  29. package/dist/{chunk-M23H4LSY.js → chunk-ON7LK6QH.js} +5 -5
  30. package/dist/{chunk-MY4HMUWU.js → chunk-Q72EOY4T.js} +3 -3
  31. package/dist/{chunk-H2KIJEYM.js → chunk-SS7Y66P5.js} +2 -2
  32. package/dist/{chunk-52OIBKPO.js → chunk-TBHAZK52.js} +1 -1
  33. package/dist/{chunk-VQZEGCRF.js → chunk-VDJFTZ2H.js} +1 -1
  34. package/dist/{chunk-RFOKJE3A.js → chunk-WTV6SQYK.js} +11 -11
  35. package/dist/{chunk-SIVS3XSV.js → chunk-X6PIU7FE.js} +224 -5
  36. package/dist/{chunk-ILPQAQB5.js → chunk-XCSCD3IU.js} +465 -219
  37. package/dist/{chunk-K6HD5GC7.js → chunk-XNU2PLJ2.js} +4 -4
  38. package/dist/{chunk-SUIH376K.js → chunk-YYVRBROH.js} +1 -1
  39. package/dist/{chunk-VFLHURFM.js → chunk-ZDCJPQ5M.js} +1 -1
  40. package/dist/executions.js +14 -14
  41. package/dist/history.js +6 -6
  42. package/dist/index.d.ts +408 -1
  43. package/dist/index.js +46 -46
  44. package/dist/{node-detail-view-CMQ7DUYM.js → node-detail-view-GAGSLHAO.js} +10 -10
  45. package/dist/nodes.js +2 -2
  46. package/dist/observability.js +7 -7
  47. package/dist/{quick-config-panel-NJ72QZPM.js → quick-config-panel-44RBX6YR.js} +7 -7
  48. package/dist/settings.js +7 -7
  49. package/dist/templates.js +13 -13
  50. package/dist/workflow-builder.js +15 -15
  51. package/dist/workflows-list.js +9 -9
  52. package/package.json +4 -4
  53. package/dist/ExecutionDetailPage-JRBUIU5J.js +0 -25
@@ -1,16 +1,16 @@
1
- import { CreateWorkflowRefusalDialog, firstWorkflowProgress, GUIDED_TOUR_STATE, builderPathFor } from './chunk-52OIBKPO.js';
2
- import { useExecutions } from './chunk-6WPW42TX.js';
3
- import { useExportWorkflowAs, downloadWorkflowExport, importAcceptAttribute, QuotaExhaustedDialog, importFileKind, parseWorkflowImport, CODE_EXPORT_FORMATS, ImportSourceError, assertImportByteSize, MAX_IMPORT_ARCHIVE_BYTES, readProjectArchive, checkTypeScriptImport, MAX_IMPORT_SOURCE_BYTES, typeScriptModuleFile, typeScriptImportSource, workflowNameFromFile, primaryImportModule } from './chunk-SIVS3XSV.js';
1
+ import { CreateWorkflowRefusalDialog, firstWorkflowProgress, GUIDED_TOUR_STATE, builderPathFor } from './chunk-TBHAZK52.js';
2
+ import { useExecutions } from './chunk-5D4XS3WJ.js';
3
+ import { useExportWorkflowAs, WorkflowShareDialog, downloadWorkflowExport, importAcceptAttribute, canEditWorkflow, canShareWorkflow, QuotaExhaustedDialog, importFileKind, parseWorkflowImport, CODE_EXPORT_FORMATS, ImportSourceError, assertImportByteSize, MAX_IMPORT_ARCHIVE_BYTES, readProjectArchive, checkTypeScriptImport, MAX_IMPORT_SOURCE_BYTES, typeScriptModuleFile, typeScriptImportSource, workflowNameFromFile, primaryImportModule } from './chunk-X6PIU7FE.js';
4
4
  import { workflowsListControls } from './chunk-FNZZ5JJL.js';
5
- import { useCreateWorkflow, useWorkflowDefinitions, useLazyWorkflowDefinition, useImportWorkflow, useDuplicateWorkflow, useDeleteWorkflow } from './chunk-QXACKASD.js';
5
+ import { useCreateWorkflow, useWorkflowDefinitions, useLazyWorkflowDefinition, useImportWorkflow, usePreviewN8nImport, useDuplicateWorkflow, useDeleteWorkflow } from './chunk-AFX3EKFN.js';
6
6
  import { useFluidGridsPageControls } from './chunk-PJAWNFJV.js';
7
7
  import { FluidGridsDocsLink } from './chunk-4VJ3MDOV.js';
8
- import { createThenOpen, useFluidGridsFlag, FLUIDGRIDS_FLAGS, BILLING_PLANS_PATH, describeOperationError, useFlowStore, throwIfResultError, isQuotaExhaustedFailure } from './chunk-YC76QFWZ.js';
9
- import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton, SdkPermissionGate } from './chunk-ZUVFD5KV.js';
10
- import { WorkflowFoldersDocument, CreateWorkflowFolderDocument, RenameWorkflowFolderDocument, MoveWorkflowFolderDocument, DeleteWorkflowFolderDocument, WorkflowProjectsDocument, CreateWorkflowProjectDocument, RenameWorkflowProjectDocument, DeleteWorkflowProjectDocument, BulkMoveWorkflowsToFolderDocument, BulkAssignWorkflowsToProjectDocument, BulkDeleteWorkflowsDocument } from './chunk-JTQFBZTV.js';
8
+ import { createThenOpen, FluidGridsContext, useFluidGridsFlag, FLUIDGRIDS_FLAGS, BILLING_PLANS_PATH, describeOperationError, useFlowStore, throwIfResultError, isQuotaExhaustedFailure } from './chunk-AAIZ6S6E.js';
9
+ import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton, SdkPermissionGate } from './chunk-5375NUIO.js';
10
+ import { WorkflowFoldersDocument, CreateWorkflowFolderDocument, RenameWorkflowFolderDocument, MoveWorkflowFolderDocument, DeleteWorkflowFolderDocument, WorkflowProjectsDocument, CreateWorkflowProjectDocument, RenameWorkflowProjectDocument, DeleteWorkflowProjectDocument, BulkMoveWorkflowsToFolderDocument, BulkAssignWorkflowsToProjectDocument, BulkDeleteWorkflowsDocument } from './chunk-AVHBWJRY.js';
11
11
  import { useTr } from './chunk-UULVIT25.js';
12
12
  import { getFluidGridsClient } from './chunk-NTWG3CJX.js';
13
- import { useState, useRef, useCallback, useMemo, useEffect } from 'react';
13
+ import { useState, useRef, useCallback, useContext, useMemo, useEffect } from 'react';
14
14
  import { useNavigate } from 'react-router';
15
15
  import { v4 } from 'uuid';
16
16
  import { Icon } from '@iconify/react';
@@ -18,7 +18,6 @@ import { NextSteps, Button, Badge, Input, IllustratedEmptyState, Checkbox, Dialo
18
18
  import { cn } from '@burdenoff/fe-libs/utils';
19
19
  import { TagBadge } from '@burdenoff/fe-libs/tag';
20
20
  import { toast } from 'sonner';
21
- import { Share2, Copy } from 'lucide-react';
22
21
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
22
 
24
23
  function useCreateWorkflowFirst(options = {}) {
@@ -52,200 +51,6 @@ function useCreateWorkflowFirst(options = {}) {
52
51
  const clearRefusal = useCallback(() => setRefusal(null), []);
53
52
  return { start, creating, refusal, clearRefusal };
54
53
  }
55
-
56
- // src/components/share-target.ts
57
- var PLACEHOLDER_SEGMENTS = /* @__PURE__ */ new Set(["undefined", "null"]);
58
- function toPublicUrl(raw) {
59
- if (typeof raw !== "string" || raw.trim() === "") return null;
60
- let parsed;
61
- try {
62
- parsed = new URL(raw);
63
- } catch {
64
- return null;
65
- }
66
- if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
67
- if (!parsed.hostname || PLACEHOLDER_SEGMENTS.has(parsed.hostname)) {
68
- return null;
69
- }
70
- const hasPlaceholderSegment = parsed.pathname.split("/").some((segment) => PLACEHOLDER_SEGMENTS.has(segment.toLowerCase()));
71
- if (hasPlaceholderSegment) return null;
72
- return parsed.href;
73
- }
74
- function resolveShareTarget(input) {
75
- const shareUrl = toPublicUrl(input.shareUrl);
76
- if (!shareUrl) return null;
77
- const embedUrl = toPublicUrl(input.embedUrl);
78
- return embedUrl ? { shareUrl, embedUrl } : { shareUrl };
79
- }
80
- var MIN_EMBED_SIZE = 100;
81
- var MAX_EMBED_SIZE = 4e3;
82
- function clampEmbedSize(value, fallback) {
83
- if (!Number.isFinite(value)) return fallback;
84
- return Math.min(MAX_EMBED_SIZE, Math.max(MIN_EMBED_SIZE, Math.round(value)));
85
- }
86
- function buildEmbedSnippet(embedUrl, width, height) {
87
- const w = clampEmbedSize(width, 600);
88
- const h = clampEmbedSize(height, 400);
89
- return `<iframe src="${embedUrl}" width="${w}" height="${h}" frameborder="0"></iframe>`;
90
- }
91
- function SharePopup({ shareUrl, embedUrl }) {
92
- const tr = useTr();
93
- const [isOpen, setIsOpen] = useState(false);
94
- const [width, setWidth] = useState(600);
95
- const [height, setHeight] = useState(400);
96
- const [activeTab, setActiveTab] = useState("link");
97
- const target = resolveShareTarget({ shareUrl, embedUrl });
98
- if (!target) {
99
- return /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "icon", disabled: true, "aria-disabled": "true", children: [
100
- /* @__PURE__ */ jsx(Share2, { className: "h-4 w-4" }),
101
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: tr(
102
- "fluidgrids.components.sharePopup.unavailableLabel",
103
- "Sharing is not available yet"
104
- ) })
105
- ] });
106
- }
107
- const embedCode = target.embedUrl ? buildEmbedSnippet(target.embedUrl, width, height) : "";
108
- const copyToClipboard = (text, message) => {
109
- navigator.clipboard.writeText(text).then(
110
- () => toast.success(message),
111
- () => toast.error(
112
- tr(
113
- "fluidgrids.components.sharePopup.copyFailedToast",
114
- "Could not copy to clipboard"
115
- )
116
- )
117
- );
118
- };
119
- if (!isOpen) {
120
- return /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "icon", onClick: () => setIsOpen(true), children: [
121
- /* @__PURE__ */ jsx(Share2, { className: "h-4 w-4" }),
122
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: tr("fluidgrids.components.sharePopup.openLabel", "Share") })
123
- ] });
124
- }
125
- return /* @__PURE__ */ jsx(
126
- "div",
127
- {
128
- className: "fixed inset-0 z-50 flex items-center justify-center bg-bg-overlay",
129
- onClick: () => setIsOpen(false),
130
- children: /* @__PURE__ */ jsxs(
131
- "div",
132
- {
133
- className: "bg-card rounded-lg p-6 max-w-md w-full mx-4",
134
- onClick: (e) => e.stopPropagation(),
135
- children: [
136
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-4", children: [
137
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold", children: tr("fluidgrids.components.sharePopup.title", "Share") }),
138
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", onClick: () => setIsOpen(false), children: "\xD7" })
139
- ] }),
140
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mb-4", children: [
141
- /* @__PURE__ */ jsx(
142
- Button,
143
- {
144
- variant: activeTab === "link" ? "default" : "outline",
145
- size: "sm",
146
- onClick: () => setActiveTab("link"),
147
- children: tr("fluidgrids.components.sharePopup.tabShareLink", "Share Link")
148
- }
149
- ),
150
- target.embedUrl && /* @__PURE__ */ jsx(
151
- Button,
152
- {
153
- variant: activeTab === "embed" ? "default" : "outline",
154
- size: "sm",
155
- onClick: () => setActiveTab("embed"),
156
- children: tr("fluidgrids.components.sharePopup.tabEmbed", "Embed")
157
- }
158
- )
159
- ] }),
160
- activeTab === "link" && /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
161
- /* @__PURE__ */ jsx(
162
- "input",
163
- {
164
- readOnly: true,
165
- value: target.shareUrl,
166
- className: "flex-1 h-9 px-3 rounded-md border bg-background text-sm"
167
- }
168
- ),
169
- /* @__PURE__ */ jsx(
170
- Button,
171
- {
172
- size: "sm",
173
- onClick: () => copyToClipboard(
174
- target.shareUrl,
175
- tr(
176
- "fluidgrids.components.sharePopup.linkCopiedToast",
177
- "Link copied to clipboard"
178
- )
179
- ),
180
- children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
181
- }
182
- )
183
- ] }),
184
- activeTab === "embed" && target.embedUrl && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
185
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
186
- /* @__PURE__ */ jsxs("div", { children: [
187
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: tr("fluidgrids.components.sharePopup.widthLabel", "Width") }),
188
- /* @__PURE__ */ jsx(
189
- "input",
190
- {
191
- type: "number",
192
- value: width,
193
- onChange: (e) => setWidth(Number(e.target.value)),
194
- className: "w-full h-9 px-3 rounded-md border bg-background text-sm mt-1"
195
- }
196
- )
197
- ] }),
198
- /* @__PURE__ */ jsxs("div", { children: [
199
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: tr("fluidgrids.components.sharePopup.heightLabel", "Height") }),
200
- /* @__PURE__ */ jsx(
201
- "input",
202
- {
203
- type: "number",
204
- value: height,
205
- onChange: (e) => setHeight(Number(e.target.value)),
206
- className: "w-full h-9 px-3 rounded-md border bg-background text-sm mt-1"
207
- }
208
- )
209
- ] })
210
- ] }),
211
- /* @__PURE__ */ jsxs("div", { children: [
212
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: tr(
213
- "fluidgrids.components.sharePopup.embedCodeLabel",
214
- "Embed Code"
215
- ) }),
216
- /* @__PURE__ */ jsxs("div", { className: "relative mt-1", children: [
217
- /* @__PURE__ */ jsx(
218
- "input",
219
- {
220
- readOnly: true,
221
- value: embedCode,
222
- className: "w-full h-9 px-3 pr-12 rounded-md border bg-background text-sm font-mono"
223
- }
224
- ),
225
- /* @__PURE__ */ jsx(
226
- Button,
227
- {
228
- size: "sm",
229
- className: "absolute right-1 top-1/2 -translate-y-1/2 h-7",
230
- onClick: () => copyToClipboard(
231
- embedCode,
232
- tr(
233
- "fluidgrids.components.sharePopup.embedCopiedToast",
234
- "Embed code copied to clipboard"
235
- )
236
- ),
237
- children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
238
- }
239
- )
240
- ] })
241
- ] })
242
- ] })
243
- ]
244
- }
245
- )
246
- }
247
- );
248
- }
249
54
  function WorkflowStatusPill({ status }) {
250
55
  const tr = useTr();
251
56
  const styles = {
@@ -360,7 +165,9 @@ var CardWorkflow = ({
360
165
  onUpdateSuccess,
361
166
  onExport,
362
167
  onExportAs,
363
- exportingFormat = null
168
+ exportingFormat = null,
169
+ onShare,
170
+ onMoveToProject
364
171
  }) => {
365
172
  const tr = useTr();
366
173
  const navigate = useNavigate();
@@ -435,6 +242,9 @@ var CardWorkflow = ({
435
242
  return;
436
243
  handleOnEdit();
437
244
  };
245
+ const restricted = workflow.visibility === "RESTRICTED";
246
+ const editable = canEditWorkflow(workflow.my_access);
247
+ const shareable = canShareWorkflow(workflow.my_access);
438
248
  const updatedExact = workflow.updated_at ? new Date(workflow.updated_at).toLocaleString() : void 0;
439
249
  return /* @__PURE__ */ jsxs(TooltipProvider, { children: [
440
250
  /* @__PURE__ */ jsxs(
@@ -460,7 +270,27 @@ var CardWorkflow = ({
460
270
  /* @__PURE__ */ jsx("div", { className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-primary/20 bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:transit-connection-variant", className: "size-5" }) }),
461
271
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
462
272
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
463
- /* @__PURE__ */ jsx("h3", { className: "truncate font-semibold leading-6 text-card-foreground", children: workflow?.name }),
273
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
274
+ /* @__PURE__ */ jsx("h3", { className: "truncate font-semibold leading-6 text-card-foreground", children: workflow?.name }),
275
+ restricted && /* @__PURE__ */ jsxs(Tooltip, { children: [
276
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
277
+ "span",
278
+ {
279
+ className: "shrink-0 text-muted-foreground",
280
+ "data-testid": "workflow-restricted-badge",
281
+ "aria-label": tr(
282
+ "fluidgrids.builder.cardWorkflow.restricted",
283
+ "Shared only with chosen people"
284
+ ),
285
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:lock-outline", className: "size-3.5" })
286
+ }
287
+ ) }),
288
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsx("p", { children: tr(
289
+ "fluidgrids.builder.cardWorkflow.restricted",
290
+ "Shared only with chosen people"
291
+ ) }) })
292
+ ] })
293
+ ] }),
464
294
  /* @__PURE__ */ jsx(WorkflowStatusPill, { status: workflow.status })
465
295
  ] }),
466
296
  /* @__PURE__ */ jsx("p", { className: "mt-1 line-clamp-2 text-xs leading-snug text-muted-foreground", children: workflow.description || tr(
@@ -556,13 +386,60 @@ var CardWorkflow = ({
556
386
  "Workflow settings"
557
387
  ) }) })
558
388
  ] }),
559
- /* @__PURE__ */ jsxs(Tooltip, { children: [
560
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { tabIndex: 0, "data-card-action": "", children: /* @__PURE__ */ jsx(SharePopup, {}) }) }),
561
- /* @__PURE__ */ jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsx("p", { children: tr(
562
- "fluidgrids.builder.cardWorkflow.shareUnavailable",
563
- "Sharing is not available for workflows yet"
564
- ) }) })
565
- ] }),
389
+ onShare && shareable && /* @__PURE__ */ jsx(
390
+ SdkPermissionGate,
391
+ {
392
+ permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_SHARE,
393
+ children: /* @__PURE__ */ jsxs(Tooltip, { children: [
394
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
395
+ Button,
396
+ {
397
+ variant: "ghost",
398
+ size: "icon",
399
+ className: "size-8",
400
+ onClick: onShare,
401
+ "data-testid": "workflow-card-share",
402
+ "aria-label": tr(
403
+ "fluidgrids.builder.cardWorkflow.shareWorkflow",
404
+ "Share workflow"
405
+ ),
406
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mynaui:share", className: "size-4" })
407
+ }
408
+ ) }),
409
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsx("p", { children: tr(
410
+ "fluidgrids.builder.cardWorkflow.shareWorkflow",
411
+ "Share workflow"
412
+ ) }) })
413
+ ] })
414
+ }
415
+ ),
416
+ onMoveToProject && editable && /* @__PURE__ */ jsx(
417
+ SdkPermissionGate,
418
+ {
419
+ permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_UPDATE,
420
+ children: /* @__PURE__ */ jsxs(Tooltip, { children: [
421
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
422
+ Button,
423
+ {
424
+ variant: "ghost",
425
+ size: "icon",
426
+ className: "size-8",
427
+ onClick: onMoveToProject,
428
+ "data-testid": "workflow-card-move-project",
429
+ "aria-label": tr(
430
+ "fluidgrids.builder.cardWorkflow.moveToProject",
431
+ "Move to project"
432
+ ),
433
+ children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:folder-move-outline", className: "size-4" })
434
+ }
435
+ ) }),
436
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsx("p", { children: tr(
437
+ "fluidgrids.builder.cardWorkflow.moveToProject",
438
+ "Move to project"
439
+ ) }) })
440
+ ] })
441
+ }
442
+ ),
566
443
  onExportAs ? /* @__PURE__ */ jsx("span", { "data-card-action": "", children: /* @__PURE__ */ jsx(
567
444
  WorkflowExportMenu,
568
445
  {
@@ -615,7 +492,7 @@ var CardWorkflow = ({
615
492
  ] })
616
493
  }
617
494
  ),
618
- /* @__PURE__ */ jsx(
495
+ editable && /* @__PURE__ */ jsx(
619
496
  SdkPermissionGate,
620
497
  {
621
498
  permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_DELETE,
@@ -698,6 +575,159 @@ var CardWorkflow = ({
698
575
  )
699
576
  ] });
700
577
  };
578
+ function Section({
579
+ title,
580
+ icon,
581
+ testId,
582
+ children
583
+ }) {
584
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", "data-testid": testId, children: [
585
+ /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 text-xs font-medium text-foreground", children: [
586
+ /* @__PURE__ */ jsx(Icon, { icon, className: "size-3.5 text-muted-foreground" }),
587
+ title
588
+ ] }),
589
+ /* @__PURE__ */ jsx("ul", { className: "space-y-1 pl-5 text-xs text-muted-foreground", children })
590
+ ] });
591
+ }
592
+ function keyed(entries, keyOf) {
593
+ const seen = /* @__PURE__ */ new Map();
594
+ for (const entry of entries) {
595
+ const key = keyOf(entry);
596
+ if (!seen.has(key)) seen.set(key, entry);
597
+ }
598
+ return [...seen.entries()];
599
+ }
600
+ function N8nImportReport({ report }) {
601
+ const tr = useTr();
602
+ return /* @__PURE__ */ jsxs(
603
+ "div",
604
+ {
605
+ className: "space-y-3 rounded-lg border border-border bg-background p-3",
606
+ "data-testid": "fluidgrids-import-n8n-report",
607
+ children: [
608
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
609
+ /* @__PURE__ */ jsx(
610
+ Icon,
611
+ {
612
+ icon: "mynaui:download",
613
+ className: "mt-0.5 size-4 shrink-0 text-muted-foreground"
614
+ }
615
+ ),
616
+ /* @__PURE__ */ jsxs("div", { className: "space-y-0.5", children: [
617
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-foreground", children: tr(
618
+ "fluidgrids.workflowsList.importN8nDetected",
619
+ "n8n workflow detected"
620
+ ) }),
621
+ /* @__PURE__ */ jsx(
622
+ "p",
623
+ {
624
+ className: "text-xs text-muted-foreground",
625
+ "data-testid": "fluidgrids-import-n8n-summary",
626
+ children: tr(
627
+ "fluidgrids.workflowsList.importN8nSummary",
628
+ "{{mapped}} of {{total}} nodes convert directly \xB7 {{placeholders}} placeholders \xB7 {{connections}} connections to set up",
629
+ {
630
+ mapped: String(report.mappedNodes.length),
631
+ total: String(report.nodeCount),
632
+ placeholders: String(report.placeholders.length),
633
+ connections: String(report.connectionsNeeded.length)
634
+ }
635
+ )
636
+ }
637
+ )
638
+ ] })
639
+ ] }),
640
+ report.placeholders.length > 0 && /* @__PURE__ */ jsx(
641
+ Section,
642
+ {
643
+ title: tr(
644
+ "fluidgrids.workflowsList.importN8nPlaceholders",
645
+ "Placeholders: these nodes are kept as disabled No-op nodes, with their n8n settings in the node notes"
646
+ ),
647
+ icon: "mynaui:square-dashed",
648
+ testId: "fluidgrids-import-n8n-placeholders",
649
+ children: report.placeholders.map((placeholder) => /* @__PURE__ */ jsxs("li", { children: [
650
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: placeholder.name }),
651
+ " ",
652
+ /* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
653
+ "(",
654
+ placeholder.n8nType,
655
+ ")"
656
+ ] }),
657
+ ":",
658
+ " ",
659
+ placeholder.reason
660
+ ] }, placeholder.nodeId))
661
+ }
662
+ ),
663
+ report.connectionsNeeded.length > 0 && /* @__PURE__ */ jsx(
664
+ Section,
665
+ {
666
+ title: tr(
667
+ "fluidgrids.workflowsList.importN8nConnections",
668
+ "Connections to create: n8n credentials are never imported"
669
+ ),
670
+ icon: "mynaui:key",
671
+ testId: "fluidgrids-import-n8n-connections",
672
+ children: keyed(
673
+ report.connectionsNeeded,
674
+ (connection) => `${connection.nodeId}|${connection.provider ?? ""}|${connection.n8nCredentialType ?? ""}`
675
+ ).map(([key, connection]) => /* @__PURE__ */ jsxs("li", { children: [
676
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: connection.nodeName }),
677
+ connection.provider && connection.provider !== "*" ? ` \xB7 ${connection.provider}` : "",
678
+ connection.n8nCredentialName ? ` \xB7 ${tr(
679
+ "fluidgrids.workflowsList.importN8nCredentialWas",
680
+ "was {{credential}} in n8n",
681
+ { credential: connection.n8nCredentialName }
682
+ )}` : ""
683
+ ] }, key))
684
+ }
685
+ ),
686
+ report.expressionIssues.length > 0 && /* @__PURE__ */ jsx(
687
+ Section,
688
+ {
689
+ title: tr(
690
+ "fluidgrids.workflowsList.importN8nExpressions",
691
+ "Expressions and conditions to review"
692
+ ),
693
+ icon: "mynaui:code",
694
+ testId: "fluidgrids-import-n8n-expressions",
695
+ children: keyed(
696
+ report.expressionIssues,
697
+ (issue) => `${issue.nodeName}|${issue.expression}|${issue.reason}`
698
+ ).map(([key, issue]) => /* @__PURE__ */ jsxs("li", { children: [
699
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: issue.nodeName }),
700
+ ": ",
701
+ /* @__PURE__ */ jsx("span", { className: "break-all font-mono", children: issue.expression }),
702
+ " ",
703
+ "\u2014 ",
704
+ issue.reason
705
+ ] }, key))
706
+ }
707
+ ),
708
+ report.warnings.length > 0 && /* @__PURE__ */ jsx(
709
+ Section,
710
+ {
711
+ title: tr("fluidgrids.workflowsList.importN8nNotes", "Notes"),
712
+ icon: "mynaui:info-circle",
713
+ testId: "fluidgrids-import-n8n-warnings",
714
+ children: keyed(
715
+ report.warnings,
716
+ (warning) => `${warning.nodeName ?? ""}|${warning.message}`
717
+ ).map(([key, warning]) => /* @__PURE__ */ jsxs("li", { children: [
718
+ warning.nodeName ? /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
719
+ warning.nodeName,
720
+ ":",
721
+ " "
722
+ ] }) : null,
723
+ warning.message
724
+ ] }, key))
725
+ }
726
+ )
727
+ ]
728
+ }
729
+ );
730
+ }
701
731
  function formatMiB(bytes) {
702
732
  const mib = bytes / (1024 * 1024);
703
733
  return Number.isInteger(mib) ? String(mib) : mib.toFixed(1);
@@ -788,7 +818,17 @@ function WorkflowImportDialog({
788
818
  const [workflowKey, setWorkflowKey] = useState("");
789
819
  const [version, setVersion] = useState("");
790
820
  const [loadingUrl, setLoadingUrl] = useState(false);
821
+ const { previewN8nImport } = usePreviewN8nImport();
822
+ const [n8nPreview, setN8nPreview] = useState(null);
823
+ const [previewingN8n, setPreviewingN8n] = useState(false);
824
+ const previewRequest = useRef(0);
825
+ const dropN8nPreview = () => {
826
+ previewRequest.current += 1;
827
+ setN8nPreview(null);
828
+ setPreviewingN8n(false);
829
+ };
791
830
  const reset = () => {
831
+ dropN8nPreview();
792
832
  setRawJson("");
793
833
  setUrl("");
794
834
  setParsed(null);
@@ -800,6 +840,7 @@ function WorkflowImportDialog({
800
840
  setSubmitted(false);
801
841
  };
802
842
  const selectTypeScript = (label, files) => {
843
+ dropN8nPreview();
803
844
  setParsed(null);
804
845
  setIssues(null);
805
846
  setSubmitted(false);
@@ -809,6 +850,7 @@ function WorkflowImportDialog({
809
850
  setVersion("");
810
851
  };
811
852
  const refuseSource = (error) => {
853
+ dropN8nPreview();
812
854
  setTypeScript(null);
813
855
  setParsed(null);
814
856
  setSubmitted(false);
@@ -838,16 +880,39 @@ function WorkflowImportDialog({
838
880
  }
839
881
  return true;
840
882
  };
883
+ const showN8nPreview = async (next) => {
884
+ const request = previewRequest.current;
885
+ setPreviewingN8n(true);
886
+ try {
887
+ const preview = await previewN8nImport(next.definitionJson);
888
+ if (request !== previewRequest.current) return;
889
+ setN8nPreview(preview);
890
+ setName(preview.name);
891
+ } catch (error) {
892
+ if (request !== previewRequest.current) return;
893
+ setParsed(null);
894
+ toast.error(
895
+ error instanceof Error ? error.message : tr(
896
+ "fluidgrids.workflowsList.importN8nPreviewFailed",
897
+ "The n8n workflow could not be read"
898
+ )
899
+ );
900
+ } finally {
901
+ if (request === previewRequest.current) setPreviewingN8n(false);
902
+ }
903
+ };
841
904
  const parse = (value) => {
842
905
  setTypeScript(null);
843
906
  setIssues(null);
844
907
  setSubmitted(false);
908
+ dropN8nPreview();
845
909
  try {
846
910
  const next = parseWorkflowImport(value);
847
911
  setParsed(next);
848
912
  setName(next.name);
849
913
  setWorkflowKey("");
850
914
  setVersion(next.version ?? "");
915
+ if (next.source === "n8n") void showN8nPreview(next);
851
916
  } catch (error) {
852
917
  setParsed(null);
853
918
  toast.error(
@@ -1126,6 +1191,7 @@ function WorkflowImportDialog({
1126
1191
  onChange: (event) => {
1127
1192
  setRawJson(event.target.value);
1128
1193
  setParsed(null);
1194
+ dropN8nPreview();
1129
1195
  },
1130
1196
  onBlur: () => rawJson.trim() && parse(rawJson),
1131
1197
  placeholder: tr(
@@ -1140,7 +1206,20 @@ function WorkflowImportDialog({
1140
1206
  }
1141
1207
  ),
1142
1208
  (parsed || typeScript) && /* @__PURE__ */ jsxs("div", { className: "space-y-3 rounded-lg border border-border bg-muted/30 p-3", children: [
1143
- parsed ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
1209
+ parsed?.source === "n8n" ? n8nPreview ? /* @__PURE__ */ jsx(N8nImportReport, { report: n8nPreview.report }) : /* @__PURE__ */ jsx(
1210
+ "p",
1211
+ {
1212
+ className: "text-xs text-muted-foreground",
1213
+ "data-testid": "fluidgrids-import-n8n-previewing",
1214
+ children: previewingN8n ? tr(
1215
+ "fluidgrids.workflowsList.importN8nPreviewing",
1216
+ "Reading the n8n workflow\u2026"
1217
+ ) : tr(
1218
+ "fluidgrids.workflowsList.importN8nDetected",
1219
+ "n8n workflow detected"
1220
+ )
1221
+ }
1222
+ ) : parsed ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
1144
1223
  parsed.nodeReferences.length,
1145
1224
  " ",
1146
1225
  tr(
@@ -1223,7 +1302,7 @@ function WorkflowImportDialog({
1223
1302
  Button,
1224
1303
  {
1225
1304
  onClick: () => void handleImport(),
1226
- disabled: loading || !parsed && !typeScript || !name.trim(),
1305
+ disabled: loading || !parsed && !typeScript || !name.trim() || parsed?.source === "n8n" && !n8nPreview,
1227
1306
  children: loading ? tr("fluidgrids.workflowsList.importing", "Importing\u2026") : tr("fluidgrids.workflowsList.importConfirm", "Import workflow")
1228
1307
  }
1229
1308
  )
@@ -2238,6 +2317,87 @@ function FirstWorkflowChecklist({
2238
2317
  }
2239
2318
  return /* @__PURE__ */ jsx(ChecklistWithRuns, { workflows, canCreate });
2240
2319
  }
2320
+ var NO_PROJECT = "__none__";
2321
+ function WorkflowMoveToProjectDialog({
2322
+ workflow,
2323
+ onClose,
2324
+ onMoved
2325
+ }) {
2326
+ const tr = useTr();
2327
+ const { projects } = useWorkflowProjects();
2328
+ const { bulkAssignToProject, loading } = useBulkWorkflowActions();
2329
+ const [choice, setChoice] = useState(null);
2330
+ const current = workflow?.projectId ?? NO_PROJECT;
2331
+ const selected = choice ?? current;
2332
+ const close = () => {
2333
+ setChoice(null);
2334
+ onClose();
2335
+ };
2336
+ const move = async () => {
2337
+ if (!workflow) return;
2338
+ const result = await bulkAssignToProject(
2339
+ [workflow.id],
2340
+ selected === NO_PROJECT ? null : selected
2341
+ );
2342
+ if (!result || result.failedIds.length > 0) {
2343
+ toast.error(
2344
+ tr(
2345
+ "fluidgrids.workflowsList.moveToProject.failed",
2346
+ "The workflow couldn't be moved"
2347
+ )
2348
+ );
2349
+ return;
2350
+ }
2351
+ toast.success(
2352
+ tr("fluidgrids.workflowsList.moveToProject.moved", "Workflow moved")
2353
+ );
2354
+ setChoice(null);
2355
+ onMoved?.();
2356
+ onClose();
2357
+ };
2358
+ return /* @__PURE__ */ jsx(Dialog, { open: workflow !== null, onOpenChange: (open) => !open && close(), children: /* @__PURE__ */ jsxs(DialogContent, { "data-testid": "move-to-project-dialog", children: [
2359
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
2360
+ /* @__PURE__ */ jsx(DialogTitle, { children: tr(
2361
+ "fluidgrids.workflowsList.moveToProject.title",
2362
+ "Move {{name}} to a project",
2363
+ { name: workflow?.name ?? "" }
2364
+ ) }),
2365
+ /* @__PURE__ */ jsx(DialogDescription, { children: tr(
2366
+ "fluidgrids.workflowsList.moveToProject.description",
2367
+ "Every version moves, and new versions stay in the project."
2368
+ ) })
2369
+ ] }),
2370
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
2371
+ /* @__PURE__ */ jsx(Label, { htmlFor: "move-to-project-select", children: tr("fluidgrids.workflowsList.moveToProject.label", "Project") }),
2372
+ /* @__PURE__ */ jsxs(Select, { value: selected, onValueChange: setChoice, children: [
2373
+ /* @__PURE__ */ jsx(
2374
+ SelectTrigger,
2375
+ {
2376
+ id: "move-to-project-select",
2377
+ "data-testid": "move-to-project-select",
2378
+ children: /* @__PURE__ */ jsx(SelectValue, {})
2379
+ }
2380
+ ),
2381
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
2382
+ /* @__PURE__ */ jsx(SelectItem, { value: NO_PROJECT, children: tr("fluidgrids.workflowsList.bulk.noProject", "No project") }),
2383
+ projects.map((project) => /* @__PURE__ */ jsx(SelectItem, { value: project.id, children: project.name }, project.id))
2384
+ ] })
2385
+ ] })
2386
+ ] }),
2387
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
2388
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: close, disabled: loading, children: tr("fluidgrids.workflowsList.moveToProject.cancel", "Cancel") }),
2389
+ /* @__PURE__ */ jsx(
2390
+ Button,
2391
+ {
2392
+ onClick: () => void move(),
2393
+ disabled: loading || selected === current,
2394
+ "data-testid": "move-to-project-confirm",
2395
+ children: tr("fluidgrids.workflowsList.moveToProject.confirm", "Move")
2396
+ }
2397
+ )
2398
+ ] })
2399
+ ] }) });
2400
+ }
2241
2401
  function useStatusFilters() {
2242
2402
  const tr = useTr();
2243
2403
  return useMemo(
@@ -2262,6 +2422,29 @@ function useStatusFilters() {
2262
2422
  [tr]
2263
2423
  );
2264
2424
  }
2425
+ function useAccessFilters() {
2426
+ const tr = useTr();
2427
+ return useMemo(
2428
+ () => [
2429
+ {
2430
+ value: "ALL" /* All */,
2431
+ label: tr("fluidgrids.workflowsList.access.all", "All")
2432
+ },
2433
+ {
2434
+ value: "OWNED_BY_ME" /* OwnedByMe */,
2435
+ label: tr("fluidgrids.workflowsList.access.mine", "Mine")
2436
+ },
2437
+ {
2438
+ value: "SHARED_WITH_ME" /* SharedWithMe */,
2439
+ label: tr(
2440
+ "fluidgrids.workflowsList.access.sharedWithMe",
2441
+ "Shared with me"
2442
+ )
2443
+ }
2444
+ ],
2445
+ [tr]
2446
+ );
2447
+ }
2265
2448
  function SkeletonCard() {
2266
2449
  return /* @__PURE__ */ jsxs("div", { className: "flex min-h-40 flex-col justify-between rounded-xl border border-border bg-card p-6", children: [
2267
2450
  /* @__PURE__ */ jsxs("div", { className: "space-y-2.5", children: [
@@ -2279,10 +2462,19 @@ function WorkflowsList() {
2279
2462
  const tr = useTr();
2280
2463
  const navigate = useNavigate();
2281
2464
  const STATUS_FILTERS = useStatusFilters();
2465
+ const ACCESS_FILTERS = useAccessFilters();
2466
+ const workspaceId = useContext(FluidGridsContext)?.workspaceId ?? "";
2467
+ const [accessFilter, setAccessFilter] = useState(
2468
+ "ALL" /* All */
2469
+ );
2282
2470
  const { workflows, loading, error, tagsByKey, refetch } = useWorkflowDefinitions({
2283
2471
  limit: 100,
2284
- latestOnly: true
2472
+ latestOnly: true,
2473
+ ...accessFilter === "ALL" /* All */ ? {} : { access: accessFilter }
2285
2474
  });
2475
+ const [sharing, setSharing] = useState(null);
2476
+ const [moving, setMoving] = useState(null);
2477
+ const filteredByAccess = accessFilter !== "ALL" /* All */;
2286
2478
  const { getWorkflow } = useLazyWorkflowDefinition();
2287
2479
  const { allowed: canCreate } = useFluidGridsPermission(
2288
2480
  FLUIDGRIDS_PERMISSIONS.WORKFLOW_CREATE
@@ -2469,7 +2661,7 @@ function WorkflowsList() {
2469
2661
  }
2470
2662
  ),
2471
2663
  !loading && !error && /* @__PURE__ */ jsx(FirstWorkflowChecklist, { workflows, canCreate }),
2472
- !loading && !error && workflows.length > 0 && /* @__PURE__ */ jsxs(
2664
+ !loading && !error && (workflows.length > 0 || filteredByAccess) && /* @__PURE__ */ jsxs(
2473
2665
  "div",
2474
2666
  {
2475
2667
  className: "flex flex-wrap items-center gap-3",
@@ -2507,6 +2699,29 @@ function WorkflowsList() {
2507
2699
  onSelectProject: setProjectFilter
2508
2700
  }
2509
2701
  ),
2702
+ /* @__PURE__ */ jsx(
2703
+ "div",
2704
+ {
2705
+ className: "flex flex-wrap items-center gap-1.5",
2706
+ role: "group",
2707
+ "aria-label": tr("fluidgrids.workflowsList.access.label", "Access"),
2708
+ "data-testid": "workflow-access-filter",
2709
+ children: ACCESS_FILTERS.map((option) => /* @__PURE__ */ jsx(
2710
+ "button",
2711
+ {
2712
+ type: "button",
2713
+ "aria-pressed": accessFilter === option.value,
2714
+ onClick: () => setAccessFilter(option.value),
2715
+ className: cn(
2716
+ "rounded-full border px-3 py-1 text-xs font-medium transition-colors",
2717
+ accessFilter === option.value ? "border-transparent bg-primary text-primary-foreground" : "border-border bg-card text-muted-foreground hover:text-foreground"
2718
+ ),
2719
+ children: option.label
2720
+ },
2721
+ option.value
2722
+ ))
2723
+ }
2724
+ ),
2510
2725
  /* @__PURE__ */ jsxs(
2511
2726
  Button,
2512
2727
  {
@@ -2603,7 +2818,7 @@ function WorkflowsList() {
2603
2818
  /* @__PURE__ */ jsx(Icon, { icon: "mynaui:refresh", className: "size-4" }),
2604
2819
  tr("fluidgrids.workflowsList.tryAgainButton", "Try again")
2605
2820
  ] })
2606
- ] }) }) : workflows.length === 0 ? /* @__PURE__ */ jsx("div", { className: "grid flex-1 place-items-center", children: /* @__PURE__ */ jsx(
2821
+ ] }) }) : workflows.length === 0 && !filteredByAccess ? /* @__PURE__ */ jsx("div", { className: "grid flex-1 place-items-center", children: /* @__PURE__ */ jsx(
2607
2822
  IllustratedEmptyState,
2608
2823
  {
2609
2824
  illustration: "onboarding",
@@ -2638,6 +2853,7 @@ function WorkflowsList() {
2638
2853
  setSearch("");
2639
2854
  setStatusFilter(null);
2640
2855
  setTagFilter(null);
2856
+ setAccessFilter("ALL" /* All */);
2641
2857
  },
2642
2858
  children: tr(
2643
2859
  "fluidgrids.workflowsList.clearFiltersButton",
@@ -2679,9 +2895,20 @@ function WorkflowsList() {
2679
2895
  "Tag"
2680
2896
  ),
2681
2897
  color: a.tagInfo?.color ?? void 0
2682
- }))
2898
+ })),
2899
+ visibility: workflow.visibility ?? void 0,
2900
+ my_access: workflow.myAccess ?? null
2683
2901
  },
2684
2902
  onUpdateSuccess: () => refetch(),
2903
+ onShare: () => setSharing({
2904
+ workflowKey: workflow.workflowKey,
2905
+ name: workflow.name
2906
+ }),
2907
+ onMoveToProject: () => setMoving({
2908
+ id: workflow.id,
2909
+ name: workflow.name,
2910
+ projectId: workflow.projectId ?? null
2911
+ }),
2685
2912
  onExport: () => void handleExport(workflow.id),
2686
2913
  onExportAs: codeFirst ? (format) => void handleExportAs(
2687
2914
  workflow.workflowKey,
@@ -2695,6 +2922,25 @@ function WorkflowsList() {
2695
2922
  ]
2696
2923
  }
2697
2924
  ),
2925
+ /* @__PURE__ */ jsx(
2926
+ WorkflowShareDialog,
2927
+ {
2928
+ open: sharing !== null,
2929
+ onClose: () => setSharing(null),
2930
+ workflowKey: sharing?.workflowKey ?? null,
2931
+ workflowName: sharing?.name ?? "",
2932
+ workspaceId,
2933
+ onShared: () => void refetch()
2934
+ }
2935
+ ),
2936
+ /* @__PURE__ */ jsx(
2937
+ WorkflowMoveToProjectDialog,
2938
+ {
2939
+ workflow: moving,
2940
+ onClose: () => setMoving(null),
2941
+ onMoved: () => void refetch()
2942
+ }
2943
+ ),
2698
2944
  /* @__PURE__ */ jsx(
2699
2945
  CreateWorkflowRefusalDialog,
2700
2946
  {