@dilipod/ui 0.4.7 → 0.4.8
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/components/activity-timeline.d.ts +44 -0
- package/dist/components/activity-timeline.d.ts.map +1 -0
- package/dist/components/workflow-flow.d.ts +27 -0
- package/dist/components/workflow-flow.d.ts.map +1 -0
- package/dist/components/workflow-viewer.d.ts +138 -0
- package/dist/components/workflow-viewer.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1017 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1017 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/src/components/activity-timeline.tsx +208 -0
- package/src/components/workflow-flow.tsx +277 -0
- package/src/components/workflow-viewer.tsx +1032 -0
- package/src/index.ts +16 -0
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import * as React50 from 'react';
|
|
3
|
-
import { useState, useRef } from 'react';
|
|
3
|
+
import { lazy, useMemo, useState, useRef, Suspense } from 'react';
|
|
4
|
+
import { MarkerType, useNodesState, useEdgesState, ReactFlow, Background, Handle, Position } from '@xyflow/react';
|
|
5
|
+
import '@xyflow/react/dist/style.css';
|
|
6
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
7
|
import { Slot, Slottable, createSlot } from '@radix-ui/react-slot';
|
|
5
8
|
import { cva } from 'class-variance-authority';
|
|
6
9
|
import { clsx } from 'clsx';
|
|
7
10
|
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
9
11
|
import * as SheetPrimitive from '@radix-ui/react-dialog';
|
|
10
12
|
import * as react_star from '@phosphor-icons/react';
|
|
11
|
-
import { X, CaretDown, Circle, CaretLeft, DotsThree, CaretRight, Check, House, Info, WarningCircle, Play, Download, Folder, ArrowSquareOut, CircleNotch, File, FileVideo, Lightning, Plus, CheckCircle, FileImage, FilePdf, FileDoc, Question, Warning,
|
|
13
|
+
import { X, CaretDown, Circle, CaretLeft, DotsThree, CaretRight, Check, House, Info, WarningCircle, Play, Download, Folder, ArrowSquareOut, CircleNotch, File, FileVideo, Lightning, Plus, CheckCircle, PaperPlaneTilt, CaretUp, Eye, TreeStructure, Code, PencilSimple, Copy, CloudArrowUp, CloudArrowDown, FileImage, FilePdf, FileDoc, Question, Warning, Trash, Robot, Globe, GitBranch, WebhooksLogo, Package, Timer } from '@phosphor-icons/react';
|
|
12
14
|
import 'react-dom';
|
|
13
15
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
14
16
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
@@ -26,6 +28,9 @@ var __defProp = Object.defineProperty;
|
|
|
26
28
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
27
29
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
28
30
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
31
|
+
var __esm = (fn, res) => function __init() {
|
|
32
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
33
|
+
};
|
|
29
34
|
var __export = (target, all) => {
|
|
30
35
|
for (var name in all)
|
|
31
36
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -40,6 +45,181 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
40
45
|
};
|
|
41
46
|
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget);
|
|
42
47
|
|
|
48
|
+
// src/components/workflow-flow.tsx
|
|
49
|
+
var workflow_flow_exports = {};
|
|
50
|
+
__export(workflow_flow_exports, {
|
|
51
|
+
WorkflowFlow: () => WorkflowFlow,
|
|
52
|
+
default: () => workflow_flow_default
|
|
53
|
+
});
|
|
54
|
+
function getNodeTypeLabel(type) {
|
|
55
|
+
const labels = {
|
|
56
|
+
"n8n-nodes-base.webhook": "Webhook",
|
|
57
|
+
"n8n-nodes-base.scheduleTrigger": "Schedule",
|
|
58
|
+
"n8n-nodes-base.if": "Condition",
|
|
59
|
+
"n8n-nodes-base.httpRequest": "HTTP Request",
|
|
60
|
+
"n8n-nodes-base.set": "Set Data",
|
|
61
|
+
"n8n-nodes-base.code": "Code",
|
|
62
|
+
"n8n-nodes-base.respondToWebhook": "Response",
|
|
63
|
+
"@n8n/n8n-nodes-langchain.agent": "AI Agent",
|
|
64
|
+
"@n8n/n8n-nodes-langchain.lmChatOpenAi": "OpenAI",
|
|
65
|
+
"@n8n/n8n-nodes-langchain.lmChatAnthropic": "Anthropic"
|
|
66
|
+
};
|
|
67
|
+
return labels[type] || type.split(".").pop()?.replace(/([A-Z])/g, " $1").trim() || type;
|
|
68
|
+
}
|
|
69
|
+
function CustomNode({ data }) {
|
|
70
|
+
return /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 rounded bg-white border border-slate-200 shadow-sm min-w-[110px] text-center", children: [
|
|
71
|
+
/* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Left, className: "!bg-slate-300 !w-1.5 !h-1.5 !border-0" }),
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs font-medium text-slate-700 truncate max-w-[130px]", children: data.label }),
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: "text-[10px] text-slate-400 truncate max-w-[130px]", children: getNodeTypeLabel(data.type) }),
|
|
74
|
+
/* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Right, className: "!bg-slate-300 !w-1.5 !h-1.5 !border-0" })
|
|
75
|
+
] });
|
|
76
|
+
}
|
|
77
|
+
function WorkflowFlow({ workflow, height = 350, className = "" }) {
|
|
78
|
+
const { initialNodes, initialEdges } = useMemo(() => {
|
|
79
|
+
const n8nNodes = workflow.nodes || [];
|
|
80
|
+
const connections = workflow.connections || {};
|
|
81
|
+
const nodeIdMap = new Map(n8nNodes.map((n) => [n.name, n.id || n.name]));
|
|
82
|
+
const forwardEdges = /* @__PURE__ */ new Map();
|
|
83
|
+
const backwardEdges = /* @__PURE__ */ new Map();
|
|
84
|
+
const allEdgeData = [];
|
|
85
|
+
Object.entries(connections).forEach(([fromNodeName, outputTypes]) => {
|
|
86
|
+
Object.entries(outputTypes).forEach(([outputType, outputs]) => {
|
|
87
|
+
if (!Array.isArray(outputs)) return;
|
|
88
|
+
outputs.forEach((outputArray, oi) => {
|
|
89
|
+
if (!Array.isArray(outputArray)) return;
|
|
90
|
+
outputArray.forEach((conn, ci) => {
|
|
91
|
+
if (!forwardEdges.has(fromNodeName)) forwardEdges.set(fromNodeName, []);
|
|
92
|
+
forwardEdges.get(fromNodeName).push(conn.node);
|
|
93
|
+
if (!backwardEdges.has(conn.node)) backwardEdges.set(conn.node, []);
|
|
94
|
+
backwardEdges.get(conn.node).push(fromNodeName);
|
|
95
|
+
allEdgeData.push({ from: fromNodeName, to: conn.node, outputType, oi, ci });
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
const triggerNodes = n8nNodes.filter(
|
|
101
|
+
(n) => n.type.includes("webhook") || n.type.includes("Trigger") || n.type.includes("schedule")
|
|
102
|
+
);
|
|
103
|
+
const roots = triggerNodes.length > 0 ? triggerNodes : n8nNodes.filter((n) => !backwardEdges.has(n.name) || backwardEdges.get(n.name).length === 0);
|
|
104
|
+
const levels = /* @__PURE__ */ new Map();
|
|
105
|
+
const queue = [];
|
|
106
|
+
roots.forEach((r) => {
|
|
107
|
+
levels.set(r.name, 0);
|
|
108
|
+
queue.push(r.name);
|
|
109
|
+
});
|
|
110
|
+
const visited = /* @__PURE__ */ new Set();
|
|
111
|
+
while (queue.length > 0) {
|
|
112
|
+
const name = queue.shift();
|
|
113
|
+
if (visited.has(name)) continue;
|
|
114
|
+
visited.add(name);
|
|
115
|
+
const children = forwardEdges.get(name) || [];
|
|
116
|
+
const myLevel = levels.get(name) || 0;
|
|
117
|
+
children.forEach((child) => {
|
|
118
|
+
const childLevel = levels.get(child);
|
|
119
|
+
if (childLevel === void 0 || myLevel + 1 > childLevel) {
|
|
120
|
+
levels.set(child, myLevel + 1);
|
|
121
|
+
}
|
|
122
|
+
if (!visited.has(child)) {
|
|
123
|
+
queue.push(child);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
n8nNodes.forEach((node) => {
|
|
128
|
+
if (!levels.has(node.name)) {
|
|
129
|
+
const targets = forwardEdges.get(node.name) || [];
|
|
130
|
+
if (targets.length > 0) {
|
|
131
|
+
const targetLevels = targets.map((t) => levels.get(t) ?? 0);
|
|
132
|
+
const targetLevel = Math.min(...targetLevels);
|
|
133
|
+
levels.set(node.name, Math.max(0, targetLevel - 1));
|
|
134
|
+
} else {
|
|
135
|
+
const maxLevel = Math.max(0, ...Array.from(levels.values()));
|
|
136
|
+
levels.set(node.name, maxLevel);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
const nodesByLevel = /* @__PURE__ */ new Map();
|
|
141
|
+
levels.forEach((level, name) => {
|
|
142
|
+
if (!nodesByLevel.has(level)) nodesByLevel.set(level, []);
|
|
143
|
+
nodesByLevel.get(level).push(name);
|
|
144
|
+
});
|
|
145
|
+
const sortedLevels = Array.from(nodesByLevel.keys()).sort((a, b) => a - b);
|
|
146
|
+
sortedLevels.forEach((level, levelIdx) => {
|
|
147
|
+
if (levelIdx === 0) return;
|
|
148
|
+
const nodesInLevel = nodesByLevel.get(level);
|
|
149
|
+
const prevLevel = sortedLevels[levelIdx - 1];
|
|
150
|
+
const prevNodes = nodesByLevel.get(prevLevel) || [];
|
|
151
|
+
const prevPositions = new Map(prevNodes.map((n, i) => [n, i]));
|
|
152
|
+
nodesInLevel.sort((a, b) => {
|
|
153
|
+
const parentsA = backwardEdges.get(a) || [];
|
|
154
|
+
const parentsB = backwardEdges.get(b) || [];
|
|
155
|
+
const avgA = parentsA.length > 0 ? parentsA.reduce((sum, p) => sum + (prevPositions.get(p) ?? 0), 0) / parentsA.length : 0;
|
|
156
|
+
const avgB = parentsB.length > 0 ? parentsB.reduce((sum, p) => sum + (prevPositions.get(p) ?? 0), 0) / parentsB.length : 0;
|
|
157
|
+
return avgA - avgB;
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
const positions = /* @__PURE__ */ new Map();
|
|
161
|
+
const xGap = 170;
|
|
162
|
+
const yGap = 70;
|
|
163
|
+
sortedLevels.forEach((level) => {
|
|
164
|
+
const nodesInLevel = nodesByLevel.get(level);
|
|
165
|
+
const totalHeight = (nodesInLevel.length - 1) * yGap;
|
|
166
|
+
const startY = -totalHeight / 2;
|
|
167
|
+
nodesInLevel.forEach((name, i) => {
|
|
168
|
+
positions.set(name, { x: level * xGap, y: startY + i * yGap });
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
const nodes2 = n8nNodes.map((node) => ({
|
|
172
|
+
id: node.id || node.name,
|
|
173
|
+
type: "custom",
|
|
174
|
+
position: positions.get(node.name) || { x: 0, y: 0 },
|
|
175
|
+
data: { label: node.name, type: node.type }
|
|
176
|
+
}));
|
|
177
|
+
const edges2 = allEdgeData.map(({ from, to, oi, ci }) => {
|
|
178
|
+
const fromId = nodeIdMap.get(from);
|
|
179
|
+
const toId = nodeIdMap.get(to);
|
|
180
|
+
return {
|
|
181
|
+
id: `${fromId}-${toId}-${oi}-${ci}`,
|
|
182
|
+
source: fromId,
|
|
183
|
+
target: toId,
|
|
184
|
+
type: "smoothstep",
|
|
185
|
+
pathOptions: { borderRadius: 20 },
|
|
186
|
+
style: { stroke: "#94a3b8", strokeWidth: 1.5 },
|
|
187
|
+
markerEnd: { type: MarkerType.ArrowClosed, color: "#94a3b8", width: 14, height: 14 }
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
return { initialNodes: nodes2, initialEdges: edges2 };
|
|
191
|
+
}, [workflow]);
|
|
192
|
+
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
|
193
|
+
const [edges, , onEdgesChange] = useEdgesState(initialEdges);
|
|
194
|
+
return /* @__PURE__ */ jsx("div", { style: { height }, className: `bg-slate-50 rounded-lg border border-slate-200 overflow-hidden ${className}`, children: /* @__PURE__ */ jsx(
|
|
195
|
+
ReactFlow,
|
|
196
|
+
{
|
|
197
|
+
nodes,
|
|
198
|
+
edges,
|
|
199
|
+
onNodesChange,
|
|
200
|
+
onEdgesChange,
|
|
201
|
+
nodeTypes,
|
|
202
|
+
fitView: true,
|
|
203
|
+
fitViewOptions: { padding: 0.1, minZoom: 0.8 },
|
|
204
|
+
minZoom: 0.5,
|
|
205
|
+
maxZoom: 2,
|
|
206
|
+
proOptions: { hideAttribution: true },
|
|
207
|
+
defaultEdgeOptions: {
|
|
208
|
+
type: "smoothstep"
|
|
209
|
+
},
|
|
210
|
+
children: /* @__PURE__ */ jsx(Background, { color: "#e2e8f0", gap: 24, size: 1 })
|
|
211
|
+
}
|
|
212
|
+
) });
|
|
213
|
+
}
|
|
214
|
+
var nodeTypes, workflow_flow_default;
|
|
215
|
+
var init_workflow_flow = __esm({
|
|
216
|
+
"src/components/workflow-flow.tsx"() {
|
|
217
|
+
"use client";
|
|
218
|
+
nodeTypes = { custom: CustomNode };
|
|
219
|
+
workflow_flow_default = WorkflowFlow;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
43
223
|
// src/index.ts
|
|
44
224
|
var index_exports = {};
|
|
45
225
|
__export(index_exports, {
|
|
@@ -47,6 +227,7 @@ __export(index_exports, {
|
|
|
47
227
|
AccordionContent: () => AccordionContent,
|
|
48
228
|
AccordionItem: () => AccordionItem,
|
|
49
229
|
AccordionTrigger: () => AccordionTrigger,
|
|
230
|
+
ActivityTimeline: () => ActivityTimeline,
|
|
50
231
|
Alert: () => Alert,
|
|
51
232
|
AlertDialog: () => AlertDialog,
|
|
52
233
|
AlertDialogAction: () => AlertDialogAction,
|
|
@@ -195,6 +376,8 @@ __export(index_exports, {
|
|
|
195
376
|
TooltipTrigger: () => TooltipTrigger,
|
|
196
377
|
UsageBar: () => UsageBar,
|
|
197
378
|
UsageChart: () => UsageChart,
|
|
379
|
+
WorkflowFlow: () => WorkflowFlow,
|
|
380
|
+
WorkflowViewer: () => WorkflowViewer,
|
|
198
381
|
alertVariants: () => alertVariants,
|
|
199
382
|
badgeVariants: () => badgeVariants,
|
|
200
383
|
buttonVariants: () => buttonVariants,
|
|
@@ -1241,7 +1424,7 @@ var NODES = [
|
|
|
1241
1424
|
];
|
|
1242
1425
|
var Primitive = NODES.reduce((primitive, node) => {
|
|
1243
1426
|
const Slot2 = createSlot(`Primitive.${node}`);
|
|
1244
|
-
const
|
|
1427
|
+
const Node2 = React50.forwardRef((props, forwardedRef) => {
|
|
1245
1428
|
const { asChild, ...primitiveProps } = props;
|
|
1246
1429
|
const Comp = asChild ? Slot2 : node;
|
|
1247
1430
|
if (typeof window !== "undefined") {
|
|
@@ -1249,8 +1432,8 @@ var Primitive = NODES.reduce((primitive, node) => {
|
|
|
1249
1432
|
}
|
|
1250
1433
|
return /* @__PURE__ */ jsx(Comp, { ...primitiveProps, ref: forwardedRef });
|
|
1251
1434
|
});
|
|
1252
|
-
|
|
1253
|
-
return { ...primitive, [node]:
|
|
1435
|
+
Node2.displayName = `Primitive.${node}`;
|
|
1436
|
+
return { ...primitive, [node]: Node2 };
|
|
1254
1437
|
}, {});
|
|
1255
1438
|
var NAME = "Label";
|
|
1256
1439
|
var Label = React50.forwardRef((props, forwardedRef) => {
|
|
@@ -1566,7 +1749,7 @@ var NODES2 = [
|
|
|
1566
1749
|
];
|
|
1567
1750
|
var Primitive2 = NODES2.reduce((primitive, node) => {
|
|
1568
1751
|
const Slot2 = createSlot(`Primitive.${node}`);
|
|
1569
|
-
const
|
|
1752
|
+
const Node2 = React50.forwardRef((props, forwardedRef) => {
|
|
1570
1753
|
const { asChild, ...primitiveProps } = props;
|
|
1571
1754
|
const Comp = asChild ? Slot2 : node;
|
|
1572
1755
|
if (typeof window !== "undefined") {
|
|
@@ -1574,8 +1757,8 @@ var Primitive2 = NODES2.reduce((primitive, node) => {
|
|
|
1574
1757
|
}
|
|
1575
1758
|
return /* @__PURE__ */ jsx(Comp, { ...primitiveProps, ref: forwardedRef });
|
|
1576
1759
|
});
|
|
1577
|
-
|
|
1578
|
-
return { ...primitive, [node]:
|
|
1760
|
+
Node2.displayName = `Primitive.${node}`;
|
|
1761
|
+
return { ...primitive, [node]: Node2 };
|
|
1579
1762
|
}, {});
|
|
1580
1763
|
var NAME2 = "Separator";
|
|
1581
1764
|
var DEFAULT_ORIENTATION = "horizontal";
|
|
@@ -4375,10 +4558,834 @@ function ImpactMetricsForm({
|
|
|
4375
4558
|
] })
|
|
4376
4559
|
] }) });
|
|
4377
4560
|
}
|
|
4561
|
+
function defaultFormatDate(date) {
|
|
4562
|
+
const d = typeof date === "string" ? new Date(date) : date;
|
|
4563
|
+
const now = /* @__PURE__ */ new Date();
|
|
4564
|
+
const diffMs = now.getTime() - d.getTime();
|
|
4565
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
4566
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
4567
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
4568
|
+
if (diffMins < 1) return "just now";
|
|
4569
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
4570
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
4571
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
4572
|
+
return d.toLocaleDateString();
|
|
4573
|
+
}
|
|
4574
|
+
function ActivityTimeline({
|
|
4575
|
+
activities,
|
|
4576
|
+
loading = false,
|
|
4577
|
+
activityLabels = {},
|
|
4578
|
+
collapsedCount = 3,
|
|
4579
|
+
showNoteInput = true,
|
|
4580
|
+
notePlaceholder = "Add a note...",
|
|
4581
|
+
onAddNote,
|
|
4582
|
+
submitting = false,
|
|
4583
|
+
formatDate = defaultFormatDate,
|
|
4584
|
+
loadingComponent,
|
|
4585
|
+
emptyMessage = "No activity yet",
|
|
4586
|
+
className = ""
|
|
4587
|
+
}) {
|
|
4588
|
+
const [newNote, setNewNote] = useState("");
|
|
4589
|
+
const [expanded, setExpanded] = useState(false);
|
|
4590
|
+
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
4591
|
+
const handleAddNote = async () => {
|
|
4592
|
+
if (!newNote.trim() || !onAddNote) return;
|
|
4593
|
+
setIsSubmitting(true);
|
|
4594
|
+
try {
|
|
4595
|
+
await onAddNote(newNote.trim());
|
|
4596
|
+
setNewNote("");
|
|
4597
|
+
} finally {
|
|
4598
|
+
setIsSubmitting(false);
|
|
4599
|
+
}
|
|
4600
|
+
};
|
|
4601
|
+
const handleKeyDown = (e) => {
|
|
4602
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
|
4603
|
+
handleAddNote();
|
|
4604
|
+
}
|
|
4605
|
+
};
|
|
4606
|
+
const visibleActivities = expanded ? activities : activities.slice(0, collapsedCount);
|
|
4607
|
+
const hasMore = activities.length > collapsedCount;
|
|
4608
|
+
const isCurrentlySubmitting = submitting || isSubmitting;
|
|
4609
|
+
const DefaultLoading = /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-4", children: /* @__PURE__ */ jsx(CircleNotch, { className: "w-5 h-5 animate-spin text-muted-foreground" }) });
|
|
4610
|
+
return /* @__PURE__ */ jsxs("div", { className: `space-y-3 ${className}`, children: [
|
|
4611
|
+
showNoteInput && onAddNote && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
4612
|
+
/* @__PURE__ */ jsx(
|
|
4613
|
+
Textarea,
|
|
4614
|
+
{
|
|
4615
|
+
value: newNote,
|
|
4616
|
+
onChange: (e) => setNewNote(e.target.value),
|
|
4617
|
+
onKeyDown: handleKeyDown,
|
|
4618
|
+
placeholder: notePlaceholder,
|
|
4619
|
+
rows: 1,
|
|
4620
|
+
className: "resize-none min-h-[36px] py-2"
|
|
4621
|
+
}
|
|
4622
|
+
),
|
|
4623
|
+
/* @__PURE__ */ jsx(
|
|
4624
|
+
Button,
|
|
4625
|
+
{
|
|
4626
|
+
onClick: handleAddNote,
|
|
4627
|
+
disabled: isCurrentlySubmitting || !newNote.trim(),
|
|
4628
|
+
size: "sm",
|
|
4629
|
+
className: "flex-shrink-0 h-9",
|
|
4630
|
+
children: isCurrentlySubmitting ? /* @__PURE__ */ jsx(CircleNotch, { className: "w-4 h-4 animate-spin" }) : /* @__PURE__ */ jsx(PaperPlaneTilt, { className: "w-4 h-4", weight: "bold" })
|
|
4631
|
+
}
|
|
4632
|
+
)
|
|
4633
|
+
] }),
|
|
4634
|
+
loading ? loadingComponent || DefaultLoading : activities.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground text-center py-2", children: emptyMessage }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4635
|
+
visibleActivities.map((activity) => {
|
|
4636
|
+
const label = activityLabels[activity.activity_type] || "";
|
|
4637
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-sm border-l-2 border-gray-200 pl-3 py-1", children: [
|
|
4638
|
+
/* @__PURE__ */ jsxs("p", { className: "text-gray-700", children: [
|
|
4639
|
+
label && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
4640
|
+
label,
|
|
4641
|
+
" "
|
|
4642
|
+
] }),
|
|
4643
|
+
activity.content
|
|
4644
|
+
] }),
|
|
4645
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground mt-0.5", children: [
|
|
4646
|
+
activity.user,
|
|
4647
|
+
" \xB7 ",
|
|
4648
|
+
formatDate(activity.created_at)
|
|
4649
|
+
] })
|
|
4650
|
+
] }, activity.id);
|
|
4651
|
+
}),
|
|
4652
|
+
hasMore && /* @__PURE__ */ jsx(
|
|
4653
|
+
"button",
|
|
4654
|
+
{
|
|
4655
|
+
onClick: () => setExpanded(!expanded),
|
|
4656
|
+
className: "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
4657
|
+
children: expanded ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4658
|
+
/* @__PURE__ */ jsx(CaretUp, { className: "w-3 h-3" }),
|
|
4659
|
+
"Show less"
|
|
4660
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4661
|
+
/* @__PURE__ */ jsx(CaretDown, { className: "w-3 h-3" }),
|
|
4662
|
+
"Show ",
|
|
4663
|
+
activities.length - collapsedCount,
|
|
4664
|
+
" more"
|
|
4665
|
+
] })
|
|
4666
|
+
}
|
|
4667
|
+
)
|
|
4668
|
+
] })
|
|
4669
|
+
] });
|
|
4670
|
+
}
|
|
4671
|
+
|
|
4672
|
+
// src/index.ts
|
|
4673
|
+
init_workflow_flow();
|
|
4674
|
+
var WorkflowFlow2 = lazy(() => Promise.resolve().then(() => (init_workflow_flow(), workflow_flow_exports)).then((m) => ({ default: m.WorkflowFlow })));
|
|
4675
|
+
var BLANK_N8N_WORKFLOW = {
|
|
4676
|
+
name: "New Workflow",
|
|
4677
|
+
nodes: [
|
|
4678
|
+
{
|
|
4679
|
+
id: "webhook-trigger",
|
|
4680
|
+
name: "Webhook",
|
|
4681
|
+
type: "n8n-nodes-base.webhook",
|
|
4682
|
+
parameters: {
|
|
4683
|
+
httpMethod: "POST",
|
|
4684
|
+
path: "my-webhook"
|
|
4685
|
+
}
|
|
4686
|
+
}
|
|
4687
|
+
],
|
|
4688
|
+
connections: {},
|
|
4689
|
+
settings: { executionOrder: "v1" }
|
|
4690
|
+
};
|
|
4691
|
+
var BLANK_SIM_WORKFLOW = {
|
|
4692
|
+
name: "New Workflow",
|
|
4693
|
+
description: "A new Sim workflow",
|
|
4694
|
+
trigger: { type: "webhook_input" },
|
|
4695
|
+
nodes: [
|
|
4696
|
+
{ id: "input", type: "webhook_input" },
|
|
4697
|
+
{ id: "output", type: "output" }
|
|
4698
|
+
],
|
|
4699
|
+
edges: [{ from: "input", to: "output" }]
|
|
4700
|
+
};
|
|
4701
|
+
function getNodeIcon(type) {
|
|
4702
|
+
if (type.includes("webhook")) return /* @__PURE__ */ jsx(WebhooksLogo, { size: 16, weight: "fill" });
|
|
4703
|
+
if (type.includes("Trigger") || type.includes("schedule")) return /* @__PURE__ */ jsx(Timer, { size: 16, weight: "fill" });
|
|
4704
|
+
if (type.includes("if") || type.includes("switch")) return /* @__PURE__ */ jsx(GitBranch, { size: 16, weight: "fill" });
|
|
4705
|
+
if (type.includes("httpRequest")) return /* @__PURE__ */ jsx(Globe, { size: 16, weight: "fill" });
|
|
4706
|
+
if (type.includes("langchain") || type.includes("openai") || type.includes("anthropic")) return /* @__PURE__ */ jsx(Robot, { size: 16, weight: "fill" });
|
|
4707
|
+
if (type.includes("code")) return /* @__PURE__ */ jsx(Code, { size: 16, weight: "fill" });
|
|
4708
|
+
if (type.includes("respondToWebhook")) return /* @__PURE__ */ jsx(CheckCircle, { size: 16, weight: "fill" });
|
|
4709
|
+
if (type.includes("set")) return /* @__PURE__ */ jsx(Package, { size: 16, weight: "fill" });
|
|
4710
|
+
return /* @__PURE__ */ jsx(Package, { size: 16 });
|
|
4711
|
+
}
|
|
4712
|
+
function getNodeTypeLabel2(type) {
|
|
4713
|
+
const typeMap = {
|
|
4714
|
+
"n8n-nodes-base.webhook": "Webhook Trigger",
|
|
4715
|
+
"n8n-nodes-base.scheduleTrigger": "Schedule Trigger",
|
|
4716
|
+
"n8n-nodes-base.if": "Condition",
|
|
4717
|
+
"n8n-nodes-base.httpRequest": "HTTP Request",
|
|
4718
|
+
"n8n-nodes-base.set": "Set Data",
|
|
4719
|
+
"n8n-nodes-base.code": "Code",
|
|
4720
|
+
"n8n-nodes-base.respondToWebhook": "Webhook Response",
|
|
4721
|
+
"@n8n/n8n-nodes-langchain.agent": "AI Agent",
|
|
4722
|
+
"@n8n/n8n-nodes-langchain.lmChatOpenAi": "OpenAI Model",
|
|
4723
|
+
"@n8n/n8n-nodes-langchain.lmChatAnthropic": "Anthropic Model"
|
|
4724
|
+
};
|
|
4725
|
+
return typeMap[type] || type.split(".").pop() || type;
|
|
4726
|
+
}
|
|
4727
|
+
function getSimNodeTypeLabel(type) {
|
|
4728
|
+
const typeMap = {
|
|
4729
|
+
"webhook_input": "Webhook Input",
|
|
4730
|
+
"llm": "AI/LLM",
|
|
4731
|
+
"code": "Code",
|
|
4732
|
+
"http_request": "HTTP Request",
|
|
4733
|
+
"condition": "Condition",
|
|
4734
|
+
"output": "Output"
|
|
4735
|
+
};
|
|
4736
|
+
return typeMap[type] || type;
|
|
4737
|
+
}
|
|
4738
|
+
function defaultFormatDistance(date, options) {
|
|
4739
|
+
const now = /* @__PURE__ */ new Date();
|
|
4740
|
+
const diffMs = now.getTime() - date.getTime();
|
|
4741
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
4742
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
4743
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
4744
|
+
let result = "";
|
|
4745
|
+
if (diffMins < 1) result = "less than a minute";
|
|
4746
|
+
else if (diffMins < 60) result = `${diffMins} minute${diffMins > 1 ? "s" : ""}`;
|
|
4747
|
+
else if (diffHours < 24) result = `${diffHours} hour${diffHours > 1 ? "s" : ""}`;
|
|
4748
|
+
else result = `${diffDays} day${diffDays > 1 ? "s" : ""}`;
|
|
4749
|
+
return options?.addSuffix ? `${result} ago` : result;
|
|
4750
|
+
}
|
|
4751
|
+
function N8nWorkflowSummary({ workflow, showFlow = false }) {
|
|
4752
|
+
const nodes = workflow.nodes || [];
|
|
4753
|
+
const triggerNode = nodes.find(
|
|
4754
|
+
(n) => n.type.includes("webhook") || n.type.includes("Trigger")
|
|
4755
|
+
);
|
|
4756
|
+
const aiNodes = nodes.filter(
|
|
4757
|
+
(n) => n.type.includes("langchain") || n.type.includes("openai") || n.type.includes("anthropic")
|
|
4758
|
+
);
|
|
4759
|
+
const httpNodes = nodes.filter(
|
|
4760
|
+
(n) => n.type === "n8n-nodes-base.httpRequest"
|
|
4761
|
+
);
|
|
4762
|
+
const conditionNodes = nodes.filter(
|
|
4763
|
+
(n) => n.type === "n8n-nodes-base.if"
|
|
4764
|
+
);
|
|
4765
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
4766
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3", children: [
|
|
4767
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted/50 rounded-lg p-3", children: [
|
|
4768
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground mb-1", children: [
|
|
4769
|
+
triggerNode && getNodeIcon(triggerNode.type),
|
|
4770
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Trigger" })
|
|
4771
|
+
] }),
|
|
4772
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold truncate", children: triggerNode ? getNodeTypeLabel2(triggerNode.type) : "None" })
|
|
4773
|
+
] }),
|
|
4774
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted/50 rounded-lg p-3", children: [
|
|
4775
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground mb-1", children: [
|
|
4776
|
+
/* @__PURE__ */ jsx(TreeStructure, { size: 16 }),
|
|
4777
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Steps" })
|
|
4778
|
+
] }),
|
|
4779
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold", children: [
|
|
4780
|
+
nodes.length,
|
|
4781
|
+
" nodes"
|
|
4782
|
+
] })
|
|
4783
|
+
] }),
|
|
4784
|
+
aiNodes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-purple-50 rounded-lg p-3", children: [
|
|
4785
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-purple-600 mb-1", children: [
|
|
4786
|
+
/* @__PURE__ */ jsx(Robot, { size: 16, weight: "fill" }),
|
|
4787
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "AI" })
|
|
4788
|
+
] }),
|
|
4789
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-purple-700", children: [
|
|
4790
|
+
aiNodes.length,
|
|
4791
|
+
" ",
|
|
4792
|
+
aiNodes.length === 1 ? "node" : "nodes"
|
|
4793
|
+
] })
|
|
4794
|
+
] }),
|
|
4795
|
+
httpNodes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-blue-50 rounded-lg p-3", children: [
|
|
4796
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-blue-600 mb-1", children: [
|
|
4797
|
+
/* @__PURE__ */ jsx(Globe, { size: 16, weight: "fill" }),
|
|
4798
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "APIs" })
|
|
4799
|
+
] }),
|
|
4800
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-blue-700", children: [
|
|
4801
|
+
httpNodes.length,
|
|
4802
|
+
" ",
|
|
4803
|
+
httpNodes.length === 1 ? "request" : "requests"
|
|
4804
|
+
] })
|
|
4805
|
+
] }),
|
|
4806
|
+
conditionNodes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-yellow-50 rounded-lg p-3", children: [
|
|
4807
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-yellow-600 mb-1", children: [
|
|
4808
|
+
/* @__PURE__ */ jsx(GitBranch, { size: 16, weight: "fill" }),
|
|
4809
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Logic" })
|
|
4810
|
+
] }),
|
|
4811
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-yellow-700", children: [
|
|
4812
|
+
conditionNodes.length,
|
|
4813
|
+
" ",
|
|
4814
|
+
conditionNodes.length === 1 ? "condition" : "conditions"
|
|
4815
|
+
] })
|
|
4816
|
+
] })
|
|
4817
|
+
] }),
|
|
4818
|
+
showFlow && /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "h-[320px] bg-slate-50 rounded-lg border border-slate-200 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-slate-400 text-sm", children: "Loading..." }) }), children: /* @__PURE__ */ jsx(WorkflowFlow2, { workflow, height: 320 }) }),
|
|
4819
|
+
!showFlow && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4820
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: "Workflow Nodes" }),
|
|
4821
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: nodes.map((node) => /* @__PURE__ */ jsx(
|
|
4822
|
+
"span",
|
|
4823
|
+
{
|
|
4824
|
+
className: "px-2 py-1 rounded bg-slate-100 text-slate-600 text-xs",
|
|
4825
|
+
children: node.name
|
|
4826
|
+
},
|
|
4827
|
+
node.id
|
|
4828
|
+
)) })
|
|
4829
|
+
] })
|
|
4830
|
+
] });
|
|
4831
|
+
}
|
|
4832
|
+
function SimWorkflowSummary({ workflow }) {
|
|
4833
|
+
const nodes = workflow.nodes || [];
|
|
4834
|
+
const aiNodes = nodes.filter((n) => n.type === "llm");
|
|
4835
|
+
const httpNodes = nodes.filter((n) => n.type === "http_request");
|
|
4836
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
4837
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3", children: [
|
|
4838
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted/50 rounded-lg p-3", children: [
|
|
4839
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground mb-1", children: [
|
|
4840
|
+
/* @__PURE__ */ jsx(WebhooksLogo, { size: 16, weight: "fill" }),
|
|
4841
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Trigger" })
|
|
4842
|
+
] }),
|
|
4843
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: workflow.trigger?.type ? getSimNodeTypeLabel(workflow.trigger.type) : "Manual" })
|
|
4844
|
+
] }),
|
|
4845
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-muted/50 rounded-lg p-3", children: [
|
|
4846
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground mb-1", children: [
|
|
4847
|
+
/* @__PURE__ */ jsx(TreeStructure, { size: 16 }),
|
|
4848
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "Steps" })
|
|
4849
|
+
] }),
|
|
4850
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold", children: [
|
|
4851
|
+
nodes.length,
|
|
4852
|
+
" nodes"
|
|
4853
|
+
] })
|
|
4854
|
+
] }),
|
|
4855
|
+
aiNodes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-purple-50 rounded-lg p-3", children: [
|
|
4856
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-purple-600 mb-1", children: [
|
|
4857
|
+
/* @__PURE__ */ jsx(Robot, { size: 16, weight: "fill" }),
|
|
4858
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "AI" })
|
|
4859
|
+
] }),
|
|
4860
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-purple-700", children: [
|
|
4861
|
+
aiNodes.length,
|
|
4862
|
+
" LLM ",
|
|
4863
|
+
aiNodes.length === 1 ? "node" : "nodes"
|
|
4864
|
+
] })
|
|
4865
|
+
] }),
|
|
4866
|
+
httpNodes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "bg-blue-50 rounded-lg p-3", children: [
|
|
4867
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-blue-600 mb-1", children: [
|
|
4868
|
+
/* @__PURE__ */ jsx(Globe, { size: 16, weight: "fill" }),
|
|
4869
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium", children: "APIs" })
|
|
4870
|
+
] }),
|
|
4871
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-semibold text-blue-700", children: [
|
|
4872
|
+
httpNodes.length,
|
|
4873
|
+
" ",
|
|
4874
|
+
httpNodes.length === 1 ? "request" : "requests"
|
|
4875
|
+
] })
|
|
4876
|
+
] })
|
|
4877
|
+
] }),
|
|
4878
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4879
|
+
/* @__PURE__ */ jsx("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: "Workflow Nodes" }),
|
|
4880
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: nodes.map((node) => /* @__PURE__ */ jsxs(
|
|
4881
|
+
"div",
|
|
4882
|
+
{
|
|
4883
|
+
className: "flex items-center gap-1.5 px-2.5 py-1.5 rounded-md border text-xs bg-gray-100 text-gray-700 border-gray-300",
|
|
4884
|
+
children: [
|
|
4885
|
+
/* @__PURE__ */ jsx(Package, { size: 14 }),
|
|
4886
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: getSimNodeTypeLabel(node.type) })
|
|
4887
|
+
]
|
|
4888
|
+
},
|
|
4889
|
+
node.id
|
|
4890
|
+
)) })
|
|
4891
|
+
] })
|
|
4892
|
+
] });
|
|
4893
|
+
}
|
|
4894
|
+
function WorkflowViewer({
|
|
4895
|
+
workflow,
|
|
4896
|
+
platform,
|
|
4897
|
+
title = "Workflow",
|
|
4898
|
+
webhookUrl,
|
|
4899
|
+
workflowId,
|
|
4900
|
+
workflowDefinitionId,
|
|
4901
|
+
workerId,
|
|
4902
|
+
workerName,
|
|
4903
|
+
internalWorkerType,
|
|
4904
|
+
lastSynced,
|
|
4905
|
+
isActive,
|
|
4906
|
+
syncError,
|
|
4907
|
+
className = "",
|
|
4908
|
+
editable = false,
|
|
4909
|
+
allowCreate = false,
|
|
4910
|
+
allowPlatformChange = false,
|
|
4911
|
+
allowStatusChange = false,
|
|
4912
|
+
onWorkflowUpdate,
|
|
4913
|
+
onWorkflowCreated,
|
|
4914
|
+
onPlatformChange,
|
|
4915
|
+
onStatusChange,
|
|
4916
|
+
apiHandlers,
|
|
4917
|
+
loadingComponent,
|
|
4918
|
+
formatDistance = defaultFormatDistance
|
|
4919
|
+
}) {
|
|
4920
|
+
const [viewMode, setViewMode] = useState("summary");
|
|
4921
|
+
const [editedJson, setEditedJson] = useState("");
|
|
4922
|
+
const [jsonError, setJsonError] = useState(null);
|
|
4923
|
+
const [message, setMessage] = useState(null);
|
|
4924
|
+
const [saving, setSaving] = useState(false);
|
|
4925
|
+
const [syncing, setSyncing] = useState(false);
|
|
4926
|
+
const [pulling, setPulling] = useState(false);
|
|
4927
|
+
const [creating, setCreating] = useState(false);
|
|
4928
|
+
const [selectedTemplate, setSelectedTemplate] = useState("blank");
|
|
4929
|
+
const [localPlatform, setLocalPlatform] = useState(platform);
|
|
4930
|
+
const [localIsActive, setLocalIsActive] = useState(isActive ?? true);
|
|
4931
|
+
const hasUnsavedChanges = localPlatform !== platform || localIsActive !== (isActive ?? true);
|
|
4932
|
+
function copyToClipboard(text, label = "Copied") {
|
|
4933
|
+
navigator.clipboard.writeText(text);
|
|
4934
|
+
setMessage({ type: "success", text: label });
|
|
4935
|
+
setTimeout(() => setMessage(null), 2e3);
|
|
4936
|
+
}
|
|
4937
|
+
function handleLocalPlatformChange(newPlatform) {
|
|
4938
|
+
setLocalPlatform(newPlatform);
|
|
4939
|
+
}
|
|
4940
|
+
function handleLocalStatusChange(newStatus) {
|
|
4941
|
+
setLocalIsActive(newStatus);
|
|
4942
|
+
}
|
|
4943
|
+
function cancelChanges() {
|
|
4944
|
+
setLocalPlatform(platform);
|
|
4945
|
+
setLocalIsActive(isActive ?? true);
|
|
4946
|
+
setMessage(null);
|
|
4947
|
+
}
|
|
4948
|
+
async function saveSettings() {
|
|
4949
|
+
if (!workflowDefinitionId || !apiHandlers?.saveSettings) {
|
|
4950
|
+
setMessage({ type: "error", text: "Cannot save - no workflow definition or API handler." });
|
|
4951
|
+
return;
|
|
4952
|
+
}
|
|
4953
|
+
setSaving(true);
|
|
4954
|
+
setMessage(null);
|
|
4955
|
+
try {
|
|
4956
|
+
const updateData = {};
|
|
4957
|
+
if (localPlatform !== platform) {
|
|
4958
|
+
updateData.platform = localPlatform;
|
|
4959
|
+
}
|
|
4960
|
+
if (localIsActive !== (isActive ?? true)) {
|
|
4961
|
+
updateData.is_active = localIsActive;
|
|
4962
|
+
}
|
|
4963
|
+
if (Object.keys(updateData).length === 0) {
|
|
4964
|
+
setMessage({ type: "success", text: "No changes to save" });
|
|
4965
|
+
setSaving(false);
|
|
4966
|
+
return;
|
|
4967
|
+
}
|
|
4968
|
+
const result = await apiHandlers.saveSettings(workflowDefinitionId, updateData);
|
|
4969
|
+
if (result.success) {
|
|
4970
|
+
setMessage({ type: "success", text: "Settings saved successfully" });
|
|
4971
|
+
onPlatformChange?.(localPlatform);
|
|
4972
|
+
onStatusChange?.(localIsActive);
|
|
4973
|
+
} else {
|
|
4974
|
+
setMessage({ type: "error", text: result.error || "Failed to save settings" });
|
|
4975
|
+
}
|
|
4976
|
+
} catch {
|
|
4977
|
+
setMessage({ type: "error", text: "Failed to save settings" });
|
|
4978
|
+
} finally {
|
|
4979
|
+
setSaving(false);
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
function startEditing() {
|
|
4983
|
+
setEditedJson(JSON.stringify(workflow, null, 2));
|
|
4984
|
+
setJsonError(null);
|
|
4985
|
+
setViewMode("edit");
|
|
4986
|
+
}
|
|
4987
|
+
function cancelEditing() {
|
|
4988
|
+
setEditedJson("");
|
|
4989
|
+
setJsonError(null);
|
|
4990
|
+
setViewMode("summary");
|
|
4991
|
+
}
|
|
4992
|
+
function validateJson(json) {
|
|
4993
|
+
try {
|
|
4994
|
+
const parsed = JSON.parse(json);
|
|
4995
|
+
if (platform === "n8n") {
|
|
4996
|
+
if (!parsed.nodes || !Array.isArray(parsed.nodes)) {
|
|
4997
|
+
throw new Error("n8n workflow must have a nodes array");
|
|
4998
|
+
}
|
|
4999
|
+
} else {
|
|
5000
|
+
if (!parsed.nodes || !Array.isArray(parsed.nodes)) {
|
|
5001
|
+
throw new Error("Sim workflow must have a nodes array");
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
return parsed;
|
|
5005
|
+
} catch {
|
|
5006
|
+
return null;
|
|
5007
|
+
}
|
|
5008
|
+
}
|
|
5009
|
+
async function saveWorkflow() {
|
|
5010
|
+
const parsed = validateJson(editedJson);
|
|
5011
|
+
if (!parsed) {
|
|
5012
|
+
setJsonError("Invalid JSON. Please check the syntax.");
|
|
5013
|
+
return;
|
|
5014
|
+
}
|
|
5015
|
+
if (!workflowDefinitionId || !apiHandlers?.saveWorkflow) {
|
|
5016
|
+
setJsonError("Cannot save - no workflow definition or API handler.");
|
|
5017
|
+
return;
|
|
5018
|
+
}
|
|
5019
|
+
setSaving(true);
|
|
5020
|
+
setJsonError(null);
|
|
5021
|
+
try {
|
|
5022
|
+
const result = await apiHandlers.saveWorkflow(workflowDefinitionId, parsed, platform);
|
|
5023
|
+
if (result.success) {
|
|
5024
|
+
setMessage({ type: "success", text: "Workflow saved to database" });
|
|
5025
|
+
setViewMode("summary");
|
|
5026
|
+
onWorkflowUpdate?.(parsed);
|
|
5027
|
+
} else {
|
|
5028
|
+
setJsonError(result.error || "Failed to save workflow");
|
|
5029
|
+
}
|
|
5030
|
+
} catch {
|
|
5031
|
+
setJsonError("Failed to save workflow");
|
|
5032
|
+
} finally {
|
|
5033
|
+
setSaving(false);
|
|
5034
|
+
}
|
|
5035
|
+
}
|
|
5036
|
+
async function pushToN8n() {
|
|
5037
|
+
if (!workerId || !apiHandlers?.pushToN8n) {
|
|
5038
|
+
setMessage({ type: "error", text: "Cannot sync - no worker ID or API handler" });
|
|
5039
|
+
return;
|
|
5040
|
+
}
|
|
5041
|
+
setSyncing(true);
|
|
5042
|
+
setMessage(null);
|
|
5043
|
+
try {
|
|
5044
|
+
const result = await apiHandlers.pushToN8n(workerId);
|
|
5045
|
+
if (result.success) {
|
|
5046
|
+
setMessage({ type: "success", text: "Pushed to n8n successfully" });
|
|
5047
|
+
} else {
|
|
5048
|
+
setMessage({ type: "error", text: result.error || "Failed to push to n8n" });
|
|
5049
|
+
}
|
|
5050
|
+
} catch {
|
|
5051
|
+
setMessage({ type: "error", text: "Failed to push to n8n" });
|
|
5052
|
+
} finally {
|
|
5053
|
+
setSyncing(false);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
async function pullFromN8n() {
|
|
5057
|
+
if (!workflowId || !workflowDefinitionId || !apiHandlers?.pullFromN8n) {
|
|
5058
|
+
setMessage({ type: "error", text: "Cannot pull - no n8n workflow ID or API handler" });
|
|
5059
|
+
return;
|
|
5060
|
+
}
|
|
5061
|
+
setPulling(true);
|
|
5062
|
+
setMessage(null);
|
|
5063
|
+
try {
|
|
5064
|
+
const result = await apiHandlers.pullFromN8n(workflowDefinitionId);
|
|
5065
|
+
if (result.success) {
|
|
5066
|
+
if (result.descriptionSync?.needsUpdate) {
|
|
5067
|
+
setMessage({
|
|
5068
|
+
type: "success",
|
|
5069
|
+
text: `Pulled from n8n. Note: ${result.descriptionSync.reason || "Worker description may need updating."}`
|
|
5070
|
+
});
|
|
5071
|
+
} else {
|
|
5072
|
+
setMessage({ type: "success", text: "Pulled from n8n successfully" });
|
|
5073
|
+
}
|
|
5074
|
+
} else {
|
|
5075
|
+
setMessage({ type: "error", text: result.error || "Failed to pull from n8n" });
|
|
5076
|
+
}
|
|
5077
|
+
} catch {
|
|
5078
|
+
setMessage({ type: "error", text: "Failed to pull from n8n" });
|
|
5079
|
+
} finally {
|
|
5080
|
+
setPulling(false);
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
5083
|
+
function startCreating() {
|
|
5084
|
+
if (internalWorkerType) {
|
|
5085
|
+
setSelectedTemplate(internalWorkerType);
|
|
5086
|
+
} else {
|
|
5087
|
+
setSelectedTemplate("blank");
|
|
5088
|
+
}
|
|
5089
|
+
const blank = platform === "n8n" ? BLANK_N8N_WORKFLOW : BLANK_SIM_WORKFLOW;
|
|
5090
|
+
setEditedJson(JSON.stringify(blank, null, 2));
|
|
5091
|
+
setViewMode("create");
|
|
5092
|
+
}
|
|
5093
|
+
async function createWorkflow() {
|
|
5094
|
+
const parsed = validateJson(editedJson);
|
|
5095
|
+
if (!parsed) {
|
|
5096
|
+
setJsonError("Invalid JSON. Please check the syntax.");
|
|
5097
|
+
return;
|
|
5098
|
+
}
|
|
5099
|
+
if (!workerId || !apiHandlers?.createWorkflow) {
|
|
5100
|
+
setJsonError("Cannot create - no worker ID or API handler.");
|
|
5101
|
+
return;
|
|
5102
|
+
}
|
|
5103
|
+
setCreating(true);
|
|
5104
|
+
setJsonError(null);
|
|
5105
|
+
try {
|
|
5106
|
+
const workflowName = parsed.name || `${workerName || "Worker"} Workflow`;
|
|
5107
|
+
const result = await apiHandlers.createWorkflow({
|
|
5108
|
+
agent_id: workerId,
|
|
5109
|
+
name: workflowName,
|
|
5110
|
+
platform,
|
|
5111
|
+
n8n_workflow: platform === "n8n" ? parsed : null,
|
|
5112
|
+
sim_workflow: platform === "sim" ? parsed : null,
|
|
5113
|
+
is_active: true,
|
|
5114
|
+
is_global: false
|
|
5115
|
+
});
|
|
5116
|
+
if (result.success && result.workflow) {
|
|
5117
|
+
setMessage({ type: "success", text: "Workflow created successfully" });
|
|
5118
|
+
onWorkflowCreated?.(result.workflow.id);
|
|
5119
|
+
} else {
|
|
5120
|
+
setJsonError(result.error || "Failed to create workflow");
|
|
5121
|
+
}
|
|
5122
|
+
} catch {
|
|
5123
|
+
setJsonError("Failed to create workflow");
|
|
5124
|
+
} finally {
|
|
5125
|
+
setCreating(false);
|
|
5126
|
+
}
|
|
5127
|
+
}
|
|
5128
|
+
async function loadTemplate() {
|
|
5129
|
+
if (!workerId || !workerName || !apiHandlers?.loadTemplate) {
|
|
5130
|
+
setJsonError("Worker information or API handler required to generate template.");
|
|
5131
|
+
return;
|
|
5132
|
+
}
|
|
5133
|
+
if (selectedTemplate === "blank" || selectedTemplate === "custom") {
|
|
5134
|
+
return;
|
|
5135
|
+
}
|
|
5136
|
+
setCreating(true);
|
|
5137
|
+
setJsonError(null);
|
|
5138
|
+
try {
|
|
5139
|
+
const result = await apiHandlers.loadTemplate(selectedTemplate, workerId);
|
|
5140
|
+
if (result.success && result.workflow) {
|
|
5141
|
+
setEditedJson(JSON.stringify(result.workflow, null, 2));
|
|
5142
|
+
setMessage({ type: "success", text: "Template loaded" });
|
|
5143
|
+
} else {
|
|
5144
|
+
setJsonError(result.error || "Failed to load template");
|
|
5145
|
+
}
|
|
5146
|
+
} catch {
|
|
5147
|
+
setJsonError("Failed to load template");
|
|
5148
|
+
} finally {
|
|
5149
|
+
setCreating(false);
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
const DefaultLoading = /* @__PURE__ */ jsx("div", { className: "h-[320px] bg-slate-50 rounded-lg border border-slate-200 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "text-slate-400 text-sm", children: "Loading..." }) });
|
|
5153
|
+
if (!workflow) {
|
|
5154
|
+
return /* @__PURE__ */ jsxs(Card, { className, children: [
|
|
5155
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
5156
|
+
/* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: title }),
|
|
5157
|
+
allowCreate && viewMode !== "create" && /* @__PURE__ */ jsx(Button, { onClick: startCreating, variant: "primary", size: "sm", children: "Create Workflow" })
|
|
5158
|
+
] }) }),
|
|
5159
|
+
/* @__PURE__ */ jsx(CardContent, { children: viewMode === "create" ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
5160
|
+
message && /* @__PURE__ */ jsx(Alert, { variant: message.type === "success" ? "success" : "error", children: message.text }),
|
|
5161
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
5162
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Start from template:" }),
|
|
5163
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
5164
|
+
/* @__PURE__ */ jsx(
|
|
5165
|
+
Button,
|
|
5166
|
+
{
|
|
5167
|
+
onClick: () => {
|
|
5168
|
+
setSelectedTemplate("blank");
|
|
5169
|
+
const blank = platform === "n8n" ? BLANK_N8N_WORKFLOW : BLANK_SIM_WORKFLOW;
|
|
5170
|
+
setEditedJson(JSON.stringify(blank, null, 2));
|
|
5171
|
+
},
|
|
5172
|
+
variant: selectedTemplate === "blank" ? "primary" : "outline",
|
|
5173
|
+
size: "sm",
|
|
5174
|
+
children: "Blank"
|
|
5175
|
+
}
|
|
5176
|
+
),
|
|
5177
|
+
internalWorkerType && apiHandlers?.loadTemplate && /* @__PURE__ */ jsxs(
|
|
5178
|
+
Button,
|
|
5179
|
+
{
|
|
5180
|
+
onClick: () => {
|
|
5181
|
+
setSelectedTemplate(internalWorkerType);
|
|
5182
|
+
loadTemplate();
|
|
5183
|
+
},
|
|
5184
|
+
variant: selectedTemplate === internalWorkerType ? "primary" : "outline",
|
|
5185
|
+
size: "sm",
|
|
5186
|
+
children: [
|
|
5187
|
+
internalWorkerType.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()),
|
|
5188
|
+
" Template"
|
|
5189
|
+
]
|
|
5190
|
+
}
|
|
5191
|
+
)
|
|
5192
|
+
] })
|
|
5193
|
+
] }),
|
|
5194
|
+
jsonError && /* @__PURE__ */ jsx(Alert, { variant: "error", children: jsonError }),
|
|
5195
|
+
/* @__PURE__ */ jsx(
|
|
5196
|
+
Textarea,
|
|
5197
|
+
{
|
|
5198
|
+
value: editedJson,
|
|
5199
|
+
onChange: (e) => {
|
|
5200
|
+
setEditedJson(e.target.value);
|
|
5201
|
+
setJsonError(null);
|
|
5202
|
+
},
|
|
5203
|
+
className: "h-72 font-mono text-xs",
|
|
5204
|
+
placeholder: "Paste or edit workflow JSON here..."
|
|
5205
|
+
}
|
|
5206
|
+
),
|
|
5207
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
5208
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => setViewMode("summary"), variant: "outline", size: "sm", children: "Cancel" }),
|
|
5209
|
+
/* @__PURE__ */ jsx(
|
|
5210
|
+
Button,
|
|
5211
|
+
{
|
|
5212
|
+
onClick: createWorkflow,
|
|
5213
|
+
disabled: creating || !editedJson.trim(),
|
|
5214
|
+
variant: "primary",
|
|
5215
|
+
size: "sm",
|
|
5216
|
+
children: creating ? "Creating..." : "Create Workflow"
|
|
5217
|
+
}
|
|
5218
|
+
)
|
|
5219
|
+
] }),
|
|
5220
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: 'Create a workflow definition. After creating, use "Push to n8n" to deploy it.' })
|
|
5221
|
+
] }) : /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
5222
|
+
"No workflow defined yet.",
|
|
5223
|
+
allowCreate && ' Click "Create Workflow" to add one.'
|
|
5224
|
+
] }) })
|
|
5225
|
+
] });
|
|
5226
|
+
}
|
|
5227
|
+
return /* @__PURE__ */ jsxs(Card, { className, children: [
|
|
5228
|
+
/* @__PURE__ */ jsx(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
5229
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5230
|
+
/* @__PURE__ */ jsx(CardTitle, { className: "text-base", children: title }),
|
|
5231
|
+
allowStatusChange && workflowDefinitionId ? /* @__PURE__ */ jsx(
|
|
5232
|
+
Badge,
|
|
5233
|
+
{
|
|
5234
|
+
variant: localIsActive ? "success" : "default",
|
|
5235
|
+
size: "sm",
|
|
5236
|
+
children: localIsActive ? "Active" : "Inactive"
|
|
5237
|
+
}
|
|
5238
|
+
) : isActive !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: isActive ? "success" : "default", size: "sm", children: isActive ? "Active" : "Inactive" }),
|
|
5239
|
+
hasUnsavedChanges && /* @__PURE__ */ jsx(Badge, { variant: "warning", size: "sm", children: "Unsaved" }),
|
|
5240
|
+
syncError && /* @__PURE__ */ jsx(Badge, { variant: "error", size: "sm", children: "Sync Error" })
|
|
5241
|
+
] }),
|
|
5242
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: viewMode === "edit" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5243
|
+
/* @__PURE__ */ jsx(Button, { onClick: cancelEditing, variant: "outline", size: "sm", children: "Cancel" }),
|
|
5244
|
+
/* @__PURE__ */ jsx(Button, { onClick: saveWorkflow, disabled: saving, variant: "primary", size: "sm", children: saving ? "Saving..." : "Save JSON" })
|
|
5245
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5246
|
+
/* @__PURE__ */ jsxs("div", { className: "flex border border-border rounded-md overflow-hidden mr-2", children: [
|
|
5247
|
+
/* @__PURE__ */ jsxs(
|
|
5248
|
+
"button",
|
|
5249
|
+
{
|
|
5250
|
+
onClick: () => setViewMode("summary"),
|
|
5251
|
+
className: `px-3 py-1.5 text-xs font-medium flex items-center gap-1.5 transition-colors ${viewMode === "summary" ? "bg-primary text-white" : "bg-background hover:bg-muted text-muted-foreground"}`,
|
|
5252
|
+
children: [
|
|
5253
|
+
/* @__PURE__ */ jsx(Eye, { size: 14 }),
|
|
5254
|
+
"Summary"
|
|
5255
|
+
]
|
|
5256
|
+
}
|
|
5257
|
+
),
|
|
5258
|
+
platform === "n8n" && /* @__PURE__ */ jsxs(
|
|
5259
|
+
"button",
|
|
5260
|
+
{
|
|
5261
|
+
onClick: () => setViewMode("flow"),
|
|
5262
|
+
className: `px-3 py-1.5 text-xs font-medium flex items-center gap-1.5 transition-colors border-l border-border ${viewMode === "flow" ? "bg-primary text-white" : "bg-background hover:bg-muted text-muted-foreground"}`,
|
|
5263
|
+
children: [
|
|
5264
|
+
/* @__PURE__ */ jsx(TreeStructure, { size: 14 }),
|
|
5265
|
+
"Diagram"
|
|
5266
|
+
]
|
|
5267
|
+
}
|
|
5268
|
+
),
|
|
5269
|
+
/* @__PURE__ */ jsxs(
|
|
5270
|
+
"button",
|
|
5271
|
+
{
|
|
5272
|
+
onClick: () => setViewMode("json"),
|
|
5273
|
+
className: `px-3 py-1.5 text-xs font-medium flex items-center gap-1.5 transition-colors border-l border-border ${viewMode === "json" ? "bg-primary text-white" : "bg-background hover:bg-muted text-muted-foreground"}`,
|
|
5274
|
+
children: [
|
|
5275
|
+
/* @__PURE__ */ jsx(Code, { size: 14 }),
|
|
5276
|
+
"JSON"
|
|
5277
|
+
]
|
|
5278
|
+
}
|
|
5279
|
+
)
|
|
5280
|
+
] }),
|
|
5281
|
+
editable && apiHandlers?.saveWorkflow && /* @__PURE__ */ jsx(Button, { onClick: startEditing, variant: "outline", size: "sm", icon: /* @__PURE__ */ jsx(PencilSimple, { size: 14 }), children: "Edit" })
|
|
5282
|
+
] }) })
|
|
5283
|
+
] }) }),
|
|
5284
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
5285
|
+
message && /* @__PURE__ */ jsx(Alert, { variant: message.type === "success" ? "success" : "error", children: message.text }),
|
|
5286
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-4 text-xs text-muted-foreground", children: [
|
|
5287
|
+
workflowId && /* @__PURE__ */ jsx("span", { className: "font-mono bg-muted px-2 py-1 rounded", children: workflowId }),
|
|
5288
|
+
lastSynced && /* @__PURE__ */ jsxs("span", { children: [
|
|
5289
|
+
"Synced ",
|
|
5290
|
+
formatDistance(new Date(lastSynced), { addSuffix: true })
|
|
5291
|
+
] }),
|
|
5292
|
+
webhookUrl && /* @__PURE__ */ jsxs(
|
|
5293
|
+
"button",
|
|
5294
|
+
{
|
|
5295
|
+
onClick: () => copyToClipboard(webhookUrl, "Webhook URL copied"),
|
|
5296
|
+
className: "flex items-center gap-1 hover:text-foreground",
|
|
5297
|
+
children: [
|
|
5298
|
+
/* @__PURE__ */ jsx(Copy, { size: 12 }),
|
|
5299
|
+
"Copy webhook"
|
|
5300
|
+
]
|
|
5301
|
+
}
|
|
5302
|
+
)
|
|
5303
|
+
] }),
|
|
5304
|
+
(allowPlatformChange || allowStatusChange) && workflowDefinitionId && hasUnsavedChanges && apiHandlers?.saveSettings && /* @__PURE__ */ jsxs("div", { className: "p-3 bg-amber-50 border border-amber-200 rounded-lg space-y-3", children: [
|
|
5305
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
5306
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-amber-800", children: "Unsaved changes" }),
|
|
5307
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
5308
|
+
/* @__PURE__ */ jsx(Button, { onClick: cancelChanges, variant: "outline", size: "sm", children: "Cancel" }),
|
|
5309
|
+
/* @__PURE__ */ jsx(Button, { onClick: saveSettings, disabled: saving, variant: "primary", size: "sm", children: saving ? "Saving..." : "Save" })
|
|
5310
|
+
] })
|
|
5311
|
+
] }),
|
|
5312
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-4 text-sm", children: [
|
|
5313
|
+
allowPlatformChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5314
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Platform:" }),
|
|
5315
|
+
/* @__PURE__ */ jsxs(
|
|
5316
|
+
Select,
|
|
5317
|
+
{
|
|
5318
|
+
value: localPlatform,
|
|
5319
|
+
onChange: (e) => handleLocalPlatformChange(e.target.value),
|
|
5320
|
+
className: "h-8 text-sm w-28",
|
|
5321
|
+
children: [
|
|
5322
|
+
/* @__PURE__ */ jsx("option", { value: "n8n", children: "n8n" }),
|
|
5323
|
+
/* @__PURE__ */ jsx("option", { value: "sim", children: "Sim Studio" })
|
|
5324
|
+
]
|
|
5325
|
+
}
|
|
5326
|
+
)
|
|
5327
|
+
] }),
|
|
5328
|
+
allowStatusChange && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
5329
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Status:" }),
|
|
5330
|
+
/* @__PURE__ */ jsxs(
|
|
5331
|
+
Select,
|
|
5332
|
+
{
|
|
5333
|
+
value: localIsActive ? "active" : "inactive",
|
|
5334
|
+
onChange: (e) => handleLocalStatusChange(e.target.value === "active"),
|
|
5335
|
+
className: "h-8 text-sm w-28",
|
|
5336
|
+
children: [
|
|
5337
|
+
/* @__PURE__ */ jsx("option", { value: "active", children: "Active" }),
|
|
5338
|
+
/* @__PURE__ */ jsx("option", { value: "inactive", children: "Inactive" })
|
|
5339
|
+
]
|
|
5340
|
+
}
|
|
5341
|
+
)
|
|
5342
|
+
] })
|
|
5343
|
+
] })
|
|
5344
|
+
] }),
|
|
5345
|
+
syncError && /* @__PURE__ */ jsxs(Alert, { variant: "error", children: [
|
|
5346
|
+
/* @__PURE__ */ jsx("strong", { children: "Sync Error:" }),
|
|
5347
|
+
" ",
|
|
5348
|
+
syncError
|
|
5349
|
+
] }),
|
|
5350
|
+
editable && workerId && platform === "n8n" && viewMode !== "edit" && apiHandlers?.pushToN8n && /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
5351
|
+
/* @__PURE__ */ jsx(Button, { onClick: pushToN8n, disabled: syncing, variant: "primary", size: "sm", icon: /* @__PURE__ */ jsx(CloudArrowUp, { size: 16 }), children: syncing ? "Pushing..." : "Push to n8n" }),
|
|
5352
|
+
workflowId && apiHandlers?.pullFromN8n && /* @__PURE__ */ jsx(Button, { onClick: pullFromN8n, disabled: pulling, variant: "outline", size: "sm", icon: /* @__PURE__ */ jsx(CloudArrowDown, { size: 16 }), children: pulling ? "Pulling..." : "Pull from n8n" })
|
|
5353
|
+
] }),
|
|
5354
|
+
/* @__PURE__ */ jsx("div", { className: "pt-2", children: viewMode === "edit" ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
5355
|
+
jsonError && /* @__PURE__ */ jsx(Alert, { variant: "error", children: jsonError }),
|
|
5356
|
+
/* @__PURE__ */ jsx(
|
|
5357
|
+
Textarea,
|
|
5358
|
+
{
|
|
5359
|
+
value: editedJson,
|
|
5360
|
+
onChange: (e) => {
|
|
5361
|
+
setEditedJson(e.target.value);
|
|
5362
|
+
setJsonError(null);
|
|
5363
|
+
},
|
|
5364
|
+
className: "h-[400px] font-mono text-xs"
|
|
5365
|
+
}
|
|
5366
|
+
),
|
|
5367
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: 'Edit the workflow JSON above. Changes will be saved to the database. Use "Push to n8n" to sync.' })
|
|
5368
|
+
] }) : viewMode === "json" ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
5369
|
+
/* @__PURE__ */ jsx(
|
|
5370
|
+
Button,
|
|
5371
|
+
{
|
|
5372
|
+
onClick: () => copyToClipboard(JSON.stringify(workflow, null, 2), "JSON copied"),
|
|
5373
|
+
variant: "outline",
|
|
5374
|
+
size: "sm",
|
|
5375
|
+
className: "absolute top-2 right-2 z-10",
|
|
5376
|
+
icon: /* @__PURE__ */ jsx(Copy, { size: 14 }),
|
|
5377
|
+
children: "Copy"
|
|
5378
|
+
}
|
|
5379
|
+
),
|
|
5380
|
+
/* @__PURE__ */ jsx("pre", { className: "p-4 bg-slate-900 text-slate-100 rounded-lg text-xs overflow-auto max-h-[500px] font-mono", children: JSON.stringify(workflow, null, 2) })
|
|
5381
|
+
] }) : viewMode === "flow" ? platform === "n8n" && /* @__PURE__ */ jsx(Suspense, { fallback: loadingComponent || DefaultLoading, children: /* @__PURE__ */ jsx(WorkflowFlow2, { workflow, height: 380 }) }) : platform === "n8n" ? /* @__PURE__ */ jsx(N8nWorkflowSummary, { workflow, showFlow: false }) : /* @__PURE__ */ jsx(SimWorkflowSummary, { workflow }) })
|
|
5382
|
+
] })
|
|
5383
|
+
] });
|
|
5384
|
+
}
|
|
4378
5385
|
|
|
4379
5386
|
// src/index.ts
|
|
4380
5387
|
__reExport(index_exports, icons_exports);
|
|
4381
5388
|
|
|
4382
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarFallback, AvatarImage, Badge, BreadcrumbLink, Breadcrumbs, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, ConfirmDialog, DateRangePicker, DateRangeSelect, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorState, FilePreview, FormField, IconBox, ImpactMetricsForm, Input, Label2 as Label, LabeledSwitch, Logo, Metric, MetricCard, MetricLabel, MetricSubtext, MetricValue, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupCard, RadioGroupItem, RadioGroupOption, ScenariosManager, Select, Separator2 as Separator, SettingsNav, SettingsNavLink, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SimplePagination, SimpleTooltip, Skeleton, SkeletonCard, SkeletonText, Stat, StepDots, StepProgress, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsListUnderline, TabsTrigger, TabsTriggerUnderline, Tag, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastIcon, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipTrigger, UsageBar, UsageChart, alertVariants, badgeVariants, buttonVariants, cn, getDateRangeFromPreset, iconBoxVariants, metricCardVariants, navigationMenuTriggerStyle, progressVariants, statVariants, tagVariants, toast, usageBarVariants, useToast, valueVariants };
|
|
5389
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityTimeline, Alert, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarFallback, AvatarImage, Badge, BreadcrumbLink, Breadcrumbs, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, CodeBlock, ConfirmDialog, DateRangePicker, DateRangeSelect, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Divider, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorState, FilePreview, FormField, IconBox, ImpactMetricsForm, Input, Label2 as Label, LabeledSwitch, Logo, Metric, MetricCard, MetricLabel, MetricSubtext, MetricValue, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, Popover, PopoverAnchor, PopoverArrow, PopoverClose, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupCard, RadioGroupItem, RadioGroupOption, ScenariosManager, Select, Separator2 as Separator, SettingsNav, SettingsNavLink, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SimplePagination, SimpleTooltip, Skeleton, SkeletonCard, SkeletonText, Stat, StepDots, StepProgress, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsListUnderline, TabsTrigger, TabsTriggerUnderline, Tag, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastIcon, ToastProvider, ToastTitle, ToastViewport, Toaster, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipTrigger, UsageBar, UsageChart, WorkflowFlow, WorkflowViewer, alertVariants, badgeVariants, buttonVariants, cn, getDateRangeFromPreset, iconBoxVariants, metricCardVariants, navigationMenuTriggerStyle, progressVariants, statVariants, tagVariants, toast, usageBarVariants, useToast, valueVariants };
|
|
4383
5390
|
//# sourceMappingURL=index.mjs.map
|
|
4384
5391
|
//# sourceMappingURL=index.mjs.map
|