@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +508 -0
- package/MIGRATION-2.0.md +629 -0
- package/README.md +23 -23
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +14 -8
- package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
- package/dist/api/enhanced-client.js +6 -11
- package/dist/chat/batchFeedback.d.ts +39 -0
- package/dist/chat/batchFeedback.js +51 -0
- package/dist/commands/executor.js +15 -1
- package/dist/commands/storeIntegration.svelte.d.ts +4 -1
- package/dist/commands/storeIntegration.svelte.js +26 -21
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/App.svelte +163 -192
- package/dist/components/App.svelte.d.ts +47 -8
- package/dist/components/ConfigForm.svelte +77 -49
- package/dist/components/ConfigModal.svelte +7 -2
- package/dist/components/ConnectionLine.svelte +4 -2
- package/dist/components/Navbar.svelte +61 -1
- package/dist/components/NodeSidebar.svelte +27 -45
- package/dist/components/NodeStatusOverlay.svelte +94 -6
- package/dist/components/NodeSwapPicker.svelte +10 -8
- package/dist/components/PipelineStatus.svelte +22 -68
- package/dist/components/PipelineStatus.svelte.d.ts +3 -0
- package/dist/components/PortCoordinateTracker.svelte +5 -6
- package/dist/components/SchemaForm.stories.svelte +1 -3
- package/dist/components/SchemaForm.svelte +22 -27
- package/dist/components/SchemaForm.svelte.d.ts +0 -8
- package/dist/components/SettingsModal.svelte +8 -3
- package/dist/components/SettingsPanel.svelte +20 -4
- package/dist/components/SwapMappingEditor.svelte +67 -49
- package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
- package/dist/components/UniversalNode.svelte +9 -7
- package/dist/components/WorkflowEditor.svelte +121 -111
- package/dist/components/WorkflowEditor.svelte.d.ts +21 -10
- package/dist/components/chat/AIChatPanel.svelte +98 -89
- package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
- package/dist/components/chat/CommandPreview.svelte +2 -1
- package/dist/components/console/CommandConsole.svelte +7 -5
- package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
- package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
- package/dist/components/console/ConsoleInput.svelte +15 -6
- package/dist/components/console/ConsoleOutput.svelte +2 -1
- package/dist/components/form/FormArray.svelte +5 -9
- package/dist/components/form/FormArray.svelte.d.ts +2 -1
- package/dist/components/form/FormAutocomplete.svelte +16 -15
- package/dist/components/form/FormField.svelte +4 -2
- package/dist/components/form/FormFieldLight.svelte +34 -3
- package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
- package/dist/components/form/FormMarkdownEditor.svelte +9 -4
- package/dist/components/form/FormRangeField.svelte +1 -0
- package/dist/components/form/FormTemplateEditor.svelte +11 -3
- package/dist/components/form/FormToggle.svelte +5 -12
- package/dist/components/form/FormToggle.svelte.d.ts +4 -2
- package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
- package/dist/components/form/templateAutocomplete.js +1 -5
- package/dist/components/form/types.d.ts +1 -14
- package/dist/components/interrupt/FormPrompt.svelte +3 -2
- package/dist/components/interrupt/InterruptBubble.svelte +25 -17
- package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
- package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
- package/dist/components/layouts/MainLayout.svelte +20 -13
- package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
- package/dist/components/nodes/AtomNode.svelte +17 -5
- package/dist/components/nodes/GatewayNode.svelte +19 -10
- package/dist/components/nodes/IdeaNode.svelte +7 -0
- package/dist/components/nodes/SimpleNode.svelte +11 -6
- package/dist/components/nodes/SquareNode.svelte +15 -8
- package/dist/components/nodes/TerminalNode.svelte +9 -4
- package/dist/components/nodes/ToolNode.svelte +7 -1
- package/dist/components/nodes/WorkflowNode.svelte +16 -7
- package/dist/components/playground/ChatInput.svelte +11 -14
- package/dist/components/playground/ChatPanel.svelte +6 -49
- package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
- package/dist/components/playground/ControlPanel.svelte +134 -123
- package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
- package/dist/components/playground/ExecutionLogs.svelte +11 -9
- package/dist/components/playground/InputCollector.svelte +11 -9
- package/dist/components/playground/MessageStream.svelte +17 -23
- package/dist/components/playground/PipelineKanbanView.svelte +69 -8
- package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
- package/dist/components/playground/PipelinePanel.svelte +31 -8
- package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
- package/dist/components/playground/PipelineTableView.svelte +188 -44
- package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
- package/dist/components/playground/Playground.svelte +154 -105
- package/dist/components/playground/Playground.svelte.d.ts +5 -0
- package/dist/components/playground/PlaygroundApp.svelte +11 -1
- package/dist/components/playground/PlaygroundApp.svelte.d.ts +6 -0
- package/dist/components/playground/PlaygroundModal.svelte +18 -3
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +6 -0
- package/dist/components/playground/PlaygroundStudio.svelte +40 -32
- package/dist/components/playground/PlaygroundStudio.svelte.d.ts +6 -0
- package/dist/components/playground/SessionManager.svelte +9 -12
- package/dist/components/playground/pipelineViewUtils.svelte.d.ts +30 -1
- package/dist/components/playground/pipelineViewUtils.svelte.js +40 -3
- package/dist/config/endpoints.d.ts +23 -7
- package/dist/config/endpoints.js +30 -10
- package/dist/core/index.d.ts +5 -6
- package/dist/core/index.js +8 -12
- package/dist/display/index.d.ts +6 -3
- package/dist/display/index.js +7 -5
- package/dist/editor/index.d.ts +20 -21
- package/dist/editor/index.js +26 -36
- package/dist/form/code.d.ts +25 -15
- package/dist/form/code.js +44 -41
- package/dist/form/fieldRegistry.d.ts +17 -13
- package/dist/form/fieldRegistry.js +32 -12
- package/dist/form/full.d.ts +19 -14
- package/dist/form/full.js +26 -28
- package/dist/form/index.d.ts +3 -4
- package/dist/form/index.js +6 -5
- package/dist/form/markdown.d.ts +13 -8
- package/dist/form/markdown.js +22 -23
- package/dist/helpers/proximityConnect.d.ts +3 -2
- package/dist/helpers/proximityConnect.js +2 -5
- package/dist/helpers/workflowEditorHelper.d.ts +14 -5
- package/dist/helpers/workflowEditorHelper.js +28 -25
- package/dist/index.d.ts +28 -24
- package/dist/index.js +27 -50
- package/dist/messages/defaults.d.ts +2 -5
- package/dist/messages/defaults.js +3 -6
- package/dist/messages/index.d.ts +0 -1
- package/dist/messages/index.js +0 -1
- package/dist/mocks/app-forms.d.ts +6 -2
- package/dist/mocks/app-forms.js +11 -4
- package/dist/openapi/v1/openapi.yaml +3 -3
- package/dist/playground/index.d.ts +4 -5
- package/dist/playground/index.js +4 -32
- package/dist/playground/mount.d.ts +25 -0
- package/dist/playground/mount.js +50 -20
- package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
- package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
- package/dist/registry/builtinFormats.d.ts +9 -18
- package/dist/registry/builtinFormats.js +9 -39
- package/dist/registry/builtinNodeTypes.d.ts +53 -0
- package/dist/registry/builtinNodeTypes.js +67 -0
- package/dist/registry/builtinNodes.d.ts +2 -64
- package/dist/registry/builtinNodes.js +7 -103
- package/dist/registry/index.d.ts +3 -4
- package/dist/registry/index.js +4 -6
- package/dist/registry/nodeComponentRegistry.d.ts +182 -15
- package/dist/registry/nodeComponentRegistry.js +235 -17
- package/dist/registry/workflowFormatRegistry.d.ts +14 -9
- package/dist/registry/workflowFormatRegistry.js +24 -8
- package/dist/{schema → schemas}/index.d.ts +2 -2
- package/dist/{schema → schemas}/index.js +2 -2
- package/dist/schemas/v1/workflow.schema.json +3 -3
- package/dist/services/agentSpecExecutionService.d.ts +0 -2
- package/dist/services/agentSpecExecutionService.js +0 -3
- package/dist/services/apiVariableService.d.ts +2 -1
- package/dist/services/apiVariableService.js +16 -47
- package/dist/services/autoSaveService.d.ts +7 -0
- package/dist/services/autoSaveService.js +6 -4
- package/dist/services/categoriesApi.js +3 -6
- package/dist/services/chatService.d.ts +9 -4
- package/dist/services/chatService.js +23 -28
- package/dist/services/draftStorage.d.ts +129 -13
- package/dist/services/draftStorage.js +185 -37
- package/dist/services/dynamicSchemaService.d.ts +2 -1
- package/dist/services/dynamicSchemaService.js +5 -22
- package/dist/services/globalSave.d.ts +13 -12
- package/dist/services/globalSave.js +29 -51
- package/dist/services/historyService.d.ts +9 -3
- package/dist/services/historyService.js +9 -3
- package/dist/services/interruptService.d.ts +15 -9
- package/dist/services/interruptService.js +35 -37
- package/dist/services/nodeExecutionService.d.ts +18 -3
- package/dist/services/nodeExecutionService.js +71 -45
- package/dist/services/playgroundService.d.ts +16 -10
- package/dist/services/playgroundService.js +42 -43
- package/dist/services/portConfigApi.js +3 -6
- package/dist/services/settingsService.d.ts +9 -4
- package/dist/services/settingsService.js +23 -12
- package/dist/services/variableService.d.ts +2 -1
- package/dist/services/variableService.js +2 -2
- package/dist/services/workflowStorage.js +6 -6
- package/dist/stores/apiContext.d.ts +56 -0
- package/dist/stores/apiContext.js +80 -0
- package/dist/stores/categoriesStore.svelte.d.ts +28 -23
- package/dist/stores/categoriesStore.svelte.js +69 -64
- package/dist/stores/getInstance.svelte.d.ts +39 -0
- package/dist/stores/getInstance.svelte.js +65 -0
- package/dist/stores/historyStore.svelte.d.ts +77 -93
- package/dist/stores/historyStore.svelte.js +134 -160
- package/dist/stores/instanceContainer.svelte.d.ts +111 -0
- package/dist/stores/instanceContainer.svelte.js +114 -0
- package/dist/stores/interruptStore.svelte.d.ts +112 -82
- package/dist/stores/interruptStore.svelte.js +253 -226
- package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
- package/dist/stores/pipelinePanelStore.svelte.js +61 -14
- package/dist/stores/playgroundStore.svelte.d.ts +169 -222
- package/dist/stores/playgroundStore.svelte.js +513 -580
- package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
- package/dist/stores/portCoordinateStore.svelte.js +109 -98
- package/dist/stores/settingsStore.svelte.d.ts +4 -1
- package/dist/stores/settingsStore.svelte.js +47 -12
- package/dist/stores/workflowStore.svelte.d.ts +178 -213
- package/dist/stores/workflowStore.svelte.js +449 -501
- package/dist/stories/EdgeDecorator.svelte +5 -2
- package/dist/stories/NodeDecorator.svelte +5 -3
- package/dist/svelte-app.d.ts +60 -10
- package/dist/svelte-app.js +159 -54
- package/dist/types/auth.d.ts +9 -51
- package/dist/types/auth.js +4 -54
- package/dist/types/events.d.ts +6 -3
- package/dist/types/index.d.ts +37 -5
- package/dist/types/index.js +0 -1
- package/dist/types/navbar.d.ts +7 -0
- package/dist/types/playground.d.ts +18 -3
- package/dist/types/settings.d.ts +13 -0
- package/dist/types/settings.js +1 -0
- package/dist/utils/colors.d.ts +47 -21
- package/dist/utils/colors.js +69 -68
- package/dist/utils/connections.d.ts +9 -15
- package/dist/utils/connections.js +13 -32
- package/dist/utils/duration.d.ts +13 -0
- package/dist/utils/duration.js +45 -0
- package/dist/utils/edgeStyling.js +9 -5
- package/dist/utils/fetchWithAuth.d.ts +36 -15
- package/dist/utils/fetchWithAuth.js +53 -23
- package/dist/utils/icons.d.ts +5 -2
- package/dist/utils/icons.js +6 -5
- package/dist/utils/nodeSwap.d.ts +6 -2
- package/dist/utils/nodeSwap.js +62 -126
- package/dist/utils/nodeTypes.d.ts +17 -8
- package/dist/utils/nodeTypes.js +27 -20
- package/dist/utils/performanceUtils.js +7 -0
- package/package.json +7 -5
- package/dist/messages/deprecation.d.ts +0 -20
- package/dist/messages/deprecation.js +0 -33
- package/dist/registry/plugin.d.ts +0 -215
- package/dist/registry/plugin.js +0 -249
- package/dist/services/api.d.ts +0 -129
- package/dist/services/api.js +0 -217
|
@@ -18,15 +18,7 @@
|
|
|
18
18
|
import NodeSwapPicker from './NodeSwapPicker.svelte';
|
|
19
19
|
import SwapMappingEditor from './SwapMappingEditor.svelte';
|
|
20
20
|
import Navbar from './Navbar.svelte';
|
|
21
|
-
import {
|
|
22
|
-
import { EnhancedFlowDropApiClient } from '../api/enhanced-client.js';
|
|
23
|
-
import type {
|
|
24
|
-
NodeMetadata,
|
|
25
|
-
Workflow,
|
|
26
|
-
WorkflowNode,
|
|
27
|
-
ConfigSchema,
|
|
28
|
-
NodeUIExtensions
|
|
29
|
-
} from '../types/index.js';
|
|
21
|
+
import type { NodeMetadata, Workflow, WorkflowNode, ConfigSchema } from '../types/index.js';
|
|
30
22
|
import type { InteractiveSwapState, SwapEventContext } from '../utils/nodeSwap.js';
|
|
31
23
|
import {
|
|
32
24
|
computeInteractiveState,
|
|
@@ -44,24 +36,16 @@
|
|
|
44
36
|
import type { FlowDropTheme, FlowDropThemeName } from '../types/theme.js';
|
|
45
37
|
import type { FlowDropSkinTokens } from '../types/skin.js';
|
|
46
38
|
import { resolveTheme } from '../themes/index.js';
|
|
47
|
-
import {
|
|
48
|
-
|
|
49
|
-
workflowActions,
|
|
50
|
-
getWorkflowName,
|
|
51
|
-
getWorkflowFormat,
|
|
52
|
-
markAsSaved
|
|
53
|
-
} from '../stores/workflowStore.svelte.js';
|
|
39
|
+
import { provideInstance } from '../stores/getInstance.svelte.js';
|
|
40
|
+
import type { FlowDropInstance } from '../stores/instanceContainer.svelte.js';
|
|
54
41
|
import { globalSaveWorkflow, globalExportWorkflow } from '../services/globalSave.js';
|
|
55
42
|
import { apiToasts, dismissToast } from '../services/toastService.js';
|
|
56
43
|
import { initAutoSave } from '../services/autoSaveService.js';
|
|
57
|
-
import { getUiSettings, updateSettings } from '../stores/settingsStore.svelte.js';
|
|
58
44
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} from '../
|
|
63
|
-
import { DEFAULT_PORT_CONFIG } from '../config/defaultPortConfig.js';
|
|
64
|
-
import { workflowFormatRegistry } from '../registry/workflowFormatRegistry.js';
|
|
45
|
+
getUiSettings,
|
|
46
|
+
updateSettings,
|
|
47
|
+
initializeTheme
|
|
48
|
+
} from '../stores/settingsStore.svelte.js';
|
|
65
49
|
import { logger } from '../utils/logger.js';
|
|
66
50
|
import { validateWorkflowData } from '../utils/validation.js';
|
|
67
51
|
import type { SettingsCategory } from '../types/settings.js';
|
|
@@ -84,14 +68,33 @@
|
|
|
84
68
|
showNavbar?: boolean;
|
|
85
69
|
/** Disable the node sidebar */
|
|
86
70
|
disableSidebar?: boolean;
|
|
87
|
-
/**
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Editor interaction mode. Replaces the former `readOnly` + `lockWorkflow`
|
|
73
|
+
* boolean pair (2.0 breaking change).
|
|
74
|
+
*
|
|
75
|
+
* | mode | node drag / connect / select | proximity-connect | node swap | bottom console panel + toggle |
|
|
76
|
+
* |--------------|------------------------------|-------------------|-----------|-------------------------------|
|
|
77
|
+
* | `'edit'` | enabled | enabled | enabled | available |
|
|
78
|
+
* | `'readonly'` | disabled | disabled | disabled | hidden |
|
|
79
|
+
* | `'locked'` | disabled | disabled | disabled | hidden |
|
|
80
|
+
*
|
|
81
|
+
* In 1.x `readOnly` and `lockWorkflow` gated the exact same set of
|
|
82
|
+
* interactions and were always combined as `!readOnly && !lockWorkflow`,
|
|
83
|
+
* so any combination of the two booleans collapsed to "edit" (both false)
|
|
84
|
+
* or "disabled" (either true). `'readonly'` and `'locked'` therefore behave
|
|
85
|
+
* identically today; the two names are kept as distinct intents so future
|
|
86
|
+
* versions can differentiate them without another breaking change.
|
|
87
|
+
*
|
|
88
|
+
* Migration: `readOnly` → `mode="readonly"`; `lockWorkflow` →
|
|
89
|
+
* `mode="locked"`; both `false` (or unset) → `mode="edit"` (the default).
|
|
90
|
+
*
|
|
91
|
+
* @default 'edit'
|
|
92
|
+
*/
|
|
93
|
+
mode?: 'edit' | 'readonly' | 'locked';
|
|
93
94
|
/** Pipeline ID for fetching node execution info */
|
|
94
95
|
pipelineId?: string;
|
|
96
|
+
/** Increments to force a refresh of pipeline node status from the server */
|
|
97
|
+
refreshTrigger?: number;
|
|
95
98
|
/** Custom navbar title */
|
|
96
99
|
navbarTitle?: string;
|
|
97
100
|
/** Custom navbar actions */
|
|
@@ -104,14 +107,31 @@
|
|
|
104
107
|
}>;
|
|
105
108
|
/** Show settings gear icon in navbar */
|
|
106
109
|
showSettings?: boolean;
|
|
110
|
+
/** Show the "Connected" status indicator in the navbar (default: true) */
|
|
111
|
+
showStatus?: boolean;
|
|
107
112
|
/** API base URL */
|
|
108
113
|
apiBaseUrl?: string;
|
|
109
114
|
/** Endpoint configuration */
|
|
110
115
|
endpointConfig?: EndpointConfig;
|
|
111
116
|
/** Authentication provider */
|
|
112
117
|
authProvider?: AuthProvider;
|
|
113
|
-
/**
|
|
114
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Called before save — return false to cancel. Forwarded to the save
|
|
120
|
+
* pipeline. (Flattened from the former `eventHandlers` object in 2.0.)
|
|
121
|
+
*/
|
|
122
|
+
onBeforeSave?: FlowDropEventHandlers['onBeforeSave'];
|
|
123
|
+
/** Called after a successful save. */
|
|
124
|
+
onAfterSave?: FlowDropEventHandlers['onAfterSave'];
|
|
125
|
+
/** Called when a save fails. */
|
|
126
|
+
onSaveError?: FlowDropEventHandlers['onSaveError'];
|
|
127
|
+
/** Called on any API error — return true to suppress the default toast. */
|
|
128
|
+
onApiError?: FlowDropEventHandlers['onApiError'];
|
|
129
|
+
/** Called after a workflow is loaded/imported. */
|
|
130
|
+
onWorkflowLoad?: FlowDropEventHandlers['onWorkflowLoad'];
|
|
131
|
+
/** Called before a node swap — return false to cancel. */
|
|
132
|
+
onBeforeSwap?: FlowDropEventHandlers['onBeforeSwap'];
|
|
133
|
+
/** Called after a node swap is applied. */
|
|
134
|
+
onAfterSwap?: FlowDropEventHandlers['onAfterSwap'];
|
|
115
135
|
/** Feature configuration */
|
|
116
136
|
features?: FlowDropFeatures;
|
|
117
137
|
/** Visual theme — named built-in ('default' | 'minimal') or custom theme object */
|
|
@@ -138,6 +158,8 @@
|
|
|
138
158
|
* function call you'd rather not invoke unless the prop is actually read.
|
|
139
159
|
*/
|
|
140
160
|
messages?: MessagesOverride | (() => MessagesOverride);
|
|
161
|
+
/** Per-instance state container (created by mount functions). Defaults to the page-default instance. */
|
|
162
|
+
instance?: FlowDropInstance;
|
|
141
163
|
}
|
|
142
164
|
|
|
143
165
|
let {
|
|
@@ -147,17 +169,23 @@
|
|
|
147
169
|
width = '100%',
|
|
148
170
|
showNavbar = false,
|
|
149
171
|
disableSidebar = false,
|
|
150
|
-
|
|
151
|
-
readOnly = false,
|
|
152
|
-
nodeStatuses = {},
|
|
172
|
+
mode = 'edit',
|
|
153
173
|
pipelineId,
|
|
174
|
+
refreshTrigger = 0,
|
|
154
175
|
navbarTitle,
|
|
155
176
|
navbarActions = [],
|
|
156
177
|
showSettings = true,
|
|
178
|
+
showStatus = true,
|
|
157
179
|
apiBaseUrl,
|
|
158
180
|
endpointConfig: propEndpointConfig,
|
|
159
181
|
authProvider,
|
|
160
|
-
|
|
182
|
+
onBeforeSave,
|
|
183
|
+
onAfterSave,
|
|
184
|
+
onSaveError,
|
|
185
|
+
onApiError,
|
|
186
|
+
onWorkflowLoad,
|
|
187
|
+
onBeforeSwap,
|
|
188
|
+
onAfterSwap,
|
|
161
189
|
features: propFeatures,
|
|
162
190
|
theme: themeProp,
|
|
163
191
|
settingsCategories,
|
|
@@ -165,12 +193,25 @@
|
|
|
165
193
|
showSettingsResetButton,
|
|
166
194
|
swapStrategies,
|
|
167
195
|
workflowSettingsSchema,
|
|
168
|
-
messages: messagesOverride
|
|
196
|
+
messages: messagesOverride,
|
|
197
|
+
instance
|
|
169
198
|
}: Props = $props();
|
|
170
199
|
|
|
171
|
-
//
|
|
200
|
+
// Resolve (and provide to children) the per-instance state container.
|
|
201
|
+
// Must run during component init — provideInstance reads/sets Svelte context.
|
|
202
|
+
// The instance never changes for a mounted component, so capturing it once is correct.
|
|
203
|
+
// svelte-ignore state_referenced_locally
|
|
204
|
+
const fd = provideInstance(instance);
|
|
205
|
+
|
|
206
|
+
// feature flags don't change at runtime
|
|
207
|
+
// svelte-ignore state_referenced_locally
|
|
172
208
|
const features = mergeFeatures(propFeatures);
|
|
173
209
|
|
|
210
|
+
// `mode` is the public API; internally the canvas only cares whether editing
|
|
211
|
+
// is disabled. 'readonly' and 'locked' both disable the same interactions
|
|
212
|
+
// (see the `mode` prop JSDoc for the full matrix).
|
|
213
|
+
const canvasEditable = $derived(mode === 'edit');
|
|
214
|
+
|
|
174
215
|
// Messages: merge consumer overrides over defaults; expose via context as a
|
|
175
216
|
// getter so consumer-side reactivity (e.g. paraglide-js locale switches)
|
|
176
217
|
// propagates into every child without a subscription. Accepts either a
|
|
@@ -271,7 +312,7 @@
|
|
|
271
312
|
return navbarTitle;
|
|
272
313
|
}
|
|
273
314
|
// Default workflow title logic
|
|
274
|
-
const wfName =
|
|
315
|
+
const wfName = fd.workflow.name;
|
|
275
316
|
if (!wfName || wfName === 'Untitled Workflow') {
|
|
276
317
|
return 'Workflow / New Workflow';
|
|
277
318
|
}
|
|
@@ -285,12 +326,6 @@
|
|
|
285
326
|
let error = $state<string | null>(null);
|
|
286
327
|
let endpointConfig = $state<EndpointConfig | null>(null);
|
|
287
328
|
|
|
288
|
-
/**
|
|
289
|
-
* Enhanced API client with authProvider support
|
|
290
|
-
* Used when authProvider is provided; otherwise falls back to legacy api service
|
|
291
|
-
*/
|
|
292
|
-
let apiClient = $state<EnhancedFlowDropApiClient | null>(null);
|
|
293
|
-
|
|
294
329
|
// ConfigSidebar state
|
|
295
330
|
let isConfigSidebarOpen = $state(false);
|
|
296
331
|
let selectedNodeId = $state<string | null>(null);
|
|
@@ -300,7 +335,6 @@
|
|
|
300
335
|
|
|
301
336
|
// Node swap state
|
|
302
337
|
let swapMode = $state<'idle' | 'picking' | 'mapping'>('idle');
|
|
303
|
-
let swapTargetMetadata = $state<NodeMetadata | null>(null);
|
|
304
338
|
let swapInteractiveState = $state<InteractiveSwapState | null>(null);
|
|
305
339
|
|
|
306
340
|
// Built-in workflow settings field names — consumer schemas must not reuse these.
|
|
@@ -342,7 +376,7 @@
|
|
|
342
376
|
type: 'string',
|
|
343
377
|
title: 'Workflow Format',
|
|
344
378
|
description: 'The specification format for this workflow',
|
|
345
|
-
oneOf:
|
|
379
|
+
oneOf: fd.formats.getOneOfOptions(),
|
|
346
380
|
default: 'flowdrop'
|
|
347
381
|
},
|
|
348
382
|
...extraProps
|
|
@@ -353,15 +387,15 @@
|
|
|
353
387
|
|
|
354
388
|
// Workflow configuration values
|
|
355
389
|
let workflowConfigValues = $derived({
|
|
356
|
-
name:
|
|
357
|
-
description:
|
|
358
|
-
format:
|
|
359
|
-
...(
|
|
390
|
+
name: fd.workflow.name || '',
|
|
391
|
+
description: fd.workflow.current?.description || '',
|
|
392
|
+
format: fd.workflow.current?.metadata?.format || 'flowdrop',
|
|
393
|
+
...(fd.workflow.current?.config ?? {})
|
|
360
394
|
});
|
|
361
395
|
|
|
362
396
|
// Get the current node from the workflow store
|
|
363
397
|
let selectedNodeForConfig = $derived.by(() => {
|
|
364
|
-
const wf =
|
|
398
|
+
const wf = fd.workflow.current;
|
|
365
399
|
if (!selectedNodeId || !wf) return null;
|
|
366
400
|
return wf.nodes.find((node) => node.id === selectedNodeId) || null;
|
|
367
401
|
});
|
|
@@ -379,7 +413,7 @@
|
|
|
379
413
|
// If nodes were provided as props, use them directly (skip API fetch)
|
|
380
414
|
if (propNodes && propNodes.length > 0) {
|
|
381
415
|
// Merge format-provided nodes with prop nodes (deduplicate by ID, props take priority)
|
|
382
|
-
const formatNodes =
|
|
416
|
+
const formatNodes = fd.formats.getAllFormatNodes();
|
|
383
417
|
const existingIds = new Set(propNodes.map((n) => n.id));
|
|
384
418
|
const uniqueFormatNodes = formatNodes.filter((n) => !existingIds.has(n.id));
|
|
385
419
|
nodes = [...propNodes, ...uniqueFormatNodes];
|
|
@@ -392,16 +426,11 @@
|
|
|
392
426
|
try {
|
|
393
427
|
error = null;
|
|
394
428
|
|
|
395
|
-
//
|
|
396
|
-
|
|
397
|
-
if (apiClient) {
|
|
398
|
-
fetchedNodes = await apiClient.getAvailableNodes();
|
|
399
|
-
} else {
|
|
400
|
-
fetchedNodes = await api.nodes.getNodes();
|
|
401
|
-
}
|
|
429
|
+
// Fetch via this instance's API client (configured in initializeApiEndpoints).
|
|
430
|
+
const fetchedNodes: NodeMetadata[] = await fd.api.client.getAvailableNodes();
|
|
402
431
|
|
|
403
432
|
// Merge format-provided nodes with API nodes (deduplicate by ID, API takes priority)
|
|
404
|
-
const formatNodes =
|
|
433
|
+
const formatNodes = fd.formats.getAllFormatNodes();
|
|
405
434
|
const existingIds = new Set(fetchedNodes.map((n) => n.id));
|
|
406
435
|
const uniqueFormatNodes = formatNodes.filter((n) => !existingIds.has(n.id));
|
|
407
436
|
nodes = [...fetchedNodes, ...uniqueFormatNodes];
|
|
@@ -421,8 +450,8 @@
|
|
|
421
450
|
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
|
|
422
451
|
|
|
423
452
|
// Notify parent via event handler
|
|
424
|
-
if (
|
|
425
|
-
const suppressToast =
|
|
453
|
+
if (onApiError) {
|
|
454
|
+
const suppressToast = onApiError(
|
|
426
455
|
err instanceof Error ? err : new Error(errorMessage),
|
|
427
456
|
'fetchNodes'
|
|
428
457
|
);
|
|
@@ -481,28 +510,15 @@
|
|
|
481
510
|
async function initializeApiEndpoints(): Promise<void> {
|
|
482
511
|
// First priority: Use endpointConfig prop if provided (from mountFlowDropApp)
|
|
483
512
|
if (propEndpointConfig) {
|
|
484
|
-
|
|
485
|
-
endpointConfig = propEndpointConfig;
|
|
486
|
-
|
|
487
|
-
// Create enhanced API client with authProvider support if provided
|
|
488
|
-
if (authProvider) {
|
|
489
|
-
apiClient = new EnhancedFlowDropApiClient(propEndpointConfig, authProvider);
|
|
490
|
-
}
|
|
513
|
+
configureApi(propEndpointConfig);
|
|
491
514
|
return;
|
|
492
515
|
}
|
|
493
516
|
|
|
494
|
-
// Second priority:
|
|
495
|
-
|
|
496
|
-
const existingConfig =
|
|
497
|
-
|
|
498
|
-
// If config already exists and no override provided, use existing
|
|
517
|
+
// Second priority: Reuse this instance's existing config (e.g. set by a
|
|
518
|
+
// parent layout that already configured fd.api) when no override is given.
|
|
519
|
+
const existingConfig = fd.api.config;
|
|
499
520
|
if (existingConfig && !apiBaseUrl) {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
// Create enhanced API client with authProvider support if provided
|
|
503
|
-
if (authProvider) {
|
|
504
|
-
apiClient = new EnhancedFlowDropApiClient(existingConfig, authProvider);
|
|
505
|
-
}
|
|
521
|
+
configureApi(existingConfig);
|
|
506
522
|
return;
|
|
507
523
|
}
|
|
508
524
|
|
|
@@ -510,9 +526,6 @@
|
|
|
510
526
|
const baseUrl = apiBaseUrl || '/api/flowdrop';
|
|
511
527
|
|
|
512
528
|
const config = createEndpointConfig(baseUrl, {
|
|
513
|
-
auth: {
|
|
514
|
-
type: 'none' // No authentication for now
|
|
515
|
-
},
|
|
516
529
|
timeout: 10000, // 10 second timeout
|
|
517
530
|
retry: {
|
|
518
531
|
enabled: true,
|
|
@@ -522,14 +535,16 @@
|
|
|
522
535
|
}
|
|
523
536
|
});
|
|
524
537
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
endpointConfig = config;
|
|
538
|
+
configureApi(config);
|
|
539
|
+
}
|
|
528
540
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
541
|
+
/**
|
|
542
|
+
* Configure this instance's ApiContext and mirror its config/client into the
|
|
543
|
+
* local state used by child components and the save service.
|
|
544
|
+
*/
|
|
545
|
+
function configureApi(config: EndpointConfig): void {
|
|
546
|
+
fd.api.configure(config, authProvider);
|
|
547
|
+
endpointConfig = config;
|
|
533
548
|
}
|
|
534
549
|
|
|
535
550
|
/**
|
|
@@ -545,7 +560,6 @@
|
|
|
545
560
|
isConfigSidebarOpen = true;
|
|
546
561
|
// Reset swap state when switching nodes
|
|
547
562
|
swapMode = 'idle';
|
|
548
|
-
swapTargetMetadata = null;
|
|
549
563
|
swapInteractiveState = null;
|
|
550
564
|
}
|
|
551
565
|
|
|
@@ -554,7 +568,6 @@
|
|
|
554
568
|
selectedNodeId = null;
|
|
555
569
|
// Reset swap state when closing
|
|
556
570
|
swapMode = 'idle';
|
|
557
|
-
swapTargetMetadata = null;
|
|
558
571
|
swapInteractiveState = null;
|
|
559
572
|
}
|
|
560
573
|
|
|
@@ -574,7 +587,6 @@
|
|
|
574
587
|
*/
|
|
575
588
|
function startSwap(): void {
|
|
576
589
|
swapMode = 'picking';
|
|
577
|
-
swapTargetMetadata = null;
|
|
578
590
|
swapInteractiveState = null;
|
|
579
591
|
}
|
|
580
592
|
|
|
@@ -585,29 +597,21 @@
|
|
|
585
597
|
const node = selectedNodeForConfig;
|
|
586
598
|
if (!node) return;
|
|
587
599
|
|
|
588
|
-
const wf =
|
|
600
|
+
const wf = fd.workflow.current;
|
|
589
601
|
if (!wf) return;
|
|
590
602
|
|
|
591
603
|
// Format compatibility guard — defence-in-depth behind picker's own filter
|
|
592
|
-
const currentFormat =
|
|
604
|
+
const currentFormat = fd.workflow.format;
|
|
593
605
|
if (metadata.formats?.length && !metadata.formats.includes(currentFormat)) {
|
|
594
606
|
return;
|
|
595
607
|
}
|
|
596
608
|
|
|
597
|
-
//
|
|
598
|
-
let checker: import('../utils/connections.js').PortCompatibilityChecker | null = null;
|
|
599
|
-
try {
|
|
600
|
-
checker = getPortCompatibilityChecker();
|
|
601
|
-
} catch {
|
|
602
|
-
// Checker not initialized — computeSwapPreview will use exact dataType matching
|
|
603
|
-
}
|
|
604
|
-
|
|
609
|
+
// Port compatibility comes from this instance's checker.
|
|
605
610
|
const interactive = computeInteractiveState(node, metadata, wf.edges, wf.nodes, {
|
|
606
|
-
checker,
|
|
611
|
+
checker: fd.portCompatibility,
|
|
607
612
|
strategies: swapStrategies
|
|
608
613
|
});
|
|
609
614
|
|
|
610
|
-
swapTargetMetadata = metadata;
|
|
611
615
|
swapInteractiveState = interactive;
|
|
612
616
|
swapMode = 'mapping';
|
|
613
617
|
}
|
|
@@ -619,7 +623,7 @@
|
|
|
619
623
|
const state = finalState ?? swapInteractiveState;
|
|
620
624
|
if (!state) return;
|
|
621
625
|
|
|
622
|
-
const wf =
|
|
626
|
+
const wf = fd.workflow.current;
|
|
623
627
|
if (!wf) return;
|
|
624
628
|
|
|
625
629
|
const oldLabel = state.oldNode.data.label;
|
|
@@ -639,7 +643,7 @@
|
|
|
639
643
|
}
|
|
640
644
|
|
|
641
645
|
// onBeforeSwap hook — abort if returns false
|
|
642
|
-
if (
|
|
646
|
+
if (onBeforeSwap) {
|
|
643
647
|
const swapEventCtx: SwapEventContext = {
|
|
644
648
|
oldNode: state.oldNode,
|
|
645
649
|
newMetadata: state.newMetadata,
|
|
@@ -647,21 +651,21 @@
|
|
|
647
651
|
portOverrides: [],
|
|
648
652
|
configOverrides: []
|
|
649
653
|
};
|
|
650
|
-
const shouldProceed = await
|
|
654
|
+
const shouldProceed = await onBeforeSwap(swapEventCtx);
|
|
651
655
|
if (shouldProceed === false) return;
|
|
652
656
|
}
|
|
653
657
|
|
|
654
658
|
// Apply as a single atomic swap with descriptive history entry
|
|
655
|
-
|
|
659
|
+
fd.workflow.swapNode({
|
|
656
660
|
nodes: result.updatedNodes,
|
|
657
661
|
edges: result.updatedEdges,
|
|
658
662
|
description: `Swap node: ${oldLabel} → ${newLabel}`
|
|
659
663
|
});
|
|
660
664
|
|
|
661
665
|
// onAfterSwap hook (fire-and-forget — swap is already applied)
|
|
662
|
-
if (
|
|
666
|
+
if (onAfterSwap) {
|
|
663
667
|
try {
|
|
664
|
-
|
|
668
|
+
onAfterSwap(result, state.oldNode, state.newNodeId);
|
|
665
669
|
} catch (err) {
|
|
666
670
|
logger.error('onAfterSwap hook error:', err);
|
|
667
671
|
}
|
|
@@ -673,7 +677,6 @@
|
|
|
673
677
|
|
|
674
678
|
// Reset swap state
|
|
675
679
|
swapMode = 'idle';
|
|
676
|
-
swapTargetMetadata = null;
|
|
677
680
|
swapInteractiveState = null;
|
|
678
681
|
|
|
679
682
|
// Wait for SvelteFlow to process the new node before updating visual state
|
|
@@ -694,35 +697,9 @@
|
|
|
694
697
|
*/
|
|
695
698
|
function cancelSwap(): void {
|
|
696
699
|
swapMode = 'idle';
|
|
697
|
-
swapTargetMetadata = null;
|
|
698
700
|
swapInteractiveState = null;
|
|
699
701
|
}
|
|
700
702
|
|
|
701
|
-
/**
|
|
702
|
-
* Handle workflow configuration save
|
|
703
|
-
*/
|
|
704
|
-
async function handleWorkflowSave(config: Record<string, unknown>): Promise<void> {
|
|
705
|
-
// Update the workflow store
|
|
706
|
-
if (getWorkflowStore()) {
|
|
707
|
-
workflowActions.batchUpdate({
|
|
708
|
-
name: config.name as string | undefined,
|
|
709
|
-
description: config.description as string | undefined
|
|
710
|
-
});
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// Close the sidebar
|
|
714
|
-
isWorkflowSettingsOpen = false;
|
|
715
|
-
|
|
716
|
-
// Also save the workflow to the backend
|
|
717
|
-
try {
|
|
718
|
-
await saveWorkflow();
|
|
719
|
-
} catch (error) {
|
|
720
|
-
logger.error('Failed to save workflow to backend:', error);
|
|
721
|
-
// Note: We don't throw the error here to avoid breaking the UI flow
|
|
722
|
-
// The user can still manually save via the main Save button if needed
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
|
|
726
703
|
/**
|
|
727
704
|
* Save workflow - thin wrapper that delegates to globalSaveWorkflow().
|
|
728
705
|
*
|
|
@@ -731,10 +708,10 @@
|
|
|
731
708
|
*/
|
|
732
709
|
async function saveWorkflow(): Promise<void> {
|
|
733
710
|
await globalSaveWorkflow({
|
|
734
|
-
|
|
735
|
-
eventHandlers,
|
|
711
|
+
eventHandlers: { onBeforeSave, onAfterSave, onSaveError, onApiError },
|
|
736
712
|
features,
|
|
737
|
-
|
|
713
|
+
instance: fd,
|
|
714
|
+
onMarkAsSaved: () => fd.workflow.markAsSaved()
|
|
738
715
|
});
|
|
739
716
|
}
|
|
740
717
|
|
|
@@ -745,7 +722,7 @@
|
|
|
745
722
|
* in globalSave.ts — the single source of truth.
|
|
746
723
|
*/
|
|
747
724
|
async function exportWorkflow(): Promise<void> {
|
|
748
|
-
await globalExportWorkflow({ features });
|
|
725
|
+
await globalExportWorkflow({ features, instance: fd });
|
|
749
726
|
}
|
|
750
727
|
|
|
751
728
|
/**
|
|
@@ -770,12 +747,12 @@
|
|
|
770
747
|
logger.warn('Workflow import validation failed:', validation.error);
|
|
771
748
|
return;
|
|
772
749
|
}
|
|
773
|
-
|
|
750
|
+
fd.workflow.initialize(data as Workflow);
|
|
774
751
|
if (features.showToasts) {
|
|
775
752
|
apiToasts.success('Import workflow', 'Workflow imported successfully');
|
|
776
753
|
}
|
|
777
|
-
if (
|
|
778
|
-
|
|
754
|
+
if (onWorkflowLoad) {
|
|
755
|
+
onWorkflowLoad(data as Workflow);
|
|
779
756
|
}
|
|
780
757
|
} catch (error) {
|
|
781
758
|
const errorObj = error instanceof Error ? error : new Error('Unknown error occurred');
|
|
@@ -822,26 +799,31 @@
|
|
|
822
799
|
|
|
823
800
|
// Load node types on mount
|
|
824
801
|
onMount(() => {
|
|
802
|
+
// Apply the persisted theme preference to the document and wire its
|
|
803
|
+
// reactivity. Idempotent — a no-op when mountFlowDropApp already
|
|
804
|
+
// initialized it; load-bearing for hosts rendering <App> directly,
|
|
805
|
+
// where nothing else applies data-theme (the persisted light/dark
|
|
806
|
+
// choice was otherwise never restored on reload).
|
|
807
|
+
initializeTheme();
|
|
808
|
+
|
|
825
809
|
(async () => {
|
|
826
810
|
try {
|
|
827
811
|
await initializeApiEndpoints();
|
|
828
812
|
|
|
829
|
-
//
|
|
830
|
-
//
|
|
831
|
-
//
|
|
832
|
-
|
|
833
|
-
initializePortCompatibility(DEFAULT_PORT_CONFIG);
|
|
834
|
-
}
|
|
813
|
+
// The instance's port compatibility checker is seeded with
|
|
814
|
+
// DEFAULT_PORT_CONFIG at construction; mountFlowDropApp re-initializes
|
|
815
|
+
// it from the backend's port config. SvelteKit routes that render
|
|
816
|
+
// <App> directly keep the defaults (no separate fetch here).
|
|
835
817
|
|
|
836
818
|
await fetchNodeTypes();
|
|
837
819
|
|
|
838
820
|
// Initialize the workflow store
|
|
839
821
|
if (initialWorkflow) {
|
|
840
|
-
|
|
822
|
+
fd.workflow.initialize(initialWorkflow);
|
|
841
823
|
|
|
842
824
|
// Emit onWorkflowLoad event
|
|
843
|
-
if (
|
|
844
|
-
|
|
825
|
+
if (onWorkflowLoad) {
|
|
826
|
+
onWorkflowLoad(initialWorkflow);
|
|
845
827
|
}
|
|
846
828
|
} else {
|
|
847
829
|
// Initialize with a default empty workflow so the editor is functional
|
|
@@ -852,13 +834,13 @@
|
|
|
852
834
|
nodes: [],
|
|
853
835
|
edges: [],
|
|
854
836
|
metadata: {
|
|
855
|
-
|
|
837
|
+
schemaVersion: '1.0.0',
|
|
856
838
|
format: DEFAULT_WORKFLOW_FORMAT,
|
|
857
839
|
createdAt: new Date().toISOString(),
|
|
858
840
|
updatedAt: new Date().toISOString()
|
|
859
841
|
}
|
|
860
842
|
};
|
|
861
|
-
|
|
843
|
+
fd.workflow.initialize(defaultWorkflow);
|
|
862
844
|
}
|
|
863
845
|
} catch (error) {
|
|
864
846
|
logger.error('Failed to initialize editor:', error);
|
|
@@ -874,6 +856,7 @@
|
|
|
874
856
|
|
|
875
857
|
// Initialize auto-save based on user settings
|
|
876
858
|
const cleanupAutoSave = initAutoSave({
|
|
859
|
+
isDirty: () => fd.workflow.isDirty,
|
|
877
860
|
onSave: async () => {
|
|
878
861
|
await saveWorkflow();
|
|
879
862
|
},
|
|
@@ -945,7 +928,7 @@
|
|
|
945
928
|
|
|
946
929
|
function handleConsoleUIAction(action: UIAction): void {
|
|
947
930
|
if (action.type === 'open_config') {
|
|
948
|
-
const wf =
|
|
931
|
+
const wf = fd.workflow.current;
|
|
949
932
|
if (!wf) return;
|
|
950
933
|
const node = wf.nodes.find((n) => n.id === action.nodeId);
|
|
951
934
|
if (node) openConfigSidebar(node);
|
|
@@ -1005,10 +988,12 @@
|
|
|
1005
988
|
<!-- MainLayout wrapper for workflow editor -->
|
|
1006
989
|
<div class="flowdrop-root">
|
|
1007
990
|
<MainLayout
|
|
991
|
+
{height}
|
|
992
|
+
{width}
|
|
1008
993
|
showHeader={showNavbar}
|
|
1009
994
|
showLeftSidebar={!disableSidebar}
|
|
1010
995
|
showRightSidebar={showRightPanel}
|
|
1011
|
-
showBottomPanel={getUiSettings().consoleOpen &&
|
|
996
|
+
showBottomPanel={getUiSettings().consoleOpen && canvasEditable}
|
|
1012
997
|
bottomPanelHeight={getUiSettings().consoleHeight}
|
|
1013
998
|
showFooter={false}
|
|
1014
999
|
headerHeight={60}
|
|
@@ -1027,7 +1012,7 @@
|
|
|
1027
1012
|
<Navbar
|
|
1028
1013
|
title={breadcrumbTitle}
|
|
1029
1014
|
primaryActions={navbarActions.length > 0 ? navbarActions : defaultPrimaryActions}
|
|
1030
|
-
showStatus
|
|
1015
|
+
{showStatus}
|
|
1031
1016
|
{showSettings}
|
|
1032
1017
|
{settingsCategories}
|
|
1033
1018
|
{showSettingsSyncButton}
|
|
@@ -1040,7 +1025,7 @@
|
|
|
1040
1025
|
<NodeSidebar
|
|
1041
1026
|
{nodes}
|
|
1042
1027
|
loading={nodeTypesLoading}
|
|
1043
|
-
activeFormat={
|
|
1028
|
+
activeFormat={fd.workflow.format}
|
|
1044
1029
|
categoriesDefaultOpen={themeConfig?.sidebar?.categoriesDefaultOpen ?? false}
|
|
1045
1030
|
/>
|
|
1046
1031
|
{/snippet}
|
|
@@ -1048,16 +1033,8 @@
|
|
|
1048
1033
|
<!-- Right Sidebar: Configuration, Swap, or Workflow Settings -->
|
|
1049
1034
|
{#snippet rightSidebar()}
|
|
1050
1035
|
{#if swapMode === 'mapping' && swapInteractiveState && selectedNodeForConfig}
|
|
1051
|
-
{@const swapChecker = (() => {
|
|
1052
|
-
try {
|
|
1053
|
-
return getPortCompatibilityChecker();
|
|
1054
|
-
} catch {
|
|
1055
|
-
return null;
|
|
1056
|
-
}
|
|
1057
|
-
})()}
|
|
1058
1036
|
<SwapMappingEditor
|
|
1059
1037
|
interactiveState={swapInteractiveState}
|
|
1060
|
-
checker={swapChecker}
|
|
1061
1038
|
onConfirm={executeNodeSwap}
|
|
1062
1039
|
onCancel={cancelSwap}
|
|
1063
1040
|
onBack={() => {
|
|
@@ -1069,22 +1046,22 @@
|
|
|
1069
1046
|
<NodeSwapPicker
|
|
1070
1047
|
currentNode={selectedNodeForConfig}
|
|
1071
1048
|
availableNodes={nodes}
|
|
1072
|
-
activeFormat={
|
|
1049
|
+
activeFormat={fd.workflow.format}
|
|
1073
1050
|
onSelect={handleSwapSelect}
|
|
1074
1051
|
onCancel={cancelSwap}
|
|
1075
1052
|
/>
|
|
1076
1053
|
{:else if isWorkflowSettingsOpen}
|
|
1077
1054
|
<ConfigPanel
|
|
1078
1055
|
title={mergedMessages.navigation.workflowSettingsPanelTitle}
|
|
1079
|
-
id={
|
|
1056
|
+
id={fd.workflow.current?.id}
|
|
1080
1057
|
details={[
|
|
1081
1058
|
{
|
|
1082
1059
|
label: 'Nodes',
|
|
1083
|
-
value: String(
|
|
1060
|
+
value: String(fd.workflow.current?.nodes?.length ?? 0)
|
|
1084
1061
|
},
|
|
1085
1062
|
{
|
|
1086
1063
|
label: 'Connections',
|
|
1087
|
-
value: String(
|
|
1064
|
+
value: String(fd.workflow.current?.edges?.length ?? 0)
|
|
1088
1065
|
}
|
|
1089
1066
|
]}
|
|
1090
1067
|
configTitle={mergedMessages.navigation.workflowSettingsPanelSubtitle}
|
|
@@ -1097,7 +1074,7 @@
|
|
|
1097
1074
|
showUIExtensions={false}
|
|
1098
1075
|
onChange={(config) => {
|
|
1099
1076
|
// Sync workflow settings changes immediately on field blur
|
|
1100
|
-
const wf =
|
|
1077
|
+
const wf = fd.workflow.current;
|
|
1101
1078
|
if (wf) {
|
|
1102
1079
|
const newFormat = (config.format as string) || DEFAULT_WORKFLOW_FORMAT;
|
|
1103
1080
|
const currentFormat = wf.metadata?.format || DEFAULT_WORKFLOW_FORMAT;
|
|
@@ -1118,7 +1095,7 @@
|
|
|
1118
1095
|
|
|
1119
1096
|
// Extract built-in fields; everything else belongs in workflow.config
|
|
1120
1097
|
const { name, description, format: _format, ...customConfig } = config;
|
|
1121
|
-
|
|
1098
|
+
fd.workflow.batchUpdate({
|
|
1122
1099
|
name: name as string,
|
|
1123
1100
|
description: description as string | undefined,
|
|
1124
1101
|
metadata: {
|
|
@@ -1149,14 +1126,14 @@
|
|
|
1149
1126
|
}
|
|
1150
1127
|
]}
|
|
1151
1128
|
onClose={closeConfigSidebar}
|
|
1152
|
-
onSwap={
|
|
1129
|
+
onSwap={canvasEditable && features.enableNodeSwap ? startSwap : undefined}
|
|
1153
1130
|
>
|
|
1154
1131
|
<ConfigForm
|
|
1155
1132
|
{authProvider}
|
|
1156
1133
|
node={currentNode}
|
|
1157
|
-
workflowId={
|
|
1158
|
-
workflowNodes={
|
|
1159
|
-
workflowEdges={
|
|
1134
|
+
workflowId={fd.workflow.current?.id}
|
|
1135
|
+
workflowNodes={fd.workflow.current?.nodes}
|
|
1136
|
+
workflowEdges={fd.workflow.current?.edges}
|
|
1160
1137
|
onChange={async (updatedConfig, uiExtensions) => {
|
|
1161
1138
|
// Sync config changes to workflow immediately on field blur
|
|
1162
1139
|
if (selectedNodeId && currentNode) {
|
|
@@ -1179,7 +1156,7 @@
|
|
|
1179
1156
|
data: updatedData
|
|
1180
1157
|
};
|
|
1181
1158
|
|
|
1182
|
-
|
|
1159
|
+
fd.workflow.updateNode(selectedNodeId, nodeUpdates);
|
|
1183
1160
|
|
|
1184
1161
|
// Update the local editor state to reflect config changes immediately
|
|
1185
1162
|
// This is needed for nodeType changes to take effect visually
|
|
@@ -1228,7 +1205,7 @@
|
|
|
1228
1205
|
>
|
|
1229
1206
|
<AIChatPanel
|
|
1230
1207
|
nodeTypes={nodes}
|
|
1231
|
-
workflowId={
|
|
1208
|
+
workflowId={fd.workflow.current?.id}
|
|
1232
1209
|
onUIAction={handleConsoleUIAction}
|
|
1233
1210
|
{endpointConfig}
|
|
1234
1211
|
/>
|
|
@@ -1260,8 +1237,7 @@
|
|
|
1260
1237
|
const defaultUrl = '/api/flowdrop';
|
|
1261
1238
|
const newUrl = prompt('Enter Backend API URL:', defaultUrl);
|
|
1262
1239
|
if (newUrl) {
|
|
1263
|
-
|
|
1264
|
-
setEndpointConfig(endpointConfig);
|
|
1240
|
+
configureApi(createEndpointConfig(newUrl));
|
|
1265
1241
|
fetchNodeTypes();
|
|
1266
1242
|
}
|
|
1267
1243
|
}}
|
|
@@ -1289,7 +1265,8 @@
|
|
|
1289
1265
|
{/if}
|
|
1290
1266
|
|
|
1291
1267
|
<!-- Main Editor Area -->
|
|
1292
|
-
<!--
|
|
1268
|
+
<!-- interactive workflow canvas region with keyboard support -->
|
|
1269
|
+
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
|
1293
1270
|
<div
|
|
1294
1271
|
class="flowdrop-editor-main"
|
|
1295
1272
|
class:pipeline-view={!!pipelineId}
|
|
@@ -1317,18 +1294,12 @@
|
|
|
1317
1294
|
|
|
1318
1295
|
<WorkflowEditor
|
|
1319
1296
|
bind:this={workflowEditorRef}
|
|
1320
|
-
{nodes}
|
|
1321
|
-
{height}
|
|
1322
|
-
{width}
|
|
1323
1297
|
endpointConfig={endpointConfig ?? undefined}
|
|
1324
|
-
{
|
|
1325
|
-
{selectedNodeForConfig}
|
|
1298
|
+
{authProvider}
|
|
1326
1299
|
{openConfigSidebar}
|
|
1327
|
-
{
|
|
1328
|
-
{lockWorkflow}
|
|
1329
|
-
{readOnly}
|
|
1330
|
-
{nodeStatuses}
|
|
1300
|
+
{mode}
|
|
1331
1301
|
{pipelineId}
|
|
1302
|
+
{refreshTrigger}
|
|
1332
1303
|
consoleOpen={getUiSettings().consoleOpen}
|
|
1333
1304
|
onToggleConsole={toggleConsole}
|
|
1334
1305
|
/>
|