@atom8n/n8n-editor-ui 2.2.0
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/.stylelintcache +1 -0
- package/README.md +59 -0
- package/biome.jsonc +8 -0
- package/build.log +55 -0
- package/data/node-popularity.json +3998 -0
- package/dist/assets/AddDataTableModal-UINkk54_.js +1555 -0
- package/dist/assets/AgentEditorModal-CVww87TJ.js +358 -0
- package/dist/assets/Alert-Dy86dyOr.js +102 -0
- package/dist/assets/AnimatedSpinner-DmPN4poP.js +15 -0
- package/dist/assets/AnnotationTagsDropdown.ee-BJ7N9lek.js +71 -0
- package/dist/assets/AuthView-D2LWHrMp.js +106 -0
- package/dist/assets/BottomMenu-CIQiK_dJ.js +532 -0
- package/dist/assets/CalendarDate-DgQUMbNo.js +875 -0
- package/dist/assets/ChangePasswordView-Z6tUkw0u.js +133 -0
- package/dist/assets/ChatAgentAvatar-50YBnv3N.js +67 -0
- package/dist/assets/ChatFile-xZxmc2nV.js +146 -0
- package/dist/assets/ChatLayout-CTE_5SiM.js +96 -0
- package/dist/assets/ChatPersonalAgentsView-BGpHk03K.js +149 -0
- package/dist/assets/ChatSidebar-BkVwIypC.js +528 -0
- package/dist/assets/ChatView-BbbdeU9x.js +1559 -0
- package/dist/assets/ChatWorkflowAgentsView-BtunOxlC.js +116 -0
- package/dist/assets/CollectionParameter-BdcPG1lu.js +52 -0
- package/dist/assets/CommitMonoVariable-ytizKI8U.woff2 +0 -0
- package/dist/assets/CommunityNodeUpdateInfo-C37kca4W.js +273 -0
- package/dist/assets/CopyInput-DDZVu2iU.js +74 -0
- package/dist/assets/CredentialIcon-8YdTTFZ1.js +80 -0
- package/dist/assets/CredentialPicker-DWtj314o.js +293 -0
- package/dist/assets/CredentialSelectorModal-DTW2fKh0.js +138 -0
- package/dist/assets/CredentialsView-BjUchcCu.js +480 -0
- package/dist/assets/DataTableActions-DpAkoxg_.js +95 -0
- package/dist/assets/DataTableDetailsView-Coq7zdW5.js +41922 -0
- package/dist/assets/DataTableView-Cs-BIkzw.js +293 -0
- package/dist/assets/DemoFooter-Cga3jvi-.js +65 -0
- package/dist/assets/Draggable-vfvXl9Sp.js +105 -0
- package/dist/assets/EmptySharedSectionActionBox-DOXZtTCv.js +36 -0
- package/dist/assets/EnterpriseEdition.ee-D_rCFexM.js +15 -0
- package/dist/assets/EntityNotFound-3dhTRWsE.js +85 -0
- package/dist/assets/EntityUnAuthorised-ChJYZakE.js +66 -0
- package/dist/assets/ErrorView-zT9cX76a.js +61 -0
- package/dist/assets/EvaluationsRootView-C-OVWYnY.js +523 -0
- package/dist/assets/EvaluationsView-CJwJTruc.js +469 -0
- package/dist/assets/ExecutionsTime-DEQiyozR.js +573 -0
- package/dist/assets/ExecutionsView-Bd5Oh8TH.js +791 -0
- package/dist/assets/ExternalSecretsProviderConnectionSwitch.ee-C7Ih-uRo.js +191 -0
- package/dist/assets/FixedCollectionParameter-CYuTDW9t.js +496 -0
- package/dist/assets/ForgotMyPasswordView-Bs_L9P27.js +102 -0
- package/dist/assets/InsightsChartAverageRuntime-Bp3VA8_7.js +62 -0
- package/dist/assets/InsightsChartFailed-KPaNWoEr.js +52 -0
- package/dist/assets/InsightsChartFailureRate-DE6kE3FM.js +54 -0
- package/dist/assets/InsightsChartTimeSaved-auABNZlc.js +68 -0
- package/dist/assets/InsightsChartTotal-BKzYRKE7.js +56 -0
- package/dist/assets/InsightsDashboard-JWx4W6Db.js +473 -0
- package/dist/assets/InsightsPaywall-C8zLLKe8.js +63 -0
- package/dist/assets/InsightsSummary-cmN1lHDm.js +210 -0
- package/dist/assets/InsightsTableWorkflows-CqcC3IbQ.js +203 -0
- package/dist/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
- package/dist/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
- package/dist/assets/ItemsRenderer-DC8WVyMv.js +922 -0
- package/dist/assets/KeyboardShortcutTooltip-D8PAK5JP.js +31 -0
- package/dist/assets/LogsPanel-BR06u9RK.js +52 -0
- package/dist/assets/LogsPanel-C-_acMHp.js +2325 -0
- package/dist/assets/MCPConnectWorkflowsModal-3g8_iUa4.js +303 -0
- package/dist/assets/MainHeader-DiQc1edn.js +2153 -0
- package/dist/assets/MainSidebar-CoPGG5Ea.js +804 -0
- package/dist/assets/MigrationRuleDetail-BAxk1Pvl.js +295 -0
- package/dist/assets/MigrationRules-IW9lZMpE.js +285 -0
- package/dist/assets/Modal-CIzXlZdZ.js +204 -0
- package/dist/assets/ModelByIdSelectorModal-DLvBjzJO.js +115 -0
- package/dist/assets/NDVEmptyState-33UoX00I.js +19743 -0
- package/dist/assets/NodeCreation-BNzbSWSB.js +240 -0
- package/dist/assets/NodeCreator-BftgCKx7.js +1288 -0
- package/dist/assets/NodeDetailsView-CsoQCpcF.js +1075 -0
- package/dist/assets/NodeDetailsViewV2-C_wNQR_3.js +981 -0
- package/dist/assets/NodeIcon-B9VW6tX6.js +87 -0
- package/dist/assets/NodeSettings-ZwVip6VR.js +1872 -0
- package/dist/assets/NodeView-D4WUEvLB.js +2452 -0
- package/dist/assets/OAuthConsentView-DlrUqZbT.js +230 -0
- package/dist/assets/PageViewLayout-NT1KPFgy.js +12 -0
- package/dist/assets/ParameterInputList-sG2nz-Jo.js +38091 -0
- package/dist/assets/PrebuiltAgentTemplatesView-Csi5U8dc.js +154 -0
- package/dist/assets/ProjectBreadcrumb-C_XiY7sc.js +98 -0
- package/dist/assets/ProjectCardBadge-t_hs7vzx.js +209 -0
- package/dist/assets/ProjectHeader-Dq5Ihb26.js +549 -0
- package/dist/assets/ProjectIcon-DY8gGuHX.js +64 -0
- package/dist/assets/ProjectRoleView-Du-KTrAC.js +435 -0
- package/dist/assets/ProjectRolesView-DjxM_y4u.js +239 -0
- package/dist/assets/ProjectSettings-C6kWuV21.js +966 -0
- package/dist/assets/ProjectSharing-CVUgNWAY.js +262 -0
- package/dist/assets/ProjectVariables-CJlAo3dv.js +467 -0
- package/dist/assets/ProviderSettingsModal-BUFC2ZLv.js +307 -0
- package/dist/assets/PushConnectionTracker-DPBnGV0v.js +27 -0
- package/dist/assets/ResolversView-3BdkvvYA.js +209 -0
- package/dist/assets/ResourceFiltersDropdown-dgyXpcEX.js +159 -0
- package/dist/assets/ResourcesListLayout-qBLtomK6.js +631 -0
- package/dist/assets/RunDataHtml-BrW0OQra.js +7 -0
- package/dist/assets/RunDataHtml-Cleia4Cj.js +40 -0
- package/dist/assets/RunDataJson-uxkrhYRK.js +227 -0
- package/dist/assets/RunDataJsonActions-DkPk7E8d.js +5007 -0
- package/dist/assets/RunDataParsedAiContent-CtPRjig-.js +26 -0
- package/dist/assets/RunDataParsedAiContent-WAuqLQ5M.js +192 -0
- package/dist/assets/RunDataSearch-YBWUr93C.js +141 -0
- package/dist/assets/RunDataTable-DcXaBynW.js +631 -0
- package/dist/assets/SamlOnboarding-BTdQ_hr3.js +78 -0
- package/dist/assets/SaveButton-D5sQSxIk.js +89 -0
- package/dist/assets/SelectedItemsInfo-BHZ-NvF5.js +58 -0
- package/dist/assets/SettingsApiView-IfZTMXx1.js +313 -0
- package/dist/assets/SettingsChatHubView-gWh2X6vX.js +285 -0
- package/dist/assets/SettingsCommunityNodesView-D8VQtpGY.js +349 -0
- package/dist/assets/SettingsExternalSecrets-CpMc7mkW.js +233 -0
- package/dist/assets/SettingsLdapView-CU5a2MAy.js +2553 -0
- package/dist/assets/SettingsLogStreamingView-uojTe-oX.js +375 -0
- package/dist/assets/SettingsMCPView-B5Swp1C_.js +1214 -0
- package/dist/assets/SettingsPersonalView-Cr3aGood.js +402 -0
- package/dist/assets/SettingsSourceControl-DXOvFDEY.js +547 -0
- package/dist/assets/SettingsSso-27MfU1HV.js +1032 -0
- package/dist/assets/SettingsUsageAndPlan-DqIO-G46.js +419 -0
- package/dist/assets/SettingsUsersView-DfHB4_Kh.js +833 -0
- package/dist/assets/SettingsView-C4sA7Uny.js +90 -0
- package/dist/assets/SetupTemplateFormStep-BmiSzZin.js +258 -0
- package/dist/assets/SetupView-VORZ-L_u.js +112 -0
- package/dist/assets/SetupWorkflowCredentialsButton-DTmkOAW5.js +73 -0
- package/dist/assets/SetupWorkflowFromTemplateView-B9NupdJE.js +286 -0
- package/dist/assets/SeverityTag-CX1qTTNA.js +45 -0
- package/dist/assets/SigninView-D9_Pm16j.js +358 -0
- package/dist/assets/SignoutView-BFsjEAGz.js +19 -0
- package/dist/assets/SignupView-Am4ot0QZ.js +137 -0
- package/dist/assets/SkeletonAgentCard-C5TL-h8F.js +191 -0
- package/dist/assets/TagsDropdown-Bvx_Hd6Q.js +230 -0
- package/dist/assets/TemplateCard-CyQ1GuVz.js +105 -0
- package/dist/assets/TemplateDetails-CZRusTxE.js +124 -0
- package/dist/assets/TemplateList-DKvbwuiY.js +333 -0
- package/dist/assets/TemplatesCollectionView-D8dxU8By.js +184 -0
- package/dist/assets/TemplatesSearchView-CebC_GLs.js +1230 -0
- package/dist/assets/TemplatesView-025CcmIY.js +57 -0
- package/dist/assets/TemplatesWorkflowView-C2JfwJAn.js +170 -0
- package/dist/assets/TestRunDetailView-Ck78TTWO.js +395 -0
- package/dist/assets/TextWithHighlights-BxumwGnv.js +57 -0
- package/dist/assets/TimeAgo-C6EN4lCs.js +123 -0
- package/dist/assets/ToolsSelectorModal-8QJoUvRL.js +368 -0
- package/dist/assets/TriggerPanel-B6pacLkk.js +1225 -0
- package/dist/assets/VirtualSchema-B3zGe_8b.js +2402 -0
- package/dist/assets/VirtualSchema-Dkh0Cu5z.js +37 -0
- package/dist/assets/VueMarkdown-CQqJL9vK.js +28 -0
- package/dist/assets/WorkerView-Caznsljo.js +563 -0
- package/dist/assets/WorkflowActivationErrorMessage-CGrfPi9O.js +17 -0
- package/dist/assets/WorkflowActivator-BINnz0f7.js +362 -0
- package/dist/assets/WorkflowExecutionsInfoAccordion-Dg37yEfT.js +166 -0
- package/dist/assets/WorkflowExecutionsLandingPage-V2wdubhK.js +93 -0
- package/dist/assets/WorkflowExecutionsPreview-DdJaqYV6.js +616 -0
- package/dist/assets/WorkflowExecutionsView-DV8ySTfn.js +808 -0
- package/dist/assets/WorkflowHistory-GtaBMzIM.js +973 -0
- package/dist/assets/WorkflowLocation-CQ9Sq-2y.js +164 -0
- package/dist/assets/WorkflowOnboardingView-C49gt0Jr.js +61 -0
- package/dist/assets/WorkflowPreview-CXdvv4Nq.js +186 -0
- package/dist/assets/WorkflowTagsDropdown-QwbICWjN.js +71 -0
- package/dist/assets/WorkflowsView-B-MWIECO.js +3253 -0
- package/dist/assets/_MapCache-CcdIl4Ae.js +363 -0
- package/dist/assets/_baseOrderBy-N8Be_6z6.js +2989 -0
- package/dist/assets/_initCloneObject-viQQyT6o.js +80 -0
- package/dist/assets/_plugin-vue_export-helper-BwBpWJRZ.js +6 -0
- package/dist/assets/aiTemplatesStarterCollection.store-nL9nePkK.js +656 -0
- package/dist/assets/apiKeys.store-BhOFmP2j.js +51 -0
- package/dist/assets/assistant.store-CNywgN4S.js +518 -0
- package/dist/assets/auth.eventBus-CWXS0Qp7.js +5 -0
- package/dist/assets/banners.store-CGEcBTDn.js +195 -0
- package/dist/assets/builder.store-Czk2ipDE.js +31417 -0
- package/dist/assets/buttons.esm-yintpW2E.js +364 -0
- package/dist/assets/chart-CNvyywtJ.js +10958 -0
- package/dist/assets/chartjs.utils-BAE52Cv9.js +155 -0
- package/dist/assets/chat.store-290YeyrQ.js +865 -0
- package/dist/assets/chatPanel.store-NDaawEZL.js +118 -0
- package/dist/assets/chunk-6z4oVpB-.js +36 -0
- package/dist/assets/col-Cmt4cmuS.js +158 -0
- package/dist/assets/constants-C8OH4tTq.js +106256 -0
- package/dist/assets/constants-DMrsrpD7.js +32 -0
- package/dist/assets/core-B9gt_4yk.js +4 -0
- package/dist/assets/core-CP5FY4aX.js +1202 -0
- package/dist/assets/core-CRbPymLT.js +9741 -0
- package/dist/assets/dataTable.store-DmipQsol.js +207 -0
- package/dist/assets/date-picker-2IDsBs2n.js +4115 -0
- package/dist/assets/dateFormatter-ik4-9_9r.js +33 -0
- package/dist/assets/dateformat-hG8NERse.js +181 -0
- package/dist/assets/dialog-lMho1TD8.js +425 -0
- package/dist/assets/dist-Cw46Is-h.js +151 -0
- package/dist/assets/doppler-B__k0MeW.webp +0 -0
- package/dist/assets/element-icons-B-tDfklg.woff +0 -0
- package/dist/assets/element-icons-_lZGOqcG.ttf +0 -0
- package/dist/assets/empty-BuGRxzl4.js +2210 -0
- package/dist/assets/en-CF30SCh2.js +95 -0
- package/dist/assets/en-DyO2pPiC.js +2 -0
- package/dist/assets/es-BkUFJVtD.js +43338 -0
- package/dist/assets/evaluation.constants-GYAwmJnh.js +284 -0
- package/dist/assets/executions.store-B9uRYwgv.js +205 -0
- package/dist/assets/exports-Crx_gvt_.js +1799 -0
- package/dist/assets/externalSecrets.ee.store-BJh4a_6G.js +118 -0
- package/dist/assets/fileUtils-CRWqOQje.js +20 -0
- package/dist/assets/folders.store-yAFj-5Vl.js +235 -0
- package/dist/assets/get-BcEmeOxn.js +2781 -0
- package/dist/assets/index-SL8542zQ.js +28372 -0
- package/dist/assets/insights.constants-BkJCYJTL.js +55 -0
- package/dist/assets/insights.store-BFc3kDUo.js +61 -0
- package/dist/assets/insights.utils-CcLXdrrz.js +77 -0
- package/dist/assets/isEmpty-C3XXoHqJ.js +35216 -0
- package/dist/assets/languageModules-9LyndCqU.js +13862 -0
- package/dist/assets/logStreaming.store-IZhWe_VK.js +190 -0
- package/dist/assets/mcp.constants-_Jcn7fPq.js +10 -0
- package/dist/assets/mcp.store-B9yfcAN9.js +116 -0
- package/dist/assets/merge-DhuTk1HM.js +564 -0
- package/dist/assets/nodeCreator.store-Bpnrwp2l.js +5444 -0
- package/dist/assets/nodeIcon-D6X-ENYt.js +102 -0
- package/dist/assets/nodeTransforms-RzcOM0v2.js +42 -0
- package/dist/assets/orderBy-Cu9F9DU_.js +15 -0
- package/dist/assets/path-browserify-RUt2u7iT.js +328 -0
- package/dist/assets/personalizedTemplatesV3.store-BGYp0YBN.js +334 -0
- package/dist/assets/pickBy-UI0Jt4wC.js +18 -0
- package/dist/assets/preload-helper-dyVz7ck7.js +59 -0
- package/dist/assets/radio-CSce3UT0.js +262 -0
- package/dist/assets/readyToRun.store-YEMvPUqo.js +626 -0
- package/dist/assets/readyToRunWorkflows.store-G3srgIze.js +1319 -0
- package/dist/assets/retry-BgHaYzbB.js +23 -0
- package/dist/assets/roles.store-CRf_zJTb.js +51 -0
- package/dist/assets/router-DNpzz3GH.js +2631 -0
- package/dist/assets/sanitize-html-CbW56HUN.js +10758 -0
- package/dist/assets/schemaPreview.store-DUgN1yVE.js +113 -0
- package/dist/assets/semver-Bk6DGseV.js +1306 -0
- package/dist/assets/smartDecimal-DAZl4HKA.js +6 -0
- package/dist/assets/sortByProperty-Cn7iGKYu.js +8 -0
- package/dist/assets/sourceControl.eventBus-D47xXSc_.js +3 -0
- package/dist/assets/sqlite3-DBpDb1lf.wasm +0 -0
- package/dist/assets/sqlite3-opfs-async-proxy-vVtmDGHX.js +461 -0
- package/dist/assets/sqlite3-worker1-bundler-friendly-DLarOZDL.js +9405 -0
- package/dist/assets/src-jviYSG25.js +55454 -0
- package/dist/assets/sso.store-DyApJwhx.js +139 -0
- package/dist/assets/style-E3CrYFV8.css +111829 -0
- package/dist/assets/table-we1DjFMV.js +3944 -0
- package/dist/assets/templateActions-bEDSARw2.js +65 -0
- package/dist/assets/templateTransforms-BHWiRbtR.js +43 -0
- package/dist/assets/truncate-C0KYt7i3.js +4176 -0
- package/dist/assets/typescript.worker-CYqLvLHh.js +152048 -0
- package/dist/assets/uniqBy-xDyuCRP0.js +10 -0
- package/dist/assets/usage.store-CU5J_nGm.js +100 -0
- package/dist/assets/useActions-B1JckIRj.js +255 -0
- package/dist/assets/useBeforeUnload-DiDkvI8p.js +40 -0
- package/dist/assets/useCanvasMapping-BXT7rGhC.js +12570 -0
- package/dist/assets/useCanvasOperations-8ULLtMkY.js +1765 -0
- package/dist/assets/useClipboard-DvjhVHqJ.js +39 -0
- package/dist/assets/useCommandBar-C4tLJbKt.js +2425 -0
- package/dist/assets/useCredentialResolvers-BKeFGJnY.js +78 -0
- package/dist/assets/useCustomAgent-DpILEt5e.js +471 -0
- package/dist/assets/useDebounce-Br5_1ug-.js +147 -0
- package/dist/assets/useExecutionData-M5iKsX6z.js +23 -0
- package/dist/assets/useExecutionDebugging-8azMzbnd.js +191 -0
- package/dist/assets/useExecutionHelpers-BgRRhpBM.js +91 -0
- package/dist/assets/useImportCurlCommand-CKiEmX5P.js +8891 -0
- package/dist/assets/useIntersectionObserver-BWMwOueh.js +33 -0
- package/dist/assets/useKeybindings-B2jfN6rd.js +62 -0
- package/dist/assets/useLogsTreeExpand-sZViUfdM.js +843 -0
- package/dist/assets/useMcp-DoMOIfqT.js +27 -0
- package/dist/assets/usePageRedirectionHelper-DjkznpX6.js +51 -0
- package/dist/assets/usePinnedData-BhZkqttf.js +203 -0
- package/dist/assets/usePushConnection-DMS-F_IW.js +513 -0
- package/dist/assets/useRecentResources-BVORr7eM.js +118 -0
- package/dist/assets/useRunWorkflow-LO7ffLp9.js +950 -0
- package/dist/assets/useSettingsItems-BhZXwMZn.js +144 -0
- package/dist/assets/useTelemetryContext-V6bv4YRq.js +34 -0
- package/dist/assets/useWorkflowActivate-DeSmDXjI.js +152 -0
- package/dist/assets/useWorkflowsCache-DtcEEAIR.js +179 -0
- package/dist/assets/userRoleProvisioning.store-kkSIdeTo.js +33 -0
- package/dist/assets/utils-DI7dLldp.js +54 -0
- package/dist/assets/versions.store-B1z2OrLE.js +191 -0
- package/dist/assets/vue-CydWIhxN.js +4378 -0
- package/dist/assets/vue-json-pretty-CsGX66mG.js +1130 -0
- package/dist/assets/vue.runtime.esm-bundler-tP5dCd7J.js +7325 -0
- package/dist/assets/xml-B_oj6Mle.js +2060 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.html +157 -0
- package/dist/static/base-path.js +1 -0
- package/dist/static/community_package_tooltip_img.png +0 -0
- package/dist/static/data-mapping-gif.gif +0 -0
- package/dist/static/form-grey.svg +1 -0
- package/dist/static/google-auth/disabled.dark.png +0 -0
- package/dist/static/google-auth/disabled.png +0 -0
- package/dist/static/google-auth/focus.dark.png +0 -0
- package/dist/static/google-auth/focus.png +0 -0
- package/dist/static/google-auth/normal.dark.png +0 -0
- package/dist/static/google-auth/normal.png +0 -0
- package/dist/static/google-auth/pressed.dark.png +0 -0
- package/dist/static/google-auth/pressed.png +0 -0
- package/dist/static/n8n-logo.png +0 -0
- package/dist/static/og_image.png +0 -0
- package/dist/static/open-ai.svg +1 -0
- package/dist/static/openChat.png +0 -0
- package/dist/static/posthog.init.js +41 -0
- package/dist/static/prefers-color-scheme.css +5 -0
- package/dist/static/webhook-icon.svg +1 -0
- package/dist/tree-sitter-bash.wasm +0 -0
- package/dist/tree-sitter.wasm +0 -0
- package/eslint.config.mjs +59 -0
- package/index.html +45 -0
- package/index.js +0 -0
- package/package.json +147 -0
- package/postcss.config.cjs +6 -0
- package/scripts/fetch-node-popularity.mjs +102 -0
- package/stylelint.config.mjs +9 -0
- package/tailwind.config.js +8 -0
- package/tsconfig.json +36 -0
- package/vite/i18n-locales-hmr-helpers.ts +19 -0
- package/vite/source-map-js-shim.ts +1 -0
- package/vite/vite-plugin-node-popularity.mts +32 -0
- package/vite.config.mts +304 -0
|
@@ -0,0 +1,1765 @@
|
|
|
1
|
+
import { o as __toESM, t as __commonJSMin } from "./chunk-6z4oVpB-.js";
|
|
2
|
+
import { C as computed, G as nextTick, It as ref, zt as shallowRef } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
|
|
3
|
+
import { rt as useI18n, v as useLocalStorage } from "./core-CRbPymLT.js";
|
|
4
|
+
import { s as createEventBus } from "./truncate-C0KYt7i3.js";
|
|
5
|
+
import { At as getExecutionErrorToastConfiguration, B as GRID_SIZE, F as CONFIGURABLE_NODE_SIZE, Hn as useTagsStore, Hr as isValidNodeConnectionType, Jn as useWorkflowState, Jr as CanvasNodeRenderType, Kn as useNodeHelpers, Kr as CanvasConnectionMode, L as CONFIGURATION_NODE_SIZE, M as usePostHog, N as useNDVStore, P as useWorkflowsStore, Pt as useNodeTypesStore, R as DEFAULT_NODE_SIZE, Sn as useDataSchema, St as isChatNode, U as doRectsOverlap, V as PUSH_NODES_OFFSET, W as generateOffsets, Wi as isPresent, Xr as AddConnectionCommand, Y as getNewNodePosition, Yi as tryToParseNumber, Yr as useHistoryStore, Z as getNodesGroupSize, Zn as useProjectsStore, Zr as AddNodeCommand, _n as useCredentialsStore, _r as useCanvasStore, aa as useUIStore, ai as ReplaceNodeParametersCommand, i as useFocusPanelStore, ii as RenameNodeCommand, k as useTelemetry, l as useTemplatesStore, ms as useSettingsStore, ni as RemoveConnectionCommand, qn as injectWorkflowState, ri as RemoveNodeCommand, ti as MoveNodeCommand, us as v4_default, x as useExternalHooks, y as useToast, z as DEFAULT_VIEWPORT_BOUNDARIES, zn as useWorkflowHelpers } from "./builder.store-Czk2ipDE.js";
|
|
6
|
+
import { _ as useRoute, v as useRouter } from "./get-BcEmeOxn.js";
|
|
7
|
+
import { $i as getNodeParameters, Dn as MCP_TRIGGER_NODE_TYPE, Fs as LOCAL_STORAGE_LOGS_SYNC_SELECTION, Ms as LOCAL_STORAGE_LOGS_PANEL_DETAILS_PANEL, Ns as LOCAL_STORAGE_LOGS_PANEL_DETAILS_PANEL_SUB_NODE, Oi as require__baseUniq, Ps as LOCAL_STORAGE_LOGS_PANEL_OPEN, Qi as getNodeOutputs, Ro as VIEWS, Ta as isCommunityPackageName, Ua as NodeConnectionTypes, Xi as getConnectionTypes, Zi as getNodeInputs, hr as WEBHOOK_NODE_TYPE, ia as getSubworkflowId, oc as CANVAS_ZOOMED_VIEW_EXPERIMENT, pr as UPDATE_WEBHOOK_ID_NODE_TYPES, qi as generateNodesGraph, sr as STICKY_NODE_TYPE, uc as NDV_IN_FOCUS_PANEL_EXPERIMENT, un as FORM_TRIGGER_NODE_TYPE, wa as deepCopy, yc as EnterpriseEditionFeature, yi as require_cloneDeep } from "./constants-C8OH4tTq.js";
|
|
8
|
+
import { k as defineStore, r as useRootStore } from "./_baseOrderBy-N8Be_6z6.js";
|
|
9
|
+
import { t as useExecutionsStore } from "./executions.store-B9uRYwgv.js";
|
|
10
|
+
import { t as usePinnedData } from "./usePinnedData-BhZkqttf.js";
|
|
11
|
+
import { a as mapCanvasConnectionToLegacyConnection, l as parseCanvasConnectionHandleString, o as mapLegacyConnectionToCanvasConnection, r as createCanvasConnectionHandleString, s as mapLegacyConnectionsToCanvasConnections, t as useNodeCreatorStore } from "./nodeCreator.store-Bpnrwp2l.js";
|
|
12
|
+
import { t as useClipboard } from "./useClipboard-DvjhVHqJ.js";
|
|
13
|
+
import { t as useFoldersStore } from "./folders.store-yAFj-5Vl.js";
|
|
14
|
+
function useUniqueNodeName() {
|
|
15
|
+
function numberSuffixedNames() {
|
|
16
|
+
return useNodeTypesStore().allNodeTypes.reduce((acc, nodeType) => {
|
|
17
|
+
if (typeof nodeType.defaults.name !== "string") throw new Error("Expected node name default to be a string");
|
|
18
|
+
if (/\d$/.test(nodeType.defaults.name)) acc.push(nodeType.defaults.name);
|
|
19
|
+
return acc;
|
|
20
|
+
}, []);
|
|
21
|
+
}
|
|
22
|
+
function uniqueNodeName(originalName, extraNames = []) {
|
|
23
|
+
const { canvasNames } = useWorkflowsStore();
|
|
24
|
+
if (!canvasNames.has(originalName) && !extraNames.includes(originalName)) return originalName;
|
|
25
|
+
const nsn = numberSuffixedNames().find((nsn$1) => originalName.startsWith(nsn$1));
|
|
26
|
+
if (nsn) {
|
|
27
|
+
let unique$1 = "";
|
|
28
|
+
let index$1 = 1;
|
|
29
|
+
const remainder = originalName.split(nsn).pop();
|
|
30
|
+
const lastChar = remainder?.[remainder.length - 1];
|
|
31
|
+
if (lastChar && Number.isInteger(Number(lastChar))) {
|
|
32
|
+
index$1 = parseInt(lastChar, 10);
|
|
33
|
+
originalName = originalName.slice(0, -1);
|
|
34
|
+
}
|
|
35
|
+
unique$1 = originalName;
|
|
36
|
+
while (canvasNames.has(unique$1) || extraNames.includes(unique$1)) unique$1 = originalName + index$1++;
|
|
37
|
+
return unique$1;
|
|
38
|
+
}
|
|
39
|
+
if (/^\d+-?\d*$/.test(originalName)) {
|
|
40
|
+
let unique$1 = "";
|
|
41
|
+
let index$1 = 1;
|
|
42
|
+
const match$1 = originalName.match(/(?<base>\d+)-?(?<suffix>\d*)/);
|
|
43
|
+
if (!match$1?.groups) throw new Error("Failed to find match for unique name");
|
|
44
|
+
if (match$1?.groups?.suffix !== "") index$1 = parseInt(match$1.groups.suffix, 10);
|
|
45
|
+
unique$1 = match$1.groups.base;
|
|
46
|
+
while (canvasNames.has(unique$1) || extraNames.includes(unique$1)) unique$1 = match$1.groups.base + "-" + index$1++;
|
|
47
|
+
return unique$1;
|
|
48
|
+
}
|
|
49
|
+
let unique = "";
|
|
50
|
+
let index = 1;
|
|
51
|
+
const match = originalName.match(/(?<base>.*\D+)(?<suffix>\d*)/);
|
|
52
|
+
if (!match?.groups) throw new Error("Failed to find match for unique name");
|
|
53
|
+
if (match?.groups?.suffix !== "") index = parseInt(match.groups.suffix, 10);
|
|
54
|
+
unique = match.groups.base;
|
|
55
|
+
while (canvasNames.has(unique) || extraNames.includes(unique)) unique = match.groups.base + index++;
|
|
56
|
+
return unique;
|
|
57
|
+
}
|
|
58
|
+
return { uniqueNodeName };
|
|
59
|
+
}
|
|
60
|
+
function createEventBus$1() {
|
|
61
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
62
|
+
function off(eventName, fn) {
|
|
63
|
+
const eventFns = handlers.get(eventName);
|
|
64
|
+
if (eventFns) eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
|
|
65
|
+
}
|
|
66
|
+
function on(eventName, fn) {
|
|
67
|
+
let eventFns = handlers.get(eventName);
|
|
68
|
+
if (!eventFns) eventFns = [fn];
|
|
69
|
+
else eventFns.push(fn);
|
|
70
|
+
handlers.set(eventName, eventFns);
|
|
71
|
+
return () => off(eventName, fn);
|
|
72
|
+
}
|
|
73
|
+
function emit(eventName, event) {
|
|
74
|
+
const eventFns = handlers.get(eventName);
|
|
75
|
+
if (eventFns) eventFns.slice().forEach(async (handler) => {
|
|
76
|
+
await handler(event);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
on,
|
|
81
|
+
off,
|
|
82
|
+
emit
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const chatEventBus = createEventBus$1();
|
|
86
|
+
const LOCAL_STORAGE_PANEL_HEIGHT = "N8N_CANVAS_CHAT_HEIGHT";
|
|
87
|
+
const LOCAL_STORAGE_PANEL_WIDTH = "N8N_CANVAS_CHAT_WIDTH";
|
|
88
|
+
const LOCAL_STORAGE_OVERVIEW_PANEL_WIDTH = "N8N_LOGS_OVERVIEW_PANEL_WIDTH";
|
|
89
|
+
const LOGS_PANEL_STATE = {
|
|
90
|
+
CLOSED: "closed",
|
|
91
|
+
ATTACHED: "attached",
|
|
92
|
+
FLOATING: "floating"
|
|
93
|
+
};
|
|
94
|
+
const LOG_DETAILS_PANEL_STATE = {
|
|
95
|
+
INPUT: "input",
|
|
96
|
+
OUTPUT: "output",
|
|
97
|
+
BOTH: "both"
|
|
98
|
+
};
|
|
99
|
+
const useLogsStore = defineStore("logs", () => {
|
|
100
|
+
const isOpen = useLocalStorage(LOCAL_STORAGE_LOGS_PANEL_OPEN, false);
|
|
101
|
+
const preferPoppedOut = ref(false);
|
|
102
|
+
const state = computed(() => isOpen.value ? preferPoppedOut.value ? LOGS_PANEL_STATE.FLOATING : LOGS_PANEL_STATE.ATTACHED : LOGS_PANEL_STATE.CLOSED);
|
|
103
|
+
const height = ref(0);
|
|
104
|
+
const detailsState = useLocalStorage(LOCAL_STORAGE_LOGS_PANEL_DETAILS_PANEL, LOG_DETAILS_PANEL_STATE.OUTPUT, { writeDefaults: false });
|
|
105
|
+
const detailsStateSubNode = useLocalStorage(LOCAL_STORAGE_LOGS_PANEL_DETAILS_PANEL_SUB_NODE, LOG_DETAILS_PANEL_STATE.BOTH, { writeDefaults: false });
|
|
106
|
+
const isLogSelectionSyncedWithCanvas = useLocalStorage(LOCAL_STORAGE_LOGS_SYNC_SELECTION, true, { writeDefaults: false });
|
|
107
|
+
const isSubNodeSelected = ref(false);
|
|
108
|
+
const telemetry = useTelemetry();
|
|
109
|
+
const chatSessionId = ref(getNewSessionId());
|
|
110
|
+
const chatSessionMessages = ref([]);
|
|
111
|
+
function setHeight(value) {
|
|
112
|
+
height.value = value;
|
|
113
|
+
}
|
|
114
|
+
function getNewSessionId() {
|
|
115
|
+
return v4_default().replace(/-/g, "");
|
|
116
|
+
}
|
|
117
|
+
function resetChatSessionId() {
|
|
118
|
+
chatSessionId.value = getNewSessionId();
|
|
119
|
+
}
|
|
120
|
+
function resetMessages() {
|
|
121
|
+
chatSessionMessages.value = [];
|
|
122
|
+
}
|
|
123
|
+
function toggleOpen(value) {
|
|
124
|
+
isOpen.value = value ?? !isOpen.value;
|
|
125
|
+
}
|
|
126
|
+
function setPreferPoppedOut(value) {
|
|
127
|
+
preferPoppedOut.value = value;
|
|
128
|
+
}
|
|
129
|
+
function setSubNodeSelected(value) {
|
|
130
|
+
isSubNodeSelected.value = value;
|
|
131
|
+
}
|
|
132
|
+
function toggleInputOpen(open) {
|
|
133
|
+
const statesWithInput = [LOG_DETAILS_PANEL_STATE.INPUT, LOG_DETAILS_PANEL_STATE.BOTH];
|
|
134
|
+
const stateRef = isSubNodeSelected.value ? detailsStateSubNode : detailsState;
|
|
135
|
+
const wasOpen = statesWithInput.includes(stateRef.value);
|
|
136
|
+
if (open === wasOpen) return;
|
|
137
|
+
stateRef.value = wasOpen ? LOG_DETAILS_PANEL_STATE.OUTPUT : LOG_DETAILS_PANEL_STATE.BOTH;
|
|
138
|
+
telemetry.track("User toggled log view sub pane", {
|
|
139
|
+
pane: "input",
|
|
140
|
+
newState: wasOpen ? "hidden" : "visible",
|
|
141
|
+
isSubNode: isSubNodeSelected.value
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function toggleOutputOpen(open) {
|
|
145
|
+
const statesWithOutput = [LOG_DETAILS_PANEL_STATE.OUTPUT, LOG_DETAILS_PANEL_STATE.BOTH];
|
|
146
|
+
const stateRef = isSubNodeSelected.value ? detailsStateSubNode : detailsState;
|
|
147
|
+
const wasOpen = statesWithOutput.includes(stateRef.value);
|
|
148
|
+
if (open === wasOpen) return;
|
|
149
|
+
stateRef.value = wasOpen ? LOG_DETAILS_PANEL_STATE.INPUT : LOG_DETAILS_PANEL_STATE.BOTH;
|
|
150
|
+
telemetry.track("User toggled log view sub pane", {
|
|
151
|
+
pane: "output",
|
|
152
|
+
newState: wasOpen ? "hidden" : "visible",
|
|
153
|
+
isSubNode: isSubNodeSelected.value
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function toggleLogSelectionSync(value) {
|
|
157
|
+
isLogSelectionSyncedWithCanvas.value = value ?? !isLogSelectionSyncedWithCanvas.value;
|
|
158
|
+
}
|
|
159
|
+
function addChatMessage(message) {
|
|
160
|
+
chatSessionMessages.value.push(message);
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
state,
|
|
164
|
+
isOpen: computed(() => state.value !== LOGS_PANEL_STATE.CLOSED),
|
|
165
|
+
detailsState: computed(() => isSubNodeSelected.value ? detailsStateSubNode.value : detailsState.value),
|
|
166
|
+
height: computed(() => height.value),
|
|
167
|
+
isLogSelectionSyncedWithCanvas: computed(() => isLogSelectionSyncedWithCanvas.value),
|
|
168
|
+
chatSessionId: computed(() => chatSessionId.value),
|
|
169
|
+
chatSessionMessages: computed(() => chatSessionMessages.value),
|
|
170
|
+
addChatMessage,
|
|
171
|
+
setHeight,
|
|
172
|
+
toggleOpen,
|
|
173
|
+
setPreferPoppedOut,
|
|
174
|
+
setSubNodeSelected,
|
|
175
|
+
toggleInputOpen,
|
|
176
|
+
toggleOutputOpen,
|
|
177
|
+
toggleLogSelectionSync,
|
|
178
|
+
resetChatSessionId,
|
|
179
|
+
resetMessages
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
var require_uniq = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
183
|
+
var baseUniq = require__baseUniq();
|
|
184
|
+
function uniq$1(array) {
|
|
185
|
+
return array && array.length ? baseUniq(array) : [];
|
|
186
|
+
}
|
|
187
|
+
module.exports = uniq$1;
|
|
188
|
+
}));
|
|
189
|
+
const useExperimentalNdvStore = defineStore("experimentalNdv", () => {
|
|
190
|
+
const workflowStore = useWorkflowsStore();
|
|
191
|
+
const postHogStore = usePostHog();
|
|
192
|
+
const isZoomedViewEnabled = computed(() => postHogStore.getVariant(CANVAS_ZOOMED_VIEW_EXPERIMENT.name) === CANVAS_ZOOMED_VIEW_EXPERIMENT.variant);
|
|
193
|
+
const isNdvInFocusPanelEnabled = computed(() => postHogStore.getVariant(NDV_IN_FOCUS_PANEL_EXPERIMENT.name) === NDV_IN_FOCUS_PANEL_EXPERIMENT.variant);
|
|
194
|
+
const maxCanvasZoom = computed(() => isZoomedViewEnabled.value ? 2 : 4);
|
|
195
|
+
const previousViewport = ref();
|
|
196
|
+
const collapsedNodes = shallowRef({});
|
|
197
|
+
const nodeNameToBeFocused = ref();
|
|
198
|
+
const isMapperOpen = ref(false);
|
|
199
|
+
function setNodeExpanded(nodeId, isExpanded) {
|
|
200
|
+
collapsedNodes.value = {
|
|
201
|
+
...collapsedNodes.value,
|
|
202
|
+
[nodeId]: isExpanded === void 0 ? !collapsedNodes.value[nodeId] : !isExpanded
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function collapseAllNodes() {
|
|
206
|
+
collapsedNodes.value = workflowStore.allNodes.reduce((acc, node) => {
|
|
207
|
+
acc[node.id] = true;
|
|
208
|
+
return acc;
|
|
209
|
+
}, {});
|
|
210
|
+
}
|
|
211
|
+
function expandAllNodes() {
|
|
212
|
+
collapsedNodes.value = {};
|
|
213
|
+
}
|
|
214
|
+
function isActive(canvasZoom) {
|
|
215
|
+
return isZoomedViewEnabled.value && Math.abs(canvasZoom - maxCanvasZoom.value) < 1e-6;
|
|
216
|
+
}
|
|
217
|
+
function setNodeNameToBeFocused(nodeName) {
|
|
218
|
+
nodeNameToBeFocused.value = nodeName;
|
|
219
|
+
}
|
|
220
|
+
function setMapperOpen(value) {
|
|
221
|
+
isMapperOpen.value = value;
|
|
222
|
+
}
|
|
223
|
+
function focusNode(node, { canvasDimensions, canvasViewport, setCenter }) {
|
|
224
|
+
collapsedNodes.value = {
|
|
225
|
+
...collapsedNodes.value,
|
|
226
|
+
[node.id]: false
|
|
227
|
+
};
|
|
228
|
+
const topMargin = 80;
|
|
229
|
+
const nodeWidth = node.dimensions.width * (isActive(canvasViewport.zoom) ? 1 : 1.5);
|
|
230
|
+
if (nodeNameToBeFocused.value === node.data.name) nodeNameToBeFocused.value = void 0;
|
|
231
|
+
setCenter(node.position.x + nodeWidth / 2, node.position.y + (canvasDimensions.height * (1 / 2) - topMargin) / maxCanvasZoom.value, {
|
|
232
|
+
duration: 200,
|
|
233
|
+
zoom: maxCanvasZoom.value,
|
|
234
|
+
interpolate: "linear"
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
function toggleZoomMode(options) {
|
|
238
|
+
if (isActive(options.canvasViewport.zoom)) {
|
|
239
|
+
if (previousViewport.value === void 0) {
|
|
240
|
+
options.fitView({
|
|
241
|
+
duration: 200,
|
|
242
|
+
interpolate: "linear"
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
options.setViewport(previousViewport.value, {
|
|
247
|
+
duration: 200,
|
|
248
|
+
interpolate: "linear"
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
previousViewport.value = options.canvasViewport;
|
|
253
|
+
const toFocus = options.selectedNodes.filter((node) => node.data.render.type === CanvasNodeRenderType.Default).toSorted((a, b) => a.position.y === b.position.y ? a.position.x - b.position.x : a.position.y - b.position.y)[0];
|
|
254
|
+
if (toFocus) {
|
|
255
|
+
focusNode(toFocus, options);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
options.zoomTo(maxCanvasZoom.value, {
|
|
259
|
+
duration: 200,
|
|
260
|
+
interpolate: "linear"
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
isZoomedViewEnabled,
|
|
265
|
+
isNdvInFocusPanelEnabled,
|
|
266
|
+
maxCanvasZoom,
|
|
267
|
+
previousZoom: computed(() => previousViewport.value),
|
|
268
|
+
collapsedNodes: computed(() => collapsedNodes.value),
|
|
269
|
+
nodeNameToBeFocused: computed(() => nodeNameToBeFocused.value),
|
|
270
|
+
isMapperOpen: computed(() => isMapperOpen.value),
|
|
271
|
+
isActive,
|
|
272
|
+
setNodeExpanded,
|
|
273
|
+
expandAllNodes,
|
|
274
|
+
collapseAllNodes,
|
|
275
|
+
toggleZoomMode,
|
|
276
|
+
focusNode,
|
|
277
|
+
setNodeNameToBeFocused,
|
|
278
|
+
setMapperOpen
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
const canvasEventBus = createEventBus();
|
|
282
|
+
function useParentFolder() {
|
|
283
|
+
const foldersStore = useFoldersStore();
|
|
284
|
+
const projectsStore = useProjectsStore();
|
|
285
|
+
const workflowsStore = useWorkflowsStore();
|
|
286
|
+
const fetchAndSetParentFolder = async (folderId) => {
|
|
287
|
+
if (!folderId) return;
|
|
288
|
+
let parentFolder = foldersStore.getCachedFolder(folderId);
|
|
289
|
+
if (!parentFolder && projectsStore.currentProjectId) {
|
|
290
|
+
await foldersStore.getFolderPath(projectsStore.currentProjectId, folderId);
|
|
291
|
+
parentFolder = foldersStore.getCachedFolder(folderId);
|
|
292
|
+
}
|
|
293
|
+
if (parentFolder) workflowsStore.setParentFolder({
|
|
294
|
+
...parentFolder,
|
|
295
|
+
parentFolderId: parentFolder.parentFolder ?? null
|
|
296
|
+
});
|
|
297
|
+
return parentFolder ?? null;
|
|
298
|
+
};
|
|
299
|
+
return { fetchAndSetParentFolder };
|
|
300
|
+
}
|
|
301
|
+
var import_cloneDeep = /* @__PURE__ */ __toESM(require_cloneDeep());
|
|
302
|
+
var import_uniq = /* @__PURE__ */ __toESM(require_uniq());
|
|
303
|
+
function useCanvasOperations() {
|
|
304
|
+
const rootStore = useRootStore();
|
|
305
|
+
const workflowsStore = useWorkflowsStore();
|
|
306
|
+
const workflowState = injectWorkflowState();
|
|
307
|
+
const credentialsStore = useCredentialsStore();
|
|
308
|
+
const historyStore = useHistoryStore();
|
|
309
|
+
const uiStore = useUIStore();
|
|
310
|
+
const ndvStore = useNDVStore();
|
|
311
|
+
const nodeTypesStore = useNodeTypesStore();
|
|
312
|
+
const canvasStore = useCanvasStore();
|
|
313
|
+
const settingsStore = useSettingsStore();
|
|
314
|
+
const tagsStore = useTagsStore();
|
|
315
|
+
const nodeCreatorStore = useNodeCreatorStore();
|
|
316
|
+
const executionsStore = useExecutionsStore();
|
|
317
|
+
const projectsStore = useProjectsStore();
|
|
318
|
+
const logsStore = useLogsStore();
|
|
319
|
+
const experimentalNdvStore = useExperimentalNdvStore();
|
|
320
|
+
const templatesStore = useTemplatesStore();
|
|
321
|
+
const focusPanelStore = useFocusPanelStore();
|
|
322
|
+
const i18n = useI18n();
|
|
323
|
+
const toast = useToast();
|
|
324
|
+
const workflowHelpers = useWorkflowHelpers();
|
|
325
|
+
const nodeHelpers = useNodeHelpers();
|
|
326
|
+
const telemetry = useTelemetry();
|
|
327
|
+
const externalHooks = useExternalHooks();
|
|
328
|
+
const clipboard = useClipboard();
|
|
329
|
+
const { uniqueNodeName } = useUniqueNodeName();
|
|
330
|
+
const { fetchAndSetParentFolder } = useParentFolder();
|
|
331
|
+
const router = useRouter();
|
|
332
|
+
const route = useRoute();
|
|
333
|
+
const lastClickPosition = ref([0, 0]);
|
|
334
|
+
const preventOpeningNDV = !!localStorage.getItem("NodeView.preventOpeningNDV");
|
|
335
|
+
const editableWorkflow = computed(() => workflowsStore.workflow);
|
|
336
|
+
const editableWorkflowObject = computed(() => workflowsStore.workflowObject);
|
|
337
|
+
const triggerNodes = computed(() => {
|
|
338
|
+
return workflowsStore.workflowTriggerNodes;
|
|
339
|
+
});
|
|
340
|
+
function tidyUp({ result, source, target }, { trackEvents = true } = {}) {
|
|
341
|
+
updateNodesPosition(result.nodes.map(({ id, x, y }) => ({
|
|
342
|
+
id,
|
|
343
|
+
position: {
|
|
344
|
+
x,
|
|
345
|
+
y
|
|
346
|
+
}
|
|
347
|
+
})), {
|
|
348
|
+
trackBulk: true,
|
|
349
|
+
trackHistory: true
|
|
350
|
+
});
|
|
351
|
+
if (trackEvents) trackTidyUp({
|
|
352
|
+
result,
|
|
353
|
+
source,
|
|
354
|
+
target
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
function trackTidyUp({ result, source, target }) {
|
|
358
|
+
telemetry.track("User tidied up canvas", {
|
|
359
|
+
source,
|
|
360
|
+
target,
|
|
361
|
+
nodes_count: result.nodes.length
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
function updateNodesPosition(events, { trackHistory = false, trackBulk = true } = {}) {
|
|
365
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
366
|
+
events.forEach(({ id, position }) => {
|
|
367
|
+
updateNodePosition(id, position, { trackHistory });
|
|
368
|
+
});
|
|
369
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
370
|
+
}
|
|
371
|
+
function updateNodePosition(id, position, { trackHistory = false } = {}) {
|
|
372
|
+
const node = workflowsStore.getNodeById(id);
|
|
373
|
+
if (!node) return;
|
|
374
|
+
const oldPosition = [...node.position];
|
|
375
|
+
const newPosition = [position.x, position.y];
|
|
376
|
+
workflowState.setNodePositionById(id, newPosition);
|
|
377
|
+
if (trackHistory) historyStore.pushCommandToUndo(new MoveNodeCommand(node.name, oldPosition, newPosition, Date.now()));
|
|
378
|
+
}
|
|
379
|
+
function revertUpdateNodePosition(nodeName, position) {
|
|
380
|
+
const node = workflowsStore.getNodeByName(nodeName);
|
|
381
|
+
if (!node) return;
|
|
382
|
+
updateNodePosition(node.id, position);
|
|
383
|
+
}
|
|
384
|
+
function replaceNodeParameters(nodeId, currentParameters, newParameters, { trackHistory = false, trackBulk = true } = {}) {
|
|
385
|
+
const node = workflowsStore.getNodeById(nodeId);
|
|
386
|
+
if (!node) return;
|
|
387
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
388
|
+
workflowState.setNodeParameters({
|
|
389
|
+
name: node.name,
|
|
390
|
+
value: newParameters
|
|
391
|
+
});
|
|
392
|
+
if (trackHistory) historyStore.pushCommandToUndo(new ReplaceNodeParametersCommand(nodeId, currentParameters, newParameters, Date.now()));
|
|
393
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
394
|
+
}
|
|
395
|
+
async function revertReplaceNodeParameters(nodeId, currentParameters, newParameters) {
|
|
396
|
+
replaceNodeParameters(nodeId, newParameters, currentParameters);
|
|
397
|
+
}
|
|
398
|
+
async function renameNode(currentName, newName, { trackHistory = false, trackBulk = true } = {}) {
|
|
399
|
+
if (currentName === newName) return;
|
|
400
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
401
|
+
newName = uniqueNodeName(newName);
|
|
402
|
+
const workflow = workflowsStore.cloneWorkflowObject();
|
|
403
|
+
try {
|
|
404
|
+
workflow.renameNode(currentName, newName);
|
|
405
|
+
} catch (error) {
|
|
406
|
+
toast.showMessage({
|
|
407
|
+
type: "error",
|
|
408
|
+
title: error.message,
|
|
409
|
+
message: error.description
|
|
410
|
+
});
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (trackHistory) historyStore.pushCommandToUndo(new RenameNodeCommand(currentName, newName, Date.now()));
|
|
414
|
+
workflowsStore.renameNodeSelectedAndExecution({
|
|
415
|
+
old: currentName,
|
|
416
|
+
new: newName
|
|
417
|
+
});
|
|
418
|
+
workflowsStore.setNodes(Object.values(workflow.nodes));
|
|
419
|
+
workflowsStore.setConnections(workflow.connectionsBySourceNode);
|
|
420
|
+
if (ndvStore.activeNodeName === currentName) ndvStore.setActiveNodeName(newName, "other");
|
|
421
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
422
|
+
}
|
|
423
|
+
async function revertRenameNode(currentName, previousName) {
|
|
424
|
+
await renameNode(currentName, previousName);
|
|
425
|
+
}
|
|
426
|
+
function connectAdjacentNodes(id, { trackHistory = false } = {}) {
|
|
427
|
+
const node = workflowsStore.getNodeById(id);
|
|
428
|
+
if (!node) return;
|
|
429
|
+
const outputConnectionsByType = workflowsStore.outgoingConnectionsByNodeName(node.name);
|
|
430
|
+
const incomingConnectionsByType = workflowsStore.incomingConnectionsByNodeName(node.name);
|
|
431
|
+
for (const [type, incomingConnectionsByInputIndex] of Object.entries(incomingConnectionsByType)) for (const incomingConnection of incomingConnectionsByInputIndex.at(0) ?? []) {
|
|
432
|
+
const incomingNodeId = workflowsStore.getNodeByName(incomingConnection.node)?.id;
|
|
433
|
+
if (!incomingNodeId) continue;
|
|
434
|
+
for (const outgoingConnection of outputConnectionsByType[type]?.at(0) ?? []) {
|
|
435
|
+
const outgoingNodeId = workflowsStore.getNodeByName(outgoingConnection.node)?.id;
|
|
436
|
+
if (!outgoingNodeId) continue;
|
|
437
|
+
if (trackHistory) historyStore.pushCommandToUndo(new AddConnectionCommand([{
|
|
438
|
+
node: incomingConnection.node,
|
|
439
|
+
type,
|
|
440
|
+
index: incomingConnection.index
|
|
441
|
+
}, {
|
|
442
|
+
node: outgoingConnection.node,
|
|
443
|
+
type,
|
|
444
|
+
index: outgoingConnection.index
|
|
445
|
+
}], Date.now()));
|
|
446
|
+
createConnection({
|
|
447
|
+
source: incomingNodeId,
|
|
448
|
+
sourceHandle: createCanvasConnectionHandleString({
|
|
449
|
+
mode: CanvasConnectionMode.Output,
|
|
450
|
+
type,
|
|
451
|
+
index: incomingConnection.index
|
|
452
|
+
}),
|
|
453
|
+
target: outgoingNodeId,
|
|
454
|
+
targetHandle: createCanvasConnectionHandleString({
|
|
455
|
+
mode: CanvasConnectionMode.Input,
|
|
456
|
+
type,
|
|
457
|
+
index: outgoingConnection.index
|
|
458
|
+
})
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
function deleteNode(id, { trackHistory = false, trackBulk = true } = {}) {
|
|
464
|
+
const node = workflowsStore.getNodeById(id);
|
|
465
|
+
if (!node) return;
|
|
466
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
467
|
+
if (uiStore.lastInteractedWithNodeId === id) uiStore.lastInteractedWithNodeId = void 0;
|
|
468
|
+
connectAdjacentNodes(id, { trackHistory });
|
|
469
|
+
deleteConnectionsByNodeId(id, {
|
|
470
|
+
trackHistory,
|
|
471
|
+
trackBulk: false
|
|
472
|
+
});
|
|
473
|
+
workflowsStore.removeNodeExecutionDataById(id);
|
|
474
|
+
workflowsStore.removeNodeById(id);
|
|
475
|
+
if (trackHistory) {
|
|
476
|
+
historyStore.pushCommandToUndo(new RemoveNodeCommand(node, Date.now()));
|
|
477
|
+
if (trackBulk) historyStore.stopRecordingUndo();
|
|
478
|
+
}
|
|
479
|
+
trackDeleteNode(id);
|
|
480
|
+
}
|
|
481
|
+
function deleteNodes(ids, { trackHistory = true, trackBulk = true } = {}) {
|
|
482
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
483
|
+
ids.forEach((id) => deleteNode(id, {
|
|
484
|
+
trackHistory,
|
|
485
|
+
trackBulk: false
|
|
486
|
+
}));
|
|
487
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
488
|
+
}
|
|
489
|
+
function revertDeleteNode(node) {
|
|
490
|
+
workflowsStore.addNode(node);
|
|
491
|
+
uiStore.stateIsDirty = true;
|
|
492
|
+
}
|
|
493
|
+
function trackDeleteNode(id) {
|
|
494
|
+
const node = workflowsStore.getNodeById(id);
|
|
495
|
+
if (!node) return;
|
|
496
|
+
if (node.type === "n8n-nodes-base.stickyNote") telemetry.track("User deleted workflow note", { workflow_id: workflowsStore.workflowId });
|
|
497
|
+
else {
|
|
498
|
+
externalHooks.run("node.deleteNode", { node });
|
|
499
|
+
telemetry.track("User deleted node", {
|
|
500
|
+
node_type: node.type,
|
|
501
|
+
workflow_id: workflowsStore.workflowId
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function replaceNodeConnections(previousId, newId, { trackHistory = false, trackBulk = true, replaceInputs = true, replaceOutputs = true } = {}) {
|
|
506
|
+
const previousNode = workflowsStore.getNodeById(previousId);
|
|
507
|
+
const newNode = workflowsStore.getNodeById(newId);
|
|
508
|
+
if (!previousNode || !newNode) return;
|
|
509
|
+
const workflowObject = workflowsStore.workflowObject;
|
|
510
|
+
const inputNodeNames = replaceInputs ? (0, import_uniq.default)(workflowObject.getParentNodes(previousNode.name, "ALL", 1)) : [];
|
|
511
|
+
const outputNodeNames = replaceOutputs ? (0, import_uniq.default)(workflowObject.getChildNodes(previousNode.name, "ALL", 1)) : [];
|
|
512
|
+
const connectionPairs = [...workflowObject.getConnectionsBetweenNodes(inputNodeNames, [previousNode.name]), ...workflowObject.getConnectionsBetweenNodes([previousNode.name], outputNodeNames)];
|
|
513
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
514
|
+
for (const pair of connectionPairs) {
|
|
515
|
+
const sourceNode = workflowsStore.getNodeByName(pair[0].node);
|
|
516
|
+
const targetNode = workflowsStore.getNodeByName(pair[1].node);
|
|
517
|
+
if (!sourceNode || !targetNode) continue;
|
|
518
|
+
deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, pair), {
|
|
519
|
+
trackHistory,
|
|
520
|
+
trackBulk: false
|
|
521
|
+
});
|
|
522
|
+
const newSourceIConnection = {
|
|
523
|
+
...pair[0],
|
|
524
|
+
node: pair[0].node === previousNode.name ? newNode.name : pair[0].node
|
|
525
|
+
};
|
|
526
|
+
const newTargetIConnection = {
|
|
527
|
+
...pair[1],
|
|
528
|
+
node: pair[1].node === previousNode.name ? newNode.name : pair[1].node
|
|
529
|
+
};
|
|
530
|
+
const newSourceNode = sourceNode.name === previousNode.name ? newNode : sourceNode;
|
|
531
|
+
const newTargetNode = targetNode.name === previousNode.name ? newNode : targetNode;
|
|
532
|
+
if (!isConnectionAllowed(newSourceNode, newTargetNode, newSourceIConnection, newTargetIConnection)) continue;
|
|
533
|
+
const newCanvasConnection = mapLegacyConnectionToCanvasConnection(newSourceNode, newTargetNode, [newSourceIConnection, newTargetIConnection]);
|
|
534
|
+
createConnection(newCanvasConnection, { trackHistory });
|
|
535
|
+
revalidateNodeInputConnections(newCanvasConnection.target);
|
|
536
|
+
revalidateNodeOutputConnections(newCanvasConnection.source);
|
|
537
|
+
}
|
|
538
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
539
|
+
}
|
|
540
|
+
function setNodeActive(id, source) {
|
|
541
|
+
const node = workflowsStore.getNodeById(id);
|
|
542
|
+
if (!node) return;
|
|
543
|
+
workflowsStore.setNodePristine(node.name, false);
|
|
544
|
+
setNodeActiveByName(node.name, source);
|
|
545
|
+
}
|
|
546
|
+
function setNodeActiveByName(name, source) {
|
|
547
|
+
ndvStore.setActiveNodeName(name, source);
|
|
548
|
+
}
|
|
549
|
+
function clearNodeActive() {
|
|
550
|
+
ndvStore.unsetActiveNodeName();
|
|
551
|
+
}
|
|
552
|
+
function setNodeParameters(id, parameters) {
|
|
553
|
+
const node = workflowsStore.getNodeById(id);
|
|
554
|
+
if (!node) return;
|
|
555
|
+
workflowState.setNodeParameters({
|
|
556
|
+
name: node.name,
|
|
557
|
+
value: parameters
|
|
558
|
+
}, true);
|
|
559
|
+
}
|
|
560
|
+
function setNodeSelected(id) {
|
|
561
|
+
if (!id) {
|
|
562
|
+
uiStore.lastInteractedWithNodeId = void 0;
|
|
563
|
+
uiStore.lastSelectedNode = "";
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
const node = workflowsStore.getNodeById(id);
|
|
567
|
+
if (!node) return;
|
|
568
|
+
uiStore.lastInteractedWithNodeId = id;
|
|
569
|
+
uiStore.lastSelectedNode = node.name;
|
|
570
|
+
}
|
|
571
|
+
function toggleNodesDisabled(ids, { trackHistory = true, trackBulk = true } = {}) {
|
|
572
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
573
|
+
const nodes = workflowsStore.getNodesByIds(ids);
|
|
574
|
+
nodeHelpers.disableNodes(nodes, {
|
|
575
|
+
trackHistory,
|
|
576
|
+
trackBulk: false
|
|
577
|
+
});
|
|
578
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
579
|
+
}
|
|
580
|
+
function revertToggleNodeDisabled(nodeName) {
|
|
581
|
+
const node = workflowsStore.getNodeByName(nodeName);
|
|
582
|
+
if (node) nodeHelpers.disableNodes([node]);
|
|
583
|
+
}
|
|
584
|
+
function toggleNodesPinned(ids, source, { trackHistory = true, trackBulk = true } = {}) {
|
|
585
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
586
|
+
const pinnableNodes = workflowsStore.getNodesByIds(ids).filter((node) => {
|
|
587
|
+
return usePinnedData(node).canPinNode(true);
|
|
588
|
+
});
|
|
589
|
+
const nextStatePinned = pinnableNodes.some((node) => !workflowsStore.pinDataByNodeName(node.name));
|
|
590
|
+
for (const node of pinnableNodes) {
|
|
591
|
+
const pinnedDataForNode = usePinnedData(node);
|
|
592
|
+
if (nextStatePinned) {
|
|
593
|
+
const dataToPin = useDataSchema().getInputDataWithPinned(node);
|
|
594
|
+
if (dataToPin.length !== 0) pinnedDataForNode.setData(dataToPin, source);
|
|
595
|
+
} else pinnedDataForNode.unsetData(source);
|
|
596
|
+
}
|
|
597
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
598
|
+
}
|
|
599
|
+
function requireNodeTypeDescription(type, version) {
|
|
600
|
+
return nodeTypesStore.getNodeType(type, version) ?? nodeTypesStore.communityNodeType(type)?.nodeDescription ?? {
|
|
601
|
+
properties: [],
|
|
602
|
+
displayName: type,
|
|
603
|
+
name: type,
|
|
604
|
+
group: [],
|
|
605
|
+
description: "",
|
|
606
|
+
version: version ?? 1,
|
|
607
|
+
defaults: {},
|
|
608
|
+
inputs: [],
|
|
609
|
+
outputs: []
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
async function addNodes(nodes, { viewport,...options } = {}) {
|
|
613
|
+
let insertPosition = options.position;
|
|
614
|
+
let lastAddedNode;
|
|
615
|
+
const addedNodes = [];
|
|
616
|
+
const nodesWithTypeVersion = nodes.map((node) => {
|
|
617
|
+
const typeVersion = node.typeVersion ?? resolveNodeVersion(requireNodeTypeDescription(node.type));
|
|
618
|
+
return {
|
|
619
|
+
...node,
|
|
620
|
+
typeVersion
|
|
621
|
+
};
|
|
622
|
+
});
|
|
623
|
+
await loadNodeTypesProperties(nodesWithTypeVersion);
|
|
624
|
+
if (options.trackHistory && options.trackBulk) historyStore.startRecordingUndo();
|
|
625
|
+
for (const [index, nodeAddData] of nodesWithTypeVersion.entries()) {
|
|
626
|
+
const { isAutoAdd, openDetail: openNDV, actionName, positionOffset,...node } = nodeAddData;
|
|
627
|
+
const rawPosition = node.position ?? insertPosition;
|
|
628
|
+
const position = rawPosition && positionOffset ? [rawPosition[0] + positionOffset[0], rawPosition[1] + positionOffset[1]] : rawPosition;
|
|
629
|
+
const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
|
|
630
|
+
try {
|
|
631
|
+
const newNode = addNode({
|
|
632
|
+
...node,
|
|
633
|
+
position
|
|
634
|
+
}, nodeTypeDescription, {
|
|
635
|
+
...options,
|
|
636
|
+
...index === 0 ? { viewport } : {},
|
|
637
|
+
openNDV,
|
|
638
|
+
isAutoAdd,
|
|
639
|
+
actionName
|
|
640
|
+
});
|
|
641
|
+
lastAddedNode = newNode;
|
|
642
|
+
addedNodes.push(newNode);
|
|
643
|
+
} catch (error) {
|
|
644
|
+
toast.showError(error, i18n.baseText("error"));
|
|
645
|
+
console.error(error);
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
insertPosition = [lastAddedNode.position[0] + DEFAULT_NODE_SIZE[0] * 2 + 16, lastAddedNode.position[1]];
|
|
649
|
+
}
|
|
650
|
+
if (lastAddedNode) updatePositionForNodeWithMultipleInputs(lastAddedNode);
|
|
651
|
+
if (options.trackHistory && options.trackBulk) historyStore.stopRecordingUndo();
|
|
652
|
+
if (!options.keepPristine) uiStore.stateIsDirty = true;
|
|
653
|
+
return addedNodes;
|
|
654
|
+
}
|
|
655
|
+
function updatePositionForNodeWithMultipleInputs(node) {
|
|
656
|
+
const inputNodes = editableWorkflowObject.value.getParentNodesByDepth(node.name, 1);
|
|
657
|
+
if (inputNodes.length > 1) inputNodes.slice(1).forEach((inputNode, index) => {
|
|
658
|
+
const nodeUi = workflowsStore.getNodeByName(inputNode.name);
|
|
659
|
+
if (!nodeUi) return;
|
|
660
|
+
updateNodePosition(nodeUi.id, {
|
|
661
|
+
x: nodeUi.position[0],
|
|
662
|
+
y: nodeUi.position[1] + 100 * (index + 1)
|
|
663
|
+
});
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
function checkMaxNodesOfTypeReached(nodeTypeDescription) {
|
|
667
|
+
if (nodeTypeDescription.maxNodes !== void 0 && workflowHelpers.getNodeTypeCount(nodeTypeDescription.name) >= nodeTypeDescription.maxNodes) throw new Error(i18n.baseText("nodeView.showMessage.showMaxNodeTypeError.message", {
|
|
668
|
+
adjustToNumber: nodeTypeDescription.maxNodes,
|
|
669
|
+
interpolate: { nodeTypeDataDisplayName: nodeTypeDescription.displayName }
|
|
670
|
+
}));
|
|
671
|
+
}
|
|
672
|
+
function addNode(node, nodeTypeDescription, options = {}) {
|
|
673
|
+
checkMaxNodesOfTypeReached(nodeTypeDescription);
|
|
674
|
+
const nodeData = resolveNodeData(node, nodeTypeDescription, { viewport: options.viewport });
|
|
675
|
+
if (!nodeData) throw new Error(i18n.baseText("nodeViewV2.showError.failedToCreateNode"));
|
|
676
|
+
workflowsStore.addNode(nodeData);
|
|
677
|
+
if (options.trackHistory) historyStore.pushCommandToUndo(new AddNodeCommand(nodeData, Date.now()));
|
|
678
|
+
if (!options.isAutoAdd) createConnectionToLastInteractedWithNode(nodeData, options);
|
|
679
|
+
nextTick(() => {
|
|
680
|
+
if (!options.keepPristine) uiStore.stateIsDirty = true;
|
|
681
|
+
workflowsStore.setNodePristine(nodeData.name, true);
|
|
682
|
+
nodeHelpers.matchCredentials(nodeData);
|
|
683
|
+
nodeHelpers.updateNodeParameterIssues(nodeData);
|
|
684
|
+
nodeHelpers.updateNodeCredentialIssues(nodeData);
|
|
685
|
+
nodeHelpers.updateNodeInputIssues(nodeData);
|
|
686
|
+
const isStickyNode = nodeData.type === STICKY_NODE_TYPE;
|
|
687
|
+
const nextView = isStickyNode || !options.openNDV || preventOpeningNDV ? void 0 : experimentalNdvStore.isNdvInFocusPanelEnabled && focusPanelStore.focusPanelActive && focusPanelStore.resolvedParameter === void 0 ? "focus_panel" : experimentalNdvStore.isZoomedViewEnabled ? "zoomed_view" : "ndv";
|
|
688
|
+
if (options.telemetry) trackAddNode(nodeData, options, nextView);
|
|
689
|
+
if (!isStickyNode) {
|
|
690
|
+
externalHooks.run("nodeView.addNodeButton", { nodeTypeName: nodeData.type });
|
|
691
|
+
if (nextView === "focus_panel") {} else if (nextView === "zoomed_view") experimentalNdvStore.setNodeNameToBeFocused(nodeData.name);
|
|
692
|
+
else if (nextView === "ndv") ndvStore.setActiveNodeName(nodeData.name, "added_new_node");
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
return nodeData;
|
|
696
|
+
}
|
|
697
|
+
async function revertAddNode(nodeName) {
|
|
698
|
+
const node = workflowsStore.getNodeByName(nodeName);
|
|
699
|
+
if (!node) return;
|
|
700
|
+
deleteNode(node.id);
|
|
701
|
+
}
|
|
702
|
+
function createConnectionToLastInteractedWithNode(node, options = {}) {
|
|
703
|
+
const lastInteractedWithNode = uiStore.lastInteractedWithNode;
|
|
704
|
+
if (!lastInteractedWithNode) return;
|
|
705
|
+
const lastInteractedWithNodeId = lastInteractedWithNode.id;
|
|
706
|
+
const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
|
|
707
|
+
const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
|
|
708
|
+
if (lastInteractedWithNodeHandle) {
|
|
709
|
+
const { type: connectionType, mode } = parseCanvasConnectionHandleString(lastInteractedWithNodeHandle);
|
|
710
|
+
const nodeId = node.id;
|
|
711
|
+
const nodeHandle = createCanvasConnectionHandleString({
|
|
712
|
+
mode: CanvasConnectionMode.Input,
|
|
713
|
+
type: connectionType,
|
|
714
|
+
index: 0
|
|
715
|
+
});
|
|
716
|
+
if (mode === CanvasConnectionMode.Input) createConnection({
|
|
717
|
+
source: nodeId,
|
|
718
|
+
sourceHandle: nodeHandle,
|
|
719
|
+
target: lastInteractedWithNodeId,
|
|
720
|
+
targetHandle: lastInteractedWithNodeHandle
|
|
721
|
+
});
|
|
722
|
+
else createConnection({
|
|
723
|
+
source: lastInteractedWithNodeId,
|
|
724
|
+
sourceHandle: lastInteractedWithNodeHandle,
|
|
725
|
+
target: nodeId,
|
|
726
|
+
targetHandle: nodeHandle
|
|
727
|
+
});
|
|
728
|
+
} else createConnection({
|
|
729
|
+
source: lastInteractedWithNodeId,
|
|
730
|
+
sourceHandle: createCanvasConnectionHandleString({
|
|
731
|
+
mode: CanvasConnectionMode.Output,
|
|
732
|
+
type: NodeConnectionTypes.Main,
|
|
733
|
+
index: 0
|
|
734
|
+
}),
|
|
735
|
+
target: node.id,
|
|
736
|
+
targetHandle: createCanvasConnectionHandleString({
|
|
737
|
+
mode: CanvasConnectionMode.Input,
|
|
738
|
+
type: NodeConnectionTypes.Main,
|
|
739
|
+
index: 0
|
|
740
|
+
})
|
|
741
|
+
});
|
|
742
|
+
if (lastInteractedWithNodeConnection) {
|
|
743
|
+
deleteConnection(lastInteractedWithNodeConnection, { trackHistory: options.trackHistory });
|
|
744
|
+
if (workflowsStore.getNodeById(lastInteractedWithNodeConnection.target)) createConnection({
|
|
745
|
+
source: node.id,
|
|
746
|
+
sourceHandle: createCanvasConnectionHandleString({
|
|
747
|
+
mode: CanvasConnectionMode.Input,
|
|
748
|
+
type: NodeConnectionTypes.Main,
|
|
749
|
+
index: 0
|
|
750
|
+
}),
|
|
751
|
+
target: lastInteractedWithNodeConnection.target,
|
|
752
|
+
targetHandle: lastInteractedWithNodeConnection.targetHandle
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function trackAddNode(nodeData, options, nextView) {
|
|
757
|
+
switch (nodeData.type) {
|
|
758
|
+
case STICKY_NODE_TYPE:
|
|
759
|
+
trackAddStickyNoteNode();
|
|
760
|
+
break;
|
|
761
|
+
default: trackAddDefaultNode(nodeData, options, nextView);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function trackAddStickyNoteNode() {
|
|
765
|
+
telemetry.track("User inserted workflow note", { workflow_id: workflowsStore.workflowId });
|
|
766
|
+
}
|
|
767
|
+
function trackAddDefaultNode(nodeData, options, nextView) {
|
|
768
|
+
const nodeParameters = nodeData.parameters;
|
|
769
|
+
const resource = typeof nodeParameters?.resource === "string" ? nodeParameters.resource : void 0;
|
|
770
|
+
const operation = typeof nodeParameters?.operation === "string" ? nodeParameters.operation : void 0;
|
|
771
|
+
nodeCreatorStore.onNodeAddedToCanvas({
|
|
772
|
+
node_id: nodeData.id,
|
|
773
|
+
node_type: nodeData.type,
|
|
774
|
+
node_version: nodeData.typeVersion,
|
|
775
|
+
is_auto_add: options.isAutoAdd,
|
|
776
|
+
workflow_id: workflowsStore.workflowId,
|
|
777
|
+
drag_and_drop: options.dragAndDrop,
|
|
778
|
+
input_node_type: uiStore.lastInteractedWithNode ? uiStore.lastInteractedWithNode.type : void 0,
|
|
779
|
+
resource,
|
|
780
|
+
operation,
|
|
781
|
+
action: options.actionName,
|
|
782
|
+
next_view_shown: nextView
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
function resolveNodeData(node, nodeTypeDescription, options = {}) {
|
|
786
|
+
const id = node.id ?? nodeHelpers.assignNodeId(node);
|
|
787
|
+
const name = node.name ?? nodeHelpers.getDefaultNodeName(node) ?? nodeTypeDescription.defaults.name;
|
|
788
|
+
const type = nodeTypeDescription.name;
|
|
789
|
+
const typeVersion = node.typeVersion;
|
|
790
|
+
const position = options.forcePosition && node.position ? node.position : resolveNodePosition(node, nodeTypeDescription, { viewport: options.viewport });
|
|
791
|
+
const disabled = node.disabled ?? false;
|
|
792
|
+
const parameters = node.parameters ?? {};
|
|
793
|
+
const nodeData = {
|
|
794
|
+
...node,
|
|
795
|
+
id,
|
|
796
|
+
name,
|
|
797
|
+
type,
|
|
798
|
+
typeVersion,
|
|
799
|
+
position,
|
|
800
|
+
disabled,
|
|
801
|
+
parameters
|
|
802
|
+
};
|
|
803
|
+
resolveNodeName(nodeData);
|
|
804
|
+
resolveNodeParameters(nodeData, nodeTypeDescription);
|
|
805
|
+
resolveNodeWebhook(nodeData, nodeTypeDescription);
|
|
806
|
+
return nodeData;
|
|
807
|
+
}
|
|
808
|
+
async function loadNodeTypesProperties(nodes) {
|
|
809
|
+
const allNodeTypeDescriptions = nodeTypesStore.allNodeTypes;
|
|
810
|
+
const nodesToBeFetched = [];
|
|
811
|
+
allNodeTypeDescriptions.forEach((nodeTypeDescription) => {
|
|
812
|
+
const nodeVersions = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version : [nodeTypeDescription.version];
|
|
813
|
+
if (!!nodes.find((n) => n.type === nodeTypeDescription.name && nodeVersions.includes(n.typeVersion)) && !nodeTypeDescription.hasOwnProperty("properties")) nodesToBeFetched.push({
|
|
814
|
+
name: nodeTypeDescription.name,
|
|
815
|
+
version: Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version
|
|
816
|
+
});
|
|
817
|
+
});
|
|
818
|
+
if (nodesToBeFetched.length > 0) await nodeTypesStore.getNodesInformation(nodesToBeFetched);
|
|
819
|
+
}
|
|
820
|
+
function resolveNodeVersion(nodeTypeDescription) {
|
|
821
|
+
let nodeVersion = nodeTypeDescription.defaultVersion;
|
|
822
|
+
if (typeof nodeVersion === "undefined") nodeVersion = Array.isArray(nodeTypeDescription.version) ? nodeTypeDescription.version.slice(-1)[0] : nodeTypeDescription.version;
|
|
823
|
+
return nodeVersion;
|
|
824
|
+
}
|
|
825
|
+
function resolveNodeParameters(node, nodeTypeDescription) {
|
|
826
|
+
node.parameters = getNodeParameters(nodeTypeDescription?.properties ?? [], node.parameters, true, false, node, nodeTypeDescription) ?? {};
|
|
827
|
+
}
|
|
828
|
+
function resolveNodePosition(node, nodeTypeDescription, options = {}) {
|
|
829
|
+
const lastInteractedWithNode = uiStore.lastInteractedWithNode;
|
|
830
|
+
const lastInteractedWithNodeConnection = uiStore.lastInteractedWithNodeConnection;
|
|
831
|
+
const lastInteractedWithNodeHandle = uiStore.lastInteractedWithNodeHandle;
|
|
832
|
+
const { type: connectionType, index: connectionIndex } = parseCanvasConnectionHandleString(lastInteractedWithNodeHandle ?? lastInteractedWithNodeConnection?.sourceHandle ?? "");
|
|
833
|
+
const nodeSize = connectionType === NodeConnectionTypes.Main ? DEFAULT_NODE_SIZE : CONFIGURATION_NODE_SIZE;
|
|
834
|
+
const pushOffsets = [nodeSize[0] / 2, nodeSize[1] / 2];
|
|
835
|
+
let position = node.position;
|
|
836
|
+
if (position) return getNewNodePosition(workflowsStore.allNodes, position, {
|
|
837
|
+
offset: pushOffsets,
|
|
838
|
+
size: nodeSize,
|
|
839
|
+
viewport: options.viewport,
|
|
840
|
+
normalize: false
|
|
841
|
+
});
|
|
842
|
+
if (lastInteractedWithNode) {
|
|
843
|
+
const lastInteractedWithNodeTypeDescription = nodeTypesStore.getNodeType(lastInteractedWithNode.type, lastInteractedWithNode.typeVersion);
|
|
844
|
+
const lastInteractedWithNodeObject = editableWorkflowObject.value.getNode(lastInteractedWithNode.name);
|
|
845
|
+
const newNodeInsertPosition = uiStore.lastCancelledConnectionPosition;
|
|
846
|
+
if (newNodeInsertPosition) {
|
|
847
|
+
const xOffset = connectionType === NodeConnectionTypes.Main ? 0 : -nodeSize[0] / 2;
|
|
848
|
+
const yOffset = connectionType === NodeConnectionTypes.Main ? -nodeSize[1] / 2 : 0;
|
|
849
|
+
position = [newNodeInsertPosition[0] + xOffset, newNodeInsertPosition[1] + yOffset];
|
|
850
|
+
uiStore.lastCancelledConnectionPosition = void 0;
|
|
851
|
+
} else if (lastInteractedWithNodeTypeDescription && lastInteractedWithNodeObject) {
|
|
852
|
+
const lastInteractedWithNodeInputTypes = getConnectionTypes(getNodeInputs(editableWorkflowObject.value, lastInteractedWithNodeObject, lastInteractedWithNodeTypeDescription));
|
|
853
|
+
const lastInteractedWithNodeScopedInputTypes = (lastInteractedWithNodeInputTypes || []).filter((input) => input !== NodeConnectionTypes.Main);
|
|
854
|
+
const lastInteractedWithNodeMainOutputs = getConnectionTypes(getNodeOutputs(editableWorkflowObject.value, lastInteractedWithNodeObject, lastInteractedWithNodeTypeDescription)).filter((output) => output === NodeConnectionTypes.Main);
|
|
855
|
+
let yOffset = 0;
|
|
856
|
+
if (lastInteractedWithNodeConnection) {
|
|
857
|
+
let isNewNodeConfigurable = false;
|
|
858
|
+
if (typeof nodeTypeDescription.inputs === "string") isNewNodeConfigurable = true;
|
|
859
|
+
else if (Array.isArray(nodeTypeDescription.inputs)) isNewNodeConfigurable = getConnectionTypes(nodeTypeDescription.inputs).filter((input) => input !== NodeConnectionTypes.Main).length > 0;
|
|
860
|
+
const newNodeSize = isNewNodeConfigurable ? CONFIGURABLE_NODE_SIZE : DEFAULT_NODE_SIZE;
|
|
861
|
+
const shiftMargin = PUSH_NODES_OFFSET + (isNewNodeConfigurable ? CONFIGURABLE_NODE_SIZE[0] - DEFAULT_NODE_SIZE[0] : 0);
|
|
862
|
+
shiftDownstreamNodesPosition(lastInteractedWithNode.name, shiftMargin, {
|
|
863
|
+
trackHistory: true,
|
|
864
|
+
nodeSize: newNodeSize
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
if (lastInteractedWithNodeMainOutputs.length > 1) yOffset = generateOffsets(lastInteractedWithNodeMainOutputs.length, DEFAULT_NODE_SIZE[1], 16)[connectionIndex];
|
|
868
|
+
let outputs = [];
|
|
869
|
+
try {
|
|
870
|
+
outputs = getNodeOutputs(editableWorkflowObject.value, node, nodeTypeDescription);
|
|
871
|
+
} catch (e) {}
|
|
872
|
+
const outputTypes = getConnectionTypes(outputs);
|
|
873
|
+
const customOffset = {
|
|
874
|
+
[NodeConnectionTypes.AiLanguageModel]: nodeSize[0] * 2,
|
|
875
|
+
[NodeConnectionTypes.AiMemory]: nodeSize[0]
|
|
876
|
+
}[connectionType] ?? 0;
|
|
877
|
+
if (outputTypes.length > 0 && outputTypes.every((outputName) => outputName !== NodeConnectionTypes.Main)) {
|
|
878
|
+
const scopedConnectionIndex = lastInteractedWithNodeScopedInputTypes.findIndex((inputType) => outputs[0] === inputType);
|
|
879
|
+
const lastInteractedWithNodeWidthDivisions = Math.max(lastInteractedWithNodeScopedInputTypes.length + 1, 1);
|
|
880
|
+
position = [lastInteractedWithNode.position[0] + CONFIGURABLE_NODE_SIZE[0] / lastInteractedWithNodeWidthDivisions * (scopedConnectionIndex + 1) - nodeSize[0] / 2 - customOffset, lastInteractedWithNode.position[1] + PUSH_NODES_OFFSET];
|
|
881
|
+
} else {
|
|
882
|
+
let pushOffset = PUSH_NODES_OFFSET;
|
|
883
|
+
if (lastInteractedWithNodeInputTypes.find((input) => input !== NodeConnectionTypes.Main)) pushOffset += 140;
|
|
884
|
+
position = [lastInteractedWithNode.position[0] + pushOffset, lastInteractedWithNode.position[1] + yOffset];
|
|
885
|
+
if (lastInteractedWithNodeConnection) {
|
|
886
|
+
const adjustedY = getYPositionForStickyOverlap(position, nodeSize);
|
|
887
|
+
if (adjustedY !== null) position = [position[0], adjustedY];
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
if (!position) if (nodeTypesStore.isTriggerNode(node.type) && triggerNodes.value.length === 0) position = [0, 0];
|
|
893
|
+
else position = lastClickPosition.value;
|
|
894
|
+
return getNewNodePosition(workflowsStore.allNodes, position, {
|
|
895
|
+
offset: pushOffsets,
|
|
896
|
+
size: nodeSize,
|
|
897
|
+
viewport: options.viewport
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
function resolveNodeName(node) {
|
|
901
|
+
node.name = uniqueNodeName(i18n.localizeNodeName(rootStore.defaultLocale, node.name, node.type));
|
|
902
|
+
}
|
|
903
|
+
function resolveNodeWebhook(node, nodeTypeDescription) {
|
|
904
|
+
if (nodeTypeDescription.webhooks?.length && !node.webhookId) nodeHelpers.assignWebhookId(node);
|
|
905
|
+
if ([
|
|
906
|
+
"n8n-nodes-base.webhook",
|
|
907
|
+
"n8n-nodes-base.formTrigger",
|
|
908
|
+
"@n8n/n8n-nodes-langchain.mcpTrigger"
|
|
909
|
+
].includes(node.type) && node.parameters.path === "") node.parameters.path = node.webhookId;
|
|
910
|
+
}
|
|
911
|
+
function getNodeRect(node) {
|
|
912
|
+
if (node.type === "n8n-nodes-base.stickyNote") return {
|
|
913
|
+
x: node.position[0],
|
|
914
|
+
y: node.position[1],
|
|
915
|
+
width: node.parameters.width || DEFAULT_NODE_SIZE[0],
|
|
916
|
+
height: node.parameters.height || DEFAULT_NODE_SIZE[1]
|
|
917
|
+
};
|
|
918
|
+
return {
|
|
919
|
+
x: node.position[0],
|
|
920
|
+
y: node.position[1],
|
|
921
|
+
width: DEFAULT_NODE_SIZE[0],
|
|
922
|
+
height: DEFAULT_NODE_SIZE[1]
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
function hasSpaceForInsertion(insertPosition, nodeSize, nodesToCheck) {
|
|
926
|
+
const insertRect = {
|
|
927
|
+
x: insertPosition[0],
|
|
928
|
+
y: insertPosition[1],
|
|
929
|
+
width: nodeSize[0] + 16,
|
|
930
|
+
height: nodeSize[1]
|
|
931
|
+
};
|
|
932
|
+
for (const node of nodesToCheck) {
|
|
933
|
+
if (node.type === "n8n-nodes-base.stickyNote") continue;
|
|
934
|
+
if (doRectsOverlap(insertRect, getNodeRect(node))) return false;
|
|
935
|
+
}
|
|
936
|
+
return true;
|
|
937
|
+
}
|
|
938
|
+
function getNodesToShift(insertPosition, sourceNodeName) {
|
|
939
|
+
const allNodes = Object.values(workflowsStore.nodesByName);
|
|
940
|
+
const insertX = insertPosition[0];
|
|
941
|
+
const insertY = insertPosition[1];
|
|
942
|
+
const yTolerance = DEFAULT_NODE_SIZE[1] * 2;
|
|
943
|
+
const initialCandidates = allNodes.filter((node) => {
|
|
944
|
+
if (node.type === "n8n-nodes-base.stickyNote") return false;
|
|
945
|
+
if (node.name === sourceNodeName) return false;
|
|
946
|
+
const isSimilarY = Math.abs(node.position[1] - insertY) <= yTolerance;
|
|
947
|
+
const overlapsOrIsToTheRight = node.position[0] + DEFAULT_NODE_SIZE[0] > insertX || node.position[0] >= insertX;
|
|
948
|
+
return isSimilarY && overlapsOrIsToTheRight;
|
|
949
|
+
});
|
|
950
|
+
const candidateNames = new Set(initialCandidates.map((n) => n.name));
|
|
951
|
+
for (const candidate of initialCandidates) workflowHelpers.getConnectedNodes("downstream", editableWorkflowObject.value, candidate.name).forEach((name) => candidateNames.add(name));
|
|
952
|
+
const regularNodesToMove = allNodes.filter((node) => {
|
|
953
|
+
if (node.type === "n8n-nodes-base.stickyNote") return false;
|
|
954
|
+
return candidateNames.has(node.name);
|
|
955
|
+
});
|
|
956
|
+
const stickiesToStretch = [];
|
|
957
|
+
const stickiesToMove = [];
|
|
958
|
+
const stickyNodes = allNodes.filter((node) => node.type === STICKY_NODE_TYPE);
|
|
959
|
+
const affectedMinY = Math.min(insertY, ...regularNodesToMove.map((n) => n.position[1]));
|
|
960
|
+
const affectedMaxY = Math.max(insertY + DEFAULT_NODE_SIZE[1], ...regularNodesToMove.map((n) => n.position[1] + DEFAULT_NODE_SIZE[1]));
|
|
961
|
+
for (const sticky of stickyNodes) {
|
|
962
|
+
const stickyRect = getNodeRect(sticky);
|
|
963
|
+
const stickyLeftEdge = sticky.position[0];
|
|
964
|
+
const stickyRightEdge = stickyLeftEdge + stickyRect.width;
|
|
965
|
+
const stickyTop = sticky.position[1];
|
|
966
|
+
const overlapsVertically = !(stickyTop + stickyRect.height <= affectedMinY || stickyTop >= affectedMaxY);
|
|
967
|
+
if (stickyLeftEdge >= insertX && overlapsVertically) stickiesToMove.push(sticky);
|
|
968
|
+
else if (stickyLeftEdge < insertX && stickyRightEdge >= insertX && overlapsVertically) stickiesToStretch.push(sticky);
|
|
969
|
+
}
|
|
970
|
+
return {
|
|
971
|
+
nodesToMove: [...regularNodesToMove, ...stickiesToMove],
|
|
972
|
+
stickiesToStretch
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function getYPositionForStickyOverlap(insertPosition, nodeSize) {
|
|
976
|
+
const allNodes = Object.values(workflowsStore.nodesByName);
|
|
977
|
+
const stickyNodes = allNodes.filter((node) => node.type === STICKY_NODE_TYPE);
|
|
978
|
+
const regularNodes = allNodes.filter((node) => node.type !== STICKY_NODE_TYPE);
|
|
979
|
+
const insertRect = {
|
|
980
|
+
x: insertPosition[0],
|
|
981
|
+
y: insertPosition[1],
|
|
982
|
+
width: nodeSize[0] + 16,
|
|
983
|
+
height: nodeSize[1]
|
|
984
|
+
};
|
|
985
|
+
for (const node of regularNodes) if (doRectsOverlap(insertRect, getNodeRect(node))) return null;
|
|
986
|
+
for (const sticky of stickyNodes) {
|
|
987
|
+
const stickyRect = getNodeRect(sticky);
|
|
988
|
+
if (doRectsOverlap(insertRect, stickyRect)) {
|
|
989
|
+
const stickyContentTop = sticky.position[1] + 40;
|
|
990
|
+
const centeredY = stickyContentTop + (sticky.position[1] + stickyRect.height - 16 - stickyContentTop - nodeSize[1]) / 2;
|
|
991
|
+
return Math.round(centeredY / 16) * 16;
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
function stretchStickyNote(sticky, stretchAmount, { trackHistory = false }) {
|
|
997
|
+
const newWidth = (sticky.parameters.width || DEFAULT_NODE_SIZE[0]) + stretchAmount;
|
|
998
|
+
const newParameters = {
|
|
999
|
+
...sticky.parameters,
|
|
1000
|
+
width: newWidth
|
|
1001
|
+
};
|
|
1002
|
+
replaceNodeParameters(sticky.id, sticky.parameters, newParameters, {
|
|
1003
|
+
trackHistory,
|
|
1004
|
+
trackBulk: false
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
function shiftDownstreamNodesPosition(sourceNodeName, margin, { trackHistory = false, nodeSize = DEFAULT_NODE_SIZE }) {
|
|
1008
|
+
const sourceNode = workflowsStore.nodesByName[sourceNodeName];
|
|
1009
|
+
if (!sourceNode) return;
|
|
1010
|
+
const insertPosition = [sourceNode.position[0] + PUSH_NODES_OFFSET, sourceNode.position[1]];
|
|
1011
|
+
if (hasSpaceForInsertion(insertPosition, nodeSize, Object.values(workflowsStore.nodesByName).filter((n) => n.name !== sourceNodeName && n.type !== "n8n-nodes-base.stickyNote"))) return;
|
|
1012
|
+
const { nodesToMove, stickiesToStretch } = getNodesToShift(insertPosition, sourceNodeName);
|
|
1013
|
+
for (const node of nodesToMove) updateNodePosition(node.id, {
|
|
1014
|
+
x: node.position[0] + margin,
|
|
1015
|
+
y: node.position[1]
|
|
1016
|
+
}, { trackHistory });
|
|
1017
|
+
for (const sticky of stickiesToStretch) stretchStickyNote(sticky, margin, { trackHistory });
|
|
1018
|
+
}
|
|
1019
|
+
function createConnection(connection, { trackHistory = false, keepPristine = false } = {}) {
|
|
1020
|
+
const sourceNode = workflowsStore.getNodeById(connection.source);
|
|
1021
|
+
const targetNode = workflowsStore.getNodeById(connection.target);
|
|
1022
|
+
if (!sourceNode || !targetNode) return;
|
|
1023
|
+
if (trackHistory) historyStore.pushCommandToUndo(new AddConnectionCommand(mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection), Date.now()));
|
|
1024
|
+
const mappedConnection = mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection);
|
|
1025
|
+
if (!isConnectionAllowed(sourceNode, targetNode, mappedConnection[0], mappedConnection[1])) return;
|
|
1026
|
+
workflowsStore.addConnection({ connection: mappedConnection });
|
|
1027
|
+
nextTick(() => {
|
|
1028
|
+
nodeHelpers.updateNodeInputIssues(sourceNode);
|
|
1029
|
+
nodeHelpers.updateNodeInputIssues(targetNode);
|
|
1030
|
+
});
|
|
1031
|
+
if (!keepPristine) uiStore.stateIsDirty = true;
|
|
1032
|
+
}
|
|
1033
|
+
function revertCreateConnection(connection) {
|
|
1034
|
+
const sourceNodeName = connection[0].node;
|
|
1035
|
+
const sourceNode = workflowsStore.getNodeByName(sourceNodeName);
|
|
1036
|
+
const targetNodeName = connection[1].node;
|
|
1037
|
+
const targetNode = workflowsStore.getNodeByName(targetNodeName);
|
|
1038
|
+
if (!sourceNode || !targetNode) return;
|
|
1039
|
+
deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection));
|
|
1040
|
+
}
|
|
1041
|
+
function deleteConnectionsByNodeId(targetNodeId, { trackHistory = false, trackBulk = true } = {}) {
|
|
1042
|
+
const targetNode = workflowsStore.getNodeById(targetNodeId);
|
|
1043
|
+
if (!targetNode) return;
|
|
1044
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
1045
|
+
const connections = (0, import_cloneDeep.default)(workflowsStore.workflow.connections);
|
|
1046
|
+
for (const nodeName of Object.keys(connections)) {
|
|
1047
|
+
const node = workflowsStore.getNodeByName(nodeName);
|
|
1048
|
+
if (!node) continue;
|
|
1049
|
+
for (const type of Object.keys(connections[nodeName])) for (const index of Object.keys(connections[nodeName][type])) {
|
|
1050
|
+
const connectionsToDelete = connections[nodeName][type][parseInt(index, 10)] ?? [];
|
|
1051
|
+
for (const connectionIndex of Object.keys(connectionsToDelete)) {
|
|
1052
|
+
const connectionData = connectionsToDelete[parseInt(connectionIndex, 10)];
|
|
1053
|
+
if (!connectionData) continue;
|
|
1054
|
+
const connectionDataNode = workflowsStore.getNodeByName(connectionData.node);
|
|
1055
|
+
if (connectionDataNode && (connectionDataNode.id === targetNode.id || node.name === targetNode.name)) deleteConnection({
|
|
1056
|
+
source: node.id,
|
|
1057
|
+
sourceHandle: createCanvasConnectionHandleString({
|
|
1058
|
+
mode: CanvasConnectionMode.Output,
|
|
1059
|
+
type,
|
|
1060
|
+
index: parseInt(index, 10)
|
|
1061
|
+
}),
|
|
1062
|
+
target: connectionDataNode.id,
|
|
1063
|
+
targetHandle: createCanvasConnectionHandleString({
|
|
1064
|
+
mode: CanvasConnectionMode.Input,
|
|
1065
|
+
type: connectionData.type,
|
|
1066
|
+
index: connectionData.index
|
|
1067
|
+
})
|
|
1068
|
+
}, {
|
|
1069
|
+
trackHistory,
|
|
1070
|
+
trackBulk: false
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
delete workflowsStore.workflow.connections[targetNode.name];
|
|
1076
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
1077
|
+
}
|
|
1078
|
+
function deleteConnection(connection, { trackHistory = false, trackBulk = true } = {}) {
|
|
1079
|
+
const sourceNode = workflowsStore.getNodeById(connection.source);
|
|
1080
|
+
const targetNode = workflowsStore.getNodeById(connection.target);
|
|
1081
|
+
if (!sourceNode || !targetNode) return;
|
|
1082
|
+
const mappedConnection = mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection);
|
|
1083
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
1084
|
+
workflowsStore.removeConnection({ connection: mappedConnection });
|
|
1085
|
+
if (trackHistory) {
|
|
1086
|
+
historyStore.pushCommandToUndo(new RemoveConnectionCommand(mappedConnection, Date.now()));
|
|
1087
|
+
if (trackBulk) historyStore.stopRecordingUndo();
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
function revertDeleteConnection(connection) {
|
|
1091
|
+
workflowsStore.addConnection({ connection });
|
|
1092
|
+
}
|
|
1093
|
+
function revalidateNodeConnections(id, connectionMode) {
|
|
1094
|
+
const node = workflowsStore.getNodeById(id);
|
|
1095
|
+
const isInput = connectionMode === CanvasConnectionMode.Input;
|
|
1096
|
+
if (!node) return;
|
|
1097
|
+
if (!nodeTypesStore.getNodeType(node.type, node.typeVersion)) return;
|
|
1098
|
+
mapLegacyConnectionsToCanvasConnections(workflowsStore.workflow.connections, workflowsStore.workflow.nodes).forEach((connection) => {
|
|
1099
|
+
if (isInput ? connection.target === id : connection.source === id) {
|
|
1100
|
+
const otherNodeId = isInput ? connection.source : connection.target;
|
|
1101
|
+
const otherNode = workflowsStore.getNodeById(otherNodeId);
|
|
1102
|
+
if (!otherNode || !connection.data) return;
|
|
1103
|
+
const [firstNode, secondNode] = isInput ? [otherNode, node] : [node, otherNode];
|
|
1104
|
+
if (!isConnectionAllowed(firstNode, secondNode, connection.data.source, connection.data.target)) nextTick(() => deleteConnection(connection));
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
function revalidateNodeInputConnections(id) {
|
|
1109
|
+
return revalidateNodeConnections(id, CanvasConnectionMode.Input);
|
|
1110
|
+
}
|
|
1111
|
+
function revalidateNodeOutputConnections(id) {
|
|
1112
|
+
return revalidateNodeConnections(id, CanvasConnectionMode.Output);
|
|
1113
|
+
}
|
|
1114
|
+
function isConnectionAllowed(sourceNode, targetNode, sourceConnection, targetConnection) {
|
|
1115
|
+
const blocklist = [STICKY_NODE_TYPE];
|
|
1116
|
+
const checkIsNotInstalledCommunityNode = (node) => isCommunityPackageName(node.type) && !useNodeTypesStore().getIsNodeInstalled(node.type);
|
|
1117
|
+
const isSourceNotInstalled = checkIsNotInstalledCommunityNode(sourceNode);
|
|
1118
|
+
const isTargetNotInstalled = checkIsNotInstalledCommunityNode(targetNode);
|
|
1119
|
+
const getNodeType = (node) => {
|
|
1120
|
+
return nodeTypesStore.getNodeType(node.type, node.typeVersion) ?? nodeTypesStore.communityNodeType(node.type)?.nodeDescription;
|
|
1121
|
+
};
|
|
1122
|
+
const filterConnectionsByType = (connections, type) => connections.filter((connection) => {
|
|
1123
|
+
return (typeof connection === "string" ? connection : connection.type) === type;
|
|
1124
|
+
});
|
|
1125
|
+
const getInputFilter = (connection) => {
|
|
1126
|
+
if (connection && typeof connection === "object" && "filter" in connection) return connection.filter;
|
|
1127
|
+
};
|
|
1128
|
+
if (sourceConnection.type !== targetConnection.type) return false;
|
|
1129
|
+
if (blocklist.includes(sourceNode.type) || blocklist.includes(targetNode.type)) return false;
|
|
1130
|
+
const sourceNodeType = getNodeType(sourceNode);
|
|
1131
|
+
const sourceWorkflowNode = editableWorkflowObject.value.getNode(sourceNode.name);
|
|
1132
|
+
if (!sourceWorkflowNode) return false;
|
|
1133
|
+
let sourceNodeOutputs = [];
|
|
1134
|
+
if (sourceNodeType) sourceNodeOutputs = getNodeOutputs(editableWorkflowObject.value, sourceWorkflowNode, sourceNodeType) || [];
|
|
1135
|
+
const sourceOutputsOfType = filterConnectionsByType(sourceNodeOutputs, sourceConnection.type);
|
|
1136
|
+
const sourceNodeHasOutputConnectionOfType = sourceOutputsOfType.length > 0;
|
|
1137
|
+
const sourceNodeHasOutputConnectionPortOfType = sourceConnection.index < sourceOutputsOfType.length;
|
|
1138
|
+
if ((!sourceNodeHasOutputConnectionOfType || !sourceNodeHasOutputConnectionPortOfType) && !isSourceNotInstalled) return false;
|
|
1139
|
+
const targetNodeType = getNodeType(targetNode);
|
|
1140
|
+
const targetWorkflowNode = editableWorkflowObject.value.getNode(targetNode.name);
|
|
1141
|
+
if (!targetWorkflowNode) return false;
|
|
1142
|
+
let targetNodeInputs = [];
|
|
1143
|
+
if (targetNodeType) targetNodeInputs = getNodeInputs(editableWorkflowObject.value, targetWorkflowNode, targetNodeType) || [];
|
|
1144
|
+
const targetInputsOfType = filterConnectionsByType(targetNodeInputs, targetConnection.type);
|
|
1145
|
+
const targetNodeHasInputConnectionOfType = targetInputsOfType.length > 0;
|
|
1146
|
+
const targetNodeHasInputConnectionPortOfType = targetConnection.index < targetInputsOfType.length;
|
|
1147
|
+
const targetConnectionFilter = getInputFilter(targetNodeHasInputConnectionPortOfType ? targetInputsOfType[targetConnection.index] : void 0);
|
|
1148
|
+
if (targetConnectionFilter?.nodes?.length && !targetConnectionFilter.nodes.includes(sourceNode.type) || targetConnectionFilter?.excludedNodes?.length && targetConnectionFilter.excludedNodes.includes(sourceNode.type)) {
|
|
1149
|
+
toast.showToast({
|
|
1150
|
+
title: i18n.baseText("nodeView.showError.nodeNodeCompatible.title"),
|
|
1151
|
+
message: i18n.baseText("nodeView.showError.nodeNodeCompatible.message", { interpolate: {
|
|
1152
|
+
sourceNodeName: sourceNode.name,
|
|
1153
|
+
targetNodeName: targetNode.name
|
|
1154
|
+
} }),
|
|
1155
|
+
type: "error",
|
|
1156
|
+
duration: 5e3
|
|
1157
|
+
});
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
if ((!targetNodeHasInputConnectionOfType || !targetNodeHasInputConnectionPortOfType) && !isTargetNotInstalled) return false;
|
|
1161
|
+
return true;
|
|
1162
|
+
}
|
|
1163
|
+
async function addConnections(connections, { trackBulk = true, trackHistory = false, keepPristine = false } = {}) {
|
|
1164
|
+
await nextTick();
|
|
1165
|
+
if (trackBulk && trackHistory) historyStore.startRecordingUndo();
|
|
1166
|
+
for (const connection of connections) createConnection(connection, {
|
|
1167
|
+
trackHistory,
|
|
1168
|
+
keepPristine
|
|
1169
|
+
});
|
|
1170
|
+
if (trackBulk && trackHistory) historyStore.stopRecordingUndo();
|
|
1171
|
+
if (!keepPristine) uiStore.stateIsDirty = true;
|
|
1172
|
+
}
|
|
1173
|
+
function resetWorkspace() {
|
|
1174
|
+
nodeCreatorStore.setNodeCreatorState({ createNodeActive: false });
|
|
1175
|
+
nodeCreatorStore.setShowScrim(false);
|
|
1176
|
+
if (workflowsStore.executionWaitingForWebhook) try {
|
|
1177
|
+
workflowsStore.removeTestWebhook(workflowsStore.workflowId);
|
|
1178
|
+
} catch (error) {}
|
|
1179
|
+
workflowsStore.resetWorkflow();
|
|
1180
|
+
workflowState.resetState();
|
|
1181
|
+
workflowsStore.currentWorkflowExecutions = [];
|
|
1182
|
+
workflowState.setActiveExecutionId(void 0);
|
|
1183
|
+
workflowsStore.lastSuccessfulExecution = null;
|
|
1184
|
+
uiStore.resetLastInteractedWith();
|
|
1185
|
+
uiStore.stateIsDirty = false;
|
|
1186
|
+
executionsStore.activeExecution = null;
|
|
1187
|
+
nodeHelpers.credentialsUpdated.value = false;
|
|
1188
|
+
}
|
|
1189
|
+
async function initializeWorkspace(data) {
|
|
1190
|
+
await workflowHelpers.initState(data, useWorkflowState());
|
|
1191
|
+
data.nodes.forEach((node) => {
|
|
1192
|
+
const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
|
|
1193
|
+
const isUnknownNode = !nodeTypesStore.getNodeType(node.type, node.typeVersion) && !nodeTypesStore.communityNodeType(node.type)?.nodeDescription;
|
|
1194
|
+
nodeHelpers.matchCredentials(node);
|
|
1195
|
+
if (!isUnknownNode) {
|
|
1196
|
+
resolveNodeParameters(node, nodeTypeDescription);
|
|
1197
|
+
resolveNodeWebhook(node, nodeTypeDescription);
|
|
1198
|
+
}
|
|
1199
|
+
});
|
|
1200
|
+
workflowsStore.setNodes(data.nodes);
|
|
1201
|
+
workflowsStore.setConnections(data.connections);
|
|
1202
|
+
workflowState.setWorkflowProperty("createdAt", data.createdAt);
|
|
1203
|
+
workflowState.setWorkflowProperty("updatedAt", data.updatedAt);
|
|
1204
|
+
}
|
|
1205
|
+
const initializeUnknownNodes = (nodes) => {
|
|
1206
|
+
nodes.forEach((node) => {
|
|
1207
|
+
const nodeTypeDescription = requireNodeTypeDescription(node.type, node.typeVersion);
|
|
1208
|
+
nodeHelpers.matchCredentials(node);
|
|
1209
|
+
resolveNodeParameters(node, nodeTypeDescription);
|
|
1210
|
+
resolveNodeWebhook(node, nodeTypeDescription);
|
|
1211
|
+
const nodeIndex = workflowsStore.workflow.nodes.findIndex((n) => {
|
|
1212
|
+
return n.name === node.name;
|
|
1213
|
+
});
|
|
1214
|
+
workflowState.updateNodeAtIndex(nodeIndex, node);
|
|
1215
|
+
});
|
|
1216
|
+
};
|
|
1217
|
+
function removeUnknownCredentials(workflow) {
|
|
1218
|
+
if (!workflow?.nodes) return;
|
|
1219
|
+
for (const node of workflow.nodes) {
|
|
1220
|
+
if (!node.credentials) continue;
|
|
1221
|
+
for (const [name, credential] of Object.entries(node.credentials)) {
|
|
1222
|
+
if (typeof credential === "string" || credential.id === null) continue;
|
|
1223
|
+
if (!credentialsStore.getCredentialById(credential.id)) delete node.credentials[name];
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
async function addImportedNodesToWorkflow(data, { trackBulk = true, trackHistory = false, viewport = DEFAULT_VIEWPORT_BOUNDARIES, setStateDirty = true } = {}) {
|
|
1228
|
+
const nodeNameTable = {};
|
|
1229
|
+
const newNodeNames = new Set((data.nodes ?? []).map((node) => node.name));
|
|
1230
|
+
if (!data.nodes) throw new Error(i18n.baseText("nodeView.noNodesGivenToAdd"));
|
|
1231
|
+
const nodeTypesCount = workflowHelpers.getNodeTypesMaxCount();
|
|
1232
|
+
let oldName;
|
|
1233
|
+
let newName;
|
|
1234
|
+
const createNodes = [];
|
|
1235
|
+
await nodeHelpers.loadNodesProperties(data.nodes.map((node) => ({
|
|
1236
|
+
name: node.type,
|
|
1237
|
+
version: node.typeVersion
|
|
1238
|
+
})));
|
|
1239
|
+
data.nodes.forEach((node) => {
|
|
1240
|
+
if (nodeTypesCount[node.type] !== void 0) if (nodeTypesCount[node.type].exist >= nodeTypesCount[node.type].max) {
|
|
1241
|
+
nodeNameTable[node.name] = nodeTypesCount[node.type].nodeNames[0];
|
|
1242
|
+
return;
|
|
1243
|
+
} else nodeTypesCount[node.type].exist += 1;
|
|
1244
|
+
oldName = node.name;
|
|
1245
|
+
const localized = i18n.localizeNodeName(rootStore.defaultLocale, node.name, node.type);
|
|
1246
|
+
newNodeNames.delete(oldName);
|
|
1247
|
+
newName = uniqueNodeName(localized, Array.from(newNodeNames));
|
|
1248
|
+
newNodeNames.add(newName);
|
|
1249
|
+
nodeNameTable[oldName] = newName;
|
|
1250
|
+
createNodes.push(node);
|
|
1251
|
+
});
|
|
1252
|
+
const newConnections = {};
|
|
1253
|
+
const currentConnections = data.connections ?? {};
|
|
1254
|
+
const createNodeNames = createNodes.map((node) => node.name);
|
|
1255
|
+
let sourceNode, type, sourceIndex, connectionIndex, connectionData;
|
|
1256
|
+
for (sourceNode of Object.keys(currentConnections)) {
|
|
1257
|
+
if (!createNodeNames.includes(sourceNode)) continue;
|
|
1258
|
+
const connection = {};
|
|
1259
|
+
for (type of Object.keys(currentConnections[sourceNode])) {
|
|
1260
|
+
connection[type] = [];
|
|
1261
|
+
for (sourceIndex = 0; sourceIndex < currentConnections[sourceNode][type].length; sourceIndex++) {
|
|
1262
|
+
const nodeSourceConnections = [];
|
|
1263
|
+
const connectionsToCheck = currentConnections[sourceNode][type][sourceIndex];
|
|
1264
|
+
if (connectionsToCheck) for (connectionIndex = 0; connectionIndex < connectionsToCheck.length; connectionIndex++) {
|
|
1265
|
+
connectionData = connectionsToCheck[connectionIndex];
|
|
1266
|
+
if (!createNodeNames.includes(connectionData.node)) continue;
|
|
1267
|
+
nodeSourceConnections.push(connectionData);
|
|
1268
|
+
}
|
|
1269
|
+
connection[type].push(nodeSourceConnections);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
newConnections[sourceNode] = connection;
|
|
1273
|
+
}
|
|
1274
|
+
const tempWorkflow = workflowsStore.createWorkflowObject(createNodes, newConnections);
|
|
1275
|
+
for (oldName in nodeNameTable) {
|
|
1276
|
+
const nameToChangeTo = nodeNameTable[oldName];
|
|
1277
|
+
if (!nameToChangeTo || oldName === nameToChangeTo) continue;
|
|
1278
|
+
tempWorkflow.renameNode(oldName, nameToChangeTo);
|
|
1279
|
+
}
|
|
1280
|
+
if (data.pinData) {
|
|
1281
|
+
let pinDataSuccess = true;
|
|
1282
|
+
for (const nodeName of Object.keys(data.pinData)) {
|
|
1283
|
+
if (!pinDataSuccess) {
|
|
1284
|
+
toast.showError(new Error(i18n.baseText("ndv.pinData.error.tooLarge.description")), i18n.baseText("ndv.pinData.error.tooLarge.title"));
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
const node = tempWorkflow.nodes[nodeNameTable[nodeName] ?? nodeName];
|
|
1288
|
+
if (node) try {
|
|
1289
|
+
usePinnedData(node).setData(data.pinData[nodeName], "add-nodes");
|
|
1290
|
+
pinDataSuccess = true;
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
pinDataSuccess = false;
|
|
1293
|
+
console.error(error);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
if (trackBulk && trackHistory) historyStore.startRecordingUndo();
|
|
1298
|
+
await addNodes(Object.values(tempWorkflow.nodes), {
|
|
1299
|
+
trackBulk: false,
|
|
1300
|
+
trackHistory,
|
|
1301
|
+
viewport
|
|
1302
|
+
});
|
|
1303
|
+
await addConnections(mapLegacyConnectionsToCanvasConnections(tempWorkflow.connectionsBySourceNode, Object.values(tempWorkflow.nodes)), {
|
|
1304
|
+
trackBulk: false,
|
|
1305
|
+
trackHistory
|
|
1306
|
+
});
|
|
1307
|
+
if (trackBulk && trackHistory) historyStore.stopRecordingUndo();
|
|
1308
|
+
uiStore.stateIsDirty = setStateDirty;
|
|
1309
|
+
return {
|
|
1310
|
+
nodes: Object.values(tempWorkflow.nodes),
|
|
1311
|
+
connections: tempWorkflow.connectionsBySourceNode
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
async function importWorkflowData(workflowData, source, { importTags = true, trackBulk = true, trackHistory = true, viewport, regenerateIds = true, trackEvents = true, setStateDirty = true } = {}) {
|
|
1315
|
+
uiStore.resetLastInteractedWith();
|
|
1316
|
+
if (!workflowData.hasOwnProperty("nodes") || !workflowData.hasOwnProperty("connections")) return {};
|
|
1317
|
+
try {
|
|
1318
|
+
const nodeIdMap = {};
|
|
1319
|
+
if (workflowData.nodes) {
|
|
1320
|
+
const nodeNames = new Set(workflowData.nodes.map((node) => node.name));
|
|
1321
|
+
workflowData.nodes.forEach((node) => {
|
|
1322
|
+
if (!node.name) {
|
|
1323
|
+
const newName = uniqueNodeName(nodeTypesStore.getNodeType(node.type)?.displayName ?? node.type, Array.from(nodeNames));
|
|
1324
|
+
node.name = newName;
|
|
1325
|
+
nodeNames.add(newName);
|
|
1326
|
+
}
|
|
1327
|
+
if (node.webhookId && UPDATE_WEBHOOK_ID_NODE_TYPES.includes(node.type)) {
|
|
1328
|
+
if (Object.values(workflowsStore.workflowObject.nodes).some((n) => n.webhookId === node.webhookId)) {
|
|
1329
|
+
nodeHelpers.assignWebhookId(node);
|
|
1330
|
+
if (node.parameters.path) node.parameters.path = node.webhookId;
|
|
1331
|
+
else if (node.parameters.options.path) node.parameters.options.path = node.webhookId;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
if (node.id) {
|
|
1335
|
+
const previousId = node.id;
|
|
1336
|
+
if (regenerateIds) {
|
|
1337
|
+
const newId = nodeHelpers.assignNodeId(node);
|
|
1338
|
+
nodeIdMap[newId] = previousId;
|
|
1339
|
+
}
|
|
1340
|
+
} else nodeHelpers.assignNodeId(node);
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
removeUnknownCredentials(workflowData);
|
|
1344
|
+
try {
|
|
1345
|
+
if (trackEvents) {
|
|
1346
|
+
const nodeGraph = JSON.stringify(generateNodesGraph(workflowData, workflowHelpers.getNodeTypes(), {
|
|
1347
|
+
nodeIdMap,
|
|
1348
|
+
sourceInstanceId: workflowData.meta && workflowData.meta.instanceId !== rootStore.instanceId ? workflowData.meta.instanceId : "",
|
|
1349
|
+
isCloudDeployment: settingsStore.isCloudDeployment
|
|
1350
|
+
}).nodeGraph);
|
|
1351
|
+
if (source === "paste") telemetry.track("User pasted nodes", {
|
|
1352
|
+
workflow_id: workflowsStore.workflowId,
|
|
1353
|
+
node_graph_string: nodeGraph
|
|
1354
|
+
});
|
|
1355
|
+
else if (source === "duplicate") telemetry.track("User duplicated nodes", {
|
|
1356
|
+
workflow_id: workflowsStore.workflowId,
|
|
1357
|
+
node_graph_string: nodeGraph
|
|
1358
|
+
});
|
|
1359
|
+
else telemetry.track("User imported workflow", {
|
|
1360
|
+
source,
|
|
1361
|
+
workflow_id: workflowsStore.workflowId,
|
|
1362
|
+
node_graph_string: nodeGraph
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
} catch {}
|
|
1366
|
+
workflowHelpers.updateNodePositions(workflowData, getNewNodePosition(editableWorkflow.value.nodes, lastClickPosition.value, {
|
|
1367
|
+
...workflowData.nodes && workflowData.nodes.length > 1 ? { size: getNodesGroupSize(workflowData.nodes) } : {},
|
|
1368
|
+
viewport
|
|
1369
|
+
}));
|
|
1370
|
+
await addImportedNodesToWorkflow(workflowData, {
|
|
1371
|
+
trackBulk,
|
|
1372
|
+
trackHistory,
|
|
1373
|
+
viewport,
|
|
1374
|
+
setStateDirty
|
|
1375
|
+
});
|
|
1376
|
+
if (importTags && settingsStore.areTagsEnabled && Array.isArray(workflowData.tags)) await importWorkflowTags(workflowData);
|
|
1377
|
+
if (workflowData.name) workflowState.setWorkflowName({
|
|
1378
|
+
newName: workflowData.name,
|
|
1379
|
+
setStateDirty
|
|
1380
|
+
});
|
|
1381
|
+
return workflowData;
|
|
1382
|
+
} catch (error) {
|
|
1383
|
+
console.error(error);
|
|
1384
|
+
toast.showError(error, i18n.baseText("nodeView.showError.importWorkflowData.title"));
|
|
1385
|
+
return {};
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
async function importWorkflowTags(workflowData) {
|
|
1389
|
+
const allTags = await tagsStore.fetchAll();
|
|
1390
|
+
const tagNames = new Set(allTags.map((tag) => tag.name));
|
|
1391
|
+
const workflowTags = workflowData.tags;
|
|
1392
|
+
const notFound = workflowTags.filter((tag) => !tagNames.has(tag.name));
|
|
1393
|
+
const creatingTagPromises = [];
|
|
1394
|
+
for (const tag of notFound) {
|
|
1395
|
+
const creationPromise = tagsStore.create(tag.name).then((newTag) => {
|
|
1396
|
+
allTags.push(newTag);
|
|
1397
|
+
return newTag;
|
|
1398
|
+
});
|
|
1399
|
+
creatingTagPromises.push(creationPromise);
|
|
1400
|
+
}
|
|
1401
|
+
await Promise.all(creatingTagPromises);
|
|
1402
|
+
const tagIds = workflowTags.reduce((accu, imported) => {
|
|
1403
|
+
const tag = allTags.find((t) => t.name === imported.name);
|
|
1404
|
+
if (tag) accu.push(tag.id);
|
|
1405
|
+
return accu;
|
|
1406
|
+
}, []);
|
|
1407
|
+
workflowsStore.addWorkflowTagIds(tagIds);
|
|
1408
|
+
}
|
|
1409
|
+
async function fetchWorkflowDataFromUrl(url) {
|
|
1410
|
+
let workflowData;
|
|
1411
|
+
const projectId = projectsStore.currentProjectId ?? projectsStore.personalProject?.id;
|
|
1412
|
+
if (!projectId) throw new Error("No project selected");
|
|
1413
|
+
canvasStore.startLoading();
|
|
1414
|
+
try {
|
|
1415
|
+
workflowData = await workflowsStore.getWorkflowFromUrl(url, projectId);
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
toast.showError(error, i18n.baseText("nodeView.showError.getWorkflowDataFromUrl.title"));
|
|
1418
|
+
return;
|
|
1419
|
+
} finally {
|
|
1420
|
+
canvasStore.stopLoading();
|
|
1421
|
+
}
|
|
1422
|
+
return workflowData;
|
|
1423
|
+
}
|
|
1424
|
+
function getNodesToSave(nodes) {
|
|
1425
|
+
const data = {
|
|
1426
|
+
nodes: [],
|
|
1427
|
+
connections: {},
|
|
1428
|
+
pinData: {}
|
|
1429
|
+
};
|
|
1430
|
+
const exportedNodeNames = /* @__PURE__ */ new Set();
|
|
1431
|
+
for (const node of nodes) {
|
|
1432
|
+
const nodeSaveData = workflowHelpers.getNodeDataToSave(node);
|
|
1433
|
+
const pinDataForNode = workflowsStore.pinDataByNodeName(node.name);
|
|
1434
|
+
if (pinDataForNode) data.pinData[node.name] = pinDataForNode;
|
|
1435
|
+
if (nodeSaveData.credentials && settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]) nodeSaveData.credentials = filterAllowedCredentials(nodeSaveData.credentials, workflowsStore.usedCredentials);
|
|
1436
|
+
data.nodes.push(nodeSaveData);
|
|
1437
|
+
exportedNodeNames.add(node.name);
|
|
1438
|
+
}
|
|
1439
|
+
data.connections = getConnectionsForNodes(data.nodes, exportedNodeNames);
|
|
1440
|
+
workflowHelpers.removeForeignCredentialsFromWorkflow(data, credentialsStore.allCredentials);
|
|
1441
|
+
return data;
|
|
1442
|
+
}
|
|
1443
|
+
function filterAllowedCredentials(credentials, usedCredentials) {
|
|
1444
|
+
return Object.fromEntries(Object.entries(credentials).filter(([, credential]) => {
|
|
1445
|
+
return credential.id && (!usedCredentials[credential.id] || usedCredentials[credential.id]?.currentUserHasAccess);
|
|
1446
|
+
}));
|
|
1447
|
+
}
|
|
1448
|
+
function getConnectionsForNodes(nodes, includeNodeNames) {
|
|
1449
|
+
const connections = {};
|
|
1450
|
+
for (const node of nodes) {
|
|
1451
|
+
const outgoingConnections = workflowsStore.outgoingConnectionsByNodeName(node.name);
|
|
1452
|
+
if (!Object.keys(outgoingConnections).length) continue;
|
|
1453
|
+
const filteredConnections = filterConnectionsByNodes(outgoingConnections, includeNodeNames);
|
|
1454
|
+
if (Object.keys(filteredConnections).length) connections[node.name] = filteredConnections;
|
|
1455
|
+
}
|
|
1456
|
+
return connections;
|
|
1457
|
+
}
|
|
1458
|
+
function filterConnectionsByNodes(connections, includeNodeNames) {
|
|
1459
|
+
const filteredConnections = {};
|
|
1460
|
+
for (const [type, typeConnections] of Object.entries(connections)) {
|
|
1461
|
+
const validConnections = typeConnections.map((sourceConnections) => (sourceConnections ?? []).filter((connection) => includeNodeNames.has(connection.node)));
|
|
1462
|
+
if (validConnections.length) filteredConnections[type] = validConnections;
|
|
1463
|
+
}
|
|
1464
|
+
return filteredConnections;
|
|
1465
|
+
}
|
|
1466
|
+
async function duplicateNodes(ids, options = {}) {
|
|
1467
|
+
return (await importWorkflowData(deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids))), "duplicate", {
|
|
1468
|
+
viewport: options.viewport,
|
|
1469
|
+
importTags: false
|
|
1470
|
+
})).nodes?.map((node) => node.id).filter(isPresent) ?? [];
|
|
1471
|
+
}
|
|
1472
|
+
async function copyNodes(ids) {
|
|
1473
|
+
const workflowData = deepCopy(getNodesToSave(workflowsStore.getNodesByIds(ids)));
|
|
1474
|
+
workflowData.meta = {
|
|
1475
|
+
...workflowData.meta,
|
|
1476
|
+
...workflowsStore.workflow.meta,
|
|
1477
|
+
instanceId: rootStore.instanceId
|
|
1478
|
+
};
|
|
1479
|
+
await clipboard.copy(JSON.stringify(workflowData, null, 2));
|
|
1480
|
+
telemetry.track("User copied nodes", {
|
|
1481
|
+
node_types: workflowData.nodes.map((node) => node.type),
|
|
1482
|
+
workflow_id: workflowsStore.workflowId
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
async function cutNodes(ids) {
|
|
1486
|
+
await copyNodes(ids);
|
|
1487
|
+
deleteNodes(ids);
|
|
1488
|
+
}
|
|
1489
|
+
async function openExecution(executionId, nodeId) {
|
|
1490
|
+
let data;
|
|
1491
|
+
try {
|
|
1492
|
+
data = await workflowsStore.getExecution(executionId);
|
|
1493
|
+
} catch (error) {
|
|
1494
|
+
toast.showError(error, i18n.baseText("nodeView.showError.openExecution.title"));
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (data === void 0) throw new Error(`Execution with id "${executionId}" could not be found!`);
|
|
1498
|
+
if (data.status === "error" && data.data?.resultData.error) {
|
|
1499
|
+
const { title, message } = getExecutionErrorToastConfiguration({
|
|
1500
|
+
error: data.data.resultData.error,
|
|
1501
|
+
lastNodeExecuted: data.data.resultData.lastNodeExecuted
|
|
1502
|
+
});
|
|
1503
|
+
toast.showMessage({
|
|
1504
|
+
title,
|
|
1505
|
+
message,
|
|
1506
|
+
type: "error",
|
|
1507
|
+
duration: 0
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
await initializeWorkspace(data.workflowData);
|
|
1511
|
+
workflowState.setWorkflowExecutionData(data);
|
|
1512
|
+
if (!["manual", "evaluation"].includes(data.mode)) workflowsStore.setWorkflowPinData({});
|
|
1513
|
+
if (nodeId) {
|
|
1514
|
+
const node = workflowsStore.getNodeById(nodeId);
|
|
1515
|
+
if (node) ndvStore.setActiveNodeName(node.name, "other");
|
|
1516
|
+
else toast.showError(/* @__PURE__ */ new Error(`Node with id "${nodeId}" could not be found!`), i18n.baseText("nodeView.showError.openExecution.node"));
|
|
1517
|
+
}
|
|
1518
|
+
uiStore.stateIsDirty = false;
|
|
1519
|
+
return data;
|
|
1520
|
+
}
|
|
1521
|
+
function startChat(source) {
|
|
1522
|
+
if (!workflowsStore.allNodes.some(isChatNode)) return;
|
|
1523
|
+
const workflowObject = workflowsStore.workflowObject;
|
|
1524
|
+
logsStore.toggleOpen(true);
|
|
1525
|
+
const payload = {
|
|
1526
|
+
workflow_id: workflowObject.id,
|
|
1527
|
+
button_type: source
|
|
1528
|
+
};
|
|
1529
|
+
externalHooks.run("nodeView.onOpenChat", payload);
|
|
1530
|
+
telemetry.track("User clicked chat open button", payload);
|
|
1531
|
+
setTimeout(() => {
|
|
1532
|
+
chatEventBus.emit("focusInput");
|
|
1533
|
+
}, 0);
|
|
1534
|
+
}
|
|
1535
|
+
async function importTemplate({ id, name, workflow }) {
|
|
1536
|
+
const convertedNodes = workflow.nodes?.map(workflowsStore.convertTemplateNodeToNodeUi);
|
|
1537
|
+
if (workflow.connections) workflowsStore.setConnections(workflow.connections);
|
|
1538
|
+
await addNodes(convertedNodes ?? []);
|
|
1539
|
+
await workflowState.getNewWorkflowDataAndMakeShareable(name, projectsStore.currentProjectId);
|
|
1540
|
+
workflowsStore.addToWorkflowMetadata({ templateId: `${id}` });
|
|
1541
|
+
}
|
|
1542
|
+
function tryToOpenSubworkflowInNewTab(nodeId) {
|
|
1543
|
+
const node = workflowsStore.getNodeById(nodeId);
|
|
1544
|
+
if (!node) return false;
|
|
1545
|
+
const subWorkflowId = getSubworkflowId(node);
|
|
1546
|
+
if (!subWorkflowId) return false;
|
|
1547
|
+
window.open(`${rootStore.baseUrl}workflow/${subWorkflowId}`, "_blank");
|
|
1548
|
+
return true;
|
|
1549
|
+
}
|
|
1550
|
+
function replaceNode(previousId, newId, { trackHistory = true, trackBulk = true } = {}) {
|
|
1551
|
+
const previousNode = workflowsStore.getNodeById(previousId);
|
|
1552
|
+
const newNode = workflowsStore.getNodeById(newId);
|
|
1553
|
+
if (!previousNode || !newNode) return;
|
|
1554
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
1555
|
+
const [x, y] = previousNode.position;
|
|
1556
|
+
updateNodePosition(newId, {
|
|
1557
|
+
x,
|
|
1558
|
+
y
|
|
1559
|
+
}, { trackHistory });
|
|
1560
|
+
replaceNodeConnections(previousId, newId, {
|
|
1561
|
+
trackBulk: false,
|
|
1562
|
+
trackHistory
|
|
1563
|
+
});
|
|
1564
|
+
deleteNode(previousId, {
|
|
1565
|
+
trackHistory,
|
|
1566
|
+
trackBulk: false
|
|
1567
|
+
});
|
|
1568
|
+
uiStore.stateIsDirty = true;
|
|
1569
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
1570
|
+
}
|
|
1571
|
+
async function addNodesAndConnections(nodes, addedConnections, { trackBulk = true, trackHistory = true,...options }) {
|
|
1572
|
+
if (trackHistory && trackBulk) historyStore.startRecordingUndo();
|
|
1573
|
+
const addedNodes = await addNodes(nodes, {
|
|
1574
|
+
...options,
|
|
1575
|
+
trackHistory,
|
|
1576
|
+
trackBulk: false,
|
|
1577
|
+
telemetry: true
|
|
1578
|
+
});
|
|
1579
|
+
const offsetIndex = editableWorkflow.value.nodes.length - nodes.length;
|
|
1580
|
+
await addConnections(addedConnections.map(({ from, to }) => {
|
|
1581
|
+
const fromNode = editableWorkflow.value.nodes[offsetIndex + from.nodeIndex];
|
|
1582
|
+
const toNode = editableWorkflow.value.nodes[offsetIndex + to.nodeIndex];
|
|
1583
|
+
const type = from.type ?? to.type ?? NodeConnectionTypes.Main;
|
|
1584
|
+
return {
|
|
1585
|
+
source: fromNode.id,
|
|
1586
|
+
sourceHandle: createCanvasConnectionHandleString({
|
|
1587
|
+
mode: CanvasConnectionMode.Output,
|
|
1588
|
+
type: isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main,
|
|
1589
|
+
index: from.outputIndex ?? 0
|
|
1590
|
+
}),
|
|
1591
|
+
target: toNode.id,
|
|
1592
|
+
targetHandle: createCanvasConnectionHandleString({
|
|
1593
|
+
mode: CanvasConnectionMode.Input,
|
|
1594
|
+
type: isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main,
|
|
1595
|
+
index: to.inputIndex ?? 0
|
|
1596
|
+
}),
|
|
1597
|
+
data: {
|
|
1598
|
+
source: {
|
|
1599
|
+
index: from.outputIndex ?? 0,
|
|
1600
|
+
type
|
|
1601
|
+
},
|
|
1602
|
+
target: {
|
|
1603
|
+
index: to.inputIndex ?? 0,
|
|
1604
|
+
type
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
}), {
|
|
1609
|
+
trackHistory,
|
|
1610
|
+
trackBulk: false
|
|
1611
|
+
});
|
|
1612
|
+
uiStore.resetLastInteractedWith();
|
|
1613
|
+
if (addedNodes.length > 0 && options.replaceNodeId) {
|
|
1614
|
+
const lastAddedNodeId = addedNodes[addedNodes.length - 1].id;
|
|
1615
|
+
replaceNode(options.replaceNodeId, lastAddedNodeId, {
|
|
1616
|
+
trackHistory,
|
|
1617
|
+
trackBulk: false
|
|
1618
|
+
});
|
|
1619
|
+
}
|
|
1620
|
+
if (trackHistory && trackBulk) historyStore.stopRecordingUndo();
|
|
1621
|
+
return { addedNodes };
|
|
1622
|
+
}
|
|
1623
|
+
function fitView() {
|
|
1624
|
+
setTimeout(() => canvasEventBus.emit("fitView"));
|
|
1625
|
+
}
|
|
1626
|
+
function trackOpenWorkflowTemplate(templateId) {
|
|
1627
|
+
telemetry.track("User inserted workflow template", {
|
|
1628
|
+
source: "workflow",
|
|
1629
|
+
template_id: tryToParseNumber(templateId),
|
|
1630
|
+
wf_template_repo_session_id: templatesStore.previousSessionId
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
async function openWorkflowTemplate(templateId) {
|
|
1634
|
+
resetWorkspace();
|
|
1635
|
+
canvasStore.startLoading();
|
|
1636
|
+
canvasStore.setLoadingText(i18n.baseText("nodeView.loadingTemplate"));
|
|
1637
|
+
workflowsStore.currentWorkflowExecutions = [];
|
|
1638
|
+
executionsStore.activeExecution = null;
|
|
1639
|
+
let data;
|
|
1640
|
+
try {
|
|
1641
|
+
externalHooks.run("template.requested", { templateId });
|
|
1642
|
+
data = await templatesStore.getFixedWorkflowTemplate(templateId);
|
|
1643
|
+
if (!data) throw new Error(i18n.baseText("nodeView.workflowTemplateWithIdCouldNotBeFound", { interpolate: { templateId } }));
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
toast.showError(error, i18n.baseText("nodeView.couldntImportWorkflow"));
|
|
1646
|
+
await router.replace({ name: VIEWS.NEW_WORKFLOW });
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1649
|
+
trackOpenWorkflowTemplate(templateId);
|
|
1650
|
+
uiStore.isBlankRedirect = true;
|
|
1651
|
+
await router.replace({
|
|
1652
|
+
name: VIEWS.NEW_WORKFLOW,
|
|
1653
|
+
query: { templateId }
|
|
1654
|
+
});
|
|
1655
|
+
await importTemplate({
|
|
1656
|
+
id: templateId,
|
|
1657
|
+
name: data.name,
|
|
1658
|
+
workflow: data.workflow
|
|
1659
|
+
});
|
|
1660
|
+
if (typeof route.params.name === "string") workflowState.setWorkflowId(route.params.name);
|
|
1661
|
+
uiStore.stateIsDirty = true;
|
|
1662
|
+
canvasStore.stopLoading();
|
|
1663
|
+
externalHooks.run("template.open", {
|
|
1664
|
+
templateId,
|
|
1665
|
+
templateName: data.name,
|
|
1666
|
+
workflow: data.workflow
|
|
1667
|
+
});
|
|
1668
|
+
fitView();
|
|
1669
|
+
}
|
|
1670
|
+
async function openWorkflowTemplateFromJSON(workflow) {
|
|
1671
|
+
if (!workflow.nodes || !workflow.connections) {
|
|
1672
|
+
toast.showError(new Error(i18n.baseText("nodeView.couldntLoadWorkflow.invalidWorkflowObject")), i18n.baseText("nodeView.couldntImportWorkflow"));
|
|
1673
|
+
await router.replace({ name: VIEWS.NEW_WORKFLOW });
|
|
1674
|
+
return;
|
|
1675
|
+
}
|
|
1676
|
+
resetWorkspace();
|
|
1677
|
+
canvasStore.startLoading();
|
|
1678
|
+
canvasStore.setLoadingText(i18n.baseText("nodeView.loadingTemplate"));
|
|
1679
|
+
workflowsStore.currentWorkflowExecutions = [];
|
|
1680
|
+
executionsStore.activeExecution = null;
|
|
1681
|
+
uiStore.isBlankRedirect = true;
|
|
1682
|
+
const templateId = workflow.meta.templateId;
|
|
1683
|
+
const parentFolderId = route.query.parentFolderId;
|
|
1684
|
+
await projectsStore.refreshCurrentProject();
|
|
1685
|
+
await fetchAndSetParentFolder(parentFolderId);
|
|
1686
|
+
await router.replace({
|
|
1687
|
+
name: VIEWS.NEW_WORKFLOW,
|
|
1688
|
+
query: {
|
|
1689
|
+
templateId,
|
|
1690
|
+
parentFolderId,
|
|
1691
|
+
projectId: projectsStore.currentProjectId
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
await importTemplate({
|
|
1695
|
+
id: templateId,
|
|
1696
|
+
name: workflow.name,
|
|
1697
|
+
workflow
|
|
1698
|
+
});
|
|
1699
|
+
uiStore.stateIsDirty = true;
|
|
1700
|
+
canvasStore.stopLoading();
|
|
1701
|
+
fitView();
|
|
1702
|
+
}
|
|
1703
|
+
return {
|
|
1704
|
+
lastClickPosition,
|
|
1705
|
+
editableWorkflow,
|
|
1706
|
+
editableWorkflowObject,
|
|
1707
|
+
triggerNodes,
|
|
1708
|
+
requireNodeTypeDescription,
|
|
1709
|
+
addNodes,
|
|
1710
|
+
addNode,
|
|
1711
|
+
resolveNodePosition,
|
|
1712
|
+
revertAddNode,
|
|
1713
|
+
updateNodesPosition,
|
|
1714
|
+
updateNodePosition,
|
|
1715
|
+
tidyUp,
|
|
1716
|
+
revertUpdateNodePosition,
|
|
1717
|
+
setNodeActive,
|
|
1718
|
+
setNodeActiveByName,
|
|
1719
|
+
clearNodeActive,
|
|
1720
|
+
setNodeSelected,
|
|
1721
|
+
toggleNodesDisabled,
|
|
1722
|
+
revertToggleNodeDisabled,
|
|
1723
|
+
toggleNodesPinned,
|
|
1724
|
+
setNodeParameters,
|
|
1725
|
+
renameNode,
|
|
1726
|
+
revertRenameNode,
|
|
1727
|
+
replaceNodeParameters,
|
|
1728
|
+
revertReplaceNodeParameters,
|
|
1729
|
+
deleteNode,
|
|
1730
|
+
deleteNodes,
|
|
1731
|
+
copyNodes,
|
|
1732
|
+
cutNodes,
|
|
1733
|
+
duplicateNodes,
|
|
1734
|
+
getNodesToSave,
|
|
1735
|
+
revertDeleteNode,
|
|
1736
|
+
addConnections,
|
|
1737
|
+
createConnection,
|
|
1738
|
+
revertCreateConnection,
|
|
1739
|
+
deleteConnection,
|
|
1740
|
+
revertDeleteConnection,
|
|
1741
|
+
deleteConnectionsByNodeId,
|
|
1742
|
+
revalidateNodeInputConnections,
|
|
1743
|
+
revalidateNodeOutputConnections,
|
|
1744
|
+
isConnectionAllowed,
|
|
1745
|
+
filterConnectionsByNodes,
|
|
1746
|
+
connectAdjacentNodes,
|
|
1747
|
+
importWorkflowData,
|
|
1748
|
+
fetchWorkflowDataFromUrl,
|
|
1749
|
+
resetWorkspace,
|
|
1750
|
+
initializeWorkspace,
|
|
1751
|
+
resolveNodeWebhook,
|
|
1752
|
+
openExecution,
|
|
1753
|
+
startChat,
|
|
1754
|
+
importTemplate,
|
|
1755
|
+
replaceNodeConnections,
|
|
1756
|
+
tryToOpenSubworkflowInNewTab,
|
|
1757
|
+
initializeUnknownNodes,
|
|
1758
|
+
replaceNode,
|
|
1759
|
+
addNodesAndConnections,
|
|
1760
|
+
fitView,
|
|
1761
|
+
openWorkflowTemplate,
|
|
1762
|
+
openWorkflowTemplateFromJSON
|
|
1763
|
+
};
|
|
1764
|
+
}
|
|
1765
|
+
export { useLogsStore as a, LOCAL_STORAGE_PANEL_WIDTH as c, chatEventBus as d, useExperimentalNdvStore as i, LOGS_PANEL_STATE as l, useParentFolder as n, LOCAL_STORAGE_OVERVIEW_PANEL_WIDTH as o, canvasEventBus as r, LOCAL_STORAGE_PANEL_HEIGHT as s, useCanvasOperations as t, LOG_DETAILS_PANEL_STATE as u };
|