@burdenoff/fluidgrids-fe-sdk 2026.731.4 → 2026.731.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/ExecutionDetailPage-VCVJ2EOP.js +8 -0
  2. package/dist/{ExecutionDetailPage-Q2H7KMHW.js.map → ExecutionDetailPage-VCVJ2EOP.js.map} +1 -1
  3. package/dist/ExecutionsListPage-NXTMFIRZ.js +8 -0
  4. package/dist/{ExecutionsListPage-SMQZVUYI.js.map → ExecutionsListPage-NXTMFIRZ.js.map} +1 -1
  5. package/dist/{WorkflowBuilder-734VD3ZO.js → WorkflowBuilder-IGQYC2UR.js} +6 -6
  6. package/dist/{WorkflowBuilder-734VD3ZO.js.map → WorkflowBuilder-IGQYC2UR.js.map} +1 -1
  7. package/dist/WorkflowsList-S2MGY2UT.js +10 -0
  8. package/dist/{WorkflowsList-ZNSFZMAQ.js.map → WorkflowsList-S2MGY2UT.js.map} +1 -1
  9. package/dist/{blocks-UUACLZOU.js → blocks-K5JPCH3D.js} +4 -4
  10. package/dist/{blocks-UUACLZOU.js.map → blocks-K5JPCH3D.js.map} +1 -1
  11. package/dist/{chunk-BWUUCBIC.js → chunk-2XMPJHCW.js} +355 -121
  12. package/dist/chunk-2XMPJHCW.js.map +1 -0
  13. package/dist/{chunk-4BY7JVRA.js → chunk-6AK7GFWB.js} +3 -3
  14. package/dist/{chunk-4BY7JVRA.js.map → chunk-6AK7GFWB.js.map} +1 -1
  15. package/dist/{chunk-TH764V3S.js → chunk-IVKT244I.js} +13 -7
  16. package/dist/chunk-IVKT244I.js.map +1 -0
  17. package/dist/{chunk-XPUAUQ3I.js → chunk-JIZFSX6X.js} +3 -3
  18. package/dist/{chunk-XPUAUQ3I.js.map → chunk-JIZFSX6X.js.map} +1 -1
  19. package/dist/{chunk-42PCKNPK.js → chunk-NMS2QUXG.js} +18 -11
  20. package/dist/chunk-NMS2QUXG.js.map +1 -0
  21. package/dist/{chunk-IBPEITOH.js → chunk-TKAS26Q3.js} +4 -4
  22. package/dist/{chunk-IBPEITOH.js.map → chunk-TKAS26Q3.js.map} +1 -1
  23. package/dist/{chunk-FTWBKQUU.js → chunk-USFXD36A.js} +4 -4
  24. package/dist/{chunk-FTWBKQUU.js.map → chunk-USFXD36A.js.map} +1 -1
  25. package/dist/{chunk-IU65EQOS.js → chunk-XEYNX7YJ.js} +4 -2
  26. package/dist/chunk-XEYNX7YJ.js.map +1 -0
  27. package/dist/index.d.ts +5 -1
  28. package/dist/index.js +129 -131
  29. package/dist/index.js.map +1 -1
  30. package/package.json +1 -1
  31. package/dist/ExecutionDetailPage-Q2H7KMHW.js +0 -8
  32. package/dist/ExecutionsListPage-SMQZVUYI.js +0 -8
  33. package/dist/WorkflowsList-ZNSFZMAQ.js +0 -10
  34. package/dist/chunk-42PCKNPK.js.map +0 -1
  35. package/dist/chunk-BWUUCBIC.js.map +0 -1
  36. package/dist/chunk-IU65EQOS.js.map +0 -1
  37. package/dist/chunk-TH764V3S.js.map +0 -1
@@ -1,17 +1,18 @@
1
1
  import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, Input as Input$1, DialogFooter } from './chunk-MRVS73S2.js';
2
2
  import { Badge as Badge$1, Button } from './chunk-DBOMRIP5.js';
3
- import { refetchStoreNodes, registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, STICKY_NOTE_TYPE, useNodeExecution, getNodeDetail, ConnectionSelector, mergeStickyNotes, buildStickyNode, NODES_METADATA, NODE_CONFIGS, isNodeConfigsInitialized, NODES, NodePropertyPanel } from './chunk-TH764V3S.js';
3
+ import { refetchStoreNodes, registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, AVAILABLE_NODES, useInsertNode, NODE_TYPE_DRAG_DATA_FORMAT, NODE_OPERATION_DRAG_DATA_FORMAT, useSaveWorkflow, STICKY_NOTE_TYPE, useNodeExecution, getNodeDetail, ConnectionSelector, mergeStickyNotes, buildStickyNode, NODES_METADATA, NODE_CONFIGS, isNodeConfigsInitialized, NODES, NodePropertyPanel } from './chunk-IVKT244I.js';
4
4
  import { createGlobalStoreClient, setGlobalStoreClient, resetGlobalStoreClient, getGlobalStoreClient } from './chunk-BQXHJIER.js';
