n8n-editor-ui 1.104.0 → 1.105.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.
Files changed (125) hide show
  1. package/dist/assets/{AnimatedSpinner-CIyQ3zKd.js → AnimatedSpinner-CiVjnVTs.js} +1 -1
  2. package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-xv6FYiyR.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-Duv062St.js} +1 -1
  3. package/dist/assets/{AuthView-dJdngoqx.js → AuthView-Dpa-SRT8.js} +2 -2
  4. package/dist/assets/{ChangePasswordView-C74U84q5.js → ChangePasswordView-CB9uaGfm.js} +3 -3
  5. package/dist/assets/CollectionParameter-oBzQ1Hh-.js +4 -0
  6. package/dist/assets/{ConsumedTokensDetails.vue_vue_type_script_setup_true_lang-CkASni2S.js → ConsumedTokensDetails.vue_vue_type_script_setup_true_lang-DIcGPKiM.js} +1 -1
  7. package/dist/assets/{CredentialsView-jouDB3H1.js → CredentialsView-AW9gSm0C.js} +8 -8
  8. package/dist/assets/{DemoFooter-CHlbEpB-.js → DemoFooter-DybJBgCY.js} +6 -9
  9. package/dist/assets/{EmptySharedSectionActionBox.vue_vue_type_script_setup_true_lang-CbDihlsO.js → EmptySharedSectionActionBox.vue_vue_type_script_setup_true_lang-GcMQ_YdZ.js} +1 -1
  10. package/dist/assets/{EntityNotFound-Dtqj9thX.js → EntityNotFound-Bi2pl54e.js} +1 -1
  11. package/dist/assets/{EntityUnAuthorised-BBsbc6du.js → EntityUnAuthorised-HDf2HNt2.js} +1 -1
  12. package/dist/assets/{ErrorView-BN4Jm32q.js → ErrorView-BPodDJdx.js} +1 -1
  13. package/dist/assets/{EvaluationsRootView-B70WfmnQ.js → EvaluationsRootView-pO4cP-Fb.js} +1 -1
  14. package/dist/assets/{EvaluationsView-DQd7op3j.js → EvaluationsView-CI108a8E.js} +3 -3
  15. package/dist/assets/{ExecutionsTime-Bo7IOE5K.css → ExecutionsTime-etWexlXm.css} +6 -6
  16. package/dist/assets/{ExecutionsTime.vue_vue_type_script_setup_true_lang-C_2brmCr.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-CGxPzqoO.js} +23 -30
  17. package/dist/assets/{ExecutionsView-CKPZTnZV.js → ExecutionsView-BaQKVP7R.js} +8 -9
  18. package/dist/assets/{FixedCollectionParameter-CA-CigeR.js → FixedCollectionParameter-BpCwKUsj.js} +1 -1
  19. package/dist/assets/{ForgotMyPasswordView-YyVmo-nw.js → ForgotMyPasswordView-CPC4cOzo.js} +3 -3
  20. package/dist/assets/{InfoAccordion-BNmUe2V9.js → InfoAccordion-M_n3OwQC.js} +1 -1
  21. package/dist/assets/{InsightsChartAverageRuntime-C9sCNhzD.js → InsightsChartAverageRuntime-CECRGvo9.js} +4 -4
  22. package/dist/assets/{InsightsChartFailed-DWA6YbZj.js → InsightsChartFailed-CTysIk94.js} +4 -4
  23. package/dist/assets/{InsightsChartFailureRate-CfknGtrr.js → InsightsChartFailureRate-LYCt3dgO.js} +4 -4
  24. package/dist/assets/{InsightsChartTimeSaved-DtLO9DJx.js → InsightsChartTimeSaved-msRVtM_g.js} +4 -4
  25. package/dist/assets/{InsightsChartTotal-yX_QJ-44.js → InsightsChartTotal-B_SUDPoP.js} +4 -4
  26. package/dist/assets/{InsightsDashboard-BlYvn96O.js → InsightsDashboard-CEgagMwD.js} +10 -10
  27. package/dist/assets/{InsightsPaywall-BCfIY_xn.js → InsightsPaywall-EnxDs7BF.js} +1 -1
  28. package/dist/assets/{InsightsSummary-OiO7efWD.js → InsightsSummary-DWzNYCfc.js} +1 -1
  29. package/dist/assets/{InsightsTableWorkflows-pTl3m7wx.js → InsightsTableWorkflows-Dl55NtXk.js} +5 -5
  30. package/dist/assets/{Logo-8g4P9vyv.js → Logo-MNn4rP0b.js} +1 -1
  31. package/dist/assets/{LogsPanel-D0xdq4fV.css → LogsPanel-B-Tmod-K.css} +25 -22
  32. package/dist/assets/{LogsPanel-so01MtIR.js → LogsPanel-DN3BXSh7.js} +209 -51
  33. package/dist/assets/{MainHeader-CcUlKfHC.js → MainHeader-F9ONi2FH.js} +8 -10
  34. package/dist/assets/{MainSidebar-DOGhP_oY.js → MainSidebar-Bf58ZTkX.js} +2 -3
  35. package/dist/assets/{N8nDataTableServer-9HerjyzX.js → N8nDataTableServer-PFDwZhpw.js} +1 -1
  36. package/dist/assets/{NodeCreation-CVbCKnet.js → NodeCreation-B9FRFHG0.js} +16 -13
  37. package/dist/assets/{NodeCreator-BOosPF8_.js → NodeCreator-nBzvpVJI.js} +11 -20
  38. package/dist/assets/{NodeDetailsView-KFidngJi.js → NodeDetailsView-CQQOZQXq.js} +13 -17
  39. package/dist/assets/{NodeDetailsViewV2-BL4KKqW-.js → NodeDetailsViewV2-DKnduvJH.js} +27 -31
  40. package/dist/assets/{NodeDetailsViewV2-BxNx4ZUM.css → NodeDetailsViewV2-LLVofUjw.css} +21 -19
  41. package/dist/assets/NodeView-B2097MY0.css +852 -0
  42. package/dist/assets/NodeView-rsVaGRIZ.js +2684 -0
  43. package/dist/assets/{ProjectHeader-B9-GdGvC.js → ProjectHeader-B8m2WaGw.js} +2 -2
  44. package/dist/assets/{ProjectSettings-CE4_geFa.js → ProjectSettings-CKIJ3B4S.js} +3 -3
  45. package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-Bb8zUJvi.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-D5oQ44UZ.js} +1 -1
  46. package/dist/assets/{ResourcesListLayout-ClTEnqVS.js → ResourcesListLayout-G2r5AxKI.js} +3 -3
  47. package/dist/assets/{RunDataJson-fXQKTIFD.js → RunDataJson-CAcnDJHh.js} +3 -6
  48. package/dist/assets/{RunDataJsonActions-CMP1sUPZ.js → RunDataJsonActions-jhh18-uN.js} +13 -13
  49. package/dist/assets/{RunDataParsedAiContent-CHK6Y4ET.js → RunDataParsedAiContent-B8wa1hGI.js} +25 -11
  50. package/dist/assets/{RunDataSearch-CAZGWZzz.js → RunDataSearch-CFmNTJ3I.js} +1 -1
  51. package/dist/assets/{RunDataTable-CeqmA-n3.js → RunDataTable-91h3y7DT.js} +1 -2
  52. package/dist/assets/{SamlOnboarding-BrdzPMSK.js → SamlOnboarding-8Gb7hf0c.js} +3 -3
  53. package/dist/assets/{SettingsApiView-Cj2YYKAl.js → SettingsApiView-BozlwAdS.js} +1 -1
  54. package/dist/assets/{SettingsCommunityNodesView-ChB--kZD.js → SettingsCommunityNodesView-RlNbis18.js} +4 -4
  55. package/dist/assets/{SettingsExternalSecrets-BjghCvkE.js → SettingsExternalSecrets-Blou_9Mh.js} +1 -1
  56. package/dist/assets/{SettingsLdapView-DIB1-nTk.js → SettingsLdapView-wf-fX_Jl.js} +1 -1
  57. package/dist/assets/{SettingsLogStreamingView-BOOGkcwK.js → SettingsLogStreamingView-DNaMOOjb.js} +1 -1
  58. package/dist/assets/{SettingsPersonalView-DaNZTNUy.js → SettingsPersonalView-DzYhwUgL.js} +1 -1
  59. package/dist/assets/{SettingsSourceControl-B5fQRT0V.js → SettingsSourceControl-D5eiGsMG.js} +1 -1
  60. package/dist/assets/{SettingsSso-CWX-T13W.js → SettingsSso-BF8vNEd4.js} +7 -12
  61. package/dist/assets/{SettingsUsageAndPlan-Cnnf9k6X.js → SettingsUsageAndPlan-Di_gUxTt.js} +1 -1
  62. package/dist/assets/{SettingsUsersView-BLDi4lpv.js → SettingsUsersView-BDNxV1rM.js} +2 -3
  63. package/dist/assets/{SettingsView-Dtc8MEv6.js → SettingsView-CAaXgrDd.js} +1 -1
  64. package/dist/assets/{SetupView-C4C-2Idz.js → SetupView-DIO89PJN.js} +3 -3
  65. package/dist/assets/{SetupWorkflowCredentialsButton-Pzrxag-k.js → SetupWorkflowCredentialsButton-y92onTNS.js} +1 -1
  66. package/dist/assets/{SetupWorkflowFromTemplateView-CRsZDYct.js → SetupWorkflowFromTemplateView-Hnqry6sO.js} +3 -3
  67. package/dist/assets/{SigninView-COyoSAUi.js → SigninView-t0q2CjNU.js} +3 -3
  68. package/dist/assets/{SignoutView-B0t9kc5s.js → SignoutView-DjCS-jDi.js} +1 -1
  69. package/dist/assets/{SignupView-BN8MCOnb.js → SignupView-BoEH4AVN.js} +3 -3
  70. package/dist/assets/{TableBase-BmhIwPwZ.js → TableBase-D-1VfIgb.js} +1 -1
  71. package/dist/assets/{Tags-DeTgaVsD.js → Tags-CnT3a0bf.js} +1 -1
  72. package/dist/assets/{TemplateDetails-Bh-WSvQ-.js → TemplateDetails-B-tHb3Wq.js} +4 -4
  73. package/dist/assets/{TemplateList-DxvJMjPE.js → TemplateList-j7v4XLCo.js} +3 -3
  74. package/dist/assets/{TemplatesCollectionView-BhilAS_8.js → TemplatesCollectionView-BPxSoEA5.js} +6 -6
  75. package/dist/assets/{TemplatesSearchView-CWxnTQ8Z.js → TemplatesSearchView-kZfygKcP.js} +3 -3
  76. package/dist/assets/{TemplatesView-Co-FQLhr.js → TemplatesView-KQ5r6RZF.js} +2 -2
  77. package/dist/assets/{TemplatesWorkflowView-DAWgsT0T.js → TemplatesWorkflowView-Pdm_DUrH.js} +6 -6
  78. package/dist/assets/{TriggerPanel-JaXhe1VW.js → TriggerPanel-WYRtg2P1.js} +39 -29
  79. package/dist/assets/{TriggerPanel-DJv04feX.css → TriggerPanel-gMtmEr6n.css} +16 -13
  80. package/dist/assets/{VariablesView-JnfEn1f-.js → VariablesView-CdihBrCp.js} +5 -5
  81. package/dist/assets/{VueMarkdown-DDKnTMgT.js → VueMarkdown-CLlUve9b.js} +1 -1
  82. package/dist/assets/{WorkerView-DZG4C_Qp.js → WorkerView-C_q2Cgtl.js} +6 -6
  83. package/dist/assets/{WorkflowActivator-C8hP37n7.js → WorkflowActivator-CDlyaU2W.js} +2 -2
  84. package/dist/assets/{WorkflowExecutionsInfoAccordion-DCNvkxhh.js → WorkflowExecutionsInfoAccordion-1aoYaoWj.js} +2 -2
  85. package/dist/assets/{WorkflowExecutionsLandingPage-DVp6SoPy.js → WorkflowExecutionsLandingPage-Cuz4EdsV.js} +3 -3
  86. package/dist/assets/{WorkflowExecutionsPreview-CKYWZWv1.js → WorkflowExecutionsPreview-BmDk9pdW.js} +7 -6
  87. package/dist/assets/{WorkflowExecutionsView-BIkweP3p.js → WorkflowExecutionsView-ClPpGdce.js} +6 -8
  88. package/dist/assets/{WorkflowHistory-C0LrWJW0.js → WorkflowHistory-EoRsFrnu.js} +2 -3
  89. package/dist/assets/{WorkflowOnboardingView-CWMUgnLK.js → WorkflowOnboardingView-B4DUomvQ.js} +1 -1
  90. package/dist/assets/{WorkflowPreview-DmYMBSH3.js → WorkflowPreview-dQweS-xu.js} +1 -1
  91. package/dist/assets/{WorkflowsView-jEphnf90.js → WorkflowsView-DQJRBDtq.js} +275 -30
  92. package/dist/assets/{WorkflowsView-CyJbJBc8.css → WorkflowsView-DsJIOJ7h.css} +263 -0
  93. package/dist/assets/{aiTemplatesStarterCollection.store-oECEA5nR.js → aiTemplatesStarterCollection.store-CTW_MDA8.js} +3 -2
  94. package/dist/assets/canvas-CMXo2Bja.js +5 -0
  95. package/dist/assets/{chartjs.utils-CP28DnUQ.js → chartjs.utils-CHvsojzm.js} +2 -2
  96. package/dist/assets/{en-BX7CKkqE.js → en-D7cJPQEa.js} +22 -2
  97. package/dist/assets/{global-link-actions-BjpAG7gt.js → global-link-actions-BxO50hoE.js} +1 -1
  98. package/dist/assets/{index-BWpYwmXd.css → index-BwGKZdwg.css} +15180 -4281
  99. package/dist/assets/{index-Cm5yBbby.js → index-DycvFkIw.js} +62283 -30324
  100. package/dist/assets/{index-CjbtyS1n.js → index-T1FYm0tg.js} +1 -1
  101. package/dist/assets/{pickBy-DA-1tKxT.js → pickBy-DMiUcEKW.js} +1 -1
  102. package/dist/assets/{polyfills-B8p9DdqU.js → polyfills-eMEFRc79.js} +0 -32
  103. package/dist/assets/{templateActions-D9IAsJ2m.js → templateActions-DrHAzjmQ.js} +1 -1
  104. package/dist/assets/{useBeforeUnload-BR-V9Uaz.js → useBeforeUnload-uDmDsya_.js} +1 -1
  105. package/dist/assets/{useExecutionDebugging-C8zR-uFJ.js → useExecutionDebugging-wqUkD23F.js} +1 -1
  106. package/dist/assets/{useImportCurlCommand-B3-fEq8S.js → useImportCurlCommand-CBZG4Lbx.js} +1 -2
  107. package/dist/assets/{useProjectPages-qXIMd_UF.js → useProjectPages-CW2fEpJH.js} +1 -1
  108. package/dist/assets/{usePushConnection-Duvg6z8O.js → usePushConnection-BM5QyJob.js} +3 -3
  109. package/dist/assets/{useWorkflowActivate-BE4Ckf9k.js → useWorkflowActivate-Dw_VspVF.js} +1 -1
  110. package/dist/index.html +5 -5
  111. package/dist/static/posthog.init.js +41 -0
  112. package/dist/static/prefers-color-scheme.css +5 -0
  113. package/index.html +2 -2
  114. package/package.json +1 -1
  115. package/tsconfig.json +1 -0
  116. package/dist/assets/ActionDropdown-BmC0wfMx.css +0 -172
  117. package/dist/assets/ActionDropdown-Ct6XJ0cl.js +0 -172
  118. package/dist/assets/CollectionParameter-DCn5Jtcj.js +0 -4
  119. package/dist/assets/FileSaver.min-BvxTURBB.js +0 -81
  120. package/dist/assets/NodeView-BzC6ELga.js +0 -18815
  121. package/dist/assets/NodeView-G2qfXaOy.css +0 -7402
  122. package/dist/assets/import-curl-BD22LJ4z.js +0 -5
  123. package/dist/assets/useExecutionHelpers-DQcWcZ8o.js +0 -94
  124. package/dist/assets/useKeybindings-2A271Jke.css +0 -2007
  125. package/dist/assets/useKeybindings-DetzdpXy.js +0 -3627
