@burdenoff/fluidgrids-fe-sdk 2026.624.2 → 2026.626.1
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/{WorkflowBuilder-MITXVIMZ.js → WorkflowBuilder-2K4MMN4U.js} +5 -5
- package/dist/{WorkflowBuilder-MITXVIMZ.js.map → WorkflowBuilder-2K4MMN4U.js.map} +1 -1
- package/dist/WorkflowsList-6SIM36LA.js +8 -0
- package/dist/{WorkflowsList-J33J7EIF.js.map → WorkflowsList-6SIM36LA.js.map} +1 -1
- package/dist/{chunk-M2KBI2FX.js → chunk-BK7BS2WU.js} +3 -3
- package/dist/{chunk-M2KBI2FX.js.map → chunk-BK7BS2WU.js.map} +1 -1
- package/dist/{chunk-2YP4QVEZ.js → chunk-KBHRFZXR.js} +8 -4
- package/dist/chunk-KBHRFZXR.js.map +1 -0
- package/dist/{chunk-Z2ZEVYDE.js → chunk-KU64CCSV.js} +15 -2
- package/dist/chunk-KU64CCSV.js.map +1 -0
- package/dist/{chunk-EVUQS7DK.js → chunk-QANP2YKX.js} +725 -16
- package/dist/chunk-QANP2YKX.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +9 -9
- package/dist/useImportWorkflowTemplate-UTPGK45L.js +11 -0
- package/dist/{useImportWorkflowTemplate-PNE2ANBV.js.map → useImportWorkflowTemplate-UTPGK45L.js.map} +1 -1
- package/package.json +1 -1
- package/dist/WorkflowsList-J33J7EIF.js +0 -8
- package/dist/chunk-2YP4QVEZ.js.map +0 -1
- package/dist/chunk-EVUQS7DK.js.map +0 -1
- package/dist/chunk-Z2ZEVYDE.js.map +0 -1
- package/dist/useImportWorkflowTemplate-PNE2ANBV.js +0 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useNodeExecution, AVAILABLE_NODES, createNodeWithDefaultData, NODES_METADATA, isNodeConfigsInitialized, HeaderWithIcon, useInstalledNodes, useInstallNode, useRefreshAvailableNodes,
|
|
2
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, Input as Input$1 } from './chunk-7VEOUEIN.js';
|
|
1
|
+
import { registerWorkflowNodeTypes, ensureNodeConfigsLoaded, onNodeTypesUpdate, NODE_TYPES, getNodeMetadata, useNodeExecution, getNodeDetail, AVAILABLE_NODES, createNodeWithDefaultData, NODES_METADATA, NODE_CONFIGS, isNodeConfigsInitialized, HeaderWithIcon, useInstalledNodes, useInstallNode, useRefreshAvailableNodes, NODES, NodePropertyPanel, ConnectionSelector } from './chunk-KBHRFZXR.js';
|
|
2
|
+
import { Dialog as Dialog$1, DialogContent as DialogContent$1, DialogHeader as DialogHeader$1, DialogTitle as DialogTitle$1, DialogDescription as DialogDescription$1, DialogFooter, Input as Input$1 } from './chunk-7VEOUEIN.js';
|
|
3
3
|
import { cn, Badge as Badge$1, Button } from './chunk-Z54K22LP.js';
|
|
4
|
-
import { useFlowStore } from './chunk-
|
|
4
|
+
import { useFlowStore } from './chunk-KU64CCSV.js';
|
|
5
5
|
import { useLazyWorkflowDefinition, useCreateWorkflow, useWorkflowVersions, useRestoreWorkflowVersion, useActivateWorkflow, useDeactivateWorkflow } from './chunk-4FFPGQD3.js';
|
|
6
6
|
import { NodeSchemaIntrospectionDocument, UpdateWorkflowDefinitionDocument, CreateWorkflowDefinitionDocument, CreateWorkflowVersionDocument, NodeUsageStatusDocument, RemoveNodeFromWorkflowsDocument } from './chunk-FGYVIXQ7.js';
|
|
7
7
|
import { BrowseWorkflowTemplatesDocument, BrowseWorkflowNodesDocument, UninstallWorkflowNodeDocument, CreateStoreOrderDocument } from './chunk-LUGJJ7LL.js';
|
|
@@ -17,7 +17,7 @@ import React3__default, { forwardRef, lazy, memo, createContext, useContext, use
|
|
|
17
17
|
import { Handle, Position, getBezierPath, MarkerType, ReactFlowProvider, useReactFlow, ReactFlow, Background, useOnSelectionChange, useStore, MiniMap, getSmoothStepPath, EdgeLabelRenderer, getOutgoers, getConnectedEdges, useNodes, useNodesState, useEdgesState, addEdge, Controls, Panel } from '@xyflow/react';
|
|
18
18
|
import { produce } from 'immer';
|
|
19
19
|
import { cn as cn$1 } from '@burdenoff/fe-libs/utils';
|
|
20
|
-
import { Card as Card$1, Badge, CardContent as CardContent$1, Button as Button$1, Input, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, 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, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea } from '@burdenoff/fe-libs/ui';
|
|
20
|
+
import { Card as Card$1, Badge, CardContent as CardContent$1, Button as Button$1, Input, Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, 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, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea } from '@burdenoff/fe-libs/ui';
|
|
21
21
|
import { isEmpty } from 'radash';
|
|
22
22
|
import { Icon } from '@iconify/react';
|
|
23
23
|
import { gql } from '@apollo/client';
|
|
@@ -2573,18 +2573,18 @@ function TemplatesModal({
|
|
|
2573
2573
|
const handleCloseDetailPanel = () => {
|
|
2574
2574
|
setSelectedTemplate(null);
|
|
2575
2575
|
};
|
|
2576
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
2577
|
-
DialogContent,
|
|
2576
|
+
return /* @__PURE__ */ jsx(Dialog$1, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
2577
|
+
DialogContent$1,
|
|
2578
2578
|
{
|
|
2579
2579
|
size: "xl",
|
|
2580
2580
|
className: "!flex !flex-col !h-[75vh] !max-h-[75vh] min-h-[500px] p-0 gap-0 overflow-hidden",
|
|
2581
2581
|
children: [
|
|
2582
|
-
/* @__PURE__ */ jsxs(DialogHeader, { className: "px-6 pt-6 pb-4 border-b shrink-0", children: [
|
|
2582
|
+
/* @__PURE__ */ jsxs(DialogHeader$1, { className: "px-6 pt-6 pb-4 border-b shrink-0", children: [
|
|
2583
2583
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2584
2584
|
/* @__PURE__ */ jsx(Sparkles, { className: "size-5 text-primary" }),
|
|
2585
|
-
/* @__PURE__ */ jsx(DialogTitle, { className: "text-2xl", children: "Workflow Templates" })
|
|
2585
|
+
/* @__PURE__ */ jsx(DialogTitle$1, { className: "text-2xl", children: "Workflow Templates" })
|
|
2586
2586
|
] }),
|
|
2587
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: "Browse and use pre-built workflow templates to get started quickly" }),
|
|
2587
|
+
/* @__PURE__ */ jsx(DialogDescription$1, { children: "Browse and use pre-built workflow templates to get started quickly" }),
|
|
2588
2588
|
/* @__PURE__ */ jsx("div", { className: "pt-4", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
2589
2589
|
/* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" }),
|
|
2590
2590
|
/* @__PURE__ */ jsx(
|
|
@@ -2692,7 +2692,7 @@ function DesktopSidebarFragment({
|
|
|
2692
2692
|
const handleUseTemplate = useCallback(
|
|
2693
2693
|
async (template) => {
|
|
2694
2694
|
try {
|
|
2695
|
-
const { useImportWorkflowTemplate: useImportWorkflowTemplate2 } = await import('./useImportWorkflowTemplate-
|
|
2695
|
+
const { useImportWorkflowTemplate: useImportWorkflowTemplate2 } = await import('./useImportWorkflowTemplate-UTPGK45L.js');
|
|
2696
2696
|
const { useTemplateDetail: useTemplateDetail2 } = await import('./useTemplateDetail-NK63V3PC.js');
|
|
2697
2697
|
toast.loading("Loading template...", { id: "template-load" });
|
|
2698
2698
|
const { getGlobalStoreClient } = await import('./global-client-OW43ZRDR.js');
|
|
@@ -9929,9 +9929,9 @@ function TriggerDataDialog({
|
|
|
9929
9929
|
setSubmitted(true);
|
|
9930
9930
|
onExecute({});
|
|
9931
9931
|
}, [onExecute]);
|
|
9932
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
|
|
9933
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
9934
|
-
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
9932
|
+
return /* @__PURE__ */ jsx(Dialog$1, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent$1, { className: "sm:max-w-lg", children: [
|
|
9933
|
+
/* @__PURE__ */ jsxs(DialogHeader$1, { children: [
|
|
9934
|
+
/* @__PURE__ */ jsxs(DialogTitle$1, { className: "flex items-center gap-2", children: [
|
|
9935
9935
|
/* @__PURE__ */ jsx(
|
|
9936
9936
|
Icon,
|
|
9937
9937
|
{
|
|
@@ -9941,7 +9941,7 @@ function TriggerDataDialog({
|
|
|
9941
9941
|
),
|
|
9942
9942
|
"Execute Workflow"
|
|
9943
9943
|
] }),
|
|
9944
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: "Provide the trigger data (JSON) that will be passed to the first node in the workflow. This is the input your workflow will process." })
|
|
9944
|
+
/* @__PURE__ */ jsx(DialogDescription$1, { children: "Provide the trigger data (JSON) that will be passed to the first node in the workflow. This is the input your workflow will process." })
|
|
9945
9945
|
] }),
|
|
9946
9946
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
9947
9947
|
/* @__PURE__ */ jsx(
|
|
@@ -10710,6 +10710,714 @@ var ChatPanel = () => {
|
|
|
10710
10710
|
}
|
|
10711
10711
|
);
|
|
10712
10712
|
};
|
|
10713
|
+
|
|
10714
|
+
// src/builder/lib/field-schema.ts
|
|
10715
|
+
function isRecord(value) {
|
|
10716
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10717
|
+
}
|
|
10718
|
+
function isIdentifier(key) {
|
|
10719
|
+
return /^[A-Za-z_$][\w$]*$/.test(key);
|
|
10720
|
+
}
|
|
10721
|
+
function joinPath(base, key) {
|
|
10722
|
+
if (isIdentifier(key)) return base ? `${base}.${key}` : key;
|
|
10723
|
+
const bracket = `[${JSON.stringify(key)}]`;
|
|
10724
|
+
return base ? `${base}${bracket}` : bracket;
|
|
10725
|
+
}
|
|
10726
|
+
function pathToExpression(path) {
|
|
10727
|
+
if (!path) return "${output}";
|
|
10728
|
+
const accessor = path.startsWith("[") ? `output${path}` : `output.${path}`;
|
|
10729
|
+
return "${" + accessor + "}";
|
|
10730
|
+
}
|
|
10731
|
+
function fieldFromSpec(key, path, spec) {
|
|
10732
|
+
if (typeof spec === "string") {
|
|
10733
|
+
return { key, path, type: spec };
|
|
10734
|
+
}
|
|
10735
|
+
if (isRecord(spec)) {
|
|
10736
|
+
const declaredType = typeof spec.type === "string" ? spec.type : void 0;
|
|
10737
|
+
const description = typeof spec.description === "string" ? spec.description : void 0;
|
|
10738
|
+
const required = spec.required === true;
|
|
10739
|
+
if (isRecord(spec.properties)) {
|
|
10740
|
+
const children = Object.entries(spec.properties).map(
|
|
10741
|
+
([k, v]) => fieldFromSpec(k, joinPath(path, k), v)
|
|
10742
|
+
);
|
|
10743
|
+
return { key, path, type: "object", required, description, children };
|
|
10744
|
+
}
|
|
10745
|
+
if (spec.items !== void 0) {
|
|
10746
|
+
const element = fieldFromSpec("0", `${path}[0]`, spec.items);
|
|
10747
|
+
return {
|
|
10748
|
+
key,
|
|
10749
|
+
path,
|
|
10750
|
+
type: "array",
|
|
10751
|
+
required,
|
|
10752
|
+
description,
|
|
10753
|
+
children: [element]
|
|
10754
|
+
};
|
|
10755
|
+
}
|
|
10756
|
+
return { key, path, type: declaredType ?? "any", required, description };
|
|
10757
|
+
}
|
|
10758
|
+
return { key, path, type: "any" };
|
|
10759
|
+
}
|
|
10760
|
+
function fieldsFromIO(io, root = "") {
|
|
10761
|
+
if (!isRecord(io)) return [];
|
|
10762
|
+
return Object.entries(io).map(
|
|
10763
|
+
([key, spec]) => fieldFromSpec(key, joinPath(root, key), spec)
|
|
10764
|
+
);
|
|
10765
|
+
}
|
|
10766
|
+
function normalizeOperations(raw) {
|
|
10767
|
+
if (Array.isArray(raw)) return raw;
|
|
10768
|
+
if (isRecord(raw) && Array.isArray(raw.operations)) {
|
|
10769
|
+
return raw.operations;
|
|
10770
|
+
}
|
|
10771
|
+
return [];
|
|
10772
|
+
}
|
|
10773
|
+
function resolveNodeOperation(data, fallbackOperations2) {
|
|
10774
|
+
const nodeData = isRecord(data?.nodeData) ? data?.nodeData : void 0;
|
|
10775
|
+
let operations = normalizeOperations(nodeData?.operations);
|
|
10776
|
+
if (operations.length === 0) {
|
|
10777
|
+
operations = normalizeOperations(data?.operations);
|
|
10778
|
+
}
|
|
10779
|
+
if (operations.length === 0 && fallbackOperations2 !== void 0) {
|
|
10780
|
+
operations = normalizeOperations(fallbackOperations2);
|
|
10781
|
+
}
|
|
10782
|
+
const opName = typeof data?.operation_name === "string" ? data.operation_name : void 0;
|
|
10783
|
+
const selected = operations.find((op) => op.name === opName) ?? operations[0];
|
|
10784
|
+
return { operations, selected };
|
|
10785
|
+
}
|
|
10786
|
+
var FIELD_PATH_MIME = "application/x-fg-field-path";
|
|
10787
|
+
var TYPE_ICON = {
|
|
10788
|
+
string: "mdi:format-text",
|
|
10789
|
+
number: "mdi:numeric",
|
|
10790
|
+
integer: "mdi:numeric",
|
|
10791
|
+
boolean: "mdi:toggle-switch-outline",
|
|
10792
|
+
array: "mdi:code-brackets",
|
|
10793
|
+
object: "mdi:code-braces",
|
|
10794
|
+
any: "mdi:help-circle-outline"
|
|
10795
|
+
};
|
|
10796
|
+
function FieldRow({ field, depth, draggable }) {
|
|
10797
|
+
const [open, setOpen] = useState(depth < 1);
|
|
10798
|
+
const hasChildren = !!field.children && field.children.length > 0;
|
|
10799
|
+
const handleDragStart = (e) => {
|
|
10800
|
+
e.dataTransfer.setData(FIELD_PATH_MIME, field.path);
|
|
10801
|
+
e.dataTransfer.setData("text/plain", pathToExpression(field.path));
|
|
10802
|
+
e.dataTransfer.effectAllowed = "copy";
|
|
10803
|
+
};
|
|
10804
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
10805
|
+
/* @__PURE__ */ jsxs(
|
|
10806
|
+
"div",
|
|
10807
|
+
{
|
|
10808
|
+
className: `group flex items-center gap-1.5 rounded-md py-1 pr-2 text-xs hover:bg-muted ${draggable ? "cursor-grab active:cursor-grabbing" : ""}`,
|
|
10809
|
+
style: { paddingLeft: `${depth * 14 + 6}px` },
|
|
10810
|
+
draggable,
|
|
10811
|
+
onDragStart: draggable ? handleDragStart : void 0,
|
|
10812
|
+
"data-field-path": field.path,
|
|
10813
|
+
title: field.description || field.path,
|
|
10814
|
+
children: [
|
|
10815
|
+
hasChildren ? /* @__PURE__ */ jsx(
|
|
10816
|
+
"button",
|
|
10817
|
+
{
|
|
10818
|
+
type: "button",
|
|
10819
|
+
onClick: () => setOpen((v) => !v),
|
|
10820
|
+
className: "flex size-4 items-center justify-center text-muted-foreground hover:text-foreground",
|
|
10821
|
+
children: /* @__PURE__ */ jsx(
|
|
10822
|
+
Icon,
|
|
10823
|
+
{
|
|
10824
|
+
icon: open ? "mdi:chevron-down" : "mdi:chevron-right",
|
|
10825
|
+
className: "size-3.5"
|
|
10826
|
+
}
|
|
10827
|
+
)
|
|
10828
|
+
}
|
|
10829
|
+
) : /* @__PURE__ */ jsx("span", { className: "inline-block size-4" }),
|
|
10830
|
+
/* @__PURE__ */ jsx(
|
|
10831
|
+
Icon,
|
|
10832
|
+
{
|
|
10833
|
+
icon: TYPE_ICON[field.type] ?? TYPE_ICON.any,
|
|
10834
|
+
className: "size-3.5 shrink-0 text-primary/70"
|
|
10835
|
+
}
|
|
10836
|
+
),
|
|
10837
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium text-foreground", children: field.key }),
|
|
10838
|
+
/* @__PURE__ */ jsxs("span", { className: "ml-auto shrink-0 text-[10px] lowercase tracking-wide text-muted-foreground", children: [
|
|
10839
|
+
field.type,
|
|
10840
|
+
field.required ? " *" : ""
|
|
10841
|
+
] })
|
|
10842
|
+
]
|
|
10843
|
+
}
|
|
10844
|
+
),
|
|
10845
|
+
hasChildren && open && /* @__PURE__ */ jsx("div", { children: field.children.map((child) => /* @__PURE__ */ jsx(
|
|
10846
|
+
FieldRow,
|
|
10847
|
+
{
|
|
10848
|
+
field: child,
|
|
10849
|
+
depth: depth + 1,
|
|
10850
|
+
draggable
|
|
10851
|
+
},
|
|
10852
|
+
child.path
|
|
10853
|
+
)) })
|
|
10854
|
+
] });
|
|
10855
|
+
}
|
|
10856
|
+
function FieldTree({
|
|
10857
|
+
fields,
|
|
10858
|
+
draggable = false,
|
|
10859
|
+
emptyMessage = "No fields available."
|
|
10860
|
+
}) {
|
|
10861
|
+
if (fields.length === 0) {
|
|
10862
|
+
return /* @__PURE__ */ jsx("div", { className: "px-2 py-4 text-xs text-card-foreground/50", children: emptyMessage });
|
|
10863
|
+
}
|
|
10864
|
+
return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: fields.map((field) => /* @__PURE__ */ jsx(
|
|
10865
|
+
FieldRow,
|
|
10866
|
+
{
|
|
10867
|
+
field,
|
|
10868
|
+
depth: 0,
|
|
10869
|
+
draggable
|
|
10870
|
+
},
|
|
10871
|
+
field.path
|
|
10872
|
+
)) });
|
|
10873
|
+
}
|
|
10874
|
+
function coerceNumber(type, raw) {
|
|
10875
|
+
if (raw.trim() === "") return void 0;
|
|
10876
|
+
const n = type === "integer" ? parseInt(raw, 10) : parseFloat(raw);
|
|
10877
|
+
return Number.isNaN(n) ? void 0 : n;
|
|
10878
|
+
}
|
|
10879
|
+
function asRecord(value) {
|
|
10880
|
+
return typeof value === "object" && value !== null ? value : void 0;
|
|
10881
|
+
}
|
|
10882
|
+
function fallbackOperations(type) {
|
|
10883
|
+
if (!type) return void 0;
|
|
10884
|
+
return NODE_CONFIGS.find((c) => c.type === type)?.operations;
|
|
10885
|
+
}
|
|
10886
|
+
function selectedOperationOf(data, type) {
|
|
10887
|
+
return resolveNodeOperation(data, fallbackOperations(type)).selected;
|
|
10888
|
+
}
|
|
10889
|
+
function paramsFromOperation(op) {
|
|
10890
|
+
const io = asRecord(op?.input_fields);
|
|
10891
|
+
if (!io) return [];
|
|
10892
|
+
return Object.entries(io).map(([name, spec]) => {
|
|
10893
|
+
const rec = asRecord(spec);
|
|
10894
|
+
const optsRaw = rec?.options ?? rec?.enum;
|
|
10895
|
+
const options = Array.isArray(optsRaw) ? optsRaw.map(
|
|
10896
|
+
(o) => typeof o === "string" ? o : asRecord(o)?.value ?? asRecord(o)?.name
|
|
10897
|
+
).filter((v) => typeof v === "string") : void 0;
|
|
10898
|
+
return {
|
|
10899
|
+
name,
|
|
10900
|
+
type: typeof spec === "string" ? spec : typeof rec?.type === "string" ? rec.type : "any",
|
|
10901
|
+
required: rec?.required === true,
|
|
10902
|
+
description: typeof rec?.description === "string" ? rec.description : void 0,
|
|
10903
|
+
options,
|
|
10904
|
+
defaultValue: rec?.default
|
|
10905
|
+
};
|
|
10906
|
+
});
|
|
10907
|
+
}
|
|
10908
|
+
function nodeTitle(node) {
|
|
10909
|
+
if (!node) return "Node";
|
|
10910
|
+
const data = asRecord(node.data);
|
|
10911
|
+
const label = typeof data?.label === "string" ? data.label : "";
|
|
10912
|
+
return label || getNodeDetail(node.type).title || node.id;
|
|
10913
|
+
}
|
|
10914
|
+
function nodeSubtitle(node) {
|
|
10915
|
+
const data = asRecord(node?.data);
|
|
10916
|
+
return typeof data?.operation_name === "string" ? data.operation_name : void 0;
|
|
10917
|
+
}
|
|
10918
|
+
var SECTION_LABEL = "text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground";
|
|
10919
|
+
function NodeDetailView() {
|
|
10920
|
+
const ndv = useFlowStore((s) => s.workflow.ndv);
|
|
10921
|
+
const nodes = useFlowStore((s) => s.workflow.nodes);
|
|
10922
|
+
const edges = useFlowStore((s) => s.workflow.edges);
|
|
10923
|
+
const closeNdv = useFlowStore((s) => s.actions.ndv.close);
|
|
10924
|
+
const showNodePropertiesOf = useFlowStore(
|
|
10925
|
+
(s) => s.actions.sidebar.showNodePropertiesOf
|
|
10926
|
+
);
|
|
10927
|
+
const open = !!ndv;
|
|
10928
|
+
const node = useMemo(
|
|
10929
|
+
() => ndv ? nodes.find((n) => n.id === ndv.nodeId) : void 0,
|
|
10930
|
+
[ndv, nodes]
|
|
10931
|
+
);
|
|
10932
|
+
const incoming = useMemo(
|
|
10933
|
+
() => ndv ? edges.filter((e) => e.target === ndv.nodeId) : [],
|
|
10934
|
+
[edges, ndv]
|
|
10935
|
+
);
|
|
10936
|
+
const sourceIds = useMemo(() => incoming.map((e) => e.source), [incoming]);
|
|
10937
|
+
const sourceKey = sourceIds.join(",");
|
|
10938
|
+
const [selectedSource, setSelectedSource] = useState();
|
|
10939
|
+
const [tab, setTab] = useState("parameters");
|
|
10940
|
+
const [outputView, setOutputView] = useState("schema");
|
|
10941
|
+
const [dragField, setDragField] = useState(null);
|
|
10942
|
+
const [modeByField, setModeByField] = useState({});
|
|
10943
|
+
const panesRef = useRef(null);
|
|
10944
|
+
const dragCleanupRef = useRef(null);
|
|
10945
|
+
const [leftPct, setLeftPct] = useState(30);
|
|
10946
|
+
const [rightPct, setRightPct] = useState(30);
|
|
10947
|
+
const startDrag = (which) => (e) => {
|
|
10948
|
+
e.preventDefault();
|
|
10949
|
+
const el = panesRef.current;
|
|
10950
|
+
if (!el) return;
|
|
10951
|
+
const rect = el.getBoundingClientRect();
|
|
10952
|
+
const onMove = (ev) => {
|
|
10953
|
+
const pct = (ev.clientX - rect.left) / rect.width * 100;
|
|
10954
|
+
if (which === "left") setLeftPct(Math.min(55, Math.max(15, pct)));
|
|
10955
|
+
else setRightPct(Math.min(55, Math.max(15, 100 - pct)));
|
|
10956
|
+
};
|
|
10957
|
+
const cleanup = () => {
|
|
10958
|
+
window.removeEventListener("mousemove", onMove);
|
|
10959
|
+
window.removeEventListener("mouseup", cleanup);
|
|
10960
|
+
dragCleanupRef.current = null;
|
|
10961
|
+
};
|
|
10962
|
+
dragCleanupRef.current = cleanup;
|
|
10963
|
+
window.addEventListener("mousemove", onMove);
|
|
10964
|
+
window.addEventListener("mouseup", cleanup);
|
|
10965
|
+
};
|
|
10966
|
+
useEffect(() => () => dragCleanupRef.current?.(), []);
|
|
10967
|
+
useEffect(() => {
|
|
10968
|
+
setSelectedSource(
|
|
10969
|
+
(prev) => prev && sourceIds.includes(prev) ? prev : sourceIds[0]
|
|
10970
|
+
);
|
|
10971
|
+
}, [ndv?.nodeId, sourceKey, sourceIds]);
|
|
10972
|
+
useEffect(() => {
|
|
10973
|
+
if (open) setTab("parameters");
|
|
10974
|
+
}, [open, ndv?.nodeId]);
|
|
10975
|
+
useEffect(() => {
|
|
10976
|
+
setModeByField({});
|
|
10977
|
+
}, [ndv?.nodeId, selectedSource]);
|
|
10978
|
+
const sourceNode = useMemo(
|
|
10979
|
+
() => nodes.find((n) => n.id === selectedSource),
|
|
10980
|
+
[nodes, selectedSource]
|
|
10981
|
+
);
|
|
10982
|
+
const currentEdge = useMemo(
|
|
10983
|
+
() => incoming.find((e) => e.source === selectedSource),
|
|
10984
|
+
[incoming, selectedSource]
|
|
10985
|
+
);
|
|
10986
|
+
const currentOp = useMemo(
|
|
10987
|
+
() => selectedOperationOf(asRecord(node?.data), node?.type),
|
|
10988
|
+
[node]
|
|
10989
|
+
);
|
|
10990
|
+
const sourceOp = useMemo(
|
|
10991
|
+
() => selectedOperationOf(asRecord(sourceNode?.data), sourceNode?.type),
|
|
10992
|
+
[sourceNode]
|
|
10993
|
+
);
|
|
10994
|
+
const inputFields = useMemo(
|
|
10995
|
+
() => fieldsFromIO(sourceOp?.output_fields),
|
|
10996
|
+
[sourceOp]
|
|
10997
|
+
);
|
|
10998
|
+
const outputFields = useMemo(
|
|
10999
|
+
() => fieldsFromIO(currentOp?.output_fields),
|
|
11000
|
+
[currentOp]
|
|
11001
|
+
);
|
|
11002
|
+
const params = useMemo(() => paramsFromOperation(currentOp), [currentOp]);
|
|
11003
|
+
const mapping = currentEdge?.mapping?.definition ?? {};
|
|
11004
|
+
const argsState = useMemo(() => {
|
|
11005
|
+
const data = asRecord(node?.data);
|
|
11006
|
+
const args = asRecord(data?.args);
|
|
11007
|
+
return asRecord(args?.state) ?? {};
|
|
11008
|
+
}, [node]);
|
|
11009
|
+
const writeMapping = (field, value) => {
|
|
11010
|
+
if (!currentEdge) return;
|
|
11011
|
+
const store = useFlowStore.getState();
|
|
11012
|
+
const freshEdges = store.workflow.edges;
|
|
11013
|
+
const next = freshEdges.map((e) => {
|
|
11014
|
+
if (e.id !== currentEdge.id) return e;
|
|
11015
|
+
const def = { ...e.mapping?.definition ?? {} };
|
|
11016
|
+
if (value.trim()) def[field] = value;
|
|
11017
|
+
else delete def[field];
|
|
11018
|
+
return {
|
|
11019
|
+
...e,
|
|
11020
|
+
mapping: {
|
|
11021
|
+
definition: def,
|
|
11022
|
+
comment: e.mapping?.comment ?? `Map ${selectedSource} \u2192 ${ndv?.nodeId ?? ""}`
|
|
11023
|
+
}
|
|
11024
|
+
};
|
|
11025
|
+
});
|
|
11026
|
+
store.actions.edges.setEdges(next);
|
|
11027
|
+
};
|
|
11028
|
+
const clearMappingFromAllIncoming = (field) => {
|
|
11029
|
+
if (!ndv) return;
|
|
11030
|
+
const store = useFlowStore.getState();
|
|
11031
|
+
const fresh = store.workflow.edges;
|
|
11032
|
+
let changed = false;
|
|
11033
|
+
const next = fresh.map((e) => {
|
|
11034
|
+
if (e.target !== ndv.nodeId || !e.mapping?.definition) return e;
|
|
11035
|
+
if (!(field in e.mapping.definition)) return e;
|
|
11036
|
+
const def = { ...e.mapping.definition };
|
|
11037
|
+
delete def[field];
|
|
11038
|
+
changed = true;
|
|
11039
|
+
return { ...e, mapping: { ...e.mapping, definition: def } };
|
|
11040
|
+
});
|
|
11041
|
+
if (changed) store.actions.edges.setEdges(next);
|
|
11042
|
+
};
|
|
11043
|
+
const writeFixed = (field, value) => {
|
|
11044
|
+
if (!ndv) return;
|
|
11045
|
+
const store = useFlowStore.getState();
|
|
11046
|
+
const next = store.workflow.nodes.map((n) => {
|
|
11047
|
+
if (n.id !== ndv.nodeId) return n;
|
|
11048
|
+
const data = { ...asRecord(n.data) ?? {} };
|
|
11049
|
+
const args = { ...asRecord(data.args) ?? {} };
|
|
11050
|
+
const state = { ...asRecord(args.state) ?? {} };
|
|
11051
|
+
if (value === void 0 || value === null || value === "") {
|
|
11052
|
+
delete state[field];
|
|
11053
|
+
} else {
|
|
11054
|
+
state[field] = value;
|
|
11055
|
+
}
|
|
11056
|
+
args.state = state;
|
|
11057
|
+
data.args = args;
|
|
11058
|
+
return { ...n, data };
|
|
11059
|
+
});
|
|
11060
|
+
store.actions.nodes.setNodes(next);
|
|
11061
|
+
clearMappingFromAllIncoming(field);
|
|
11062
|
+
};
|
|
11063
|
+
const toggleMode = (field, current) => {
|
|
11064
|
+
if (current === "expression") {
|
|
11065
|
+
clearMappingFromAllIncoming(field);
|
|
11066
|
+
}
|
|
11067
|
+
setModeByField((m) => ({
|
|
11068
|
+
...m,
|
|
11069
|
+
[field]: current === "expression" ? "fixed" : "expression"
|
|
11070
|
+
}));
|
|
11071
|
+
};
|
|
11072
|
+
const handleDropOnParam = (field) => (e) => {
|
|
11073
|
+
e.preventDefault();
|
|
11074
|
+
setDragField(null);
|
|
11075
|
+
const path = e.dataTransfer.getData(FIELD_PATH_MIME);
|
|
11076
|
+
if (path) {
|
|
11077
|
+
writeMapping(field, pathToExpression(path));
|
|
11078
|
+
setModeByField((m) => ({ ...m, [field]: "expression" }));
|
|
11079
|
+
}
|
|
11080
|
+
};
|
|
11081
|
+
const openClassicPanel = () => {
|
|
11082
|
+
if (!ndv) return;
|
|
11083
|
+
showNodePropertiesOf({
|
|
11084
|
+
id: ndv.nodeId,
|
|
11085
|
+
type: ndv.type
|
|
11086
|
+
});
|
|
11087
|
+
closeNdv();
|
|
11088
|
+
};
|
|
11089
|
+
const headerIcon = getNodeDetail(node?.type).icon;
|
|
11090
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (o) => !o && closeNdv(), children: /* @__PURE__ */ jsxs(
|
|
11091
|
+
DialogContent,
|
|
11092
|
+
{
|
|
11093
|
+
style: {
|
|
11094
|
+
width: "94vw",
|
|
11095
|
+
height: "92vh",
|
|
11096
|
+
maxWidth: "none",
|
|
11097
|
+
maxHeight: "92vh",
|
|
11098
|
+
// Above the app shell navbar so the header (title/close) isn't occluded.
|
|
11099
|
+
zIndex: 1e3
|
|
11100
|
+
},
|
|
11101
|
+
className: "flex flex-col gap-0 overflow-hidden border-border bg-background p-0",
|
|
11102
|
+
"data-testid": "ndv-modal",
|
|
11103
|
+
children: [
|
|
11104
|
+
/* @__PURE__ */ jsxs(DialogHeader, { className: "flex shrink-0 flex-row items-center gap-3 space-y-0 border-b border-border px-4 py-3", children: [
|
|
11105
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-7 shrink-0 items-center justify-center rounded-md bg-muted", children: /* @__PURE__ */ jsx(Icon, { icon: headerIcon, className: "size-4 text-foreground" }) }),
|
|
11106
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
11107
|
+
/* @__PURE__ */ jsx(DialogTitle, { className: "truncate text-sm font-semibold leading-tight", children: nodeTitle(node) }),
|
|
11108
|
+
nodeSubtitle(node) && /* @__PURE__ */ jsx(DialogDescription, { className: "truncate text-xs leading-tight", children: nodeSubtitle(node) })
|
|
11109
|
+
] }),
|
|
11110
|
+
/* @__PURE__ */ jsx(
|
|
11111
|
+
"button",
|
|
11112
|
+
{
|
|
11113
|
+
type: "button",
|
|
11114
|
+
onClick: openClassicPanel,
|
|
11115
|
+
className: "rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
11116
|
+
children: "Side panel"
|
|
11117
|
+
}
|
|
11118
|
+
),
|
|
11119
|
+
/* @__PURE__ */ jsx(
|
|
11120
|
+
"button",
|
|
11121
|
+
{
|
|
11122
|
+
type: "button",
|
|
11123
|
+
"aria-label": "Close",
|
|
11124
|
+
onClick: closeNdv,
|
|
11125
|
+
className: "rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
11126
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: "mdi:close", className: "size-4" })
|
|
11127
|
+
}
|
|
11128
|
+
)
|
|
11129
|
+
] }),
|
|
11130
|
+
/* @__PURE__ */ jsxs("div", { ref: panesRef, className: "flex min-h-0 flex-1", children: [
|
|
11131
|
+
/* @__PURE__ */ jsxs(
|
|
11132
|
+
"section",
|
|
11133
|
+
{
|
|
11134
|
+
style: { width: `${leftPct}%` },
|
|
11135
|
+
className: "flex min-h-0 min-w-[180px] flex-col bg-card/40",
|
|
11136
|
+
children: [
|
|
11137
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-2.5", children: [
|
|
11138
|
+
/* @__PURE__ */ jsx("span", { className: SECTION_LABEL, children: "Input" }),
|
|
11139
|
+
sourceIds.length > 0 && /* @__PURE__ */ jsx(
|
|
11140
|
+
"select",
|
|
11141
|
+
{
|
|
11142
|
+
className: "ml-auto max-w-[60%] truncate rounded-md border border-input bg-background px-2 py-1 text-xs text-foreground outline-none focus:border-primary",
|
|
11143
|
+
value: selectedSource ?? "",
|
|
11144
|
+
onChange: (e) => setSelectedSource(e.target.value),
|
|
11145
|
+
"data-testid": "ndv-source-selector",
|
|
11146
|
+
children: sourceIds.map((sid) => {
|
|
11147
|
+
const sn = nodes.find((n) => n.id === sid);
|
|
11148
|
+
return /* @__PURE__ */ jsx("option", { value: sid, children: nodeTitle(sn) }, sid);
|
|
11149
|
+
})
|
|
11150
|
+
}
|
|
11151
|
+
)
|
|
11152
|
+
] }),
|
|
11153
|
+
/* @__PURE__ */ jsx(
|
|
11154
|
+
"div",
|
|
11155
|
+
{
|
|
11156
|
+
className: "min-h-0 flex-1 overflow-auto px-2 pb-3",
|
|
11157
|
+
"data-testid": "ndv-input-tree",
|
|
11158
|
+
children: inputFields.length > 0 ? /* @__PURE__ */ jsx(FieldTree, { fields: inputFields, draggable: true }) : /* @__PURE__ */ jsx(
|
|
11159
|
+
EmptyState,
|
|
11160
|
+
{
|
|
11161
|
+
icon: "mdi:tray-arrow-down",
|
|
11162
|
+
title: "No input data",
|
|
11163
|
+
hint: sourceIds.length === 0 ? "Connect an upstream node to map its fields." : "The selected source has no declared output fields."
|
|
11164
|
+
}
|
|
11165
|
+
)
|
|
11166
|
+
}
|
|
11167
|
+
)
|
|
11168
|
+
]
|
|
11169
|
+
}
|
|
11170
|
+
),
|
|
11171
|
+
/* @__PURE__ */ jsx(ResizeHandle, { onStart: startDrag("left") }),
|
|
11172
|
+
/* @__PURE__ */ jsxs("section", { className: "flex min-h-0 min-w-[280px] flex-1 flex-col", children: [
|
|
11173
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-4 border-b border-border px-4", children: [
|
|
11174
|
+
/* @__PURE__ */ jsx(
|
|
11175
|
+
TabButton,
|
|
11176
|
+
{
|
|
11177
|
+
active: tab === "parameters",
|
|
11178
|
+
onClick: () => setTab("parameters"),
|
|
11179
|
+
children: "Parameters"
|
|
11180
|
+
}
|
|
11181
|
+
),
|
|
11182
|
+
/* @__PURE__ */ jsx(
|
|
11183
|
+
TabButton,
|
|
11184
|
+
{
|
|
11185
|
+
active: tab === "settings",
|
|
11186
|
+
onClick: () => setTab("settings"),
|
|
11187
|
+
children: "Settings"
|
|
11188
|
+
}
|
|
11189
|
+
)
|
|
11190
|
+
] }),
|
|
11191
|
+
tab === "parameters" ? /* @__PURE__ */ jsxs(
|
|
11192
|
+
"div",
|
|
11193
|
+
{
|
|
11194
|
+
className: "min-h-0 flex-1 space-y-4 overflow-auto p-4",
|
|
11195
|
+
"data-testid": "ndv-params",
|
|
11196
|
+
children: [
|
|
11197
|
+
!currentEdge && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: "No upstream node connected \u2014 set fixed values below, or connect a node to map fields with expressions." }),
|
|
11198
|
+
params.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-xs text-muted-foreground", children: "This operation has no input parameters." }) : params.map((p) => {
|
|
11199
|
+
const mode = modeByField[p.name] ?? (mapping[p.name] !== void 0 ? "expression" : "fixed");
|
|
11200
|
+
const exprValue = mapping[p.name] ?? "";
|
|
11201
|
+
const fixedValue = argsState[p.name];
|
|
11202
|
+
const highlight = dragField === p.name;
|
|
11203
|
+
const inputCx = cn$1(
|
|
11204
|
+
"w-full rounded-md border bg-background px-2.5 py-1.5 text-sm outline-none transition-colors disabled:opacity-50",
|
|
11205
|
+
highlight ? "border-primary ring-1 ring-primary" : "border-input focus:border-primary"
|
|
11206
|
+
);
|
|
11207
|
+
return /* @__PURE__ */ jsxs(
|
|
11208
|
+
"div",
|
|
11209
|
+
{
|
|
11210
|
+
className: "flex flex-col gap-1.5",
|
|
11211
|
+
onDragOver: (e) => e.preventDefault(),
|
|
11212
|
+
onDragEnter: () => setDragField(p.name),
|
|
11213
|
+
onDragLeave: () => setDragField((f) => f === p.name ? null : f),
|
|
11214
|
+
onDrop: handleDropOnParam(p.name),
|
|
11215
|
+
children: [
|
|
11216
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11217
|
+
/* @__PURE__ */ jsx("label", { className: "text-xs font-medium text-foreground", children: p.name }),
|
|
11218
|
+
p.required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" }),
|
|
11219
|
+
/* @__PURE__ */ jsx("span", { className: "ml-auto text-[10px] uppercase tracking-wide text-muted-foreground", children: p.type }),
|
|
11220
|
+
/* @__PURE__ */ jsx(
|
|
11221
|
+
"button",
|
|
11222
|
+
{
|
|
11223
|
+
type: "button",
|
|
11224
|
+
onClick: () => toggleMode(p.name, mode),
|
|
11225
|
+
title: mode === "expression" ? "Switch to a fixed value" : "Switch to an expression",
|
|
11226
|
+
"data-testid": `ndv-mode-${p.name}`,
|
|
11227
|
+
className: cn$1(
|
|
11228
|
+
"ml-1 rounded p-0.5 hover:text-foreground",
|
|
11229
|
+
mode === "expression" ? "text-primary" : "text-muted-foreground"
|
|
11230
|
+
),
|
|
11231
|
+
children: /* @__PURE__ */ jsx(
|
|
11232
|
+
Icon,
|
|
11233
|
+
{
|
|
11234
|
+
icon: mode === "expression" ? "mdi:variable" : "mdi:form-textbox",
|
|
11235
|
+
className: "size-3.5"
|
|
11236
|
+
}
|
|
11237
|
+
)
|
|
11238
|
+
}
|
|
11239
|
+
)
|
|
11240
|
+
] }),
|
|
11241
|
+
mode === "expression" ? /* @__PURE__ */ jsx(
|
|
11242
|
+
"input",
|
|
11243
|
+
{
|
|
11244
|
+
type: "text",
|
|
11245
|
+
value: exprValue,
|
|
11246
|
+
placeholder: currentEdge ? "Drop a field or type ${output.\u2026}" : "Connect an upstream node to use expressions",
|
|
11247
|
+
disabled: !currentEdge,
|
|
11248
|
+
onChange: (e) => writeMapping(p.name, e.target.value),
|
|
11249
|
+
"data-testid": `ndv-param-${p.name}`,
|
|
11250
|
+
className: cn$1(inputCx, "font-mono text-primary")
|
|
11251
|
+
}
|
|
11252
|
+
) : p.type === "boolean" ? /* @__PURE__ */ jsxs("label", { className: "flex w-fit cursor-pointer items-center gap-2 text-sm", children: [
|
|
11253
|
+
/* @__PURE__ */ jsx(
|
|
11254
|
+
"input",
|
|
11255
|
+
{
|
|
11256
|
+
type: "checkbox",
|
|
11257
|
+
checked: fixedValue === true,
|
|
11258
|
+
onChange: (e) => writeFixed(p.name, e.target.checked),
|
|
11259
|
+
"data-testid": `ndv-param-${p.name}`,
|
|
11260
|
+
className: "size-4"
|
|
11261
|
+
}
|
|
11262
|
+
),
|
|
11263
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: fixedValue === void 0 ? "Not set (default)" : fixedValue === true ? "true" : "false" })
|
|
11264
|
+
] }) : p.options && p.options.length > 0 ? /* @__PURE__ */ jsxs(
|
|
11265
|
+
"select",
|
|
11266
|
+
{
|
|
11267
|
+
value: typeof fixedValue === "string" ? fixedValue : "",
|
|
11268
|
+
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
11269
|
+
"data-testid": `ndv-param-${p.name}`,
|
|
11270
|
+
className: inputCx,
|
|
11271
|
+
children: [
|
|
11272
|
+
/* @__PURE__ */ jsx("option", { value: "", children: p.defaultValue !== void 0 ? `Default (${String(p.defaultValue)})` : "Select\u2026" }),
|
|
11273
|
+
p.options.map((o) => /* @__PURE__ */ jsx("option", { value: o, children: o }, o))
|
|
11274
|
+
]
|
|
11275
|
+
}
|
|
11276
|
+
) : p.type === "integer" || p.type === "number" ? /* @__PURE__ */ jsx(
|
|
11277
|
+
"input",
|
|
11278
|
+
{
|
|
11279
|
+
type: "number",
|
|
11280
|
+
step: p.type === "integer" ? "1" : "any",
|
|
11281
|
+
value: typeof fixedValue === "number" ? String(fixedValue) : "",
|
|
11282
|
+
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a number",
|
|
11283
|
+
onChange: (e) => writeFixed(
|
|
11284
|
+
p.name,
|
|
11285
|
+
coerceNumber(p.type, e.target.value)
|
|
11286
|
+
),
|
|
11287
|
+
"data-testid": `ndv-param-${p.name}`,
|
|
11288
|
+
className: inputCx
|
|
11289
|
+
}
|
|
11290
|
+
) : /* @__PURE__ */ jsx(
|
|
11291
|
+
"input",
|
|
11292
|
+
{
|
|
11293
|
+
type: "text",
|
|
11294
|
+
value: fixedValue === void 0 || fixedValue === null ? "" : String(fixedValue),
|
|
11295
|
+
placeholder: p.defaultValue !== void 0 ? `Default: ${String(p.defaultValue)}` : "Enter a value",
|
|
11296
|
+
onChange: (e) => writeFixed(p.name, e.target.value),
|
|
11297
|
+
"data-testid": `ndv-param-${p.name}`,
|
|
11298
|
+
className: inputCx
|
|
11299
|
+
}
|
|
11300
|
+
),
|
|
11301
|
+
p.description && /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-snug text-muted-foreground", children: p.description })
|
|
11302
|
+
]
|
|
11303
|
+
},
|
|
11304
|
+
p.name
|
|
11305
|
+
);
|
|
11306
|
+
})
|
|
11307
|
+
]
|
|
11308
|
+
}
|
|
11309
|
+
) : /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4 text-xs text-muted-foreground", children: "No additional settings for this node." })
|
|
11310
|
+
] }),
|
|
11311
|
+
/* @__PURE__ */ jsx(ResizeHandle, { onStart: startDrag("right") }),
|
|
11312
|
+
/* @__PURE__ */ jsxs(
|
|
11313
|
+
"section",
|
|
11314
|
+
{
|
|
11315
|
+
style: { width: `${rightPct}%` },
|
|
11316
|
+
className: "flex min-h-0 min-w-[180px] flex-col bg-card/40",
|
|
11317
|
+
children: [
|
|
11318
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-2.5", children: [
|
|
11319
|
+
/* @__PURE__ */ jsx("span", { className: SECTION_LABEL, children: "Output" }),
|
|
11320
|
+
outputFields.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1", children: [
|
|
11321
|
+
/* @__PURE__ */ jsx(
|
|
11322
|
+
ToggleChip,
|
|
11323
|
+
{
|
|
11324
|
+
active: outputView === "schema",
|
|
11325
|
+
onClick: () => setOutputView("schema"),
|
|
11326
|
+
children: "Schema"
|
|
11327
|
+
}
|
|
11328
|
+
),
|
|
11329
|
+
/* @__PURE__ */ jsx(
|
|
11330
|
+
ToggleChip,
|
|
11331
|
+
{
|
|
11332
|
+
active: outputView === "json",
|
|
11333
|
+
onClick: () => setOutputView("json"),
|
|
11334
|
+
children: "JSON"
|
|
11335
|
+
}
|
|
11336
|
+
)
|
|
11337
|
+
] })
|
|
11338
|
+
] }),
|
|
11339
|
+
/* @__PURE__ */ jsx(
|
|
11340
|
+
"div",
|
|
11341
|
+
{
|
|
11342
|
+
className: "min-h-0 flex-1 overflow-auto px-2 pb-3",
|
|
11343
|
+
"data-testid": "ndv-output-tree",
|
|
11344
|
+
children: outputFields.length === 0 ? /* @__PURE__ */ jsx(
|
|
11345
|
+
EmptyState,
|
|
11346
|
+
{
|
|
11347
|
+
icon: "mdi:tray-arrow-up",
|
|
11348
|
+
title: "No output data",
|
|
11349
|
+
hint: "This operation has no declared output fields."
|
|
11350
|
+
}
|
|
11351
|
+
) : outputView === "schema" ? /* @__PURE__ */ jsx(FieldTree, { fields: outputFields }) : /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap break-words px-2 text-[11px] leading-relaxed text-muted-foreground", children: JSON.stringify(currentOp?.output_fields ?? {}, null, 2) })
|
|
11352
|
+
}
|
|
11353
|
+
)
|
|
11354
|
+
]
|
|
11355
|
+
}
|
|
11356
|
+
)
|
|
11357
|
+
] })
|
|
11358
|
+
]
|
|
11359
|
+
}
|
|
11360
|
+
) });
|
|
11361
|
+
}
|
|
11362
|
+
function ResizeHandle({ onStart }) {
|
|
11363
|
+
return /* @__PURE__ */ jsx(
|
|
11364
|
+
"div",
|
|
11365
|
+
{
|
|
11366
|
+
onMouseDown: onStart,
|
|
11367
|
+
role: "separator",
|
|
11368
|
+
"aria-orientation": "vertical",
|
|
11369
|
+
className: "group flex w-1.5 shrink-0 cursor-col-resize items-center justify-center bg-border/60 hover:bg-primary/40",
|
|
11370
|
+
children: /* @__PURE__ */ jsx("div", { className: "h-8 w-0.5 rounded bg-muted-foreground/40 group-hover:bg-primary" })
|
|
11371
|
+
}
|
|
11372
|
+
);
|
|
11373
|
+
}
|
|
11374
|
+
function TabButton({
|
|
11375
|
+
active,
|
|
11376
|
+
onClick,
|
|
11377
|
+
children
|
|
11378
|
+
}) {
|
|
11379
|
+
return /* @__PURE__ */ jsx(
|
|
11380
|
+
"button",
|
|
11381
|
+
{
|
|
11382
|
+
type: "button",
|
|
11383
|
+
onClick,
|
|
11384
|
+
className: cn$1(
|
|
11385
|
+
"-mb-px border-b-2 py-2.5 text-sm transition-colors",
|
|
11386
|
+
active ? "border-primary font-medium text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
|
|
11387
|
+
),
|
|
11388
|
+
children
|
|
11389
|
+
}
|
|
11390
|
+
);
|
|
11391
|
+
}
|
|
11392
|
+
function ToggleChip({
|
|
11393
|
+
active,
|
|
11394
|
+
onClick,
|
|
11395
|
+
children
|
|
11396
|
+
}) {
|
|
11397
|
+
return /* @__PURE__ */ jsx(
|
|
11398
|
+
"button",
|
|
11399
|
+
{
|
|
11400
|
+
type: "button",
|
|
11401
|
+
onClick,
|
|
11402
|
+
className: cn$1(
|
|
11403
|
+
"rounded px-1.5 py-0.5 text-[10px] font-medium uppercase tracking-wide transition-colors",
|
|
11404
|
+
active ? "bg-primary/10 text-primary" : "text-muted-foreground hover:text-foreground"
|
|
11405
|
+
),
|
|
11406
|
+
children
|
|
11407
|
+
}
|
|
11408
|
+
);
|
|
11409
|
+
}
|
|
11410
|
+
function EmptyState({
|
|
11411
|
+
icon,
|
|
11412
|
+
title,
|
|
11413
|
+
hint
|
|
11414
|
+
}) {
|
|
11415
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-center gap-2 px-6 text-center", children: [
|
|
11416
|
+
/* @__PURE__ */ jsx(Icon, { icon, className: "size-7 text-muted-foreground/50" }),
|
|
11417
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-foreground/80", children: title }),
|
|
11418
|
+
/* @__PURE__ */ jsx("div", { className: "max-w-[14rem] text-xs text-muted-foreground", children: hint })
|
|
11419
|
+
] });
|
|
11420
|
+
}
|
|
10713
11421
|
var STATUS_STYLES = {
|
|
10714
11422
|
DRAFT: { label: "Draft", variant: "secondary" },
|
|
10715
11423
|
ACTIVE: { label: "Active", variant: "default" },
|
|
@@ -11168,6 +11876,7 @@ var FlowBuilder = () => {
|
|
|
11168
11876
|
),
|
|
11169
11877
|
/* @__PURE__ */ jsx(ChatPanel, {}),
|
|
11170
11878
|
/* @__PURE__ */ jsx(LogsPanel, {}),
|
|
11879
|
+
/* @__PURE__ */ jsx(NodeDetailView, {}),
|
|
11171
11880
|
/* @__PURE__ */ jsx(
|
|
11172
11881
|
"div",
|
|
11173
11882
|
{
|
|
@@ -11421,5 +12130,5 @@ function WorkflowBuilder() {
|
|
|
11421
12130
|
}
|
|
11422
12131
|
|
|
11423
12132
|
export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, TemplateCard, WorkflowBuilder, useWorkflowTemplates };
|
|
11424
|
-
//# sourceMappingURL=chunk-
|
|
11425
|
-
//# sourceMappingURL=chunk-
|
|
12133
|
+
//# sourceMappingURL=chunk-QANP2YKX.js.map
|
|
12134
|
+
//# sourceMappingURL=chunk-QANP2YKX.js.map
|