5
5
  import { BrowseWorkflowTemplatesDocument, InstallWorkflowNodeDocument, InstallPurchasedNodeDocument, GetMyNodeInstallationsDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument } from './chunk-PNOA7CQV.js';
6
- import { useLazyWorkflowDefinition, useCreateWorkflow, useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeactivateWorkflow } from './chunk-42PCKNPK.js';
6
+ import { useLazyWorkflowDefinition, useCreateWorkflow, useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeleteWorkflow, useDeactivateWorkflow } from './chunk-NMS2QUXG.js';
7
7
  import { useFlowStore } from './chunk-KU64CCSV.js';
8
8
  import { SdkPermissionButton, FLUIDGRIDS_PERMISSIONS } from './chunk-UIY2HBWA.js';
9
9
  import { cn } from './chunk-3ZYUGTIT.js';
10
- import { throwIfResultError, NodeSchemaIntrospectionDocument, EventRegistrationsDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-IU65EQOS.js';
10
+ import { throwIfResultError, NodeSchemaIntrospectionDocument, EventRegistrationsDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-XEYNX7YJ.js';
11
11
  import { createFluidGridsClient, setFluidGridsClient, resetFluidGridsClient, getFluidGridsClient, getFluidGridsClientSafe } from './chunk-5BDQNSP3.js';
12
12
  import { validateTrustedOrigin, setFluidGridsConfig, resetFluidGridsConfig, getFluidGridsConfig } from './chunk-WWU2O2SR.js';
13
13
  import { deepClone, applyTemplateInputs } from './chunk-XQP33UJR.js';
14
14
  import { useNavigate, useParams } from 'react-router-dom';
15
+ import { toast } from 'sonner';
15
16
  import { Icon } from '@iconify/react';
16
17
  import { useShallow, shallow } from 'zustand/shallow';
17
18
  import * as React3 from 'react';
@@ -20,14 +21,13 @@ import { Handle, Position, getBezierPath, MarkerType, ReactFlowProvider, useReac
20
21
  import { produce } from 'immer';
21
22
  import { cn as cn$1 } from '@burdenoff/fe-libs/utils';
22
23
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
- import { Card as Card$1, Badge, CardContent as CardContent$1, Button as Button$1, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, DropdownMenuItem, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Popover, PopoverTrigger, PopoverContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, Label, DropdownMenuLabel, DropdownMenuSeparator, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea } from '@burdenoff/fe-libs/ui';
24
+ import { Card as Card$1, Badge, CardContent as CardContent$1, Button as Button$1, Input, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, TooltipProvider, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, DropdownMenuItem, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Popover, PopoverTrigger, PopoverContent, Tooltip, TooltipTrigger, TooltipContent, Toaster, Tabs, TabsList, TabsTrigger, TabsContent, CardHeader as CardHeader$1, CardTitle as CardTitle$1, CardDescription as CardDescription$1, ScrollArea, Label, DropdownMenuLabel, DropdownMenuSeparator, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea } from '@burdenoff/fe-libs/ui';
24
25
  import { isEmpty } from 'radash';
25
26
  import { gql } from '@apollo/client';
26
27
  import { ApolloProvider, useQuery, useMutation } from '@apollo/client/react';
27
28
  import 'jszip';
28
29
  import { gql as gql$1 } from '@apollo/client/core';
29
- import { Sparkles, Star, Download, Eye, History, Loader2, RotateCcw, Maximize2, LayoutGrid, Plus, Trash2, GitBranch, AlertCircle, Search, RefreshCw, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, PlusCircle, ChevronDown, Type, Code, Hash, List, Braces, Workflow, ChevronRight, Layers, X, AlertTriangle } from 'lucide-react';
30
- import { toast } from 'sonner';
30
+ import { Sparkles, Star, Download, Eye, History, Loader2, Play, RotateCcw, Trash2, Maximize2, LayoutGrid, Plus, GitBranch, AlertCircle, Search, RefreshCw, CheckCircle2, Package, Info, Copy, BadgeCheck, DollarSign, PlusCircle, ChevronDown, Type, Code, Hash, List, Braces, Workflow, ChevronRight, Layers, X, AlertTriangle } from 'lucide-react';
31
31
  import { animate, easeOut } from 'popmotion';
32
32
  import { createPortal } from 'react-dom';
33
33
  import { ThemeProvider as ThemeProvider$1 } from '@burdenoff/fe-libs/shared/providers/shell';
@@ -38,6 +38,7 @@ import { nanoid } from 'nanoid/non-secure';
38
38
  import CodeMirror from '@uiw/react-codemirror';
39
39
  import { javascript } from '@codemirror/lang-javascript';
40
40
  import { python } from '@codemirror/lang-python';
41
+ import { useActorProfiles, buildActorFallback } from '@burdenoff/fe-libs/shared';
41
42
  import { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';
42
43
 
43
44
  function useNodeList(nodes) {
@@ -4074,7 +4075,7 @@ function DesktopSidebarFragment({
4074
4075
  if (nodes) {
4075
4076
  const requiredNodeTypes = [];
4076
4077
  try {
4077
- const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-UUACLZOU.js');
4078
+ const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-K5JPCH3D.js');
4078
4079
  await ensureNodeConfigsLoaded2().catch(() => {
4079
4080
  });
4080
4081
  const workflowNodeTypes = [
@@ -5319,8 +5320,8 @@ var reducer = (state, action) => {
5319
5320
  if (toastId) {
5320
5321
  addToRemoveQueue(toastId);
5321
5322
  } else {
5322
- state.toasts.forEach((toast9) => {
5323
- addToRemoveQueue(toast9.id);
5323
+ state.toasts.forEach((toast10) => {
5324
+ addToRemoveQueue(toast10.id);
5324
5325
  });
5325
5326
  }
5326
5327
  return {
@@ -6530,7 +6531,7 @@ function VisualMapperContent({
6530
6531
  mapping,
6531
6532
  onMappingChange
6532
6533
  }) {
6533
- const { toast: toast9 } = useToast();
6534
+ const { toast: toast10 } = useToast();
6534
6535
  const reactFlowWrapper = useRef(null);
6535
6536
  const [selectedSourceNode, setSelectedSourceNode] = useState(null);
6536
6537
  const [selectedTargetNode, setSelectedTargetNode] = useState(null);
@@ -6549,7 +6550,7 @@ function VisualMapperContent({
6549
6550
  targetOperation
6550
6551
  );
6551
6552
  if (generatedNodes.length === 0) {
6552
- toast9({
6553
+ toast10({
6553
6554
  title: "No fields found",
6554
6555
  description: "Could not find fields to map between these nodes and operations.",
6555
6556
  variant: "destructive"
@@ -6569,7 +6570,7 @@ function VisualMapperContent({
6569
6570
  targetNode,
6570
6571
  targetOperation,
6571
6572
  setNodes,
6572
- toast9
6573
+ toast10
6573
6574
  ]);
6574
6575
  useEffect(() => {
6575
6576
  const newEdges = [];
@@ -6675,26 +6676,26 @@ function VisualMapperContent({
6675
6676
  }
6676
6677
  onMappingChange(updatedMapping);
6677
6678
  if (isCompatible) {
6678
- toast9({
6679
+ toast10({
6679
6680
  title: "Mapping created",
6680
6681
  description: `Mapped ${sourcePath} (${sourceType}) to ${targetPath} (${targetType})`
6681
6682
  });
6682
6683
  } else {
6683
- toast9({
6684
+ toast10({
6684
6685
  title: "Type mismatch warning",
6685
6686
  description: `Mapped ${sourcePath} (${sourceType}) to ${targetPath} (${targetType}). Types may not be compatible.`,
6686
6687
  variant: "destructive"
6687
6688
  });
6688
6689
  }
6689
6690
  } else {
6690
- toast9({
6691
+ toast10({
6691
6692
  title: "Invalid mapping",
6692
6693
  description: "You can only map from source to target fields",
6693
6694
  variant: "destructive"
6694
6695
  });
6695
6696
  }
6696
6697
  },
6697
- [nodes, mapping, onMappingChange, toast9, setEdges]
6698
+ [nodes, mapping, onMappingChange, toast10, setEdges]
6698
6699
  );
6699
6700
  const onEdgeDelete = useCallback(
6700
6701
  (edge) => {
@@ -6751,7 +6752,7 @@ function VisualMapperContent({
6751
6752
  const handleSaveMappingDialog = (expression, targetFieldName) => {
6752
6753
  const targetPath = targetFieldName || selectedTargetNode?.data?.path;
6753
6754
  if (!targetPath) {
6754
- toast9({
6755
+ toast10({
6755
6756
  title: "No target field specified",
6756
6757
  description: "Please enter a target field name or select a target field in the visual mapper",
6757
6758
  variant: "destructive"
@@ -6777,7 +6778,7 @@ function VisualMapperContent({
6777
6778
  }
6778
6779
  onMappingChange(updatedMapping);
6779
6780
  const mappingType = detectMappingType(expression);
6780
- toast9({
6781
+ toast10({
6781
6782
  title: `${mappingType.charAt(0).toUpperCase() + mappingType.slice(1)} mapping created`,
6782
6783
  description: `Applied mapping to ${targetPath}`
6783
6784
  });
@@ -7033,7 +7034,7 @@ function MappingEditor({
7033
7034
  setEdges,
7034
7035
  edgeId
7035
7036
  }) {
7036
- const { toast: toast9 } = useToast();
7037
+ const { toast: toast10 } = useToast();
7037
7038
  const [mappingJson, setMappingJson] = useState({});
7038
7039
  const [jsonDataString, setJsonDataString] = useState(
7039
7040
  JSON.stringify(mappingJson, null, 2)
@@ -7146,12 +7147,12 @@ function MappingEditor({
7146
7147
  const handleSaveMapping = () => {
7147
7148
  try {
7148
7149
  checkJsonValidity();
7149
- toast9({
7150
+ toast10({
7150
7151
  title: "Mapping saved",
7151
7152
  description: "Your mapping configuration has been saved successfully."
7152
7153
  });
7153
7154
  } catch (error) {
7154
- toast9({
7155
+ toast10({
7155
7156
  title: "Error saving mapping",
7156
7157
  description: error instanceof Error ? error.message : "Invalid mapping configuration",
7157
7158
  variant: "destructive"
@@ -7164,13 +7165,13 @@ function MappingEditor({
7164
7165
  const parsedData = checkJsonValidity();
7165
7166
  const result = await applyMapping(parsedData, sampleInput);
7166
7167
  setPreviewOutput(result);
7167
- toast9({
7168
+ toast10({
7168
7169
  title: "Mapping tested",
7169
7170
  description: "Test completed successfully."
7170
7171
  });
7171
7172
  } catch (error) {
7172
7173
  console.error("Test mapping error:", error);
7173
- toast9({
7174
+ toast10({
7174
7175
  title: "Mapping test failed",
7175
7176
  description: error instanceof Error ? error.message : "Error executing mapping",
7176
7177
  variant: "destructive"
@@ -13297,16 +13298,96 @@ var STATUS_STYLES = {
13297
13298
  ARCHIVED: { label: "Archived", variant: "outline" },
13298
13299
  DEPRECATED: { label: "Deprecated", variant: "destructive" }
13299
13300
  };
13301
+ function relativeTime(dateStr) {
13302
+ if (!dateStr) return "";
13303
+ const then = new Date(dateStr).getTime();
13304
+ if (Number.isNaN(then)) return "";
13305
+ const seconds = Math.round((Date.now() - then) / 1e3);
13306
+ if (seconds < 60) return "just now";
13307
+ const minutes = Math.round(seconds / 60);
13308
+ if (minutes < 60) return `${minutes}m ago`;
13309
+ const hours = Math.round(minutes / 60);
13310
+ if (hours < 24) return `${hours}h ago`;
13311
+ const days = Math.round(hours / 24);
13312
+ if (days < 30) return `${days}d ago`;
13313
+ return new Intl.DateTimeFormat("en-US", {
13314
+ year: "numeric",
13315
+ month: "short",
13316
+ day: "numeric"
13317
+ }).format(new Date(dateStr));
13318
+ }
13319
+ function absoluteTime(dateStr) {
13320
+ if (!dateStr) return "";
13321
+ try {
13322
+ return new Intl.DateTimeFormat("en-US", {
13323
+ year: "numeric",
13324
+ month: "short",
13325
+ day: "numeric",
13326
+ hour: "2-digit",
13327
+ minute: "2-digit"
13328
+ }).format(new Date(dateStr));
13329
+ } catch {
13330
+ return dateStr;
13331
+ }
13332
+ }
13333
+ function ActionButton({
13334
+ label,
13335
+ onClick,
13336
+ disabled,
13337
+ busy,
13338
+ icon,
13339
+ destructive
13340
+ }) {
13341
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
13342
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
13343
+ Button$1,
13344
+ {
13345
+ variant: "ghost",
13346
+ size: "sm",
13347
+ className: cn$1(
13348
+ "size-7 p-0",
13349
+ destructive && "text-[var(--color-status-error-text)] hover:text-[var(--color-status-error-text)] hover:bg-[var(--color-status-error-bg-subtle)]"
13350
+ ),
13351
+ disabled,
13352
+ onClick,
13353
+ "aria-label": label,
13354
+ children: busy ? /* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin" }) : icon
13355
+ }
13356
+ ) }),
13357
+ /* @__PURE__ */ jsx(TooltipContent, { className: "z-[130]", children: label })
13358
+ ] });
13359
+ }
13300
13360
  function VersionHistoryPanel({ className }) {
13301
13361
  const params = useParams();
13302
13362
  const navigate = useNavigate();
13303
13363
  const workflowKey = params?.id ?? "";
13304
13364
  const currentVersion = params?.version ?? "";
13305
13365
  const { versions, loading, refetch } = useWorkflowVersions(workflowKey);
13306
- const { restoreVersion, loading: restoring } = useRestoreWorkflowVersion();
13307
- const [restoringVersion, setRestoringVersion] = useState(null);
13366
+ const { restoreVersion } = useRestoreWorkflowVersion();
13367
+ const { activateWorkflow } = useActivateWorkflow();
13368
+ const { deleteWorkflow } = useDeleteWorkflow();
13369
+ const setWorkflow = useFlowStore((s) => s.actions.setWorkflow);
13370
+ const [busy, setBusy] = useState(null);
13371
+ const [deleteTarget, setDeleteTarget] = useState(null);
13372
+ const config = getFluidGridsConfig();
13373
+ const actorInputs = useMemo(() => {
13374
+ const ids = /* @__PURE__ */ new Set();
13375
+ for (const v of versions) {
13376
+ if (v.createdById) ids.add(v.createdById);
13377
+ }
13378
+ return [...ids].map((actorId) => ({ actorId, actorType: "user" }));
13379
+ }, [versions]);
13380
+ const actorProfiles = useActorProfiles(actorInputs, {
13381
+ workspaceId: config.workspaceId || void 0,
13382
+ orgId: config.organizationId,
13383
+ authToken: config.authToken
13384
+ });
13385
+ const authorName = (createdById) => {
13386
+ if (!createdById) return null;
13387
+ return actorProfiles[createdById]?.displayName ?? buildActorFallback({ actorId: createdById, actorType: "user" }).displayName;
13388
+ };
13308
13389
  const handleRestore = async (version) => {
13309
- setRestoringVersion(version);
13390
+ setBusy(`restore:${version}`);
13310
13391
  try {
13311
13392
  const result = await restoreVersion(workflowKey, version);
13312
13393
  if (result?.success && result.workflow) {
@@ -13325,7 +13406,48 @@ function VersionHistoryPanel({ className }) {
13325
13406
  description: error instanceof Error ? error.message : "Unknown error"
13326
13407
  });
13327
13408
  } finally {
13328
- setRestoringVersion(null);
13409
+ setBusy(null);
13410
+ }
13411
+ };
13412
+ const handleActivate = async (id, version) => {
13413
+ setBusy(`activate:${version}`);
13414
+ try {
13415
+ const result = await activateWorkflow(id);
13416
+ if (!result) throw new Error("Activation returned no result");
13417
+ toast.success(`Version ${version} is now ACTIVE`, {
13418
+ description: "It handles webhooks, schedules and other automatic triggers.",
13419
+ dismissible: true
13420
+ });
13421
+ if (version === currentVersion) {
13422
+ setWorkflow({ status: "ACTIVE" });
13423
+ } else {
13424
+ const refreshed = await refetch();
13425
+ const current = refreshed.find((v) => v.version === currentVersion);
13426
+ if (current?.status) setWorkflow({ status: current.status });
13427
+ }
13428
+ await refetch();
13429
+ } catch (error) {
13430
+ toast.error("Failed to activate version", {
13431
+ description: error instanceof Error ? error.message : "Unknown error"
13432
+ });
13433
+ } finally {
13434
+ setBusy(null);
13435
+ }
13436
+ };
13437
+ const handleDelete = async (version) => {
13438
+ setBusy(`delete:${version}`);
13439
+ try {
13440
+ const ok = await deleteWorkflow(workflowKey, version);
13441
+ if (!ok) throw new Error("Delete returned no result");
13442
+ toast.success(`Version ${version} deleted`, { dismissible: true });
13443
+ await refetch();
13444
+ } catch (error) {
13445
+ toast.error("Failed to delete version", {
13446
+ description: error instanceof Error ? error.message : "Unknown error"
13447
+ });
13448
+ } finally {
13449
+ setBusy(null);
13450
+ setDeleteTarget(null);
13329
13451
  }
13330
13452
  };
13331
13453
  const handleSwitchVersion = (version) => {
@@ -13346,83 +13468,185 @@ function VersionHistoryPanel({ className }) {
13346
13468
  }
13347
13469
  ) }),
13348
13470
  /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "w-[380px] sm:w-[420px]", children: [
13349
- /* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsxs(SheetTitle, { className: "flex items-center gap-2", children: [
13350
- /* @__PURE__ */ jsx(History, { className: "size-5" }),
13351
- "Version History"
13352
- ] }) }),
13353
- /* @__PURE__ */ jsx("div", { className: "mt-4 space-y-2 overflow-y-auto max-h-[calc(100vh-120px)]", children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-8", children: [
13471
+ /* @__PURE__ */ jsxs(SheetHeader, { children: [
13472
+ /* @__PURE__ */ jsxs(SheetTitle, { className: "flex items-center gap-2", children: [
13473
+ /* @__PURE__ */ jsx(History, { className: "size-5" }),
13474
+ "Version History"
13475
+ ] }),
13476
+ !loading && versions.length > 0 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
13477
+ versions.length,
13478
+ " ",
13479
+ versions.length === 1 ? "version" : "versions",
13480
+ " ",
13481
+ "\xB7 the Active version handles automatic triggers"
13482
+ ] })
13483
+ ] }),
13484
+ /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsx("div", { className: "mt-4 overflow-y-auto max-h-[calc(100vh-140px)] pr-1", children: loading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-8", children: [
13354
13485
  /* @__PURE__ */ jsx(Loader2, { className: "size-5 animate-spin text-muted-foreground" }),
13355
13486
  /* @__PURE__ */ jsx("span", { className: "ml-2 text-muted-foreground text-sm", children: "Loading versions..." })
13356
- ] }) : versions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm text-center py-8", children: "No versions found." }) : versions.map((v) => {
13487
+ ] }) : versions.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm text-center py-8", children: "No versions found." }) : /* @__PURE__ */ jsx("ul", { children: versions.map((v, index) => {
13357
13488
  const isCurrent = v.version === currentVersion;
13489
+ const isActive = v.status === "ACTIVE";
13490
+ const isLast = index === versions.length - 1;
13358
13491
  const statusInfo = STATUS_STYLES[v.status ?? "DRAFT"] ?? STATUS_STYLES.DRAFT;
13359
- return /* @__PURE__ */ jsxs(
13360
- "div",
13361
- {
13362
- className: `p-3 rounded-lg border transition-colors ${isCurrent ? "border-primary/50 bg-primary/5" : "border-border hover:bg-accent/50"}`,
13363
- children: [
13364
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
13365
- /* @__PURE__ */ jsx("span", { className: "font-mono text-sm font-medium", children: v.version }),
13366
- /* @__PURE__ */ jsx(
13367
- Badge,
13368
- {
13369
- variant: statusInfo.variant,
13370
- className: "text-[10px] px-1.5 py-0 h-5",
13371
- children: statusInfo.label
13372
- }
13373
- ),
13374
- isCurrent && /* @__PURE__ */ jsx(
13375
- Badge,
13376
- {
13377
- variant: "outline",
13378
- className: "text-[10px] px-1.5 py-0 h-5 border-primary text-primary",
13379
- children: "Current"
13380
- }
13492
+ const author = authorName(v.createdById);
13493
+ return /* @__PURE__ */ jsxs("li", { className: "flex gap-3", children: [
13494
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center pt-4", children: [
13495
+ /* @__PURE__ */ jsx(
13496
+ "span",
13497
+ {
13498
+ className: cn$1(
13499
+ "size-2.5 shrink-0 rounded-full border-2",
13500
+ isActive ? "border-[var(--color-status-success-bg)] bg-[var(--color-status-success-bg)]" : isCurrent ? "border-primary bg-primary" : "border-border bg-background"
13381
13501
  )
13382
- ] }) }),
13383
- v.alias && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-1", children: [
13384
- "Alias: ",
13385
- v.alias
13386
- ] }),
13387
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: v.updatedAt ? new Intl.DateTimeFormat("en-US", {
13388
- year: "numeric",
13389
- month: "short",
13390
- day: "numeric",
13391
- hour: "2-digit",
13392
- minute: "2-digit"
13393
- }).format(new Date(v.updatedAt)) : "N/A" }),
13394
- !isCurrent && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-2", children: [
13395
- /* @__PURE__ */ jsx(
13396
- Button$1,
13397
- {
13398
- variant: "ghost",
13399
- size: "sm",
13400
- className: "h-7 text-xs",
13401
- onClick: () => handleSwitchVersion(v.version),
13402
- children: "View"
13403
- }
13404
- ),
13502
+ }
13503
+ ),
13504
+ !isLast && /* @__PURE__ */ jsx("span", { className: "w-px flex-1 bg-border" })
13505
+ ] }),
13506
+ /* @__PURE__ */ jsxs(
13507
+ "div",
13508
+ {
13509
+ className: cn$1(
13510
+ "mb-2 flex-1 rounded-lg border p-3 transition-colors",
13511
+ isCurrent ? "border-primary/50 bg-primary/5" : "border-border hover:bg-accent/50"
13512
+ ),
13513
+ children: [
13514
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
13515
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
13516
+ /* @__PURE__ */ jsx(
13517
+ "button",
13518
+ {
13519
+ type: "button",
13520
+ className: cn$1(
13521
+ "font-mono text-sm font-semibold text-foreground",
13522
+ !isCurrent && "cursor-pointer hover:text-primary"
13523
+ ),
13524
+ onClick: () => !isCurrent && handleSwitchVersion(v.version),
13525
+ title: isCurrent ? void 0 : `Open ${v.version} in the builder`,
13526
+ children: v.version
13527
+ }
13528
+ ),
13529
+ /* @__PURE__ */ jsx(
13530
+ Badge,
13531
+ {
13532
+ variant: statusInfo.variant,
13533
+ className: "text-[10px] px-1.5 py-0 h-5",
13534
+ children: statusInfo.label
13535
+ }
13536
+ ),
13537
+ isCurrent && /* @__PURE__ */ jsx(
13538
+ Badge,
13539
+ {
13540
+ variant: "outline",
13541
+ className: "text-[10px] px-1.5 py-0 h-5 border-primary text-primary",
13542
+ children: "Current"
13543
+ }
13544
+ ),
13545
+ v.alias && /* @__PURE__ */ jsxs(
13546
+ Badge,
13547
+ {
13548
+ variant: "outline",
13549
+ className: "text-[10px] px-1.5 py-0 h-5 font-mono",
13550
+ title: "Version alias",
13551
+ children: [
13552
+ "@",
13553
+ v.alias
13554
+ ]
13555
+ }
13556
+ )
13557
+ ] }),
13558
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center", children: [
13559
+ !isCurrent && /* @__PURE__ */ jsx(
13560
+ ActionButton,
13561
+ {
13562
+ label: "View in builder",
13563
+ icon: /* @__PURE__ */ jsx(Eye, { className: "size-3.5" }),
13564
+ disabled: busy !== null,
13565
+ onClick: () => handleSwitchVersion(v.version)
13566
+ }
13567
+ ),
13568
+ !isActive && /* @__PURE__ */ jsx(
13569
+ ActionButton,
13570
+ {
13571
+ label: "Activate this version",
13572
+ icon: /* @__PURE__ */ jsx(Play, { className: "size-3.5" }),
13573
+ disabled: busy !== null,
13574
+ busy: busy === `activate:${v.version}`,
13575
+ onClick: () => handleActivate(v.id, v.version)
13576
+ }
13577
+ ),
13578
+ !isCurrent && /* @__PURE__ */ jsx(
13579
+ ActionButton,
13580
+ {
13581
+ label: "Restore as new draft",
13582
+ icon: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5" }),
13583
+ disabled: busy !== null,
13584
+ busy: busy === `restore:${v.version}`,
13585
+ onClick: () => handleRestore(v.version)
13586
+ }
13587
+ ),
13588
+ !isCurrent && !isActive && /* @__PURE__ */ jsx(
13589
+ ActionButton,
13590
+ {
13591
+ label: "Delete version",
13592
+ destructive: true,
13593
+ icon: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" }),
13594
+ disabled: busy !== null,
13595
+ busy: busy === `delete:${v.version}`,
13596
+ onClick: () => setDeleteTarget(v.version)
13597
+ }
13598
+ )
13599
+ ] })
13600
+ ] }),
13405
13601
  /* @__PURE__ */ jsxs(
13406
- Button$1,
13602
+ "p",
13407
13603
  {
13408
- variant: "outline",
13409
- size: "sm",
13410
- className: "h-7 text-xs",
13411
- disabled: restoring,
13412
- onClick: () => handleRestore(v.version),
13604
+ className: "mt-1.5 text-xs text-muted-foreground",
13605
+ title: absoluteTime(v.updatedAt),
13413
13606
  children: [
13414
- restoringVersion === v.version ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin mr-1" }) : /* @__PURE__ */ jsx(RotateCcw, { className: "size-3 mr-1" }),
13415
- "Restore"
13607
+ author ? `${author} \xB7 ` : "",
13608
+ relativeTime(v.updatedAt)
13416
13609
  ]
13417
13610
  }
13418
13611
  )
13419
- ] })
13420
- ]
13421
- },
13422
- v.id
13423
- );
13424
- }) })
13425
- ] })
13612
+ ]
13613
+ }
13614
+ )
13615
+ ] }, v.id);
13616
+ }) }) }) })
13617
+ ] }),
13618
+ /* @__PURE__ */ jsx(
13619
+ AlertDialog,
13620
+ {
13621
+ open: deleteTarget !== null,
13622
+ onOpenChange: (open) => !open && setDeleteTarget(null),
13623
+ children: /* @__PURE__ */ jsxs(AlertDialogContent, { className: "z-[120]", children: [
13624
+ /* @__PURE__ */ jsxs(AlertDialogHeader, { children: [
13625
+ /* @__PURE__ */ jsxs(AlertDialogTitle, { children: [
13626
+ "Delete version ",
13627
+ deleteTarget
13628
+ ] }),
13629
+ /* @__PURE__ */ jsxs(AlertDialogDescription, { children: [
13630
+ "This permanently removes version ",
13631
+ deleteTarget,
13632
+ " from the history. Other versions and their triggers are not affected. This action cannot be undone."
13633
+ ] })
13634
+ ] }),
13635
+ /* @__PURE__ */ jsxs(AlertDialogFooter, { children: [
13636
+ /* @__PURE__ */ jsx(AlertDialogCancel, { disabled: busy !== null, children: "Cancel" }),
13637
+ /* @__PURE__ */ jsx(
13638
+ AlertDialogAction,
13639
+ {
13640
+ disabled: busy !== null,
13641
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
13642
+ onClick: () => deleteTarget && handleDelete(deleteTarget),
13643
+ children: "Delete"
13644
+ }
13645
+ )
13646
+ ] })
13647
+ ] })
13648
+ }
13649
+ )
13426
13650
  ] });
13427
13651
  }
13428
13652
  var ActivateWorkflowButton = ({
@@ -13689,42 +13913,39 @@ var FlowBuilder = ({ readOnly = false }) => {
13689
13913
  Input,
13690
13914
  {
13691
13915
  autoFocus: true,
13692
- className: "text-card-foreground font-bold w-48",
13693
- type: "email",
13916
+ onFocus: (e) => e.currentTarget.select(),
13917
+ className: "text-card-foreground font-bold",
13918
+ style: {
13919
+ width: `${Math.min(
13920
+ Math.max((workflowName || name || "").length + 4, 16),
13921
+ 60
13922
+ )}ch`
13923
+ },
13924
+ type: "text",
13694
13925
  placeholder: "Workflow Name",
13695
13926
  value: workflowName || name,
13696
13927
  onChange: handleNameChange,
13697
13928
  onBlur: () => setIsEditingName(false),
13698
13929
  onKeyDown: (e) => {
13699
- if (e.key === "Enter") setIsEditingName(false);
13930
+ if (e.key === "Enter" || e.key === "Escape")
13931
+ setIsEditingName(false);
13700
13932
  }
13701
13933
  }
13702
- ) : /* @__PURE__ */ jsxs("div", { className: "group flex items-center gap-1.5", children: [
13703
- /* @__PURE__ */ jsx(
13704
- "div",
13705
- {
13706
- title: workflowName || name || "Untitled Workflow",
13707
- className: "w-48 overflow-x-auto whitespace-nowrap text-card-foreground font-bold [scrollbar-width:thin]",
13708
- children: workflowName || name || "Untitled Workflow"
13709
- }
13710
- ),
13934
+ ) : (
13935
+ // n8n-style: the name itself is the edit affordance — click to
13936
+ // rename (no pencil button). Long names truncate with an
13937
+ // ellipsis (full name in the tooltip) instead of scrolling.
13711
13938
  /* @__PURE__ */ jsx(
13712
- Button$1,
13939
+ "button",
13713
13940
  {
13714
- variant: "ghost",
13715
- size: "icon",
13716
- className: "size-6 shrink-0 opacity-60 group-hover:opacity-100",
13941
+ type: "button",
13942
+ title: `${workflowName || name || "Untitled Workflow"} \u2014 click to rename`,
13943
+ className: "-mx-1 min-w-[15rem] max-w-[38vw] cursor-text truncate rounded px-1 text-left font-bold text-card-foreground transition-colors hover:bg-card-foreground/10",
13717
13944
  onClick: () => setIsEditingName(true),
13718
- children: /* @__PURE__ */ jsx(
13719
- Icon,
13720
- {
13721
- icon: "mynaui:pencil",
13722
- className: "size-3.5 text-card-foreground"
13723
- }
13724
- )
13945
+ children: workflowName || name || "Untitled Workflow"
13725
13946
  }
13726
13947
  )
13727
- ] }),
13948
+ ),
13728
13949
  /* @__PURE__ */ jsx(
13729
13950
  Input,
13730
13951
  {
@@ -13962,6 +14183,7 @@ function WorkflowItem({
13962
14183
  window.history.replaceState(null, "", newUrl);
13963
14184
  }
13964
14185
  const { id, version } = useParams();
14186
+ const navigate = useNavigate();
13965
14187
  const [workflow, setWorkflow] = useState(null);
13966
14188
  const [isLoading, setIsLoading] = useState(true);
13967
14189
  const resetWorkflow = useFlowStore((s) => s.actions.resetWorkflow);
@@ -14088,7 +14310,7 @@ function WorkflowItem({
14088
14310
  };
14089
14311
  const requiredNodeTypes = [];
14090
14312
  try {
14091
- const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-UUACLZOU.js');
14313
+ const { NODE_CONFIGS: NODE_CONFIGS3, ensureNodeConfigsLoaded: ensureNodeConfigsLoaded2 } = await import('./blocks-K5JPCH3D.js');
14092
14314
  await ensureNodeConfigsLoaded2().catch(() => {
14093
14315
  });
14094
14316
  const workflowNodeTypes = [
@@ -14213,6 +14435,17 @@ function WorkflowItem({
14213
14435
  setWorkflow(fetchedWorkflowRef.current);
14214
14436
  return;
14215
14437
  }
14438
+ const anyVersion = await getWorkflow(id, void 0, void 0);
14439
+ if (anyVersion?.workflowKey) {
14440
+ toast.info(`Version ${version} not found`, {
14441
+ description: `Opening ${anyVersion.version} instead.`,
14442
+ dismissible: true
14443
+ });
14444
+ navigate(`../workflow/${id}/${anyVersion.version}`, {
14445
+ replace: true
14446
+ });
14447
+ return;
14448
+ }
14216
14449
  if (!creatingRef.current) {
14217
14450
  creatingRef.current = true;
14218
14451
  const initialDefinitionJson = {
@@ -14282,7 +14515,8 @@ function WorkflowItem({
14282
14515
  createWorkflow,
14283
14516
  getWorkflow,
14284
14517
  newWorkflow,
14285
- resetWorkflow
14518
+ resetWorkflow,
14519
+ navigate
14286
14520
  // buildNodeCheckRef is intentionally omitted — it's a ref (stable by definition)
14287
14521
  // and including buildNodeCheck here caused infinite re-runs because installedAppIds
14288
14522
  // produces a new Set reference on every render.
@@ -14374,5 +14608,5 @@ function WorkflowBuilder() {
14374
14608
  }
14375
14609
 
14376
14610
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, FlowBuilderPage, FluidGridsProvider, TemplateCard, WorkflowBuilder, useFluidGridsContext, useImportWorkflowTemplate, useWorkflowTemplates };
14377
- //# sourceMappingURL=chunk-BWUUCBIC.js.map
14378
- //# sourceMappingURL=chunk-BWUUCBIC.js.map
14611
+ //# sourceMappingURL=chunk-2XMPJHCW.js.map
14612
+ //# sourceMappingURL=chunk-2XMPJHCW.js.map