@@ -0,0 +1,2684 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/NodeCreation-B9FRFHG0.js","assets/index-DycvFkIw.js","assets/index-BwGKZdwg.css","assets/NodeCreation-CxN6JIS_.css","assets/NodeDetailsView-CQQOZQXq.js","assets/TriggerPanel-WYRtg2P1.js","assets/RunDataParsedAiContent-B8wa1hGI.js","assets/VueMarkdown-CLlUve9b.js","assets/RunDataParsedAiContent-wfIiKsq7.css","assets/ConsumedTokensDetails.vue_vue_type_script_setup_true_lang-DIcGPKiM.js","assets/InfoAccordion-M_n3OwQC.js","assets/InfoAccordion-dxudNqVC.css","assets/TriggerPanel-gMtmEr6n.css","assets/useWorkflowActivate-Dw_VspVF.js","assets/global-link-actions-BxO50hoE.js","assets/useExecutionDebugging-wqUkD23F.js","assets/useBeforeUnload-uDmDsya_.js","assets/canvas-CMXo2Bja.js","assets/aiTemplatesStarterCollection.store-CTW_MDA8.js","assets/NodeDetailsView-CaTI-1QQ.css","assets/NodeDetailsViewV2-DKnduvJH.js","assets/NodeDetailsViewV2-LLVofUjw.css","assets/SetupWorkflowCredentialsButton-y92onTNS.js"])))=>i.map(i=>d[i]);
2
+ import { d as defineComponent, x as computed, r as ref, aP as useNDVStore, ab as watch, h as createElementBlock, g as openBlock, n as normalizeClass, e as createBlock, f as createCommentVNode, l as unref, p as N8nText, w as withCtx, k as createTextVNode, t as toDisplayString, cs as _sfc_main$9, i as createVNode, a0 as _sfc_main$a, _ as _export_sfc, Q as createEventBus, ac as useCssModule, v as useSettingsStore, ct as useVueFlow, bW as toRef, cu as useCanvasMapping, cv as refThrottled, j as createBaseVNode, J as renderSlot, cw as Canvas, D as mergeProps, a5 as useWorkflowsStore, bF as useNodeHelpers, cx as useFocusPanelStore, bK as useNodeTypesStore, cy as useNodeSettingsParameters, cz as useEnvironmentsStore, cA as useDeviceSupport, S as useDebounce, cB as HTML_NODE_TYPE, cC as isValueExpression, cD as isResourceLocatorValue, cE as AI_TRANSFORM_NODE_TYPE, cF as useResolvedExpression, cf as useThrottleFn, bS as withModifiers, cG as _sfc_main$b, N as N8nIcon, cH as InfoTip, c as useI18n, cI as __unplugin_components_2, cJ as __unplugin_components_3, F as Fragment, cK as __unplugin_components_4, cL as __unplugin_components_5, cM as __unplugin_components_6, cN as __unplugin_components_7, cO as __unplugin_components_8, cP as __unplugin_components_9, cQ as N8nInput, H as N8nRadioButtons, P as normalizeStyle, cd as useStyles, cc as N8nResizeWrapper, cR as getParameterTypeOption, cS as htmlEditorEventBus, cT as parseFromExpression, cU as isValidParameterOption, cV as formatAsExpression, aA as useTelemetry, K as nextTick, cW as hasFocusOnInput, cX as isFocusableEl, br as isChatNode, cY as truncateBeforeLast, q as N8nButton, a1 as I18nT, cb as KeyboardShortcutTooltip, bT as NodeIcon, ay as N8nActionDropdown, cZ as reactive, o as onMounted, c2 as onUnmounted, b as useRouter, a6 as useRoute, a as useToast, aj as useDocumentTitle, al as useWorkflowHelpers, ak as useWorkflowSaving, T as useUIStore, af as useSourceControlStore, c_ as useNodeCreatorStore, c$ as useCredentialsStore, d0 as useExternalSecretsStore, ad as useRootStore, aQ as useExecutionsStore, ae as useCanvasStore, ai as useNpsSurveyStore, d1 as useHistoryStore, ag as useProjectsStore, u as useUsersStore, R as useTagsStore, a4 as usePushConnectionStore, be as useTemplatesStore, d2 as useBuilderStore, ah as useFoldersStore, d3 as usePostHog, d4 as useAgentRequestStore, bE as useLogsStore, bG as useRunWorkflow, bJ as useCanvasOperations, d5 as useWorkflowExtraction, c5 as useClipboard, a7 as PLACEHOLDER_EMPTY_WORKFLOW_ID, d6 as NEW_WORKFLOW_ID, V as VIEWS, d7 as NDV_UI_OVERHAUL_EXPERIMENT, bL as START_NODE_TYPE, d8 as getNodeViewTab, G as MAIN_HEADER_TABS, d9 as VALID_WORKFLOW_IMPORT_URL_REGEX, aC as useMessage, aD as MODAL_CONFIRM, da as jsonParse, an as getResourcePermissions, bB as CHAT_TRIGGER_NODE_TYPE, bA as MANUAL_CHAT_TRIGGER_NODE_TYPE, db as EVALUATION_TRIGGER_NODE_TYPE, dc as getBounds, dd as onBeforeRouteLeave, aU as onBeforeMount, aE as WORKFLOW_SETTINGS_MODAL_KEY, bg as useExternalHooks, de as onActivated, df as onDeactivated, I as onBeforeUnmount, dg as Suspense, dh as defineAsyncComponent, di as N8nCallout, aL as __vitePreload, aq as EnterpriseEditionFeature, dj as NODE_CREATOR_OPEN_SOURCES, dk as EVALUATION_NODE_TYPE, dl as getEasyAiWorkflowJson, dm as getRagStarterWorkflowJson, dn as tryToParseNumber, aB as nodeViewEventBus, bs as NodeConnectionTypes, dp as createCanvasConnectionHandleString, dq as isValidNodeConnectionType, dr as CanvasConnectionMode, b4 as sourceControlEventBus, ds as getNodesWithNormalizedPosition, aN as h, dt as CanvasNodeRenderType, aT as STICKY_NODE_TYPE, du as needsAgentInput, dv as FROM_AI_PARAMETERS_MODAL_KEY, dw as historyBus, dx as DRAG_EVENT_DATA_KEY } from "./index-DycvFkIw.js";
3
+ import { g as globalLinkActionsEventBus } from "./global-link-actions-BxO50hoE.js";
4
+ import { u as useExecutionDebugging } from "./useExecutionDebugging-wqUkD23F.js";
5
+ import { u as useBeforeUnload } from "./useBeforeUnload-uDmDsya_.js";
6
+ import { c as canvasEventBus } from "./canvas-CMXo2Bja.js";
7
+ import { u as useAITemplatesStarterCollectionStore } from "./aiTemplatesStarterCollection.store-CTW_MDA8.js";
8
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
9
+ __name: "ExperimentalNodeDetailsDrawer",
10
+ props: {
11
+ selectedNodes: {}
12
+ },
13
+ setup(__props) {
14
+ const content2 = computed(
15
+ () => __props.selectedNodes.length > 1 ? `${__props.selectedNodes.length} nodes selected` : __props.selectedNodes.length > 0 ? __props.selectedNodes[0] : void 0
16
+ );
17
+ const lastContent = ref();
18
+ const { setActiveNodeName } = useNDVStore();
19
+ function handleOpenNdv() {
20
+ if (typeof content2.value === "object" && content2.value.data) {
21
+ setActiveNodeName(content2.value.data.name);
22
+ }
23
+ }
24
+ watch(
25
+ content2,
26
+ (newContent) => {
27
+ if (newContent !== void 0) {
28
+ lastContent.value = newContent;
29
+ }
30
+ },
31
+ { immediate: true }
32
+ );
33
+ return (_ctx, _cache) => {
34
+ const _component_N8nIconButton = _sfc_main$a;
35
+ return openBlock(), createElementBlock("div", {
36
+ class: normalizeClass([_ctx.$style.component, content2.value === void 0 ? _ctx.$style.closed : ""])
37
+ }, [
38
+ typeof lastContent.value === "string" ? (openBlock(), createBlock(unref(N8nText), {
39
+ key: 0,
40
+ color: "text-base"
41
+ }, {
42
+ default: withCtx(() => [
43
+ createTextVNode(toDisplayString(lastContent.value), 1)
44
+ ]),
45
+ _: 1
46
+ })) : lastContent.value !== void 0 ? (openBlock(), createBlock(_sfc_main$9, {
47
+ key: lastContent.value.id,
48
+ "node-id": lastContent.value.id
49
+ }, {
50
+ actions: withCtx(() => [
51
+ createVNode(_component_N8nIconButton, {
52
+ icon: "maximize-2",
53
+ type: "secondary",
54
+ text: "",
55
+ size: "mini",
56
+ "icon-size": "large",
57
+ "aria-label": "Expand",
58
+ onClick: handleOpenNdv
59
+ })
60
+ ]),
61
+ _: 1
62
+ }, 8, ["node-id"])) : createCommentVNode("", true)
63
+ ], 2);
64
+ };
65
+ }
66
+ });
67
+ const component$1 = "_component_wojby_123";
68
+ const closed = "_closed_wojby_138";
69
+ const style0$4 = {
70
+ component: component$1,
71
+ closed
72
+ };
73
+ const cssModules$4 = {
74
+ "$style": style0$4
75
+ };
76
+ const ExperimentalNodeDetailsDrawer = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__cssModules", cssModules$4]]);
77
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
78
+ ...{
79
+ inheritAttrs: false
80
+ },
81
+ __name: "WorkflowCanvas",
82
+ props: {
83
+ id: { default: "canvas" },
84
+ workflow: {},
85
+ workflowObject: {},
86
+ fallbackNodes: { default: () => [] },
87
+ showFallbackNodes: { type: Boolean, default: true },
88
+ eventBus: { default: () => createEventBus() },
89
+ readOnly: { type: Boolean },
90
+ executing: { type: Boolean }
91
+ },
92
+ setup(__props) {
93
+ const props = __props;
94
+ const $style = useCssModule();
95
+ const settingsStore = useSettingsStore();
96
+ const { onNodesInitialized, getSelectedNodes } = useVueFlow(props.id);
97
+ const workflow = toRef(props, "workflow");
98
+ const workflowObject = toRef(props, "workflowObject");
99
+ const nodes = computed(() => {
100
+ return props.showFallbackNodes ? [...props.workflow.nodes, ...props.fallbackNodes] : props.workflow.nodes;
101
+ });
102
+ const connections = computed(() => props.workflow.connections);
103
+ const { nodes: mappedNodes, connections: mappedConnections } = useCanvasMapping({
104
+ nodes,
105
+ connections,
106
+ workflowObject
107
+ });
108
+ const initialFitViewDone = ref(false);
109
+ onNodesInitialized(() => {
110
+ if (!initialFitViewDone.value || props.showFallbackNodes) {
111
+ props.eventBus.emit("fitView");
112
+ initialFitViewDone.value = true;
113
+ }
114
+ });
115
+ const mappedNodesThrottled = refThrottled(mappedNodes, 200);
116
+ const mappedConnectionsThrottled = refThrottled(mappedConnections, 200);
117
+ return (_ctx, _cache) => {
118
+ return openBlock(), createElementBlock("div", {
119
+ class: normalizeClass(unref($style).wrapper),
120
+ "data-test-id": "canvas-wrapper"
121
+ }, [
122
+ createBaseVNode("div", {
123
+ class: normalizeClass(unref($style).canvas)
124
+ }, [
125
+ workflow.value ? (openBlock(), createBlock(Canvas, mergeProps({
126
+ key: 0,
127
+ id: _ctx.id,
128
+ nodes: _ctx.executing ? unref(mappedNodesThrottled) : unref(mappedNodes),
129
+ connections: _ctx.executing ? unref(mappedConnectionsThrottled) : unref(mappedConnections),
130
+ "event-bus": _ctx.eventBus,
131
+ "read-only": _ctx.readOnly,
132
+ executing: _ctx.executing
133
+ }, _ctx.$attrs), null, 16, ["id", "nodes", "connections", "event-bus", "read-only", "executing"])) : createCommentVNode("", true)
134
+ ], 2),
135
+ renderSlot(_ctx.$slots, "default"),
136
+ unref(settingsStore).experimental__dockedNodeSettingsEnabled && !props.readOnly ? (openBlock(), createBlock(ExperimentalNodeDetailsDrawer, {
137
+ key: 0,
138
+ "selected-nodes": unref(getSelectedNodes)
139
+ }, null, 8, ["selected-nodes"])) : createCommentVNode("", true)
140
+ ], 2);
141
+ };
142
+ }
143
+ });
144
+ const wrapper$2 = "_wrapper_jyurh_123";
145
+ const canvas = "_canvas_jyurh_131";
146
+ const style0$3 = {
147
+ wrapper: wrapper$2,
148
+ canvas
149
+ };
150
+ const cssModules$3 = {
151
+ "$style": style0$3
152
+ };
153
+ const WorkflowCanvas = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__cssModules", cssModules$3]]);
154
+ function useExecutionData({ node }) {
155
+ const workflowsStore = useWorkflowsStore();
156
+ const workflowExecution = computed(() => {
157
+ return workflowsStore.getWorkflowExecution;
158
+ });
159
+ const workflowRunData = computed(() => {
160
+ if (workflowExecution.value === null) {
161
+ return null;
162
+ }
163
+ const executionData = workflowExecution.value.data;
164
+ if (!executionData?.resultData?.runData) {
165
+ return null;
166
+ }
167
+ return executionData.resultData.runData;
168
+ });
169
+ const hasNodeRun = computed(() => {
170
+ if (workflowsStore.subWorkflowExecutionError) return true;
171
+ return Boolean(
172
+ node.value && workflowRunData.value && Object.prototype.hasOwnProperty.bind(workflowRunData.value)(node.value.name)
173
+ );
174
+ });
175
+ return {
176
+ workflowExecution,
177
+ workflowRunData,
178
+ hasNodeRun
179
+ };
180
+ }
181
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
182
+ ...{ name: "FocusPanel" },
183
+ __name: "FocusPanel",
184
+ props: {
185
+ isCanvasReadOnly: { type: Boolean }
186
+ },
187
+ emits: ["focus", "saveKeyboardShortcut"],
188
+ setup(__props, { emit: __emit }) {
189
+ const props = __props;
190
+ const emit = __emit;
191
+ const inputField = ref();
192
+ const locale = useI18n();
193
+ const nodeHelpers = useNodeHelpers();
194
+ const focusPanelStore = useFocusPanelStore();
195
+ const workflowsStore = useWorkflowsStore();
196
+ const nodeTypesStore = useNodeTypesStore();
197
+ const telemetry = useTelemetry();
198
+ const nodeSettingsParameters = useNodeSettingsParameters();
199
+ const environmentsStore = useEnvironmentsStore();
200
+ const deviceSupport = useDeviceSupport();
201
+ const { debounce } = useDebounce();
202
+ const styles = useStyles();
203
+ const focusedNodeParameter = computed(() => focusPanelStore.focusedNodeParameters[0]);
204
+ const resolvedParameter = computed(
205
+ () => focusedNodeParameter.value && focusPanelStore.isRichParameter(focusedNodeParameter.value) ? focusedNodeParameter.value : void 0
206
+ );
207
+ const focusPanelActive = computed(() => focusPanelStore.focusPanelActive);
208
+ const focusPanelWidth = computed(() => focusPanelStore.focusPanelWidth);
209
+ const isDisabled = computed(() => {
210
+ if (!resolvedParameter.value) return false;
211
+ return !!resolvedParameter.value.parameter.disabledOptions && nodeSettingsParameters.shouldDisplayNodeParameter(
212
+ resolvedParameter.value.node.parameters,
213
+ resolvedParameter.value.node,
214
+ resolvedParameter.value.parameter,
215
+ resolvedParameter.value.parameterPath.split(".").slice(1, -1).join("."),
216
+ "disabledOptions"
217
+ );
218
+ });
219
+ const isDisplayed = computed(() => {
220
+ if (!resolvedParameter.value) return true;
221
+ return nodeSettingsParameters.shouldDisplayNodeParameter(
222
+ resolvedParameter.value.node.parameters,
223
+ resolvedParameter.value.node,
224
+ resolvedParameter.value.parameter,
225
+ resolvedParameter.value.parameterPath.split(".").slice(1, -1).join("."),
226
+ "displayOptions"
227
+ );
228
+ });
229
+ const isExecutable = computed(() => {
230
+ if (!resolvedParameter.value) return false;
231
+ if (!isDisplayed.value) return false;
232
+ const foreignCredentials = nodeHelpers.getForeignCredentialsIfSharingEnabled(
233
+ resolvedParameter.value.node.credentials
234
+ );
235
+ return nodeHelpers.isNodeExecutable(
236
+ resolvedParameter.value.node,
237
+ !props.isCanvasReadOnly,
238
+ foreignCredentials
239
+ );
240
+ });
241
+ const node = computed(() => resolvedParameter.value?.node);
242
+ const { workflowRunData } = useExecutionData({ node });
243
+ const hasNodeRun = computed(() => {
244
+ if (!node.value) return true;
245
+ const parentNode = workflowsStore.getCurrentWorkflow().getParentNodes(node.value.name, "main", 1)[0];
246
+ return Boolean(
247
+ parentNode && workflowRunData.value && Object.prototype.hasOwnProperty.bind(workflowRunData.value)(parentNode)
248
+ );
249
+ });
250
+ function getTypeOption(optionName) {
251
+ return resolvedParameter.value ? getParameterTypeOption(resolvedParameter.value.parameter, optionName) : void 0;
252
+ }
253
+ const codeEditorMode = computed(() => {
254
+ return resolvedParameter.value?.node.parameters.mode;
255
+ });
256
+ const editorType = computed(() => {
257
+ return getTypeOption("editor") ?? void 0;
258
+ });
259
+ const editorLanguage = computed(() => {
260
+ if (editorType.value === "json" || resolvedParameter.value?.parameter.type === "json")
261
+ return "json";
262
+ return getTypeOption("editorLanguage") ?? "javaScript";
263
+ });
264
+ const editorRows = computed(() => getTypeOption("rows"));
265
+ const isToolNode = computed(
266
+ () => resolvedParameter.value ? nodeTypesStore.isToolNode(resolvedParameter.value?.node.type) : false
267
+ );
268
+ const isHtmlNode = computed(
269
+ () => !!resolvedParameter.value && resolvedParameter.value.node.type === HTML_NODE_TYPE
270
+ );
271
+ const expressionModeEnabled = computed(
272
+ () => resolvedParameter.value && isValueExpression(resolvedParameter.value.parameter, resolvedParameter.value.value)
273
+ );
274
+ const expression = computed(() => {
275
+ if (!expressionModeEnabled.value) return "";
276
+ return isResourceLocatorValue(resolvedParameter.value) ? resolvedParameter.value.value : resolvedParameter.value;
277
+ });
278
+ const shouldCaptureForPosthog = computed(
279
+ () => resolvedParameter.value?.node.type === AI_TRANSFORM_NODE_TYPE
280
+ );
281
+ const isReadOnly = computed(() => props.isCanvasReadOnly || isDisabled.value);
282
+ const resolvedAdditionalExpressionData = computed(() => {
283
+ return {
284
+ $vars: environmentsStore.variablesAsObject
285
+ };
286
+ });
287
+ const targetNodeParameterContext = computed(() => {
288
+ if (!resolvedParameter.value) return void 0;
289
+ return {
290
+ nodeName: resolvedParameter.value.node.name,
291
+ parameterPath: resolvedParameter.value.parameterPath
292
+ };
293
+ });
294
+ const isNodeExecuting = computed(() => workflowsStore.isNodeExecuting(node.value?.name ?? ""));
295
+ const { resolvedExpression } = useResolvedExpression({
296
+ expression,
297
+ additionalData: resolvedAdditionalExpressionData,
298
+ stringifyObject: resolvedParameter.value && resolvedParameter.value.parameter.type !== "multiOptions"
299
+ });
300
+ function valueChanged(value) {
301
+ if (resolvedParameter.value === void 0) {
302
+ return;
303
+ }
304
+ nodeSettingsParameters.updateNodeParameter(
305
+ toRef(resolvedParameter.value.node.parameters),
306
+ { value, name: resolvedParameter.value.parameterPath },
307
+ value,
308
+ resolvedParameter.value.node,
309
+ isToolNode.value
310
+ );
311
+ }
312
+ async function setFocus() {
313
+ await nextTick();
314
+ if (inputField.value) {
315
+ if (hasFocusOnInput(inputField.value)) {
316
+ inputField.value.focusOnInput();
317
+ } else if (isFocusableEl(inputField.value)) {
318
+ inputField.value.focus();
319
+ }
320
+ }
321
+ emit("focus");
322
+ }
323
+ function optionSelected(command) {
324
+ if (!resolvedParameter.value) return;
325
+ switch (command) {
326
+ case "resetValue": {
327
+ if (typeof resolvedParameter.value.parameter.default === "string") {
328
+ valueChanged(resolvedParameter.value.parameter.default);
329
+ }
330
+ void setFocus();
331
+ break;
332
+ }
333
+ case "addExpression": {
334
+ const newValue = formatAsExpression(
335
+ resolvedParameter.value.value,
336
+ resolvedParameter.value.parameter.type
337
+ );
338
+ valueChanged(typeof newValue === "string" ? newValue : newValue.value);
339
+ void setFocus();
340
+ break;
341
+ }
342
+ case "removeExpression": {
343
+ const newValue = parseFromExpression(
344
+ resolvedParameter.value.value,
345
+ resolvedExpression.value,
346
+ resolvedParameter.value.parameter.type,
347
+ resolvedParameter.value.parameter.default,
348
+ (resolvedParameter.value.parameter.options ?? []).filter(isValidParameterOption)
349
+ );
350
+ if (typeof newValue === "string") {
351
+ valueChanged(newValue);
352
+ } else if (newValue && typeof newValue.value === "string") {
353
+ valueChanged(newValue.value);
354
+ }
355
+ void setFocus();
356
+ break;
357
+ }
358
+ case "formatHtml":
359
+ htmlEditorEventBus.emit("format-html");
360
+ break;
361
+ }
362
+ }
363
+ function closeFocusPanel() {
364
+ telemetry.track("User closed focus panel", {
365
+ source: "closeIcon",
366
+ parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat
367
+ });
368
+ focusPanelStore.closeFocusPanel();
369
+ }
370
+ function onExecute() {
371
+ telemetry.track(
372
+ "User executed node from focus panel",
373
+ focusPanelStore.focusedNodeParametersInTelemetryFormat[0]
374
+ );
375
+ }
376
+ const valueChangedDebounced = debounce(valueChanged, { debounceTime: 0 });
377
+ function focusWithDelay() {
378
+ setTimeout(() => {
379
+ void setFocus();
380
+ }, 50);
381
+ }
382
+ function handleKeydown(event) {
383
+ if (event.key === "s" && deviceSupport.isCtrlKeyPressed(event)) {
384
+ event.stopPropagation();
385
+ event.preventDefault();
386
+ if (isReadOnly.value) return;
387
+ emit("saveKeyboardShortcut", event);
388
+ }
389
+ }
390
+ const registerKeyboardListener = () => {
391
+ document.addEventListener("keydown", handleKeydown, true);
392
+ };
393
+ const unregisterKeyboardListener = () => {
394
+ document.removeEventListener("keydown", handleKeydown, true);
395
+ };
396
+ watch(
397
+ [() => focusPanelStore.lastFocusTimestamp, () => expressionModeEnabled.value],
398
+ () => focusWithDelay()
399
+ );
400
+ watch(
401
+ () => focusPanelStore.focusPanelActive,
402
+ (newValue) => {
403
+ if (newValue) {
404
+ registerKeyboardListener();
405
+ } else {
406
+ unregisterKeyboardListener();
407
+ }
408
+ },
409
+ { immediate: true }
410
+ );
411
+ function onResize(event) {
412
+ focusPanelStore.updateWidth(event.width);
413
+ }
414
+ const onResizeThrottle = useThrottleFn(onResize, 10);
415
+ return (_ctx, _cache) => {
416
+ const _component_NodeExecuteButton = _sfc_main$b;
417
+ const _component_N8nIcon = N8nIcon;
418
+ const _component_ParameterOptions = __unplugin_components_2;
419
+ const _component_ExpressionEditorModalInput = __unplugin_components_3;
420
+ const _component_CodeNodeEditor = __unplugin_components_4;
421
+ const _component_HtmlEditor = __unplugin_components_5;
422
+ const _component_CssEditor = __unplugin_components_6;
423
+ const _component_SqlEditor = __unplugin_components_7;
424
+ const _component_JsEditor = __unplugin_components_8;
425
+ const _component_JsonEditor = __unplugin_components_9;
426
+ const _component_N8nRadioButtons = N8nRadioButtons;
427
+ return focusPanelActive.value ? (openBlock(), createElementBlock("div", {
428
+ key: 0,
429
+ class: normalizeClass(_ctx.$style.wrapper),
430
+ onKeydown: _cache[1] || (_cache[1] = withModifiers(() => {
431
+ }, ["stop"]))
432
+ }, [
433
+ createVNode(unref(N8nResizeWrapper), {
434
+ width: focusPanelWidth.value,
435
+ "supported-directions": ["left"],
436
+ "min-width": 300,
437
+ "max-width": 1e3,
438
+ "grid-size": 8,
439
+ style: normalizeStyle({ width: `${focusPanelWidth.value}px`, zIndex: unref(styles).APP_Z_INDEXES.FOCUS_PANEL }),
440
+ onResize: unref(onResizeThrottle)
441
+ }, {
442
+ default: withCtx(() => [
443
+ createBaseVNode("div", {
444
+ class: normalizeClass(_ctx.$style.container)
445
+ }, [
446
+ resolvedParameter.value ? (openBlock(), createElementBlock("div", {
447
+ key: 0,
448
+ class: normalizeClass(_ctx.$style.content)
449
+ }, [
450
+ createBaseVNode("div", {
451
+ class: normalizeClass(_ctx.$style.tabHeader)
452
+ }, [
453
+ createBaseVNode("div", {
454
+ class: normalizeClass(_ctx.$style.tabHeaderText)
455
+ }, [
456
+ createVNode(unref(N8nText), {
457
+ color: "text-dark",
458
+ size: "small"
459
+ }, {
460
+ default: withCtx(() => [
461
+ createTextVNode(toDisplayString(resolvedParameter.value.parameter.displayName), 1)
462
+ ]),
463
+ _: 1
464
+ }),
465
+ createVNode(unref(N8nText), {
466
+ color: "text-base",
467
+ size: "xsmall"
468
+ }, {
469
+ default: withCtx(() => [
470
+ createTextVNode(toDisplayString(resolvedParameter.value.node.name), 1)
471
+ ]),
472
+ _: 1
473
+ })
474
+ ], 2),
475
+ createBaseVNode("div", {
476
+ class: normalizeClass(_ctx.$style.buttonWrapper)
477
+ }, [
478
+ createVNode(_component_NodeExecuteButton, {
479
+ "data-test-id": "node-execute-button",
480
+ "node-name": resolvedParameter.value.node.name,
481
+ tooltip: `Execute ${resolvedParameter.value.node.name}`,
482
+ disabled: !isExecutable.value,
483
+ size: "small",
484
+ icon: "play",
485
+ square: true,
486
+ "hide-label": true,
487
+ "telemetry-source": "focus",
488
+ onExecute
489
+ }, null, 8, ["node-name", "tooltip", "disabled"]),
490
+ createVNode(_component_N8nIcon, {
491
+ class: normalizeClass(_ctx.$style.closeButton),
492
+ icon: "x",
493
+ color: "text-base",
494
+ size: "xlarge",
495
+ onClick: closeFocusPanel
496
+ }, null, 8, ["class"])
497
+ ], 2)
498
+ ], 2),
499
+ createBaseVNode("div", {
500
+ class: normalizeClass(_ctx.$style.parameterDetailsWrapper)
501
+ }, [
502
+ createBaseVNode("div", {
503
+ class: normalizeClass(_ctx.$style.parameterOptionsWrapper)
504
+ }, [
505
+ createBaseVNode("div", {
506
+ class: normalizeClass(_ctx.$style.noExecutionDataTip)
507
+ }, [
508
+ !hasNodeRun.value && !isNodeExecuting.value ? (openBlock(), createBlock(unref(InfoTip), {
509
+ key: 0,
510
+ class: normalizeClass(_ctx.$style.delayedShow),
511
+ bold: true
512
+ }, {
513
+ default: withCtx(() => [
514
+ createTextVNode(toDisplayString(unref(locale).baseText("nodeView.focusPanel.noExecutionData")), 1)
515
+ ]),
516
+ _: 1
517
+ }, 8, ["class"])) : createCommentVNode("", true)
518
+ ], 2),
519
+ isDisplayed.value ? (openBlock(), createBlock(_component_ParameterOptions, {
520
+ key: 0,
521
+ parameter: resolvedParameter.value.parameter,
522
+ value: resolvedParameter.value.value,
523
+ "is-read-only": isReadOnly.value,
524
+ "onUpdate:modelValue": optionSelected
525
+ }, null, 8, ["parameter", "value", "is-read-only"])) : createCommentVNode("", true)
526
+ ], 2),
527
+ typeof resolvedParameter.value.value === "string" ? (openBlock(), createElementBlock("div", {
528
+ key: 0,
529
+ class: normalizeClass(_ctx.$style.editorContainer)
530
+ }, [
531
+ !isDisplayed.value ? (openBlock(), createElementBlock("div", {
532
+ key: 0,
533
+ class: normalizeClass([_ctx.$style.content, _ctx.$style.emptyContent])
534
+ }, [
535
+ createBaseVNode("div", {
536
+ class: normalizeClass(_ctx.$style.emptyText)
537
+ }, [
538
+ createVNode(unref(N8nText), { color: "text-base" }, {
539
+ default: withCtx(() => [
540
+ createTextVNode(toDisplayString(unref(locale).baseText("nodeView.focusPanel.missingParameter")), 1)
541
+ ]),
542
+ _: 1
543
+ })
544
+ ], 2)
545
+ ], 2)) : expressionModeEnabled.value ? (openBlock(), createBlock(_component_ExpressionEditorModalInput, {
546
+ key: 1,
547
+ ref_key: "inputField",
548
+ ref: inputField,
549
+ "model-value": resolvedParameter.value.value,
550
+ class: normalizeClass(_ctx.$style.editor),
551
+ "is-read-only": isReadOnly.value,
552
+ path: resolvedParameter.value.parameterPath,
553
+ "data-test-id": "expression-modal-input",
554
+ "target-node-parameter-context": targetNodeParameterContext.value,
555
+ onChange: _cache[0] || (_cache[0] = ($event) => unref(valueChangedDebounced)($event.value))
556
+ }, null, 8, ["model-value", "class", "is-read-only", "path", "target-node-parameter-context"])) : ["json", "string"].includes(resolvedParameter.value.parameter.type) ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
557
+ editorType.value === "codeNodeEditor" ? (openBlock(), createBlock(_component_CodeNodeEditor, {
558
+ key: 0,
559
+ id: resolvedParameter.value.parameterPath,
560
+ ref_key: "inputField",
561
+ ref: inputField,
562
+ class: normalizeClass(_ctx.$style.heightFull),
563
+ mode: codeEditorMode.value,
564
+ "model-value": resolvedParameter.value.value,
565
+ "default-value": resolvedParameter.value.parameter.default,
566
+ language: editorLanguage.value,
567
+ "is-read-only": isReadOnly.value,
568
+ "target-node-parameter-context": targetNodeParameterContext.value,
569
+ "fill-parent": "",
570
+ "disable-ask-ai": true,
571
+ "onUpdate:modelValue": unref(valueChangedDebounced)
572
+ }, null, 8, ["id", "class", "mode", "model-value", "default-value", "language", "is-read-only", "target-node-parameter-context", "onUpdate:modelValue"])) : editorType.value === "htmlEditor" ? (openBlock(), createBlock(_component_HtmlEditor, {
573
+ key: 1,
574
+ ref_key: "inputField",
575
+ ref: inputField,
576
+ "model-value": resolvedParameter.value.value,
577
+ "is-read-only": isReadOnly.value,
578
+ rows: editorRows.value,
579
+ "disable-expression-coloring": !isHtmlNode.value,
580
+ "disable-expression-completions": !isHtmlNode.value,
581
+ fullscreen: "",
582
+ "target-node-parameter-context": targetNodeParameterContext.value,
583
+ "onUpdate:modelValue": unref(valueChangedDebounced)
584
+ }, null, 8, ["model-value", "is-read-only", "rows", "disable-expression-coloring", "disable-expression-completions", "target-node-parameter-context", "onUpdate:modelValue"])) : editorType.value === "cssEditor" ? (openBlock(), createBlock(_component_CssEditor, {
585
+ key: 2,
586
+ ref_key: "inputField",
587
+ ref: inputField,
588
+ "model-value": resolvedParameter.value.value,
589
+ "is-read-only": isReadOnly.value,
590
+ rows: editorRows.value,
591
+ fullscreen: "",
592
+ "target-node-parameter-context": targetNodeParameterContext.value,
593
+ "onUpdate:modelValue": unref(valueChangedDebounced)
594
+ }, null, 8, ["model-value", "is-read-only", "rows", "target-node-parameter-context", "onUpdate:modelValue"])) : editorType.value === "sqlEditor" ? (openBlock(), createBlock(_component_SqlEditor, {
595
+ key: 3,
596
+ ref_key: "inputField",
597
+ ref: inputField,
598
+ "model-value": resolvedParameter.value.value,
599
+ dialect: getTypeOption("sqlDialect"),
600
+ "is-read-only": isReadOnly.value,
601
+ rows: editorRows.value,
602
+ fullscreen: "",
603
+ "target-node-parameter-context": targetNodeParameterContext.value,
604
+ "onUpdate:modelValue": unref(valueChangedDebounced)
605
+ }, null, 8, ["model-value", "dialect", "is-read-only", "rows", "target-node-parameter-context", "onUpdate:modelValue"])) : editorType.value === "jsEditor" ? (openBlock(), createBlock(_component_JsEditor, {
606
+ key: 4,
607
+ ref_key: "inputField",
608
+ ref: inputField,
609
+ "model-value": resolvedParameter.value.value,
610
+ "is-read-only": isReadOnly.value,
611
+ rows: editorRows.value,
612
+ "posthog-capture": shouldCaptureForPosthog.value,
613
+ "fill-parent": "",
614
+ "onUpdate:modelValue": unref(valueChangedDebounced)
615
+ }, null, 8, ["model-value", "is-read-only", "rows", "posthog-capture", "onUpdate:modelValue"])) : resolvedParameter.value.parameter.type === "json" ? (openBlock(), createBlock(_component_JsonEditor, {
616
+ key: 5,
617
+ ref_key: "inputField",
618
+ ref: inputField,
619
+ "model-value": resolvedParameter.value.value,
620
+ "is-read-only": isReadOnly.value,
621
+ rows: editorRows.value,
622
+ fullscreen: "",
623
+ "fill-parent": "",
624
+ "onUpdate:modelValue": unref(valueChangedDebounced)
625
+ }, null, 8, ["model-value", "is-read-only", "rows", "onUpdate:modelValue"])) : (openBlock(), createBlock(unref(N8nInput), {
626
+ key: 6,
627
+ ref_key: "inputField",
628
+ ref: inputField,
629
+ "model-value": resolvedParameter.value.value,
630
+ class: normalizeClass(_ctx.$style.editor),
631
+ readonly: isReadOnly.value,
632
+ type: "textarea",
633
+ resize: "none",
634
+ "onUpdate:modelValue": unref(valueChangedDebounced)
635
+ }, null, 8, ["model-value", "class", "readonly", "onUpdate:modelValue"]))
636
+ ], 64)) : createCommentVNode("", true)
637
+ ], 2)) : createCommentVNode("", true)
638
+ ], 2)
639
+ ], 2)) : (openBlock(), createElementBlock("div", {
640
+ key: 1,
641
+ class: normalizeClass([_ctx.$style.content, _ctx.$style.emptyContent])
642
+ }, [
643
+ createBaseVNode("div", {
644
+ class: normalizeClass(_ctx.$style.emptyText)
645
+ }, [
646
+ createBaseVNode("div", {
647
+ class: normalizeClass(_ctx.$style.focusParameterWrapper)
648
+ }, [
649
+ createBaseVNode("div", {
650
+ class: normalizeClass(_ctx.$style.iconWrapper)
651
+ }, [
652
+ createVNode(_component_N8nIcon, {
653
+ class: normalizeClass(_ctx.$style.forceHover),
654
+ icon: "panel-right",
655
+ size: "medium"
656
+ }, null, 8, ["class"]),
657
+ createVNode(_component_N8nIcon, {
658
+ class: normalizeClass(_ctx.$style.pointerIcon),
659
+ icon: "mouse-pointer",
660
+ color: "text-dark",
661
+ size: "large"
662
+ }, null, 8, ["class"])
663
+ ], 2),
664
+ createVNode(_component_N8nIcon, {
665
+ icon: "ellipsis-vertical",
666
+ size: "small",
667
+ color: "text-base"
668
+ }),
669
+ createVNode(_component_N8nRadioButtons, {
670
+ size: "small",
671
+ "model-value": "expression",
672
+ disabled: true,
673
+ options: [
674
+ { label: unref(locale).baseText("parameterInput.fixed"), value: "fixed" },
675
+ { label: unref(locale).baseText("parameterInput.expression"), value: "expression" }
676
+ ]
677
+ }, null, 8, ["options"])
678
+ ], 2),
679
+ createVNode(unref(N8nText), {
680
+ color: "text-base",
681
+ size: "medium",
682
+ bold: true
683
+ }, {
684
+ default: withCtx(() => [
685
+ createTextVNode(toDisplayString(unref(locale).baseText("nodeView.focusPanel.noParameters.title")), 1)
686
+ ]),
687
+ _: 1
688
+ }),
689
+ createVNode(unref(N8nText), {
690
+ color: "text-base",
691
+ size: "small"
692
+ }, {
693
+ default: withCtx(() => [
694
+ createTextVNode(toDisplayString(unref(locale).baseText("nodeView.focusPanel.noParameters.subtitle")), 1)
695
+ ]),
696
+ _: 1
697
+ })
698
+ ], 2)
699
+ ], 2))
700
+ ], 2)
701
+ ]),
702
+ _: 1
703
+ }, 8, ["width", "style", "onResize"])
704
+ ], 34)) : createCommentVNode("", true);
705
+ };
706
+ }
707
+ });
708
+ const wrapper$1 = "_wrapper_1ebmp_123";
709
+ const container = "_container_1ebmp_132";
710
+ const content = "_content_1ebmp_138";
711
+ const emptyContent = "_emptyContent_1ebmp_144";
712
+ const emptyText = "_emptyText_1ebmp_149";
713
+ const focusParameterWrapper = "_focusParameterWrapper_1ebmp_155";
714
+ const iconWrapper = "_iconWrapper_1ebmp_162";
715
+ const pointerIcon = "_pointerIcon_1ebmp_166";
716
+ const tabHeader = "_tabHeader_1ebmp_176";
717
+ const tabHeaderText = "_tabHeaderText_1ebmp_183";
718
+ const buttonWrapper = "_buttonWrapper_1ebmp_188";
719
+ const parameterDetailsWrapper = "_parameterDetailsWrapper_1ebmp_193";
720
+ const parameterOptionsWrapper = "_parameterOptionsWrapper_1ebmp_200";
721
+ const noExecutionDataTip = "_noExecutionDataTip_1ebmp_204";
722
+ const editorContainer = "_editorContainer_1ebmp_207";
723
+ const editor = "_editor_1ebmp_207";
724
+ const delayedShow = "_delayedShow_1ebmp_222";
725
+ const triggerShow = "_triggerShow_1ebmp_1";
726
+ const closeButton = "_closeButton_1ebmp_233";
727
+ const heightFull = "_heightFull_1ebmp_237";
728
+ const forceHover = "_forceHover_1ebmp_241";
729
+ const style0$2 = {
730
+ wrapper: wrapper$1,
731
+ container,
732
+ content,
733
+ emptyContent,
734
+ emptyText,
735
+ focusParameterWrapper,
736
+ iconWrapper,
737
+ pointerIcon,
738
+ tabHeader,
739
+ tabHeaderText,
740
+ buttonWrapper,
741
+ parameterDetailsWrapper,
742
+ parameterOptionsWrapper,
743
+ noExecutionDataTip,
744
+ editorContainer,
745
+ editor,
746
+ delayedShow,
747
+ triggerShow,
748
+ closeButton,
749
+ heightFull,
750
+ forceHover
751
+ };
752
+ const cssModules$2 = {
753
+ "$style": style0$2
754
+ };
755
+ const FocusPanel = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__cssModules", cssModules$2]]);
756
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
757
+ __name: "CanvasRunWorkflowButton",
758
+ props: {
759
+ selectedTriggerNodeName: {},
760
+ triggerNodes: {},
761
+ waitingForWebhook: { type: Boolean },
762
+ executing: { type: Boolean },
763
+ disabled: { type: Boolean },
764
+ getNodeType: { type: Function }
765
+ },
766
+ emits: ["mouseenter", "mouseleave", "execute", "selectTriggerNode"],
767
+ setup(__props, { emit: __emit }) {
768
+ const emit = __emit;
769
+ const props = __props;
770
+ const i18n = useI18n();
771
+ const selectableTriggerNodes = computed(
772
+ () => props.triggerNodes.filter((node) => !node.disabled && !isChatNode(node))
773
+ );
774
+ const label = computed(() => {
775
+ if (!props.executing) {
776
+ return i18n.baseText("nodeView.runButtonText.executeWorkflow");
777
+ }
778
+ if (props.waitingForWebhook) {
779
+ return i18n.baseText("nodeView.runButtonText.waitingForTriggerEvent");
780
+ }
781
+ return i18n.baseText("nodeView.runButtonText.executingWorkflow");
782
+ });
783
+ const actions = computed(
784
+ () => props.triggerNodes.filter((node) => !isChatNode(node)).toSorted((a, b) => {
785
+ const [aX, aY] = a.position;
786
+ const [bX, bY] = b.position;
787
+ return aY === bY ? aX - bX : aY - bY;
788
+ }).map((node) => ({
789
+ label: truncateBeforeLast(node.name, 25),
790
+ disabled: !!node.disabled || props.executing,
791
+ id: node.name,
792
+ checked: props.selectedTriggerNodeName === node.name
793
+ }))
794
+ );
795
+ const isSplitButton = computed(
796
+ () => selectableTriggerNodes.value.length > 1 && props.selectedTriggerNodeName !== void 0
797
+ );
798
+ function getNodeTypeByName(name) {
799
+ const node = props.triggerNodes.find((trigger) => trigger.name === name);
800
+ if (!node) {
801
+ return null;
802
+ }
803
+ return props.getNodeType(node.type, node.typeVersion);
804
+ }
805
+ return (_ctx, _cache) => {
806
+ const _component_NodeIcon = NodeIcon;
807
+ return openBlock(), createElementBlock("div", {
808
+ class: normalizeClass([_ctx.$style.component, isSplitButton.value ? _ctx.$style.split : ""])
809
+ }, [
810
+ createVNode(KeyboardShortcutTooltip, {
811
+ label: label.value,
812
+ shortcut: { metaKey: true, keys: ["↵"] },
813
+ disabled: _ctx.executing
814
+ }, {
815
+ default: withCtx(() => [
816
+ createVNode(unref(N8nButton), {
817
+ class: normalizeClass(_ctx.$style.button),
818
+ loading: _ctx.executing,
819
+ disabled: _ctx.disabled,
820
+ size: "large",
821
+ icon: "flask-conical",
822
+ type: "primary",
823
+ "data-test-id": "execute-workflow-button",
824
+ onMouseenter: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("mouseenter", $event)),
825
+ onMouseleave: _cache[1] || (_cache[1] = ($event) => _ctx.$emit("mouseleave", $event)),
826
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("execute"))
827
+ }, {
828
+ default: withCtx(() => [
829
+ createBaseVNode("span", {
830
+ class: normalizeClass(_ctx.$style.buttonContent)
831
+ }, [
832
+ createTextVNode(toDisplayString(label.value) + " ", 1),
833
+ isSplitButton.value ? (openBlock(), createBlock(unref(N8nText), {
834
+ key: 0,
835
+ class: normalizeClass(_ctx.$style.subText),
836
+ bold: false
837
+ }, {
838
+ default: withCtx(() => [
839
+ createVNode(unref(I18nT), {
840
+ keypath: "nodeView.runButtonText.from",
841
+ scope: "global"
842
+ }, {
843
+ nodeName: withCtx(() => [
844
+ createVNode(unref(N8nText), {
845
+ bold: "",
846
+ size: "mini"
847
+ }, {
848
+ default: withCtx(() => [
849
+ createTextVNode(toDisplayString(unref(truncateBeforeLast)(props.selectedTriggerNodeName ?? "", 25)), 1)
850
+ ]),
851
+ _: 1
852
+ })
853
+ ]),
854
+ _: 1
855
+ })
856
+ ]),
857
+ _: 1
858
+ }, 8, ["class"])) : createCommentVNode("", true)
859
+ ], 2)
860
+ ]),
861
+ _: 1
862
+ }, 8, ["class", "loading", "disabled"])
863
+ ]),
864
+ _: 1
865
+ }, 8, ["label", "disabled"]),
866
+ isSplitButton.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
867
+ createBaseVNode("div", {
868
+ role: "presentation",
869
+ class: normalizeClass(_ctx.$style.divider)
870
+ }, null, 2),
871
+ createVNode(unref(N8nActionDropdown), {
872
+ class: normalizeClass(_ctx.$style.menu),
873
+ items: actions.value,
874
+ disabled: _ctx.disabled,
875
+ placement: "top",
876
+ onSelect: _cache[3] || (_cache[3] = ($event) => emit("selectTriggerNode", $event))
877
+ }, {
878
+ activator: withCtx(() => [
879
+ createVNode(unref(N8nButton), {
880
+ type: "primary",
881
+ "icon-size": "large",
882
+ disabled: _ctx.disabled,
883
+ class: normalizeClass(_ctx.$style.chevron),
884
+ "aria-label": "Select trigger node",
885
+ icon: "chevron-down"
886
+ }, null, 8, ["disabled", "class"])
887
+ ]),
888
+ menuItem: withCtx((item) => [
889
+ createBaseVNode("div", {
890
+ class: normalizeClass([_ctx.$style.menuItem, item.disabled ? _ctx.$style.disabled : ""])
891
+ }, [
892
+ createVNode(_component_NodeIcon, {
893
+ class: normalizeClass(_ctx.$style.menuIcon),
894
+ size: 16,
895
+ "node-type": getNodeTypeByName(item.id)
896
+ }, null, 8, ["class", "node-type"]),
897
+ createBaseVNode("span", null, [
898
+ createVNode(unref(I18nT), {
899
+ keypath: "nodeView.runButtonText.from",
900
+ scope: "global"
901
+ }, {
902
+ nodeName: withCtx(() => [
903
+ createVNode(unref(N8nText), {
904
+ bold: "",
905
+ size: "small"
906
+ }, {
907
+ default: withCtx(() => [
908
+ createTextVNode(toDisplayString(item.label), 1)
909
+ ]),
910
+ _: 2
911
+ }, 1024)
912
+ ]),
913
+ _: 2
914
+ }, 1024)
915
+ ])
916
+ ], 2)
917
+ ]),
918
+ _: 1
919
+ }, 8, ["class", "items", "disabled"])
920
+ ], 64)) : createCommentVNode("", true)
921
+ ], 2);
922
+ };
923
+ }
924
+ });
925
+ const component = "_component_p52lz_123";
926
+ const split = "_split_p52lz_129";
927
+ const button = "_button_p52lz_129";
928
+ const divider = "_divider_p52lz_137";
929
+ const chevron = "_chevron_p52lz_142";
930
+ const menu = "_menu_p52lz_148";
931
+ const menuItem = "_menuItem_p52lz_152";
932
+ const disabled = "_disabled_p52lz_158";
933
+ const menuIcon = "_menuIcon_p52lz_158";
934
+ const buttonContent = "_buttonContent_p52lz_162";
935
+ const subText = "_subText_p52lz_169";
936
+ const style0$1 = {
937
+ component,
938
+ split,
939
+ button,
940
+ divider,
941
+ chevron,
942
+ menu,
943
+ menuItem,
944
+ disabled,
945
+ menuIcon,
946
+ buttonContent,
947
+ subText
948
+ };
949
+ const cssModules$1 = {
950
+ "$style": style0$1
951
+ };
952
+ const CanvasRunWorkflowButton = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$1]]);
953
+ const state = reactive({
954
+ customActions: {},
955
+ delegatedClickHandler: null
956
+ });
957
+ function useGlobalLinkActions() {
958
+ function registerCustomAction({ key, action }) {
959
+ state.customActions[key] = action;
960
+ }
961
+ function unregisterCustomAction(key) {
962
+ const { [key]: _, ...rest } = state.customActions;
963
+ state.customActions = rest;
964
+ }
965
+ function getElementAttributes(element) {
966
+ const attributesObject = {};
967
+ for (let i = 0; i < element.attributes.length; i++) {
968
+ const attr = element.attributes[i];
969
+ if (attr.name.startsWith("data-action-parameter-")) {
970
+ attributesObject[attr.name.replace("data-action-parameter-", "")] = attr.value;
971
+ }
972
+ }
973
+ return attributesObject;
974
+ }
975
+ function delegateClick(e) {
976
+ const clickedElement = e.target;
977
+ if (!(clickedElement instanceof Element) || clickedElement.tagName !== "A") return;
978
+ const actionAttribute = clickedElement.getAttribute("data-action");
979
+ if (actionAttribute && typeof availableActions.value[actionAttribute] === "function") {
980
+ e.preventDefault();
981
+ const elementAttributes = getElementAttributes(clickedElement);
982
+ availableActions.value[actionAttribute](elementAttributes);
983
+ }
984
+ }
985
+ function reload() {
986
+ if (window.top) {
987
+ window.top.location.reload();
988
+ } else {
989
+ window.location.reload();
990
+ }
991
+ }
992
+ const availableActions = computed(() => ({
993
+ reload,
994
+ ...state.customActions
995
+ }));
996
+ onMounted(() => {
997
+ if (state.delegatedClickHandler) return;
998
+ state.delegatedClickHandler = delegateClick;
999
+ window.addEventListener("click", delegateClick);
1000
+ globalLinkActionsEventBus.on("registerGlobalLinkAction", registerCustomAction);
1001
+ });
1002
+ onUnmounted(() => {
1003
+ window.removeEventListener("click", delegateClick);
1004
+ state.delegatedClickHandler = null;
1005
+ globalLinkActionsEventBus.off("registerGlobalLinkAction", registerCustomAction);
1006
+ });
1007
+ return {
1008
+ registerCustomAction,
1009
+ unregisterCustomAction
1010
+ };
1011
+ }
1012
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
1013
+ __name: "CanvasStopCurrentExecutionButton",
1014
+ props: {
1015
+ stopping: { type: Boolean }
1016
+ },
1017
+ setup(__props) {
1018
+ const props = __props;
1019
+ const i18n = useI18n();
1020
+ const title = computed(
1021
+ () => props.stopping ? i18n.baseText("nodeView.stoppingCurrentExecution") : i18n.baseText("nodeView.stopCurrentExecution")
1022
+ );
1023
+ return (_ctx, _cache) => {
1024
+ const _component_N8nIconButton = _sfc_main$a;
1025
+ return openBlock(), createBlock(_component_N8nIconButton, {
1026
+ icon: "square",
1027
+ size: "large",
1028
+ class: "stop-execution",
1029
+ type: "secondary",
1030
+ title: title.value,
1031
+ loading: _ctx.stopping,
1032
+ "data-test-id": "stop-execution-button"
1033
+ }, null, 8, ["title", "loading"]);
1034
+ };
1035
+ }
1036
+ });
1037
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
1038
+ __name: "CanvasStopWaitingForWebhookButton",
1039
+ setup(__props) {
1040
+ const i18n = useI18n();
1041
+ return (_ctx, _cache) => {
1042
+ const _component_N8nIconButton = _sfc_main$a;
1043
+ return openBlock(), createBlock(_component_N8nIconButton, {
1044
+ class: "stop-execution",
1045
+ icon: "square",
1046
+ size: "large",
1047
+ title: unref(i18n).baseText("nodeView.stopWaitingForWebhookCall"),
1048
+ type: "secondary",
1049
+ "data-test-id": "stop-execution-waiting-for-webhook-button"
1050
+ }, null, 8, ["title"]);
1051
+ };
1052
+ }
1053
+ });
1054
+ const _hoisted_1 = { "data-action": "reload" };
1055
+ const _hoisted_2 = {
1056
+ href: "https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.wait/",
1057
+ target: "_blank"
1058
+ };
1059
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
1060
+ __name: "NodeViewUnfinishedWorkflowMessage",
1061
+ setup(__props) {
1062
+ const i18 = useI18n();
1063
+ return (_ctx, _cache) => {
1064
+ return openBlock(), createElementBlock("div", null, [
1065
+ createBaseVNode("a", _hoisted_1, toDisplayString(unref(i18).baseText("nodeView.refresh")), 1),
1066
+ createTextVNode(" " + toDisplayString(unref(i18).baseText("nodeView.toSeeTheLatestStatus")) + ". ", 1),
1067
+ _cache[0] || (_cache[0] = createBaseVNode("br", null, null, -1)),
1068
+ createBaseVNode("a", _hoisted_2, toDisplayString(unref(i18).baseText("nodeView.moreInfo")), 1)
1069
+ ]);
1070
+ };
1071
+ }
1072
+ });
1073
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
1074
+ __name: "CanvasChatButton",
1075
+ props: {
1076
+ label: {},
1077
+ type: {}
1078
+ },
1079
+ setup(__props) {
1080
+ return (_ctx, _cache) => {
1081
+ const _component_N8nButton = N8nButton;
1082
+ return openBlock(), createBlock(_component_N8nButton, {
1083
+ label: _ctx.label,
1084
+ size: "large",
1085
+ icon: "message-circle",
1086
+ type: _ctx.type,
1087
+ "data-test-id": "workflow-chat-button"
1088
+ }, null, 8, ["label", "type"]);
1089
+ };
1090
+ }
1091
+ });
1092
+ const _sfc_main = /* @__PURE__ */ defineComponent({
1093
+ ...{
1094
+ name: "NodeView"
1095
+ },
1096
+ __name: "NodeView",
1097
+ setup(__props) {
1098
+ const LazyNodeCreation = defineAsyncComponent(
1099
+ async () => await __vitePreload(() => import("./NodeCreation-B9FRFHG0.js").then((n) => n.N), true ? __vite__mapDeps([0,1,2,3]) : void 0)
1100
+ );
1101
+ const LazyNodeDetailsView = defineAsyncComponent(
1102
+ async () => await __vitePreload(() => import("./NodeDetailsView-CQQOZQXq.js"), true ? __vite__mapDeps([4,1,2,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]) : void 0)
1103
+ );
1104
+ const LazyNodeDetailsViewV2 = defineAsyncComponent(
1105
+ async () => await __vitePreload(() => import("./NodeDetailsViewV2-DKnduvJH.js"), true ? __vite__mapDeps([20,1,2,5,6,7,8,9,10,11,12,13,14,15,16,17,18,21]) : void 0)
1106
+ );
1107
+ const LazySetupWorkflowCredentialsButton = defineAsyncComponent(
1108
+ async () => await __vitePreload(() => import("./SetupWorkflowCredentialsButton-y92onTNS.js"), true ? __vite__mapDeps([22,1,2]) : void 0)
1109
+ );
1110
+ const $style = useCssModule();
1111
+ const router = useRouter();
1112
+ const route = useRoute();
1113
+ const i18n = useI18n();
1114
+ const telemetry = useTelemetry();
1115
+ const externalHooks = useExternalHooks();
1116
+ const toast = useToast();
1117
+ const message = useMessage();
1118
+ const documentTitle = useDocumentTitle();
1119
+ const workflowHelpers = useWorkflowHelpers();
1120
+ const workflowSaving = useWorkflowSaving({ router });
1121
+ const nodeHelpers = useNodeHelpers();
1122
+ const nodeTypesStore = useNodeTypesStore();
1123
+ const uiStore = useUIStore();
1124
+ const workflowsStore = useWorkflowsStore();
1125
+ const sourceControlStore = useSourceControlStore();
1126
+ const nodeCreatorStore = useNodeCreatorStore();
1127
+ const settingsStore = useSettingsStore();
1128
+ const credentialsStore = useCredentialsStore();
1129
+ const environmentsStore = useEnvironmentsStore();
1130
+ const externalSecretsStore = useExternalSecretsStore();
1131
+ const rootStore = useRootStore();
1132
+ const executionsStore = useExecutionsStore();
1133
+ const canvasStore = useCanvasStore();
1134
+ const npsSurveyStore = useNpsSurveyStore();
1135
+ const historyStore = useHistoryStore();
1136
+ const projectsStore = useProjectsStore();
1137
+ const usersStore = useUsersStore();
1138
+ const tagsStore = useTagsStore();
1139
+ const pushConnectionStore = usePushConnectionStore();
1140
+ const ndvStore = useNDVStore();
1141
+ const focusPanelStore = useFocusPanelStore();
1142
+ const templatesStore = useTemplatesStore();
1143
+ const builderStore = useBuilderStore();
1144
+ const foldersStore = useFoldersStore();
1145
+ const posthogStore = usePostHog();
1146
+ const agentRequestStore = useAgentRequestStore();
1147
+ const logsStore = useLogsStore();
1148
+ const aiTemplatesStarterCollectionStore = useAITemplatesStarterCollectionStore();
1149
+ const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings } = useBeforeUnload({
1150
+ route
1151
+ });
1152
+ const { registerCustomAction, unregisterCustomAction } = useGlobalLinkActions();
1153
+ const { runWorkflow, runEntireWorkflow, stopCurrentExecution, stopWaitingForWebhook } = useRunWorkflow({ router });
1154
+ const {
1155
+ updateNodePosition,
1156
+ updateNodesPosition,
1157
+ tidyUp,
1158
+ revertUpdateNodePosition,
1159
+ renameNode,
1160
+ revertRenameNode,
1161
+ revertReplaceNodeParameters,
1162
+ setNodeActive,
1163
+ setNodeSelected,
1164
+ toggleNodesDisabled,
1165
+ revertToggleNodeDisabled,
1166
+ toggleNodesPinned,
1167
+ setNodeParameters,
1168
+ deleteNode,
1169
+ deleteNodes,
1170
+ copyNodes,
1171
+ cutNodes,
1172
+ duplicateNodes,
1173
+ revertDeleteNode,
1174
+ addNodes,
1175
+ importTemplate,
1176
+ revertAddNode,
1177
+ createConnection,
1178
+ revertCreateConnection,
1179
+ deleteConnection,
1180
+ revertDeleteConnection,
1181
+ revalidateNodeInputConnections,
1182
+ revalidateNodeOutputConnections,
1183
+ setNodeActiveByName,
1184
+ clearNodeActive,
1185
+ addConnections,
1186
+ tryToOpenSubworkflowInNewTab,
1187
+ importWorkflowData,
1188
+ fetchWorkflowDataFromUrl,
1189
+ resetWorkspace,
1190
+ initializeWorkspace,
1191
+ openExecution,
1192
+ editableWorkflow,
1193
+ editableWorkflowObject,
1194
+ lastClickPosition,
1195
+ startChat
1196
+ } = useCanvasOperations();
1197
+ const { extractWorkflow } = useWorkflowExtraction();
1198
+ const { applyExecutionData } = useExecutionDebugging();
1199
+ useClipboard({ onPaste: onClipboardPaste });
1200
+ const isLoading = ref(true);
1201
+ const isBlankRedirect = ref(false);
1202
+ const readOnlyNotification = ref(null);
1203
+ const isProductionExecutionPreview = ref(false);
1204
+ const isExecutionPreview = ref(false);
1205
+ const canOpenNDV = ref(true);
1206
+ const hideNodeIssues = ref(false);
1207
+ const fallbackNodes = ref([]);
1208
+ const initializedWorkflowId = ref();
1209
+ const workflowId = computed(() => {
1210
+ const workflowIdParam = route.params.name;
1211
+ return [PLACEHOLDER_EMPTY_WORKFLOW_ID, NEW_WORKFLOW_ID].includes(workflowIdParam) ? void 0 : workflowIdParam;
1212
+ });
1213
+ const routeNodeId = computed(() => route.params.nodeId);
1214
+ const isNewWorkflowRoute = computed(() => route.name === VIEWS.NEW_WORKFLOW || !workflowId.value);
1215
+ const isWorkflowRoute = computed(() => !!route?.meta?.nodeView || isDemoRoute.value);
1216
+ const isDemoRoute = computed(() => route.name === VIEWS.DEMO);
1217
+ const isReadOnlyRoute = computed(() => !!route?.meta?.readOnlyCanvas);
1218
+ const isReadOnlyEnvironment = computed(() => {
1219
+ return sourceControlStore.preferences.branchReadOnly;
1220
+ });
1221
+ const isNDVV2 = computed(
1222
+ () => posthogStore.isVariantEnabled(
1223
+ NDV_UI_OVERHAUL_EXPERIMENT.name,
1224
+ NDV_UI_OVERHAUL_EXPERIMENT.variant
1225
+ )
1226
+ );
1227
+ const isCanvasReadOnly = computed(() => {
1228
+ return isDemoRoute.value || isReadOnlyEnvironment.value || !(workflowPermissions.value.update ?? projectPermissions.value.workflow.update) || editableWorkflow.value.isArchived;
1229
+ });
1230
+ const showFallbackNodes = computed(() => triggerNodes.value.length === 0);
1231
+ const keyBindingsEnabled = computed(() => {
1232
+ return !ndvStore.activeNode && uiStore.activeModals.length === 0;
1233
+ });
1234
+ const isLogsPanelOpen = computed(() => logsStore.isOpen);
1235
+ async function initializeData() {
1236
+ const loadPromises = (() => {
1237
+ if (settingsStore.isPreviewMode && isDemoRoute.value) return [];
1238
+ const promises = [
1239
+ workflowsStore.fetchActiveWorkflows(),
1240
+ credentialsStore.fetchAllCredentials(),
1241
+ credentialsStore.fetchCredentialTypes(true)
1242
+ ];
1243
+ if (settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Variables]) {
1244
+ promises.push(environmentsStore.fetchAllVariables());
1245
+ }
1246
+ if (settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.ExternalSecrets]) {
1247
+ promises.push(externalSecretsStore.fetchAllSecrets());
1248
+ }
1249
+ return promises;
1250
+ })();
1251
+ if (nodeTypesStore.allNodeTypes.length === 0) {
1252
+ loadPromises.push(nodeTypesStore.getNodeTypes());
1253
+ }
1254
+ try {
1255
+ await Promise.all(loadPromises);
1256
+ } catch (error) {
1257
+ toast.showError(
1258
+ error,
1259
+ i18n.baseText("nodeView.showError.mounted1.title"),
1260
+ i18n.baseText("nodeView.showError.mounted1.message") + ":"
1261
+ );
1262
+ return;
1263
+ }
1264
+ }
1265
+ async function initializeRoute(force = false) {
1266
+ if (route.query.action === "workflowSave") {
1267
+ uiStore.stateIsDirty = false;
1268
+ await router.replace({
1269
+ query: { ...route.query, action: void 0 }
1270
+ });
1271
+ return;
1272
+ }
1273
+ if (route.query.action === "addEvaluationTrigger") {
1274
+ nodeCreatorStore.openNodeCreatorForTriggerNodes(
1275
+ NODE_CREATOR_OPEN_SOURCES.ADD_EVALUATION_TRIGGER_BUTTON
1276
+ );
1277
+ } else if (route.query.action === "addEvaluationNode") {
1278
+ nodeCreatorStore.openNodeCreatorForActions(
1279
+ EVALUATION_NODE_TYPE,
1280
+ NODE_CREATOR_OPEN_SOURCES.ADD_EVALUATION_NODE_BUTTON
1281
+ );
1282
+ } else if (route.query.action === "executeEvaluation") {
1283
+ if (evaluationTriggerNode.value) {
1284
+ void runEntireWorkflow("node", evaluationTriggerNode.value.name);
1285
+ }
1286
+ }
1287
+ const isAlreadyInitialized = !force && initializedWorkflowId.value && [NEW_WORKFLOW_ID, workflowId.value].includes(initializedWorkflowId.value);
1288
+ if (isBlankRedirect.value) {
1289
+ isBlankRedirect.value = false;
1290
+ } else if (route.name === VIEWS.TEMPLATE_IMPORT) {
1291
+ const templateId = route.params.id;
1292
+ const loadWorkflowFromJSON = route.query.fromJson === "true";
1293
+ if (loadWorkflowFromJSON) {
1294
+ const easyAiWorkflowJson = getEasyAiWorkflowJson();
1295
+ const ragStarterWorkflowJson = getRagStarterWorkflowJson();
1296
+ switch (templateId) {
1297
+ case easyAiWorkflowJson.meta.templateId:
1298
+ await openTemplateFromWorkflowJSON(easyAiWorkflowJson);
1299
+ break;
1300
+ case ragStarterWorkflowJson.meta.templateId:
1301
+ await openTemplateFromWorkflowJSON(ragStarterWorkflowJson);
1302
+ break;
1303
+ default:
1304
+ toast.showError(
1305
+ new Error(i18n.baseText("nodeView.couldntLoadWorkflow.invalidWorkflowObject")),
1306
+ i18n.baseText("nodeView.couldntImportWorkflow")
1307
+ );
1308
+ await router.replace({ name: VIEWS.NEW_WORKFLOW });
1309
+ }
1310
+ } else {
1311
+ await openWorkflowTemplate(templateId.toString());
1312
+ }
1313
+ } else if (isWorkflowRoute.value) {
1314
+ if (!isAlreadyInitialized) {
1315
+ historyStore.reset();
1316
+ if (!isDemoRoute.value) {
1317
+ await loadCredentials();
1318
+ }
1319
+ if (isNewWorkflowRoute.value || !workflowId.value) {
1320
+ if (route.meta?.nodeView === true) {
1321
+ await initializeWorkspaceForNewWorkflow();
1322
+ }
1323
+ return;
1324
+ }
1325
+ await initializeWorkspaceForExistingWorkflow(workflowId.value);
1326
+ void nextTick(() => {
1327
+ updateNodesIssues();
1328
+ });
1329
+ }
1330
+ if (route.name === VIEWS.EXECUTION_DEBUG) {
1331
+ await initializeDebugMode();
1332
+ }
1333
+ }
1334
+ }
1335
+ async function initializeWorkspaceForNewWorkflow() {
1336
+ resetWorkspace();
1337
+ const parentFolderId = route.query.parentFolderId;
1338
+ await workflowsStore.getNewWorkflowDataAndMakeShareable(
1339
+ void 0,
1340
+ projectsStore.currentProjectId,
1341
+ parentFolderId
1342
+ );
1343
+ if (projectsStore.currentProjectId) {
1344
+ await fetchAndSetProject(projectsStore.currentProjectId);
1345
+ }
1346
+ await fetchAndSetParentFolder(parentFolderId);
1347
+ uiStore.nodeViewInitialized = true;
1348
+ initializedWorkflowId.value = NEW_WORKFLOW_ID;
1349
+ }
1350
+ async function fetchAndSetParentFolder(folderId) {
1351
+ if (folderId) {
1352
+ let parentFolder = foldersStore.getCachedFolder(folderId);
1353
+ if (!parentFolder && projectsStore.currentProjectId) {
1354
+ await foldersStore.getFolderPath(projectsStore.currentProjectId, folderId);
1355
+ parentFolder = foldersStore.getCachedFolder(folderId);
1356
+ }
1357
+ if (parentFolder) {
1358
+ workflowsStore.setParentFolder({
1359
+ ...parentFolder,
1360
+ parentFolderId: parentFolder.parentFolder ?? null
1361
+ });
1362
+ }
1363
+ }
1364
+ }
1365
+ async function fetchAndSetProject(projectId) {
1366
+ if (!projectsStore.currentProject) {
1367
+ const project = await projectsStore.fetchProject(projectId);
1368
+ projectsStore.setCurrentProject(project);
1369
+ }
1370
+ }
1371
+ async function initializeWorkspaceForExistingWorkflow(id) {
1372
+ try {
1373
+ const workflowData = await workflowsStore.fetchWorkflow(id);
1374
+ openWorkflow(workflowData);
1375
+ if (workflowData.parentFolder) {
1376
+ workflowsStore.setParentFolder(workflowData.parentFolder);
1377
+ }
1378
+ if (workflowData.meta?.onboardingId) {
1379
+ trackOpenWorkflowFromOnboardingTemplate();
1380
+ }
1381
+ if (workflowData.meta?.templateId?.startsWith("035_template_onboarding")) {
1382
+ aiTemplatesStarterCollectionStore.trackUserOpenedWorkflow(
1383
+ workflowData.meta.templateId.split("-").pop() ?? ""
1384
+ );
1385
+ }
1386
+ await projectsStore.setProjectNavActiveIdByWorkflowHomeProject(workflowData.homeProject);
1387
+ } catch (error) {
1388
+ if (error.httpStatusCode === 404) {
1389
+ return await router.replace({
1390
+ name: VIEWS.ENTITY_NOT_FOUND,
1391
+ params: { entityType: "workflow" }
1392
+ });
1393
+ }
1394
+ if (error.httpStatusCode === 403) {
1395
+ return await router.replace({
1396
+ name: VIEWS.ENTITY_UNAUTHORIZED,
1397
+ params: { entityType: "workflow" }
1398
+ });
1399
+ }
1400
+ toast.showError(error, i18n.baseText("openWorkflow.workflowNotFoundError"));
1401
+ void router.push({
1402
+ name: VIEWS.NEW_WORKFLOW
1403
+ });
1404
+ } finally {
1405
+ uiStore.nodeViewInitialized = true;
1406
+ initializedWorkflowId.value = workflowId.value;
1407
+ }
1408
+ }
1409
+ function updateNodesIssues() {
1410
+ nodeHelpers.updateNodesInputIssues();
1411
+ nodeHelpers.updateNodesCredentialsIssues();
1412
+ nodeHelpers.updateNodesParameterIssues();
1413
+ }
1414
+ function openWorkflow(data) {
1415
+ resetWorkspace();
1416
+ workflowHelpers.setDocumentTitle(data.name, "IDLE");
1417
+ initializeWorkspace(data);
1418
+ void externalHooks.run("workflow.open", {
1419
+ workflowId: data.id,
1420
+ workflowName: data.name
1421
+ });
1422
+ fitView();
1423
+ }
1424
+ function trackOpenWorkflowFromOnboardingTemplate() {
1425
+ telemetry.track(
1426
+ `User opened workflow from onboarding template with ID ${editableWorkflow.value.meta?.onboardingId}`,
1427
+ {
1428
+ workflow_id: workflowId.value
1429
+ }
1430
+ );
1431
+ }
1432
+ async function openTemplateFromWorkflowJSON(workflow) {
1433
+ if (!workflow.nodes || !workflow.connections) {
1434
+ toast.showError(
1435
+ new Error(i18n.baseText("nodeView.couldntLoadWorkflow.invalidWorkflowObject")),
1436
+ i18n.baseText("nodeView.couldntImportWorkflow")
1437
+ );
1438
+ await router.replace({ name: VIEWS.NEW_WORKFLOW });
1439
+ return;
1440
+ }
1441
+ resetWorkspace();
1442
+ canvasStore.startLoading();
1443
+ canvasStore.setLoadingText(i18n.baseText("nodeView.loadingTemplate"));
1444
+ workflowsStore.currentWorkflowExecutions = [];
1445
+ executionsStore.activeExecution = null;
1446
+ isBlankRedirect.value = true;
1447
+ const templateId = workflow.meta.templateId;
1448
+ const parentFolderId = route.query.parentFolderId;
1449
+ await router.replace({
1450
+ name: VIEWS.NEW_WORKFLOW,
1451
+ query: { templateId, parentFolderId }
1452
+ });
1453
+ await importTemplate({ id: templateId, name: workflow.name, workflow });
1454
+ uiStore.stateIsDirty = true;
1455
+ canvasStore.stopLoading();
1456
+ fitView();
1457
+ }
1458
+ async function openWorkflowTemplate(templateId) {
1459
+ resetWorkspace();
1460
+ canvasStore.startLoading();
1461
+ canvasStore.setLoadingText(i18n.baseText("nodeView.loadingTemplate"));
1462
+ workflowsStore.currentWorkflowExecutions = [];
1463
+ executionsStore.activeExecution = null;
1464
+ let data;
1465
+ try {
1466
+ void externalHooks.run("template.requested", { templateId });
1467
+ data = await templatesStore.getFixedWorkflowTemplate(templateId);
1468
+ if (!data) {
1469
+ throw new Error(
1470
+ i18n.baseText("nodeView.workflowTemplateWithIdCouldNotBeFound", {
1471
+ interpolate: { templateId }
1472
+ })
1473
+ );
1474
+ }
1475
+ } catch (error) {
1476
+ toast.showError(error, i18n.baseText("nodeView.couldntImportWorkflow"));
1477
+ await router.replace({ name: VIEWS.NEW_WORKFLOW });
1478
+ return;
1479
+ }
1480
+ trackOpenWorkflowTemplate(templateId);
1481
+ isBlankRedirect.value = true;
1482
+ await router.replace({ name: VIEWS.NEW_WORKFLOW, query: { templateId } });
1483
+ await importTemplate({ id: templateId, name: data.name, workflow: data.workflow });
1484
+ uiStore.stateIsDirty = true;
1485
+ canvasStore.stopLoading();
1486
+ void externalHooks.run("template.open", {
1487
+ templateId,
1488
+ templateName: data.name,
1489
+ workflow: data.workflow
1490
+ });
1491
+ fitView();
1492
+ }
1493
+ function trackOpenWorkflowTemplate(templateId) {
1494
+ telemetry.track("User inserted workflow template", {
1495
+ source: "workflow",
1496
+ template_id: tryToParseNumber(templateId),
1497
+ wf_template_repo_session_id: templatesStore.previousSessionId
1498
+ });
1499
+ }
1500
+ const triggerNodes = computed(() => {
1501
+ return editableWorkflow.value.nodes.filter(
1502
+ (node) => node.type === START_NODE_TYPE || nodeTypesStore.isTriggerNode(node.type)
1503
+ );
1504
+ });
1505
+ const containsTriggerNodes = computed(() => triggerNodes.value.length > 0);
1506
+ const allTriggerNodesDisabled = computed(() => {
1507
+ const disabledTriggerNodes = triggerNodes.value.filter((node) => node.disabled);
1508
+ return disabledTriggerNodes.length === triggerNodes.value.length;
1509
+ });
1510
+ function onTidyUp(event) {
1511
+ tidyUp(event);
1512
+ }
1513
+ function onExtractWorkflow(nodeIds) {
1514
+ void extractWorkflow(nodeIds);
1515
+ }
1516
+ function onUpdateNodesPosition(events) {
1517
+ updateNodesPosition(events, { trackHistory: true });
1518
+ }
1519
+ function onUpdateNodePosition(id, position) {
1520
+ updateNodePosition(id, position, { trackHistory: true });
1521
+ }
1522
+ function onRevertNodePosition({ nodeName, position }) {
1523
+ revertUpdateNodePosition(nodeName, { x: position[0], y: position[1] });
1524
+ }
1525
+ function onDeleteNode(id) {
1526
+ const matchedFallbackNode = fallbackNodes.value.findIndex((node) => node.id === id);
1527
+ if (matchedFallbackNode >= 0) {
1528
+ fallbackNodes.value.splice(matchedFallbackNode, 1);
1529
+ } else {
1530
+ deleteNode(id, { trackHistory: true });
1531
+ }
1532
+ }
1533
+ function onDeleteNodes(ids) {
1534
+ deleteNodes(ids);
1535
+ }
1536
+ function onRevertDeleteNode({ node }) {
1537
+ revertDeleteNode(node);
1538
+ }
1539
+ function onToggleNodeDisabled(id) {
1540
+ if (!checkIfEditingIsAllowed()) {
1541
+ return;
1542
+ }
1543
+ toggleNodesDisabled([id]);
1544
+ }
1545
+ function onRevertToggleNodeDisabled({ nodeName }) {
1546
+ revertToggleNodeDisabled(nodeName);
1547
+ }
1548
+ function onToggleNodesDisabled(ids) {
1549
+ if (!checkIfEditingIsAllowed()) {
1550
+ return;
1551
+ }
1552
+ toggleNodesDisabled(ids);
1553
+ }
1554
+ function onClickNode(_id, event) {
1555
+ lastClickPosition.value = [event.x, event.y];
1556
+ closeNodeCreator();
1557
+ }
1558
+ function onSetNodeActivated(id, event) {
1559
+ if (event?.metaKey || event?.ctrlKey) {
1560
+ const didOpen = tryToOpenSubworkflowInNewTab(id);
1561
+ if (didOpen) {
1562
+ return;
1563
+ }
1564
+ }
1565
+ setNodeActive(id);
1566
+ }
1567
+ function onOpenSubWorkflow(id) {
1568
+ tryToOpenSubworkflowInNewTab(id);
1569
+ }
1570
+ function onSetNodeDeactivated() {
1571
+ clearNodeActive();
1572
+ }
1573
+ function onSetNodeSelected(id) {
1574
+ closeNodeCreator();
1575
+ setNodeSelected(id);
1576
+ }
1577
+ async function onCopyNodes(ids) {
1578
+ await copyNodes(ids);
1579
+ toast.showMessage({ title: i18n.baseText("generic.copiedToClipboard"), type: "success" });
1580
+ }
1581
+ async function onClipboardPaste(plainTextData) {
1582
+ if (getNodeViewTab(route) !== MAIN_HEADER_TABS.WORKFLOW || !keyBindingsEnabled.value || !checkIfEditingIsAllowed()) {
1583
+ return;
1584
+ }
1585
+ let workflowData = null;
1586
+ if (plainTextData.match(VALID_WORKFLOW_IMPORT_URL_REGEX)) {
1587
+ const importConfirm = await message.confirm(
1588
+ i18n.baseText("nodeView.confirmMessage.onClipboardPasteEvent.message", {
1589
+ interpolate: { plainTextData }
1590
+ }),
1591
+ i18n.baseText("nodeView.confirmMessage.onClipboardPasteEvent.headline"),
1592
+ {
1593
+ type: "warning",
1594
+ confirmButtonText: i18n.baseText(
1595
+ "nodeView.confirmMessage.onClipboardPasteEvent.confirmButtonText"
1596
+ ),
1597
+ cancelButtonText: i18n.baseText(
1598
+ "nodeView.confirmMessage.onClipboardPasteEvent.cancelButtonText"
1599
+ )
1600
+ }
1601
+ );
1602
+ if (importConfirm !== MODAL_CONFIRM) {
1603
+ return;
1604
+ }
1605
+ workflowData = await fetchWorkflowDataFromUrl(plainTextData);
1606
+ } else {
1607
+ workflowData = jsonParse(plainTextData, { fallbackValue: null });
1608
+ }
1609
+ if (!workflowData) {
1610
+ return;
1611
+ }
1612
+ const result = await importWorkflowData(workflowData, "paste", {
1613
+ importTags: false,
1614
+ viewport: viewportBoundaries.value
1615
+ });
1616
+ selectNodes(result.nodes?.map((node) => node.id) ?? []);
1617
+ }
1618
+ async function onCutNodes(ids) {
1619
+ if (isCanvasReadOnly.value) {
1620
+ await copyNodes(ids);
1621
+ } else {
1622
+ await cutNodes(ids);
1623
+ }
1624
+ }
1625
+ async function onDuplicateNodes(ids) {
1626
+ if (!checkIfEditingIsAllowed()) {
1627
+ return;
1628
+ }
1629
+ const newIds = await duplicateNodes(ids, {
1630
+ viewport: viewportBoundaries.value
1631
+ });
1632
+ selectNodes(newIds);
1633
+ }
1634
+ function onPinNodes(ids, source) {
1635
+ if (!checkIfEditingIsAllowed()) {
1636
+ return;
1637
+ }
1638
+ toggleNodesPinned(ids, source);
1639
+ }
1640
+ async function onSaveWorkflow() {
1641
+ const workflowIsSaved = !uiStore.stateIsDirty && !workflowsStore.isNewWorkflow;
1642
+ const workflowIsArchived = workflowsStore.workflow.isArchived;
1643
+ if (workflowIsSaved || workflowIsArchived) {
1644
+ return;
1645
+ }
1646
+ const saved = await workflowSaving.saveCurrentWorkflow();
1647
+ if (saved) {
1648
+ canvasEventBus.emit("saved:workflow");
1649
+ }
1650
+ }
1651
+ function addWorkflowSavedEventBindings() {
1652
+ canvasEventBus.on("saved:workflow", npsSurveyStore.fetchPromptsData);
1653
+ canvasEventBus.on("saved:workflow", onSaveFromWithinNDV);
1654
+ }
1655
+ function removeWorkflowSavedEventBindings() {
1656
+ canvasEventBus.off("saved:workflow", npsSurveyStore.fetchPromptsData);
1657
+ canvasEventBus.off("saved:workflow", onSaveFromWithinNDV);
1658
+ canvasEventBus.off("saved:workflow", onSaveFromWithinExecutionDebug);
1659
+ }
1660
+ async function onSaveFromWithinNDV() {
1661
+ if (ndvStore.activeNodeName) {
1662
+ toast.showMessage({
1663
+ title: i18n.baseText("generic.workflowSaved"),
1664
+ type: "success"
1665
+ });
1666
+ }
1667
+ }
1668
+ async function onCreateWorkflow() {
1669
+ await router.push({ name: VIEWS.NEW_WORKFLOW });
1670
+ }
1671
+ function onRenameNode(name) {
1672
+ if (ndvStore.activeNode?.name) {
1673
+ void renameNode(ndvStore.activeNode.name, name);
1674
+ }
1675
+ }
1676
+ async function onOpenRenameNodeModal(id) {
1677
+ const currentName = workflowsStore.getNodeById(id)?.name ?? "";
1678
+ const activeElement = document.activeElement;
1679
+ if (activeElement && activeElement.tagName === "INPUT") {
1680
+ return;
1681
+ }
1682
+ if (!keyBindingsEnabled.value || document.querySelector(".rename-prompt")) return;
1683
+ try {
1684
+ const promptResponsePromise = message.prompt(
1685
+ i18n.baseText("nodeView.prompt.newName") + ":",
1686
+ i18n.baseText("nodeView.prompt.renameNode") + `: ${currentName}`,
1687
+ {
1688
+ customClass: "rename-prompt",
1689
+ confirmButtonText: i18n.baseText("nodeView.prompt.rename"),
1690
+ cancelButtonText: i18n.baseText("nodeView.prompt.cancel"),
1691
+ inputErrorMessage: i18n.baseText("nodeView.prompt.invalidName"),
1692
+ inputValue: currentName,
1693
+ inputValidator: (value) => {
1694
+ if (!value.trim()) {
1695
+ return i18n.baseText("nodeView.prompt.invalidName");
1696
+ }
1697
+ return true;
1698
+ }
1699
+ }
1700
+ );
1701
+ await nextTick();
1702
+ const nameInput = document.querySelector(".rename-prompt .el-input__inner");
1703
+ nameInput?.focus();
1704
+ nameInput?.select();
1705
+ const promptResponse = await promptResponsePromise;
1706
+ if (promptResponse.action === MODAL_CONFIRM) {
1707
+ await renameNode(currentName, promptResponse.value, { trackHistory: true });
1708
+ }
1709
+ } catch (e) {
1710
+ }
1711
+ }
1712
+ async function onRevertRenameNode({
1713
+ currentName,
1714
+ newName
1715
+ }) {
1716
+ await revertRenameNode(currentName, newName);
1717
+ }
1718
+ async function onRevertReplaceNodeParameters({
1719
+ nodeId,
1720
+ currentProperties,
1721
+ newProperties
1722
+ }) {
1723
+ await revertReplaceNodeParameters(nodeId, currentProperties, newProperties);
1724
+ }
1725
+ function onUpdateNodeParameters(id, parameters) {
1726
+ setNodeParameters(id, parameters);
1727
+ }
1728
+ function onUpdateNodeInputs(id) {
1729
+ revalidateNodeInputConnections(id);
1730
+ }
1731
+ function onUpdateNodeOutputs(id) {
1732
+ revalidateNodeOutputConnections(id);
1733
+ }
1734
+ function onClickNodeAdd(source, sourceHandle) {
1735
+ nodeCreatorStore.openNodeCreatorForConnectingNode({
1736
+ connection: {
1737
+ source,
1738
+ sourceHandle
1739
+ },
1740
+ eventSource: NODE_CREATOR_OPEN_SOURCES.PLUS_ENDPOINT
1741
+ });
1742
+ }
1743
+ async function loadCredentials() {
1744
+ let options;
1745
+ if (workflowId.value) {
1746
+ options = { workflowId: workflowId.value };
1747
+ } else {
1748
+ const queryParam = typeof route.query?.projectId === "string" ? route.query?.projectId : void 0;
1749
+ const projectId = queryParam ?? projectsStore.personalProject?.id;
1750
+ if (projectId === void 0) {
1751
+ throw new Error(
1752
+ "Could not find projectId in the query nor could I find the personal project in the project store"
1753
+ );
1754
+ }
1755
+ options = { projectId };
1756
+ }
1757
+ await credentialsStore.fetchAllCredentialsForWorkflow(options);
1758
+ }
1759
+ function onCreateConnection(connection) {
1760
+ createConnection(connection, { trackHistory: true });
1761
+ }
1762
+ function onRevertCreateConnection({ connection }) {
1763
+ revertCreateConnection(connection);
1764
+ }
1765
+ function onCreateConnectionCancelled(event, position, mouseEvent) {
1766
+ const preventDefault = (mouseEvent?.target).classList?.contains("clickable");
1767
+ if (preventDefault) {
1768
+ return;
1769
+ }
1770
+ uiStore.lastInteractedWithNodeId = event.nodeId;
1771
+ uiStore.lastInteractedWithNodeHandle = event.handleId;
1772
+ uiStore.lastCancelledConnectionPosition = [position.x, position.y];
1773
+ setTimeout(() => {
1774
+ if (!event.nodeId) return;
1775
+ nodeCreatorStore.openNodeCreatorForConnectingNode({
1776
+ connection: {
1777
+ source: event.nodeId,
1778
+ sourceHandle: event.handleId
1779
+ },
1780
+ eventSource: NODE_CREATOR_OPEN_SOURCES.NODE_CONNECTION_DROP
1781
+ });
1782
+ });
1783
+ }
1784
+ function onDeleteConnection(connection) {
1785
+ deleteConnection(connection, { trackHistory: true });
1786
+ }
1787
+ function onRevertDeleteConnection({ connection }) {
1788
+ revertDeleteConnection(connection);
1789
+ }
1790
+ async function importWorkflowExact({ workflow: workflowData }) {
1791
+ if (!workflowData.nodes || !workflowData.connections) {
1792
+ throw new Error("Invalid workflow object");
1793
+ }
1794
+ resetWorkspace();
1795
+ await initializeData();
1796
+ initializeWorkspace({
1797
+ ...workflowData,
1798
+ nodes: getNodesWithNormalizedPosition(workflowData.nodes)
1799
+ });
1800
+ fitView();
1801
+ }
1802
+ async function onImportWorkflowDataEvent(data) {
1803
+ const workflowData = data.data;
1804
+ await importWorkflowData(workflowData, "file", {
1805
+ viewport: viewportBoundaries.value,
1806
+ regenerateIds: data.regenerateIds === true || data.regenerateIds === void 0
1807
+ });
1808
+ fitView();
1809
+ selectNodes(workflowData.nodes?.map((node) => node.id) ?? []);
1810
+ if (data.tidyUp) {
1811
+ const nodesIdsToTidyUp = data.nodesIdsToTidyUp;
1812
+ setTimeout(() => {
1813
+ canvasEventBus.emit("tidyUp", {
1814
+ source: "import-workflow-data",
1815
+ nodeIdsFilter: nodesIdsToTidyUp
1816
+ });
1817
+ }, 0);
1818
+ }
1819
+ }
1820
+ async function onImportWorkflowUrlEvent(data) {
1821
+ const workflowData = await fetchWorkflowDataFromUrl(data.url);
1822
+ if (!workflowData) {
1823
+ return;
1824
+ }
1825
+ await importWorkflowData(workflowData, "url", {
1826
+ viewport: viewportBoundaries.value
1827
+ });
1828
+ fitView();
1829
+ selectNodes(workflowData.nodes?.map((node) => node.id) ?? []);
1830
+ }
1831
+ function addImportEventBindings() {
1832
+ nodeViewEventBus.on("importWorkflowData", onImportWorkflowDataEvent);
1833
+ nodeViewEventBus.on("importWorkflowUrl", onImportWorkflowUrlEvent);
1834
+ nodeViewEventBus.on("openChat", onOpenChat);
1835
+ }
1836
+ function removeImportEventBindings() {
1837
+ nodeViewEventBus.off("importWorkflowData", onImportWorkflowDataEvent);
1838
+ nodeViewEventBus.off("importWorkflowUrl", onImportWorkflowUrlEvent);
1839
+ nodeViewEventBus.off("openChat", onOpenChat);
1840
+ }
1841
+ async function onAddNodesAndConnections({ nodes, connections }, dragAndDrop = false, position) {
1842
+ if (!checkIfEditingIsAllowed()) {
1843
+ return;
1844
+ }
1845
+ const addedNodes = await addNodes(nodes, {
1846
+ dragAndDrop,
1847
+ position,
1848
+ viewport: viewportBoundaries.value,
1849
+ trackHistory: true,
1850
+ telemetry: true
1851
+ });
1852
+ const offsetIndex = editableWorkflow.value.nodes.length - nodes.length;
1853
+ const mappedConnections = connections.map(({ from, to }) => {
1854
+ const fromNode = editableWorkflow.value.nodes[offsetIndex + from.nodeIndex];
1855
+ const toNode = editableWorkflow.value.nodes[offsetIndex + to.nodeIndex];
1856
+ const type = from.type ?? to.type ?? NodeConnectionTypes.Main;
1857
+ return {
1858
+ source: fromNode.id,
1859
+ sourceHandle: createCanvasConnectionHandleString({
1860
+ mode: CanvasConnectionMode.Output,
1861
+ type: isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main,
1862
+ index: from.outputIndex ?? 0
1863
+ }),
1864
+ target: toNode.id,
1865
+ targetHandle: createCanvasConnectionHandleString({
1866
+ mode: CanvasConnectionMode.Input,
1867
+ type: isValidNodeConnectionType(type) ? type : NodeConnectionTypes.Main,
1868
+ index: to.inputIndex ?? 0
1869
+ }),
1870
+ data: {
1871
+ source: {
1872
+ index: from.outputIndex ?? 0,
1873
+ type
1874
+ },
1875
+ target: {
1876
+ index: to.inputIndex ?? 0,
1877
+ type
1878
+ }
1879
+ }
1880
+ };
1881
+ });
1882
+ await addConnections(mappedConnections);
1883
+ uiStore.resetLastInteractedWith();
1884
+ if (addedNodes.length > 0) {
1885
+ selectNodes([addedNodes[addedNodes.length - 1].id]);
1886
+ }
1887
+ }
1888
+ async function onRevertAddNode({ node }) {
1889
+ await revertAddNode(node.name);
1890
+ }
1891
+ function onSwitchActiveNode(nodeName) {
1892
+ const node = workflowsStore.getNodeByName(nodeName);
1893
+ if (!node) return;
1894
+ setNodeActiveByName(nodeName);
1895
+ selectNodes([node.id]);
1896
+ }
1897
+ function onOpenSelectiveNodeCreator(node, connectionType, connectionIndex = 0) {
1898
+ nodeCreatorStore.openSelectiveNodeCreator({ node, connectionType, connectionIndex });
1899
+ }
1900
+ function onToggleNodeCreator(options) {
1901
+ nodeCreatorStore.setNodeCreatorState(options);
1902
+ if (!options.createNodeActive && !options.hasAddedNodes) {
1903
+ uiStore.resetLastInteractedWith();
1904
+ }
1905
+ }
1906
+ function onOpenNodeCreatorFromCanvas(source) {
1907
+ onToggleNodeCreator({ createNodeActive: true, source });
1908
+ }
1909
+ function onOpenNodeCreatorForTriggerNodes(source) {
1910
+ nodeCreatorStore.openNodeCreatorForTriggerNodes(source);
1911
+ }
1912
+ function onToggleFocusPanel() {
1913
+ focusPanelStore.toggleFocusPanel();
1914
+ telemetry.track(`User ${focusPanelStore.focusPanelActive ? "opened" : "closed"} focus panel`, {
1915
+ source: "canvasKeyboardShortcut",
1916
+ parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat,
1917
+ parameterCount: focusPanelStore.focusedNodeParametersInTelemetryFormat.length
1918
+ });
1919
+ }
1920
+ function closeNodeCreator() {
1921
+ if (nodeCreatorStore.isCreateNodeActive) {
1922
+ nodeCreatorStore.isCreateNodeActive = false;
1923
+ }
1924
+ }
1925
+ function onCreateSticky() {
1926
+ void onAddNodesAndConnections({ nodes: [{ type: STICKY_NODE_TYPE }], connections: [] });
1927
+ }
1928
+ function onClickConnectionAdd(connection) {
1929
+ nodeCreatorStore.openNodeCreatorForConnectingNode({
1930
+ connection,
1931
+ eventSource: NODE_CREATOR_OPEN_SOURCES.NODE_CONNECTION_ACTION
1932
+ });
1933
+ }
1934
+ const workflowPermissions = computed(() => {
1935
+ return workflowId.value ? getResourcePermissions(workflowsStore.getWorkflowById(workflowId.value)?.scopes).workflow : {};
1936
+ });
1937
+ const projectPermissions = computed(() => {
1938
+ const project = route.query?.projectId ? projectsStore.myProjects.find((p) => p.id === route.query.projectId) : projectsStore.currentProject ?? projectsStore.personalProject;
1939
+ return getResourcePermissions(project?.scopes);
1940
+ });
1941
+ const isStoppingExecution = ref(false);
1942
+ const isWorkflowRunning = computed(() => workflowsStore.isWorkflowRunning);
1943
+ const isExecutionWaitingForWebhook = computed(() => workflowsStore.executionWaitingForWebhook);
1944
+ const isExecutionDisabled = computed(() => {
1945
+ if (containsChatTriggerNodes.value && isOnlyChatTriggerNodeActive.value && !chatTriggerNodePinnedData.value) {
1946
+ return true;
1947
+ }
1948
+ return !containsTriggerNodes.value || allTriggerNodesDisabled.value;
1949
+ });
1950
+ const isRunWorkflowButtonVisible = computed(
1951
+ () => !isOnlyChatTriggerNodeActive.value || chatTriggerNodePinnedData.value
1952
+ );
1953
+ const isStopExecutionButtonVisible = computed(
1954
+ () => isWorkflowRunning.value && !isExecutionWaitingForWebhook.value
1955
+ );
1956
+ const isStopWaitingForWebhookButtonVisible = computed(
1957
+ () => isWorkflowRunning.value && isExecutionWaitingForWebhook.value
1958
+ );
1959
+ async function onRunWorkflowToNode(id) {
1960
+ const node = workflowsStore.getNodeById(id);
1961
+ if (!node) return;
1962
+ if (needsAgentInput(node) && nodeTypesStore.isToolNode(node.type)) {
1963
+ uiStore.openModalWithData({
1964
+ name: FROM_AI_PARAMETERS_MODAL_KEY,
1965
+ data: {
1966
+ nodeName: node.name
1967
+ }
1968
+ });
1969
+ } else {
1970
+ trackRunWorkflowToNode(node);
1971
+ agentRequestStore.clearAgentRequests(workflowsStore.workflowId, node.id);
1972
+ void runWorkflow({ destinationNode: node.name, source: "Node.executeNode" });
1973
+ }
1974
+ }
1975
+ function trackRunWorkflowToNode(node) {
1976
+ const telemetryPayload = {
1977
+ node_type: node.type,
1978
+ workflow_id: workflowsStore.workflowId,
1979
+ source: "canvas",
1980
+ push_ref: ndvStore.pushRef
1981
+ };
1982
+ telemetry.track("User clicked execute node button", telemetryPayload);
1983
+ void externalHooks.run("nodeView.onRunNode", telemetryPayload);
1984
+ }
1985
+ async function onOpenExecution(executionId, nodeId) {
1986
+ canvasStore.startLoading();
1987
+ resetWorkspace();
1988
+ await initializeData();
1989
+ const data = await openExecution(executionId, nodeId);
1990
+ if (!data) {
1991
+ return;
1992
+ }
1993
+ void nextTick(() => {
1994
+ updateNodesIssues();
1995
+ });
1996
+ canvasStore.stopLoading();
1997
+ fitView();
1998
+ canvasEventBus.emit("open:execution", data);
1999
+ void externalHooks.run("execution.open", {
2000
+ workflowId: data.workflowData.id,
2001
+ workflowName: data.workflowData.name,
2002
+ executionId
2003
+ });
2004
+ telemetry.track("User opened read-only execution", {
2005
+ workflow_id: data.workflowData.id,
2006
+ execution_mode: data.mode,
2007
+ execution_finished: data.finished
2008
+ });
2009
+ }
2010
+ function onExecutionOpenedWithError(data) {
2011
+ if (!data.finished && data.data?.resultData?.error) {
2012
+ let nodeErrorFound = false;
2013
+ if (data.data.resultData.runData) {
2014
+ const runData = data.data.resultData.runData;
2015
+ errorCheck: for (const nodeName of Object.keys(runData)) {
2016
+ for (const taskData of runData[nodeName]) {
2017
+ if (taskData.error) {
2018
+ nodeErrorFound = true;
2019
+ break errorCheck;
2020
+ }
2021
+ }
2022
+ }
2023
+ }
2024
+ if (!nodeErrorFound && (data.data.resultData.error.stack ?? data.data.resultData.error.message)) {
2025
+ console.error(`Execution ${data.id} error:`);
2026
+ console.error(data.data.resultData.error.stack);
2027
+ toast.showMessage({
2028
+ title: i18n.baseText("nodeView.showError.workflowError"),
2029
+ message: data.data.resultData.error.message,
2030
+ type: "error",
2031
+ duration: 0
2032
+ });
2033
+ }
2034
+ }
2035
+ }
2036
+ function onExecutionOpenedWithWaitTill(data) {
2037
+ if (data.waitTill) {
2038
+ toast.showMessage({
2039
+ title: i18n.baseText("nodeView.thisExecutionHasntFinishedYet"),
2040
+ message: h(_sfc_main$2),
2041
+ type: "warning",
2042
+ duration: 0
2043
+ });
2044
+ }
2045
+ }
2046
+ function addExecutionOpenedEventBindings() {
2047
+ canvasEventBus.on("open:execution", onExecutionOpenedWithError);
2048
+ canvasEventBus.on("open:execution", onExecutionOpenedWithWaitTill);
2049
+ }
2050
+ function removeExecutionOpenedEventBindings() {
2051
+ canvasEventBus.off("open:execution", onExecutionOpenedWithError);
2052
+ canvasEventBus.off("open:execution", onExecutionOpenedWithWaitTill);
2053
+ }
2054
+ async function onStopExecution() {
2055
+ isStoppingExecution.value = true;
2056
+ await stopCurrentExecution();
2057
+ isStoppingExecution.value = false;
2058
+ }
2059
+ async function onStopWaitingForWebhook() {
2060
+ await stopWaitingForWebhook();
2061
+ }
2062
+ function onRunWorkflowButtonMouseEnter() {
2063
+ nodeViewEventBus.emit("runWorkflowButton:mouseenter");
2064
+ }
2065
+ function onRunWorkflowButtonMouseLeave() {
2066
+ nodeViewEventBus.emit("runWorkflowButton:mouseleave");
2067
+ }
2068
+ const chatTriggerNode = computed(() => {
2069
+ return editableWorkflow.value.nodes.find((node) => node.type === CHAT_TRIGGER_NODE_TYPE);
2070
+ });
2071
+ const containsChatTriggerNodes = computed(() => {
2072
+ return !isExecutionWaitingForWebhook.value && !!editableWorkflow.value.nodes.find(
2073
+ (node) => [MANUAL_CHAT_TRIGGER_NODE_TYPE, CHAT_TRIGGER_NODE_TYPE].includes(node.type) && node.disabled !== true
2074
+ );
2075
+ });
2076
+ const isOnlyChatTriggerNodeActive = computed(() => {
2077
+ return triggerNodes.value.every((node) => node.disabled || node.type === CHAT_TRIGGER_NODE_TYPE);
2078
+ });
2079
+ const chatTriggerNodePinnedData = computed(() => {
2080
+ if (!chatTriggerNode.value) return null;
2081
+ return workflowsStore.pinDataByNodeName(chatTriggerNode.value.name);
2082
+ });
2083
+ function onOpenChat() {
2084
+ startChat("main");
2085
+ }
2086
+ const evaluationTriggerNode = computed(() => {
2087
+ return editableWorkflow.value.nodes.find((node) => node.type === EVALUATION_TRIGGER_NODE_TYPE);
2088
+ });
2089
+ function addUndoRedoEventBindings() {
2090
+ historyBus.on("nodeMove", onRevertNodePosition);
2091
+ historyBus.on("revertAddNode", onRevertAddNode);
2092
+ historyBus.on("revertRemoveNode", onRevertDeleteNode);
2093
+ historyBus.on("revertAddConnection", onRevertCreateConnection);
2094
+ historyBus.on("revertRemoveConnection", onRevertDeleteConnection);
2095
+ historyBus.on("revertRenameNode", onRevertRenameNode);
2096
+ historyBus.on("revertReplaceNodeParameters", onRevertReplaceNodeParameters);
2097
+ historyBus.on("enableNodeToggle", onRevertToggleNodeDisabled);
2098
+ }
2099
+ function removeUndoRedoEventBindings() {
2100
+ historyBus.off("nodeMove", onRevertNodePosition);
2101
+ historyBus.off("revertAddNode", onRevertAddNode);
2102
+ historyBus.off("revertRemoveNode", onRevertDeleteNode);
2103
+ historyBus.off("revertAddConnection", onRevertCreateConnection);
2104
+ historyBus.off("revertRemoveConnection", onRevertDeleteConnection);
2105
+ historyBus.off("revertRenameNode", onRevertRenameNode);
2106
+ historyBus.off("revertReplaceNodeParameters", onRevertReplaceNodeParameters);
2107
+ historyBus.off("enableNodeToggle", onRevertToggleNodeDisabled);
2108
+ }
2109
+ async function onSourceControlPull() {
2110
+ try {
2111
+ await Promise.all([
2112
+ environmentsStore.fetchAllVariables(),
2113
+ tagsStore.fetchAll(),
2114
+ loadCredentials()
2115
+ ]);
2116
+ if (workflowId.value && !uiStore.stateIsDirty) {
2117
+ const workflowData = await workflowsStore.fetchWorkflow(workflowId.value);
2118
+ if (workflowData) {
2119
+ workflowHelpers.setDocumentTitle(workflowData.name, "IDLE");
2120
+ openWorkflow(workflowData);
2121
+ }
2122
+ }
2123
+ } catch (error) {
2124
+ console.error(error);
2125
+ }
2126
+ }
2127
+ function addSourceControlEventBindings() {
2128
+ sourceControlEventBus.on("pull", onSourceControlPull);
2129
+ }
2130
+ function removeSourceControlEventBindings() {
2131
+ sourceControlEventBus.off("pull", onSourceControlPull);
2132
+ }
2133
+ function addPostMessageEventBindings() {
2134
+ window.addEventListener("message", onPostMessageReceived);
2135
+ }
2136
+ function removePostMessageEventBindings() {
2137
+ window.removeEventListener("message", onPostMessageReceived);
2138
+ }
2139
+ function emitPostMessageReady() {
2140
+ if (window.parent) {
2141
+ window.parent.postMessage(
2142
+ JSON.stringify({ command: "n8nReady", version: rootStore.versionCli }),
2143
+ "*"
2144
+ );
2145
+ }
2146
+ }
2147
+ async function onPostMessageReceived(messageEvent) {
2148
+ if (!messageEvent || typeof messageEvent.data !== "string" || !messageEvent.data?.includes?.('"command"')) {
2149
+ return;
2150
+ }
2151
+ try {
2152
+ const json = JSON.parse(messageEvent.data);
2153
+ if (json && json.command === "openWorkflow") {
2154
+ try {
2155
+ await importWorkflowExact(json);
2156
+ canOpenNDV.value = json.canOpenNDV ?? true;
2157
+ hideNodeIssues.value = json.hideNodeIssues ?? false;
2158
+ isExecutionPreview.value = false;
2159
+ } catch (e) {
2160
+ if (window.top) {
2161
+ window.top.postMessage(
2162
+ JSON.stringify({
2163
+ command: "error",
2164
+ message: i18n.baseText("openWorkflow.workflowImportError")
2165
+ }),
2166
+ "*"
2167
+ );
2168
+ }
2169
+ toast.showError(e, i18n.baseText("openWorkflow.workflowImportError"));
2170
+ }
2171
+ } else if (json && json.command === "openExecution") {
2172
+ try {
2173
+ isProductionExecutionPreview.value = json.executionMode !== "manual" && json.executionMode !== "evaluation";
2174
+ await onOpenExecution(json.executionId, json.nodeId);
2175
+ canOpenNDV.value = json.canOpenNDV ?? true;
2176
+ hideNodeIssues.value = json.hideNodeIssues ?? false;
2177
+ isExecutionPreview.value = true;
2178
+ } catch (e) {
2179
+ if (window.top) {
2180
+ window.top.postMessage(
2181
+ JSON.stringify({
2182
+ command: "error",
2183
+ message: i18n.baseText("nodeView.showError.openExecution.title")
2184
+ }),
2185
+ "*"
2186
+ );
2187
+ }
2188
+ toast.showMessage({
2189
+ title: i18n.baseText("nodeView.showError.openExecution.title"),
2190
+ message: e.message,
2191
+ type: "error"
2192
+ });
2193
+ }
2194
+ } else if (json?.command === "setActiveExecution") {
2195
+ executionsStore.activeExecution = await executionsStore.fetchExecution(
2196
+ json.executionId
2197
+ );
2198
+ }
2199
+ } catch (e) {
2200
+ }
2201
+ }
2202
+ function checkIfEditingIsAllowed() {
2203
+ if (!initializedWorkflowId.value) {
2204
+ return true;
2205
+ }
2206
+ if (readOnlyNotification.value?.visible) {
2207
+ return false;
2208
+ }
2209
+ if (isReadOnlyRoute.value || isReadOnlyEnvironment.value) {
2210
+ const messageContext = isReadOnlyRoute.value ? "executions" : "workflows";
2211
+ readOnlyNotification.value = toast.showMessage({
2212
+ title: i18n.baseText(
2213
+ isReadOnlyEnvironment.value ? `readOnlyEnv.showMessage.${messageContext}.title` : "readOnly.showMessage.executions.title"
2214
+ ),
2215
+ message: i18n.baseText(
2216
+ isReadOnlyEnvironment.value ? `readOnlyEnv.showMessage.${messageContext}.message` : "readOnly.showMessage.executions.message"
2217
+ ),
2218
+ type: "info"
2219
+ });
2220
+ return false;
2221
+ }
2222
+ return true;
2223
+ }
2224
+ function checkIfRouteIsAllowed() {
2225
+ if (isReadOnlyEnvironment.value && [VIEWS.NEW_WORKFLOW, VIEWS.TEMPLATE_IMPORT].find((view) => view === route.name)) {
2226
+ void nextTick(async () => {
2227
+ resetWorkspace();
2228
+ uiStore.stateIsDirty = false;
2229
+ await router.replace({ name: VIEWS.HOMEPAGE });
2230
+ });
2231
+ }
2232
+ }
2233
+ async function initializeDebugMode() {
2234
+ workflowHelpers.setDocumentTitle(workflowsStore.workflowName, "DEBUG");
2235
+ if (!workflowsStore.isInDebugMode) {
2236
+ await applyExecutionData(route.params.executionId);
2237
+ workflowsStore.isInDebugMode = true;
2238
+ }
2239
+ canvasEventBus.on("saved:workflow", onSaveFromWithinExecutionDebug);
2240
+ }
2241
+ async function onSaveFromWithinExecutionDebug() {
2242
+ if (route.name !== VIEWS.EXECUTION_DEBUG) return;
2243
+ await router.replace({
2244
+ name: VIEWS.WORKFLOW,
2245
+ params: { name: workflowId.value }
2246
+ });
2247
+ }
2248
+ const viewportTransform = ref({ x: 0, y: 0, zoom: 1 });
2249
+ const viewportDimensions = ref({ width: 0, height: 0 });
2250
+ const viewportBoundaries = computed(
2251
+ () => getBounds(viewportTransform.value, viewportDimensions.value)
2252
+ );
2253
+ function onViewportChange(viewport, dimensions) {
2254
+ viewportTransform.value = viewport;
2255
+ viewportDimensions.value = dimensions;
2256
+ uiStore.nodeViewOffsetPosition = [viewport.x, viewport.y];
2257
+ }
2258
+ function fitView() {
2259
+ setTimeout(() => canvasEventBus.emit("fitView"));
2260
+ }
2261
+ function selectNodes(ids) {
2262
+ setTimeout(() => canvasEventBus.emit("nodes:select", { ids }));
2263
+ }
2264
+ function onClickPane(position) {
2265
+ lastClickPosition.value = [position.x, position.y];
2266
+ onSetNodeSelected();
2267
+ }
2268
+ function onSelectionEnd(position) {
2269
+ lastClickPosition.value = [position.x, position.y];
2270
+ }
2271
+ async function onDragAndDrop(position, event) {
2272
+ if (!event.dataTransfer) {
2273
+ return;
2274
+ }
2275
+ const dropData = jsonParse(
2276
+ event.dataTransfer.getData(DRAG_EVENT_DATA_KEY)
2277
+ );
2278
+ if (dropData) {
2279
+ const insertNodePosition = [position.x, position.y];
2280
+ await onAddNodesAndConnections(dropData, true, insertNodePosition);
2281
+ onToggleNodeCreator({ createNodeActive: false, hasAddedNodes: true });
2282
+ }
2283
+ }
2284
+ function registerCustomActions() {
2285
+ registerCustomAction({
2286
+ key: "openNodeDetail",
2287
+ action: ({ node }) => {
2288
+ setNodeActiveByName(node);
2289
+ }
2290
+ });
2291
+ registerCustomAction({
2292
+ key: "openSelectiveNodeCreator",
2293
+ action: ({
2294
+ creatorview: creatorView,
2295
+ connectiontype: connectionType,
2296
+ node
2297
+ }) => {
2298
+ nodeCreatorStore.openSelectiveNodeCreator({ node, connectionType, creatorView });
2299
+ }
2300
+ });
2301
+ registerCustomAction({
2302
+ key: "showNodeCreator",
2303
+ action: () => {
2304
+ ndvStore.activeNodeName = null;
2305
+ void nextTick(() => {
2306
+ void onOpenNodeCreatorForTriggerNodes(NODE_CREATOR_OPEN_SOURCES.TAB);
2307
+ });
2308
+ }
2309
+ });
2310
+ }
2311
+ function unregisterCustomActions() {
2312
+ unregisterCustomAction("openNodeDetail");
2313
+ unregisterCustomAction("openSelectiveNodeCreator");
2314
+ unregisterCustomAction("showNodeCreator");
2315
+ }
2316
+ function showAddFirstStepIfEnabled() {
2317
+ if (uiStore.addFirstStepOnLoad) {
2318
+ void onOpenNodeCreatorForTriggerNodes(NODE_CREATOR_OPEN_SOURCES.TRIGGER_PLACEHOLDER_BUTTON);
2319
+ uiStore.addFirstStepOnLoad = false;
2320
+ }
2321
+ }
2322
+ function updateNodeRoute(nodeId) {
2323
+ const nodeUi = workflowsStore.findNodeByPartialId(nodeId);
2324
+ if (nodeUi) {
2325
+ setNodeActive(nodeUi.id);
2326
+ } else {
2327
+ toast.showToast({
2328
+ title: i18n.baseText("nodeView.showMessage.ndvUrl.missingNodes.title"),
2329
+ message: i18n.baseText("nodeView.showMessage.ndvUrl.missingNodes.content"),
2330
+ type: "warning"
2331
+ });
2332
+ void router.replace({
2333
+ name: route.name,
2334
+ params: { name: workflowId.value }
2335
+ });
2336
+ }
2337
+ }
2338
+ watch(
2339
+ () => route.name,
2340
+ async (newRouteName, oldRouteName) => {
2341
+ const force = newRouteName === VIEWS.NEW_WORKFLOW && oldRouteName === VIEWS.WORKFLOW || newRouteName === VIEWS.WORKFLOW && oldRouteName === VIEWS.NEW_WORKFLOW;
2342
+ await initializeRoute(force);
2343
+ }
2344
+ );
2345
+ watch(
2346
+ () => {
2347
+ return isLoading.value || isCanvasReadOnly.value || editableWorkflow.value.nodes.length !== 0;
2348
+ },
2349
+ (isReadOnlyOrLoading) => {
2350
+ const defaultFallbackNodes = [
2351
+ {
2352
+ id: CanvasNodeRenderType.AddNodes,
2353
+ name: CanvasNodeRenderType.AddNodes,
2354
+ type: CanvasNodeRenderType.AddNodes,
2355
+ typeVersion: 1,
2356
+ position: [0, 0],
2357
+ parameters: {}
2358
+ }
2359
+ ];
2360
+ if (builderStore.isAIBuilderEnabled && builderStore.isAssistantEnabled) {
2361
+ defaultFallbackNodes.unshift({
2362
+ id: CanvasNodeRenderType.AIPrompt,
2363
+ name: CanvasNodeRenderType.AIPrompt,
2364
+ type: CanvasNodeRenderType.AIPrompt,
2365
+ typeVersion: 1,
2366
+ position: [-690, -15],
2367
+ parameters: {}
2368
+ });
2369
+ }
2370
+ fallbackNodes.value = isReadOnlyOrLoading ? [] : defaultFallbackNodes;
2371
+ }
2372
+ );
2373
+ watch(
2374
+ () => route.params.nodeId,
2375
+ async (newId) => {
2376
+ if (typeof newId !== "string" || newId === "") ndvStore.activeNodeName = null;
2377
+ else {
2378
+ updateNodeRoute(newId);
2379
+ }
2380
+ }
2381
+ );
2382
+ watch(
2383
+ () => ndvStore.activeNode,
2384
+ async (val) => {
2385
+ if (![VIEWS.WORKFLOW].includes(String(route.name))) return;
2386
+ const nodeId = val?.id ? workflowsStore.getPartialIdForNode(val?.id) : "";
2387
+ if (nodeId !== route.params.nodeId) {
2388
+ await router.replace({
2389
+ name: route.name,
2390
+ params: { name: workflowId.value, nodeId }
2391
+ });
2392
+ }
2393
+ }
2394
+ );
2395
+ onBeforeRouteLeave(async (to, from, next) => {
2396
+ const toNodeViewTab = getNodeViewTab(to);
2397
+ if (toNodeViewTab === MAIN_HEADER_TABS.EXECUTIONS || from.name === VIEWS.TEMPLATE_IMPORT || toNodeViewTab === MAIN_HEADER_TABS.WORKFLOW && from.name === VIEWS.EXECUTION_DEBUG || isReadOnlyEnvironment.value) {
2398
+ next();
2399
+ return;
2400
+ }
2401
+ await useWorkflowSaving({ router }).promptSaveUnsavedWorkflowChanges(next, {
2402
+ async confirm() {
2403
+ if (from.name === VIEWS.NEW_WORKFLOW) {
2404
+ const savedWorkflowId = workflowsStore.workflowId;
2405
+ await router.replace({
2406
+ name: VIEWS.WORKFLOW,
2407
+ params: { name: savedWorkflowId }
2408
+ });
2409
+ await router.push(to);
2410
+ return false;
2411
+ }
2412
+ workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
2413
+ return true;
2414
+ }
2415
+ });
2416
+ });
2417
+ onBeforeMount(() => {
2418
+ if (!isDemoRoute.value) {
2419
+ pushConnectionStore.pushConnect();
2420
+ }
2421
+ addPostMessageEventBindings();
2422
+ });
2423
+ onMounted(() => {
2424
+ canvasStore.startLoading();
2425
+ documentTitle.reset();
2426
+ resetWorkspace();
2427
+ void initializeData().then(() => {
2428
+ void initializeRoute().then(() => {
2429
+ toast.showNotificationForViews([VIEWS.WORKFLOW, VIEWS.NEW_WORKFLOW]);
2430
+ if (route.query.settings) {
2431
+ uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
2432
+ void router.replace({ query: { settings: void 0 } });
2433
+ }
2434
+ }).finally(() => {
2435
+ isLoading.value = false;
2436
+ canvasStore.stopLoading();
2437
+ void externalHooks.run("nodeView.mount").catch(() => {
2438
+ });
2439
+ setTimeout(() => {
2440
+ if (routeNodeId.value) {
2441
+ updateNodeRoute(routeNodeId.value);
2442
+ }
2443
+ }, 500);
2444
+ emitPostMessageReady();
2445
+ });
2446
+ void usersStore.showPersonalizationSurvey();
2447
+ checkIfRouteIsAllowed();
2448
+ });
2449
+ addSourceControlEventBindings();
2450
+ addWorkflowSavedEventBindings();
2451
+ addBeforeUnloadEventBindings();
2452
+ addImportEventBindings();
2453
+ addExecutionOpenedEventBindings();
2454
+ registerCustomActions();
2455
+ });
2456
+ onActivated(async () => {
2457
+ addUndoRedoEventBindings();
2458
+ showAddFirstStepIfEnabled();
2459
+ });
2460
+ onDeactivated(() => {
2461
+ uiStore.closeModal(WORKFLOW_SETTINGS_MODAL_KEY);
2462
+ removeUndoRedoEventBindings();
2463
+ });
2464
+ onBeforeUnmount(() => {
2465
+ removeSourceControlEventBindings();
2466
+ removePostMessageEventBindings();
2467
+ removeWorkflowSavedEventBindings();
2468
+ removeBeforeUnloadEventBindings();
2469
+ removeImportEventBindings();
2470
+ removeExecutionOpenedEventBindings();
2471
+ unregisterCustomActions();
2472
+ if (!isDemoRoute.value) {
2473
+ pushConnectionStore.pushDisconnect();
2474
+ }
2475
+ });
2476
+ return (_ctx, _cache) => {
2477
+ return openBlock(), createElementBlock("div", {
2478
+ class: normalizeClass(unref($style).wrapper)
2479
+ }, [
2480
+ unref(editableWorkflow) && unref(editableWorkflowObject) && !isLoading.value ? (openBlock(), createBlock(WorkflowCanvas, {
2481
+ key: 0,
2482
+ id: unref(editableWorkflow).id,
2483
+ workflow: unref(editableWorkflow),
2484
+ "workflow-object": unref(editableWorkflowObject),
2485
+ "fallback-nodes": fallbackNodes.value,
2486
+ "show-fallback-nodes": showFallbackNodes.value,
2487
+ "event-bus": unref(canvasEventBus),
2488
+ "read-only": isCanvasReadOnly.value,
2489
+ executing: isWorkflowRunning.value,
2490
+ "key-bindings": keyBindingsEnabled.value,
2491
+ "onUpdate:nodes:position": onUpdateNodesPosition,
2492
+ "onUpdate:node:position": onUpdateNodePosition,
2493
+ "onUpdate:node:activated": onSetNodeActivated,
2494
+ "onUpdate:node:deactivated": onSetNodeDeactivated,
2495
+ "onUpdate:node:selected": onSetNodeSelected,
2496
+ "onUpdate:node:enabled": onToggleNodeDisabled,
2497
+ "onUpdate:node:name": onOpenRenameNodeModal,
2498
+ "onUpdate:node:parameters": onUpdateNodeParameters,
2499
+ "onUpdate:node:inputs": onUpdateNodeInputs,
2500
+ "onUpdate:node:outputs": onUpdateNodeOutputs,
2501
+ "onUpdate:logsOpen": _cache[3] || (_cache[3] = ($event) => unref(logsStore).toggleOpen($event)),
2502
+ "onUpdate:logs:inputOpen": unref(logsStore).toggleInputOpen,
2503
+ "onUpdate:logs:outputOpen": unref(logsStore).toggleOutputOpen,
2504
+ "onUpdate:hasRangeSelection": unref(canvasStore).setHasRangeSelection,
2505
+ "onOpen:subWorkflow": onOpenSubWorkflow,
2506
+ "onClick:node": onClickNode,
2507
+ "onClick:node:add": onClickNodeAdd,
2508
+ "onRun:node": onRunWorkflowToNode,
2509
+ "onDelete:node": onDeleteNode,
2510
+ "onCreate:connection": onCreateConnection,
2511
+ "onCreate:connection:cancelled": onCreateConnectionCancelled,
2512
+ "onDelete:connection": onDeleteConnection,
2513
+ "onClick:connection:add": onClickConnectionAdd,
2514
+ "onClick:pane": onClickPane,
2515
+ "onCreate:node": onOpenNodeCreatorFromCanvas,
2516
+ "onCreate:sticky": onCreateSticky,
2517
+ "onDelete:nodes": onDeleteNodes,
2518
+ "onUpdate:nodes:enabled": onToggleNodesDisabled,
2519
+ "onUpdate:nodes:pin": onPinNodes,
2520
+ "onDuplicate:nodes": onDuplicateNodes,
2521
+ "onCopy:nodes": onCopyNodes,
2522
+ "onCut:nodes": onCutNodes,
2523
+ "onRun:workflow": _cache[4] || (_cache[4] = ($event) => unref(runEntireWorkflow)("main")),
2524
+ "onSave:workflow": onSaveWorkflow,
2525
+ "onCreate:workflow": onCreateWorkflow,
2526
+ "onViewport:change": onViewportChange,
2527
+ "onSelection:end": onSelectionEnd,
2528
+ onDragAndDrop,
2529
+ onTidyUp,
2530
+ "onToggle:focusPanel": onToggleFocusPanel,
2531
+ onExtractWorkflow,
2532
+ onStartChat: _cache[5] || (_cache[5] = ($event) => unref(startChat)())
2533
+ }, {
2534
+ default: withCtx(() => [
2535
+ (openBlock(), createBlock(Suspense, null, {
2536
+ default: withCtx(() => [
2537
+ createVNode(unref(LazySetupWorkflowCredentialsButton), {
2538
+ class: normalizeClass(unref($style).setupCredentialsButtonWrapper)
2539
+ }, null, 8, ["class"])
2540
+ ]),
2541
+ _: 1
2542
+ })),
2543
+ !isCanvasReadOnly.value ? (openBlock(), createElementBlock("div", {
2544
+ key: 0,
2545
+ class: normalizeClass(unref($style).executionButtons)
2546
+ }, [
2547
+ isRunWorkflowButtonVisible.value ? (openBlock(), createBlock(CanvasRunWorkflowButton, {
2548
+ key: 0,
2549
+ "waiting-for-webhook": isExecutionWaitingForWebhook.value,
2550
+ disabled: isExecutionDisabled.value,
2551
+ executing: isWorkflowRunning.value,
2552
+ "trigger-nodes": triggerNodes.value,
2553
+ "get-node-type": unref(nodeTypesStore).getNodeType,
2554
+ "selected-trigger-node-name": unref(workflowsStore).selectedTriggerNodeName,
2555
+ onMouseenter: onRunWorkflowButtonMouseEnter,
2556
+ onMouseleave: onRunWorkflowButtonMouseLeave,
2557
+ onExecute: _cache[0] || (_cache[0] = ($event) => unref(runEntireWorkflow)("main")),
2558
+ onSelectTriggerNode: unref(workflowsStore).setSelectedTriggerNodeName
2559
+ }, null, 8, ["waiting-for-webhook", "disabled", "executing", "trigger-nodes", "get-node-type", "selected-trigger-node-name", "onSelectTriggerNode"])) : createCommentVNode("", true),
2560
+ containsChatTriggerNodes.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2561
+ isLogsPanelOpen.value ? (openBlock(), createBlock(_sfc_main$1, {
2562
+ key: 0,
2563
+ type: "tertiary",
2564
+ label: unref(i18n).baseText("chat.hide"),
2565
+ class: normalizeClass(unref($style).chatButton),
2566
+ onClick: _cache[1] || (_cache[1] = ($event) => unref(logsStore).toggleOpen(false))
2567
+ }, null, 8, ["label", "class"])) : (openBlock(), createBlock(KeyboardShortcutTooltip, {
2568
+ key: 1,
2569
+ label: unref(i18n).baseText("chat.open"),
2570
+ shortcut: { keys: ["c"] }
2571
+ }, {
2572
+ default: withCtx(() => [
2573
+ createVNode(_sfc_main$1, {
2574
+ type: isRunWorkflowButtonVisible.value ? "secondary" : "primary",
2575
+ label: unref(i18n).baseText("chat.open"),
2576
+ class: normalizeClass(unref($style).chatButton),
2577
+ onClick: onOpenChat
2578
+ }, null, 8, ["type", "label", "class"])
2579
+ ]),
2580
+ _: 1
2581
+ }, 8, ["label"]))
2582
+ ], 64)) : createCommentVNode("", true),
2583
+ isStopExecutionButtonVisible.value ? (openBlock(), createBlock(_sfc_main$4, {
2584
+ key: 2,
2585
+ stopping: isStoppingExecution.value,
2586
+ onClick: onStopExecution
2587
+ }, null, 8, ["stopping"])) : createCommentVNode("", true),
2588
+ isStopWaitingForWebhookButtonVisible.value ? (openBlock(), createBlock(_sfc_main$3, {
2589
+ key: 3,
2590
+ onClick: onStopWaitingForWebhook
2591
+ })) : createCommentVNode("", true)
2592
+ ], 2)) : createCommentVNode("", true),
2593
+ isReadOnlyEnvironment.value ? (openBlock(), createBlock(unref(N8nCallout), {
2594
+ key: 1,
2595
+ theme: "warning",
2596
+ icon: "lock",
2597
+ class: normalizeClass(unref($style).readOnlyEnvironmentNotification)
2598
+ }, {
2599
+ default: withCtx(() => [
2600
+ createTextVNode(toDisplayString(unref(i18n).baseText("readOnlyEnv.cantEditOrRun")), 1)
2601
+ ]),
2602
+ _: 1
2603
+ }, 8, ["class"])) : createCommentVNode("", true),
2604
+ (openBlock(), createBlock(Suspense, null, {
2605
+ default: withCtx(() => [
2606
+ !isCanvasReadOnly.value ? (openBlock(), createBlock(unref(LazyNodeCreation), {
2607
+ key: 0,
2608
+ "create-node-active": unref(nodeCreatorStore).isCreateNodeActive,
2609
+ "node-view-scale": viewportTransform.value.zoom,
2610
+ onToggleNodeCreator,
2611
+ onAddNodes: onAddNodesAndConnections
2612
+ }, null, 8, ["create-node-active", "node-view-scale"])) : createCommentVNode("", true)
2613
+ ]),
2614
+ _: 1
2615
+ })),
2616
+ (openBlock(), createBlock(Suspense, null, {
2617
+ default: withCtx(() => [
2618
+ !isNDVV2.value ? (openBlock(), createBlock(unref(LazyNodeDetailsView), {
2619
+ key: 0,
2620
+ "workflow-object": unref(editableWorkflowObject),
2621
+ "read-only": isCanvasReadOnly.value,
2622
+ "is-production-execution-preview": isProductionExecutionPreview.value,
2623
+ renaming: false,
2624
+ onValueChanged: _cache[2] || (_cache[2] = ($event) => onRenameNode($event.value)),
2625
+ onStopExecution,
2626
+ onSwitchSelectedNode: onSwitchActiveNode,
2627
+ onOpenConnectionNodeCreator: onOpenSelectiveNodeCreator,
2628
+ onSaveKeyboardShortcut: onSaveWorkflow
2629
+ }, null, 8, ["workflow-object", "read-only", "is-production-execution-preview"])) : createCommentVNode("", true)
2630
+ ]),
2631
+ _: 1
2632
+ })),
2633
+ (openBlock(), createBlock(Suspense, null, {
2634
+ default: withCtx(() => [
2635
+ isNDVV2.value ? (openBlock(), createBlock(unref(LazyNodeDetailsViewV2), {
2636
+ key: 0,
2637
+ "workflow-object": unref(editableWorkflowObject),
2638
+ "read-only": isCanvasReadOnly.value,
2639
+ "is-production-execution-preview": isProductionExecutionPreview.value,
2640
+ onRenameNode,
2641
+ onStopExecution,
2642
+ onSwitchSelectedNode: onSwitchActiveNode,
2643
+ onOpenConnectionNodeCreator: onOpenSelectiveNodeCreator,
2644
+ onSaveKeyboardShortcut: onSaveWorkflow
2645
+ }, null, 8, ["workflow-object", "read-only", "is-production-execution-preview"])) : createCommentVNode("", true)
2646
+ ]),
2647
+ _: 1
2648
+ }))
2649
+ ]),
2650
+ _: 1
2651
+ }, 8, ["id", "workflow", "workflow-object", "fallback-nodes", "show-fallback-nodes", "event-bus", "read-only", "executing", "key-bindings", "onUpdate:logs:inputOpen", "onUpdate:logs:outputOpen", "onUpdate:hasRangeSelection"])) : createCommentVNode("", true),
2652
+ !isLoading.value ? (openBlock(), createBlock(FocusPanel, {
2653
+ key: 1,
2654
+ "is-canvas-read-only": isCanvasReadOnly.value,
2655
+ onSaveKeyboardShortcut: onSaveWorkflow
2656
+ }, null, 8, ["is-canvas-read-only"])) : createCommentVNode("", true)
2657
+ ], 2);
2658
+ };
2659
+ }
2660
+ });
2661
+ const wrapper = "_wrapper_1xmhy_123";
2662
+ const executionButtons = "_executionButtons_1xmhy_128";
2663
+ const chatButton = "_chatButton_1xmhy_165";
2664
+ const setupCredentialsButtonWrapper = "_setupCredentialsButtonWrapper_1xmhy_169";
2665
+ const readOnlyEnvironmentNotification = "_readOnlyEnvironmentNotification_1xmhy_175";
2666
+ const style0 = {
2667
+ wrapper,
2668
+ executionButtons,
2669
+ chatButton,
2670
+ setupCredentialsButtonWrapper,
2671
+ readOnlyEnvironmentNotification
2672
+ };
2673
+ const cssModules = {
2674
+ "$style": style0
2675
+ };
2676
+ const NodeView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
2677
+ const NodeView$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2678
+ __proto__: null,
2679
+ default: NodeView
2680
+ }, Symbol.toStringTag, { value: "Module" }));
2681
+ export {
2682
+ NodeView$1 as N,
2683
+ useExecutionData as u
2684
+ };