@atom8n/n8n-editor-ui 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/.stylelintcache +1 -0
  2. package/README.md +59 -0
  3. package/biome.jsonc +8 -0
  4. package/build.log +55 -0
  5. package/data/node-popularity.json +3998 -0
  6. package/dist/assets/AddDataTableModal-UINkk54_.js +1555 -0
  7. package/dist/assets/AgentEditorModal-CVww87TJ.js +358 -0
  8. package/dist/assets/Alert-Dy86dyOr.js +102 -0
  9. package/dist/assets/AnimatedSpinner-DmPN4poP.js +15 -0
  10. package/dist/assets/AnnotationTagsDropdown.ee-BJ7N9lek.js +71 -0
  11. package/dist/assets/AuthView-D2LWHrMp.js +106 -0
  12. package/dist/assets/BottomMenu-CIQiK_dJ.js +532 -0
  13. package/dist/assets/CalendarDate-DgQUMbNo.js +875 -0
  14. package/dist/assets/ChangePasswordView-Z6tUkw0u.js +133 -0
  15. package/dist/assets/ChatAgentAvatar-50YBnv3N.js +67 -0
  16. package/dist/assets/ChatFile-xZxmc2nV.js +146 -0
  17. package/dist/assets/ChatLayout-CTE_5SiM.js +96 -0
  18. package/dist/assets/ChatPersonalAgentsView-BGpHk03K.js +149 -0
  19. package/dist/assets/ChatSidebar-BkVwIypC.js +528 -0
  20. package/dist/assets/ChatView-BbbdeU9x.js +1559 -0
  21. package/dist/assets/ChatWorkflowAgentsView-BtunOxlC.js +116 -0
  22. package/dist/assets/CollectionParameter-BdcPG1lu.js +52 -0
  23. package/dist/assets/CommitMonoVariable-ytizKI8U.woff2 +0 -0
  24. package/dist/assets/CommunityNodeUpdateInfo-C37kca4W.js +273 -0
  25. package/dist/assets/CopyInput-DDZVu2iU.js +74 -0
  26. package/dist/assets/CredentialIcon-8YdTTFZ1.js +80 -0
  27. package/dist/assets/CredentialPicker-DWtj314o.js +293 -0
  28. package/dist/assets/CredentialSelectorModal-DTW2fKh0.js +138 -0
  29. package/dist/assets/CredentialsView-BjUchcCu.js +480 -0
  30. package/dist/assets/DataTableActions-DpAkoxg_.js +95 -0
  31. package/dist/assets/DataTableDetailsView-Coq7zdW5.js +41922 -0
  32. package/dist/assets/DataTableView-Cs-BIkzw.js +293 -0
  33. package/dist/assets/DemoFooter-Cga3jvi-.js +65 -0
  34. package/dist/assets/Draggable-vfvXl9Sp.js +105 -0
  35. package/dist/assets/EmptySharedSectionActionBox-DOXZtTCv.js +36 -0
  36. package/dist/assets/EnterpriseEdition.ee-D_rCFexM.js +15 -0
  37. package/dist/assets/EntityNotFound-3dhTRWsE.js +85 -0
  38. package/dist/assets/EntityUnAuthorised-ChJYZakE.js +66 -0
  39. package/dist/assets/ErrorView-zT9cX76a.js +61 -0
  40. package/dist/assets/EvaluationsRootView-C-OVWYnY.js +523 -0
  41. package/dist/assets/EvaluationsView-CJwJTruc.js +469 -0
  42. package/dist/assets/ExecutionsTime-DEQiyozR.js +573 -0
  43. package/dist/assets/ExecutionsView-Bd5Oh8TH.js +791 -0
  44. package/dist/assets/ExternalSecretsProviderConnectionSwitch.ee-C7Ih-uRo.js +191 -0
  45. package/dist/assets/FixedCollectionParameter-CYuTDW9t.js +496 -0
  46. package/dist/assets/ForgotMyPasswordView-Bs_L9P27.js +102 -0
  47. package/dist/assets/InsightsChartAverageRuntime-Bp3VA8_7.js +62 -0
  48. package/dist/assets/InsightsChartFailed-KPaNWoEr.js +52 -0
  49. package/dist/assets/InsightsChartFailureRate-DE6kE3FM.js +54 -0
  50. package/dist/assets/InsightsChartTimeSaved-auABNZlc.js +68 -0
  51. package/dist/assets/InsightsChartTotal-BKzYRKE7.js +56 -0
  52. package/dist/assets/InsightsDashboard-JWx4W6Db.js +473 -0
  53. package/dist/assets/InsightsPaywall-C8zLLKe8.js +63 -0
  54. package/dist/assets/InsightsSummary-cmN1lHDm.js +210 -0
  55. package/dist/assets/InsightsTableWorkflows-CqcC3IbQ.js +203 -0
  56. package/dist/assets/InterVariable-DiVDrmQJ.woff2 +0 -0
  57. package/dist/assets/InterVariable-Italic-FCBEiFp6.woff2 +0 -0
  58. package/dist/assets/ItemsRenderer-DC8WVyMv.js +922 -0
  59. package/dist/assets/KeyboardShortcutTooltip-D8PAK5JP.js +31 -0
  60. package/dist/assets/LogsPanel-BR06u9RK.js +52 -0
  61. package/dist/assets/LogsPanel-C-_acMHp.js +2325 -0
  62. package/dist/assets/MCPConnectWorkflowsModal-3g8_iUa4.js +303 -0
  63. package/dist/assets/MainHeader-DiQc1edn.js +2153 -0
  64. package/dist/assets/MainSidebar-CoPGG5Ea.js +804 -0
  65. package/dist/assets/MigrationRuleDetail-BAxk1Pvl.js +295 -0
  66. package/dist/assets/MigrationRules-IW9lZMpE.js +285 -0
  67. package/dist/assets/Modal-CIzXlZdZ.js +204 -0
  68. package/dist/assets/ModelByIdSelectorModal-DLvBjzJO.js +115 -0
  69. package/dist/assets/NDVEmptyState-33UoX00I.js +19743 -0
  70. package/dist/assets/NodeCreation-BNzbSWSB.js +240 -0
  71. package/dist/assets/NodeCreator-BftgCKx7.js +1288 -0
  72. package/dist/assets/NodeDetailsView-CsoQCpcF.js +1075 -0
  73. package/dist/assets/NodeDetailsViewV2-C_wNQR_3.js +981 -0
  74. package/dist/assets/NodeIcon-B9VW6tX6.js +87 -0
  75. package/dist/assets/NodeSettings-ZwVip6VR.js +1872 -0
  76. package/dist/assets/NodeView-D4WUEvLB.js +2452 -0
  77. package/dist/assets/OAuthConsentView-DlrUqZbT.js +230 -0
  78. package/dist/assets/PageViewLayout-NT1KPFgy.js +12 -0
  79. package/dist/assets/ParameterInputList-sG2nz-Jo.js +38091 -0
  80. package/dist/assets/PrebuiltAgentTemplatesView-Csi5U8dc.js +154 -0
  81. package/dist/assets/ProjectBreadcrumb-C_XiY7sc.js +98 -0
  82. package/dist/assets/ProjectCardBadge-t_hs7vzx.js +209 -0
  83. package/dist/assets/ProjectHeader-Dq5Ihb26.js +549 -0
  84. package/dist/assets/ProjectIcon-DY8gGuHX.js +64 -0
  85. package/dist/assets/ProjectRoleView-Du-KTrAC.js +435 -0
  86. package/dist/assets/ProjectRolesView-DjxM_y4u.js +239 -0
  87. package/dist/assets/ProjectSettings-C6kWuV21.js +966 -0
  88. package/dist/assets/ProjectSharing-CVUgNWAY.js +262 -0
  89. package/dist/assets/ProjectVariables-CJlAo3dv.js +467 -0
  90. package/dist/assets/ProviderSettingsModal-BUFC2ZLv.js +307 -0
  91. package/dist/assets/PushConnectionTracker-DPBnGV0v.js +27 -0
  92. package/dist/assets/ResolversView-3BdkvvYA.js +209 -0
  93. package/dist/assets/ResourceFiltersDropdown-dgyXpcEX.js +159 -0
  94. package/dist/assets/ResourcesListLayout-qBLtomK6.js +631 -0
  95. package/dist/assets/RunDataHtml-BrW0OQra.js +7 -0
  96. package/dist/assets/RunDataHtml-Cleia4Cj.js +40 -0
  97. package/dist/assets/RunDataJson-uxkrhYRK.js +227 -0
  98. package/dist/assets/RunDataJsonActions-DkPk7E8d.js +5007 -0
  99. package/dist/assets/RunDataParsedAiContent-CtPRjig-.js +26 -0
  100. package/dist/assets/RunDataParsedAiContent-WAuqLQ5M.js +192 -0
  101. package/dist/assets/RunDataSearch-YBWUr93C.js +141 -0
  102. package/dist/assets/RunDataTable-DcXaBynW.js +631 -0
  103. package/dist/assets/SamlOnboarding-BTdQ_hr3.js +78 -0
  104. package/dist/assets/SaveButton-D5sQSxIk.js +89 -0
  105. package/dist/assets/SelectedItemsInfo-BHZ-NvF5.js +58 -0
  106. package/dist/assets/SettingsApiView-IfZTMXx1.js +313 -0
  107. package/dist/assets/SettingsChatHubView-gWh2X6vX.js +285 -0
  108. package/dist/assets/SettingsCommunityNodesView-D8VQtpGY.js +349 -0
  109. package/dist/assets/SettingsExternalSecrets-CpMc7mkW.js +233 -0
  110. package/dist/assets/SettingsLdapView-CU5a2MAy.js +2553 -0
  111. package/dist/assets/SettingsLogStreamingView-uojTe-oX.js +375 -0
  112. package/dist/assets/SettingsMCPView-B5Swp1C_.js +1214 -0
  113. package/dist/assets/SettingsPersonalView-Cr3aGood.js +402 -0
  114. package/dist/assets/SettingsSourceControl-DXOvFDEY.js +547 -0
  115. package/dist/assets/SettingsSso-27MfU1HV.js +1032 -0
  116. package/dist/assets/SettingsUsageAndPlan-DqIO-G46.js +419 -0
  117. package/dist/assets/SettingsUsersView-DfHB4_Kh.js +833 -0
  118. package/dist/assets/SettingsView-C4sA7Uny.js +90 -0
  119. package/dist/assets/SetupTemplateFormStep-BmiSzZin.js +258 -0
  120. package/dist/assets/SetupView-VORZ-L_u.js +112 -0
  121. package/dist/assets/SetupWorkflowCredentialsButton-DTmkOAW5.js +73 -0
  122. package/dist/assets/SetupWorkflowFromTemplateView-B9NupdJE.js +286 -0
  123. package/dist/assets/SeverityTag-CX1qTTNA.js +45 -0
  124. package/dist/assets/SigninView-D9_Pm16j.js +358 -0
  125. package/dist/assets/SignoutView-BFsjEAGz.js +19 -0
  126. package/dist/assets/SignupView-Am4ot0QZ.js +137 -0
  127. package/dist/assets/SkeletonAgentCard-C5TL-h8F.js +191 -0
  128. package/dist/assets/TagsDropdown-Bvx_Hd6Q.js +230 -0
  129. package/dist/assets/TemplateCard-CyQ1GuVz.js +105 -0
  130. package/dist/assets/TemplateDetails-CZRusTxE.js +124 -0
  131. package/dist/assets/TemplateList-DKvbwuiY.js +333 -0
  132. package/dist/assets/TemplatesCollectionView-D8dxU8By.js +184 -0
  133. package/dist/assets/TemplatesSearchView-CebC_GLs.js +1230 -0
  134. package/dist/assets/TemplatesView-025CcmIY.js +57 -0
  135. package/dist/assets/TemplatesWorkflowView-C2JfwJAn.js +170 -0
  136. package/dist/assets/TestRunDetailView-Ck78TTWO.js +395 -0
  137. package/dist/assets/TextWithHighlights-BxumwGnv.js +57 -0
  138. package/dist/assets/TimeAgo-C6EN4lCs.js +123 -0
  139. package/dist/assets/ToolsSelectorModal-8QJoUvRL.js +368 -0
  140. package/dist/assets/TriggerPanel-B6pacLkk.js +1225 -0
  141. package/dist/assets/VirtualSchema-B3zGe_8b.js +2402 -0
  142. package/dist/assets/VirtualSchema-Dkh0Cu5z.js +37 -0
  143. package/dist/assets/VueMarkdown-CQqJL9vK.js +28 -0
  144. package/dist/assets/WorkerView-Caznsljo.js +563 -0
  145. package/dist/assets/WorkflowActivationErrorMessage-CGrfPi9O.js +17 -0
  146. package/dist/assets/WorkflowActivator-BINnz0f7.js +362 -0
  147. package/dist/assets/WorkflowExecutionsInfoAccordion-Dg37yEfT.js +166 -0
  148. package/dist/assets/WorkflowExecutionsLandingPage-V2wdubhK.js +93 -0
  149. package/dist/assets/WorkflowExecutionsPreview-DdJaqYV6.js +616 -0
  150. package/dist/assets/WorkflowExecutionsView-DV8ySTfn.js +808 -0
  151. package/dist/assets/WorkflowHistory-GtaBMzIM.js +973 -0
  152. package/dist/assets/WorkflowLocation-CQ9Sq-2y.js +164 -0
  153. package/dist/assets/WorkflowOnboardingView-C49gt0Jr.js +61 -0
  154. package/dist/assets/WorkflowPreview-CXdvv4Nq.js +186 -0
  155. package/dist/assets/WorkflowTagsDropdown-QwbICWjN.js +71 -0
  156. package/dist/assets/WorkflowsView-B-MWIECO.js +3253 -0
  157. package/dist/assets/_MapCache-CcdIl4Ae.js +363 -0
  158. package/dist/assets/_baseOrderBy-N8Be_6z6.js +2989 -0
  159. package/dist/assets/_initCloneObject-viQQyT6o.js +80 -0
  160. package/dist/assets/_plugin-vue_export-helper-BwBpWJRZ.js +6 -0
  161. package/dist/assets/aiTemplatesStarterCollection.store-nL9nePkK.js +656 -0
  162. package/dist/assets/apiKeys.store-BhOFmP2j.js +51 -0
  163. package/dist/assets/assistant.store-CNywgN4S.js +518 -0
  164. package/dist/assets/auth.eventBus-CWXS0Qp7.js +5 -0
  165. package/dist/assets/banners.store-CGEcBTDn.js +195 -0
  166. package/dist/assets/builder.store-Czk2ipDE.js +31417 -0
  167. package/dist/assets/buttons.esm-yintpW2E.js +364 -0
  168. package/dist/assets/chart-CNvyywtJ.js +10958 -0
  169. package/dist/assets/chartjs.utils-BAE52Cv9.js +155 -0
  170. package/dist/assets/chat.store-290YeyrQ.js +865 -0
  171. package/dist/assets/chatPanel.store-NDaawEZL.js +118 -0
  172. package/dist/assets/chunk-6z4oVpB-.js +36 -0
  173. package/dist/assets/col-Cmt4cmuS.js +158 -0
  174. package/dist/assets/constants-C8OH4tTq.js +106256 -0
  175. package/dist/assets/constants-DMrsrpD7.js +32 -0
  176. package/dist/assets/core-B9gt_4yk.js +4 -0
  177. package/dist/assets/core-CP5FY4aX.js +1202 -0
  178. package/dist/assets/core-CRbPymLT.js +9741 -0
  179. package/dist/assets/dataTable.store-DmipQsol.js +207 -0
  180. package/dist/assets/date-picker-2IDsBs2n.js +4115 -0
  181. package/dist/assets/dateFormatter-ik4-9_9r.js +33 -0
  182. package/dist/assets/dateformat-hG8NERse.js +181 -0
  183. package/dist/assets/dialog-lMho1TD8.js +425 -0
  184. package/dist/assets/dist-Cw46Is-h.js +151 -0
  185. package/dist/assets/doppler-B__k0MeW.webp +0 -0
  186. package/dist/assets/element-icons-B-tDfklg.woff +0 -0
  187. package/dist/assets/element-icons-_lZGOqcG.ttf +0 -0
  188. package/dist/assets/empty-BuGRxzl4.js +2210 -0
  189. package/dist/assets/en-CF30SCh2.js +95 -0
  190. package/dist/assets/en-DyO2pPiC.js +2 -0
  191. package/dist/assets/es-BkUFJVtD.js +43338 -0
  192. package/dist/assets/evaluation.constants-GYAwmJnh.js +284 -0
  193. package/dist/assets/executions.store-B9uRYwgv.js +205 -0
  194. package/dist/assets/exports-Crx_gvt_.js +1799 -0
  195. package/dist/assets/externalSecrets.ee.store-BJh4a_6G.js +118 -0
  196. package/dist/assets/fileUtils-CRWqOQje.js +20 -0
  197. package/dist/assets/folders.store-yAFj-5Vl.js +235 -0
  198. package/dist/assets/get-BcEmeOxn.js +2781 -0
  199. package/dist/assets/index-SL8542zQ.js +28372 -0
  200. package/dist/assets/insights.constants-BkJCYJTL.js +55 -0
  201. package/dist/assets/insights.store-BFc3kDUo.js +61 -0
  202. package/dist/assets/insights.utils-CcLXdrrz.js +77 -0
  203. package/dist/assets/isEmpty-C3XXoHqJ.js +35216 -0
  204. package/dist/assets/languageModules-9LyndCqU.js +13862 -0
  205. package/dist/assets/logStreaming.store-IZhWe_VK.js +190 -0
  206. package/dist/assets/mcp.constants-_Jcn7fPq.js +10 -0
  207. package/dist/assets/mcp.store-B9yfcAN9.js +116 -0
  208. package/dist/assets/merge-DhuTk1HM.js +564 -0
  209. package/dist/assets/nodeCreator.store-Bpnrwp2l.js +5444 -0
  210. package/dist/assets/nodeIcon-D6X-ENYt.js +102 -0
  211. package/dist/assets/nodeTransforms-RzcOM0v2.js +42 -0
  212. package/dist/assets/orderBy-Cu9F9DU_.js +15 -0
  213. package/dist/assets/path-browserify-RUt2u7iT.js +328 -0
  214. package/dist/assets/personalizedTemplatesV3.store-BGYp0YBN.js +334 -0
  215. package/dist/assets/pickBy-UI0Jt4wC.js +18 -0
  216. package/dist/assets/preload-helper-dyVz7ck7.js +59 -0
  217. package/dist/assets/radio-CSce3UT0.js +262 -0
  218. package/dist/assets/readyToRun.store-YEMvPUqo.js +626 -0
  219. package/dist/assets/readyToRunWorkflows.store-G3srgIze.js +1319 -0
  220. package/dist/assets/retry-BgHaYzbB.js +23 -0
  221. package/dist/assets/roles.store-CRf_zJTb.js +51 -0
  222. package/dist/assets/router-DNpzz3GH.js +2631 -0
  223. package/dist/assets/sanitize-html-CbW56HUN.js +10758 -0
  224. package/dist/assets/schemaPreview.store-DUgN1yVE.js +113 -0
  225. package/dist/assets/semver-Bk6DGseV.js +1306 -0
  226. package/dist/assets/smartDecimal-DAZl4HKA.js +6 -0
  227. package/dist/assets/sortByProperty-Cn7iGKYu.js +8 -0
  228. package/dist/assets/sourceControl.eventBus-D47xXSc_.js +3 -0
  229. package/dist/assets/sqlite3-DBpDb1lf.wasm +0 -0
  230. package/dist/assets/sqlite3-opfs-async-proxy-vVtmDGHX.js +461 -0
  231. package/dist/assets/sqlite3-worker1-bundler-friendly-DLarOZDL.js +9405 -0
  232. package/dist/assets/src-jviYSG25.js +55454 -0
  233. package/dist/assets/sso.store-DyApJwhx.js +139 -0
  234. package/dist/assets/style-E3CrYFV8.css +111829 -0
  235. package/dist/assets/table-we1DjFMV.js +3944 -0
  236. package/dist/assets/templateActions-bEDSARw2.js +65 -0
  237. package/dist/assets/templateTransforms-BHWiRbtR.js +43 -0
  238. package/dist/assets/truncate-C0KYt7i3.js +4176 -0
  239. package/dist/assets/typescript.worker-CYqLvLHh.js +152048 -0
  240. package/dist/assets/uniqBy-xDyuCRP0.js +10 -0
  241. package/dist/assets/usage.store-CU5J_nGm.js +100 -0
  242. package/dist/assets/useActions-B1JckIRj.js +255 -0
  243. package/dist/assets/useBeforeUnload-DiDkvI8p.js +40 -0
  244. package/dist/assets/useCanvasMapping-BXT7rGhC.js +12570 -0
  245. package/dist/assets/useCanvasOperations-8ULLtMkY.js +1765 -0
  246. package/dist/assets/useClipboard-DvjhVHqJ.js +39 -0
  247. package/dist/assets/useCommandBar-C4tLJbKt.js +2425 -0
  248. package/dist/assets/useCredentialResolvers-BKeFGJnY.js +78 -0
  249. package/dist/assets/useCustomAgent-DpILEt5e.js +471 -0
  250. package/dist/assets/useDebounce-Br5_1ug-.js +147 -0
  251. package/dist/assets/useExecutionData-M5iKsX6z.js +23 -0
  252. package/dist/assets/useExecutionDebugging-8azMzbnd.js +191 -0
  253. package/dist/assets/useExecutionHelpers-BgRRhpBM.js +91 -0
  254. package/dist/assets/useImportCurlCommand-CKiEmX5P.js +8891 -0
  255. package/dist/assets/useIntersectionObserver-BWMwOueh.js +33 -0
  256. package/dist/assets/useKeybindings-B2jfN6rd.js +62 -0
  257. package/dist/assets/useLogsTreeExpand-sZViUfdM.js +843 -0
  258. package/dist/assets/useMcp-DoMOIfqT.js +27 -0
  259. package/dist/assets/usePageRedirectionHelper-DjkznpX6.js +51 -0
  260. package/dist/assets/usePinnedData-BhZkqttf.js +203 -0
  261. package/dist/assets/usePushConnection-DMS-F_IW.js +513 -0
  262. package/dist/assets/useRecentResources-BVORr7eM.js +118 -0
  263. package/dist/assets/useRunWorkflow-LO7ffLp9.js +950 -0
  264. package/dist/assets/useSettingsItems-BhZXwMZn.js +144 -0
  265. package/dist/assets/useTelemetryContext-V6bv4YRq.js +34 -0
  266. package/dist/assets/useWorkflowActivate-DeSmDXjI.js +152 -0
  267. package/dist/assets/useWorkflowsCache-DtcEEAIR.js +179 -0
  268. package/dist/assets/userRoleProvisioning.store-kkSIdeTo.js +33 -0
  269. package/dist/assets/utils-DI7dLldp.js +54 -0
  270. package/dist/assets/versions.store-B1z2OrLE.js +191 -0
  271. package/dist/assets/vue-CydWIhxN.js +4378 -0
  272. package/dist/assets/vue-json-pretty-CsGX66mG.js +1130 -0
  273. package/dist/assets/vue.runtime.esm-bundler-tP5dCd7J.js +7325 -0
  274. package/dist/assets/xml-B_oj6Mle.js +2060 -0
  275. package/dist/favicon.ico +0 -0
  276. package/dist/index.html +157 -0
  277. package/dist/static/base-path.js +1 -0
  278. package/dist/static/community_package_tooltip_img.png +0 -0
  279. package/dist/static/data-mapping-gif.gif +0 -0
  280. package/dist/static/form-grey.svg +1 -0
  281. package/dist/static/google-auth/disabled.dark.png +0 -0
  282. package/dist/static/google-auth/disabled.png +0 -0
  283. package/dist/static/google-auth/focus.dark.png +0 -0
  284. package/dist/static/google-auth/focus.png +0 -0
  285. package/dist/static/google-auth/normal.dark.png +0 -0
  286. package/dist/static/google-auth/normal.png +0 -0
  287. package/dist/static/google-auth/pressed.dark.png +0 -0
  288. package/dist/static/google-auth/pressed.png +0 -0
  289. package/dist/static/n8n-logo.png +0 -0
  290. package/dist/static/og_image.png +0 -0
  291. package/dist/static/open-ai.svg +1 -0
  292. package/dist/static/openChat.png +0 -0
  293. package/dist/static/posthog.init.js +41 -0
  294. package/dist/static/prefers-color-scheme.css +5 -0
  295. package/dist/static/webhook-icon.svg +1 -0
  296. package/dist/tree-sitter-bash.wasm +0 -0
  297. package/dist/tree-sitter.wasm +0 -0
  298. package/eslint.config.mjs +59 -0
  299. package/index.html +45 -0
  300. package/index.js +0 -0
  301. package/package.json +147 -0
  302. package/postcss.config.cjs +6 -0
  303. package/scripts/fetch-node-popularity.mjs +102 -0
  304. package/stylelint.config.mjs +9 -0
  305. package/tailwind.config.js +8 -0
  306. package/tsconfig.json +36 -0
  307. package/vite/i18n-locales-hmr-helpers.ts +19 -0
  308. package/vite/source-map-js-shim.ts +1 -0
  309. package/vite/vite-plugin-node-popularity.mts +32 -0
  310. package/vite.config.mts +304 -0
@@ -0,0 +1,2153 @@
1
+ import { o as __toESM } from "./chunk-6z4oVpB-.js";
2
+ import { $t as hasOwn, C as computed, Cn as toDisplayString, D as createElementBlock, E as createCommentVNode, G as nextTick, Gt as unref, It as ref, J as onBeforeUnmount, L as h, M as createVNode, P as defineComponent, T as createBlock, Z as onMounted, _ as Fragment, _t as watch, at as renderSlot, bn as normalizeStyle, bt as withCtx, c as useCssModule, en as hyphenate, et as openBlock, it as renderList, j as createTextVNode, mt as useTemplateRef, ot as resolveComponent, p as vShow, q as onBeforeMount, tn as init_shared_esm_bundler, vn as normalizeClass, w as createBaseVNode, xt as withDirectives } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
3
+ import { it as I18nT, rt as useI18n, u as useDocumentVisibility, v as useLocalStorage } from "./core-CRbPymLT.js";
4
+ import { Cn as N8nIcon_default, T as N8nRadioButtons_default, b as SuggestedActions_default, c as N8nInlineTextEdit_default, h as N8nUserStack_default, ht as N8nTooltip_default, lt as N8nBadge_default, ot as N8nActionDropdown_default, x as N8nTag_default, xn as N8nButton_default, xt as N8nIconButton_default } from "./src-jviYSG25.js";
5
+ import "./en-CF30SCh2.js";
6
+ import { t as __vitePreload } from "./preload-helper-dyVz7ck7.js";
7
+ import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js";
8
+ import { s as createEventBus } from "./truncate-C0KYt7i3.js";
9
+ import { $n as ProjectTypes, C as getBannerRowHeight, Er as useUsersStore, Hn as useTagsStore, It as useEvaluationStore, N as useNDVStore, P as useWorkflowsStore, Pt as useNodeTypesStore, Qi as nodeViewEventBus, Qn as useSourceControlStore, Xn as useDocumentTitle, Zn as useProjectsStore, aa as useUIStore, ci as ResourceType, g as useNpsSurveyStore, ga as PROJECT_MOVE_RESOURCE_MODAL, h as useMessage, j as telemetry, k as useTelemetry, mi as getActivatableTriggerNodes, ms as useSettingsStore, n as useWorkflowSaving, v as require_FileSaver_min, wc as STORES, y as useToast, yr as hasPermission, zn as useWorkflowHelpers } from "./builder.store-Czk2ipDE.js";
10
+ import "./empty-BuGRxzl4.js";
11
+ import { _ as useRoute, v as useRouter } from "./get-BcEmeOxn.js";
12
+ import "./sanitize-html-CbW56HUN.js";
13
+ import "./CalendarDate-DgQUMbNo.js";
14
+ import "./path-browserify-RUt2u7iT.js";
15
+ import "./_MapCache-CcdIl4Ae.js";
16
+ import { Dc as TIME, Go as DUPLICATE_MODAL_KEY, Hc as WORKFLOW_MENU_ACTIONS, Lo as MAIN_HEADER_TABS, Oo as getResourcePermissions, Qo as IMPORT_WORKFLOW_URL_MODAL_KEY, Ro as VIEWS, Ss as WORKFLOW_SHARE_MODAL_KEY, a as IS_DRAFT_PUBLISH_ENABLED, bs as WORKFLOW_PUBLISH_MODAL_KEY, fr as TIME_SAVED_NODE_TYPE, g as EVALUATIONS_DOCS_URL, h as ERROR_WORKFLOW_DOCS_URL, js as LOCAL_STORAGE_HIDE_GITHUB_STAR_BUTTON, ms as WORKFLOW_DESCRIPTION_MODAL_KEY, o as MAX_WORKFLOW_NAME_LENGTH, ps as WORKFLOW_ACTIVE_MODAL_KEY, rs as MODAL_CONFIRM, sr as STICKY_NODE_TYPE, v as N8N_MAIN_GITHUB_REPO_URL, w as TIME_SAVED_DOCS_URL, xs as WORKFLOW_SETTINGS_MODAL_KEY, yc as EnterpriseEditionFeature, ys as WORKFLOW_HISTORY_VERSION_UNPUBLISH } from "./constants-C8OH4tTq.js";
17
+ import "./merge-DhuTk1HM.js";
18
+ import { k as defineStore, r as useRootStore } from "./_baseOrderBy-N8Be_6z6.js";
19
+ import "./dateformat-hG8NERse.js";
20
+ import { n as require_debounce, t as useDebounce } from "./useDebounce-Br5_1ug-.js";
21
+ import "./assistant.store-CNywgN4S.js";
22
+ import "./retry-BgHaYzbB.js";
23
+ import { t as useExecutionsStore } from "./executions.store-B9uRYwgv.js";
24
+ import { i as usePushConnectionStore } from "./useRunWorkflow-LO7ffLp9.js";
25
+ import "./usePinnedData-BhZkqttf.js";
26
+ import "./nodeCreator.store-Bpnrwp2l.js";
27
+ import "./nodeIcon-D6X-ENYt.js";
28
+ import "./useClipboard-DvjhVHqJ.js";
29
+ import "./useCanvasOperations-8ULLtMkY.js";
30
+ import { t as useFoldersStore } from "./folders.store-yAFj-5Vl.js";
31
+ import "./NodeIcon-B9VW6tX6.js";
32
+ import "./KeyboardShortcutTooltip-D8PAK5JP.js";
33
+ import "./versions.store-B1z2OrLE.js";
34
+ import { t as usePageRedirectionHelper } from "./usePageRedirectionHelper-DjkznpX6.js";
35
+ import { t as useBannersStore } from "./banners.store-CGEcBTDn.js";
36
+ import "./dataTable.store-DmipQsol.js";
37
+ import "./ProjectIcon-DY8gGuHX.js";
38
+ import "./schemaPreview.store-DUgN1yVE.js";
39
+ import { t as EnterpriseEdition_ee_default } from "./EnterpriseEdition.ee-D_rCFexM.js";
40
+ import { t as TimeAgo_default } from "./TimeAgo-C6EN4lCs.js";
41
+ import "./roles.store-CRf_zJTb.js";
42
+ import { t as SaveButton_default } from "./SaveButton-D5sQSxIk.js";
43
+ import { t as router_default } from "./router-DNpzz3GH.js";
44
+ import "./TagsDropdown-Bvx_Hd6Q.js";
45
+ import { t as WorkflowTagsDropdown_default } from "./WorkflowTagsDropdown-QwbICWjN.js";
46
+ import "./sso.store-DyApJwhx.js";
47
+ import "./insights.store-BFc3kDUo.js";
48
+ import "./insights.constants-BkJCYJTL.js";
49
+ import "./insights.utils-CcLXdrrz.js";
50
+ import { a as MCP_DOCS_PAGE_URL, s as MCP_SETTINGS_VIEW } from "./mcp.constants-_Jcn7fPq.js";
51
+ import "./constants-DMrsrpD7.js";
52
+ import "./useRecentResources-BVORr7eM.js";
53
+ import { t as useMcp } from "./useMcp-DoMOIfqT.js";
54
+ import { t as useWorkflowActivate } from "./useWorkflowActivate-DeSmDXjI.js";
55
+ import "./WorkflowActivationErrorMessage-CGrfPi9O.js";
56
+ import { i as getLastPublishedVersion, r as generateVersionName } from "./utils-DI7dLldp.js";
57
+ import "./ProjectBreadcrumb-C_XiY7sc.js";
58
+ import { n as FolderBreadcrumbs_default, t as WorkflowActivator_default } from "./WorkflowActivator-BINnz0f7.js";
59
+ import { t as PushConnectionTracker_default } from "./PushConnectionTracker-DPBnGV0v.js";
60
+ import { t as useWorkflowSettingsCache } from "./useWorkflowsCache-DtcEEAIR.js";
61
+ import { t as useBeforeUnload } from "./useBeforeUnload-DiDkvI8p.js";
62
+ import { t as usePushConnection } from "./usePushConnection-DMS-F_IW.js";
63
+ import "./aiTemplatesStarterCollection.store-nL9nePkK.js";
64
+ import "./readyToRun.store-YEMvPUqo.js";
65
+ var TabBar_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
66
+ __name: "TabBar",
67
+ props: {
68
+ items: {},
69
+ modelValue: { default: MAIN_HEADER_TABS.WORKFLOW }
70
+ },
71
+ emits: ["update:modelValue"],
72
+ setup(__props, { emit: __emit }) {
73
+ const emit = __emit;
74
+ function onUpdateModelValue(tab, event) {
75
+ emit("update:modelValue", tab, event);
76
+ }
77
+ return (_ctx, _cache) => {
78
+ return _ctx.items ? (openBlock(), createElementBlock("div", {
79
+ key: 0,
80
+ class: normalizeClass({
81
+ [_ctx.$style.container]: true,
82
+ ["tab-bar-container"]: true
83
+ })
84
+ }, [createVNode(unref(N8nRadioButtons_default), {
85
+ "model-value": _ctx.modelValue,
86
+ options: _ctx.items,
87
+ "onUpdate:modelValue": onUpdateModelValue
88
+ }, null, 8, ["model-value", "options"])], 2)) : createCommentVNode("", true);
89
+ };
90
+ }
91
+ });
92
+ var TabBar_vue_vue_type_style_index_0_lang_module_default = { container: "_container_cznfu_123" };
93
+ var TabBar_default = /* @__PURE__ */ __plugin_vue_export_helper_default(TabBar_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": TabBar_vue_vue_type_style_index_0_lang_module_default }]]);
94
+ var BreakpointsObserver_default = /* @__PURE__ */ defineComponent({
95
+ __name: "BreakpointsObserver",
96
+ props: {
97
+ valueXS: {},
98
+ valueXL: {},
99
+ valueLG: {},
100
+ valueMD: {},
101
+ valueSM: {},
102
+ valueDefault: {}
103
+ },
104
+ setup(__props) {
105
+ const props = __props;
106
+ const { callDebounced } = useDebounce();
107
+ const bannersStore = useBannersStore();
108
+ const width = ref(window.innerWidth);
109
+ const bp = computed(() => {
110
+ if (width.value < 768) return "XS";
111
+ if (width.value >= 1920) return "XL";
112
+ if (width.value >= 1200) return "LG";
113
+ if (width.value >= 992) return "MD";
114
+ return "SM";
115
+ });
116
+ const value = computed(() => {
117
+ if (props.valueXS && width.value < 768) return props.valueXS;
118
+ if (props.valueXL && width.value >= 1920) return props.valueXL;
119
+ if (props.valueLG && width.value >= 1200) return props.valueLG;
120
+ if (props.valueMD && width.value >= 992) return props.valueMD;
121
+ if (props.valueSM) return props.valueSM;
122
+ return props.valueDefault;
123
+ });
124
+ const onResize = () => {
125
+ callDebounced(onResizeEnd, { debounceTime: 50 });
126
+ };
127
+ const onResizeEnd = async () => {
128
+ width.value = window.innerWidth;
129
+ await nextTick();
130
+ const bannerHeight = await getBannerRowHeight();
131
+ bannersStore.updateBannersHeight(bannerHeight);
132
+ };
133
+ onMounted(() => {
134
+ window.addEventListener("resize", onResize);
135
+ });
136
+ onBeforeUnmount(() => {
137
+ window.removeEventListener("resize", onResize);
138
+ });
139
+ return (_ctx, _cache) => {
140
+ return openBlock(), createElementBlock("span", null, [renderSlot(_ctx.$slots, "default", {
141
+ bp: bp.value,
142
+ value: value.value
143
+ })]);
144
+ };
145
+ }
146
+ });
147
+ var WorkflowProductionChecklist_default = /* @__PURE__ */ defineComponent({
148
+ __name: "WorkflowProductionChecklist",
149
+ props: { workflow: {} },
150
+ setup(__props) {
151
+ const props = __props;
152
+ const i18n = useI18n();
153
+ const router = useRouter();
154
+ const evaluationStore = useEvaluationStore();
155
+ const nodeTypesStore = useNodeTypesStore();
156
+ const workflowsCache = useWorkflowSettingsCache();
157
+ const uiStore = useUIStore();
158
+ const message = useMessage();
159
+ const telemetry$1 = useTelemetry();
160
+ const sourceControlStore = useSourceControlStore();
161
+ const settingsStore = useSettingsStore();
162
+ const { isEligibleForMcpAccess } = useMcp();
163
+ const usersStore = useUsersStore();
164
+ const isPopoverOpen = ref(false);
165
+ const cachedSettings = ref(null);
166
+ const hasAINode = computed(() => {
167
+ return props.workflow.nodes.some((node) => {
168
+ return nodeTypesStore.getNodeType(node.type, node.typeVersion)?.codex?.categories?.includes("AI");
169
+ });
170
+ });
171
+ const hasEvaluationSetOutputsNode = computed(() => {
172
+ return evaluationStore.evaluationSetOutputsNodeExist;
173
+ });
174
+ const hasErrorWorkflow = computed(() => {
175
+ return !!props.workflow.settings?.errorWorkflow;
176
+ });
177
+ const hasSavedTimeNodes = computed(() => {
178
+ if (!props.workflow?.nodes) return false;
179
+ return props.workflow.nodes.some((node) => node.type === "n8n-nodes-base.timeSaved" && node.disabled !== true);
180
+ });
181
+ const hasTimeSaved = computed(() => {
182
+ return props.workflow.settings?.timeSavedPerExecution !== void 0 || hasSavedTimeNodes.value;
183
+ });
184
+ const isActivationModalOpen = computed(() => {
185
+ return uiStore.isModalActiveById[WORKFLOW_ACTIVE_MODAL_KEY];
186
+ });
187
+ const isProtectedEnvironment = computed(() => {
188
+ return sourceControlStore.preferences.branchReadOnly;
189
+ });
190
+ const isOwner = computed(() => usersStore.isInstanceOwner);
191
+ const isAdmin = computed(() => usersStore.isAdmin);
192
+ const isMcpModuleEnabled = computed(() => {
193
+ return settingsStore.isModuleActive("mcp");
194
+ });
195
+ const isMcpAccessEnabled = computed(() => {
196
+ return settingsStore.moduleSettings.mcp?.mcpAccessEnabled ?? false;
197
+ });
198
+ const isWorkflowEligibleForMcpAccess = computed(() => {
199
+ return isEligibleForMcpAccess(props.workflow);
200
+ });
201
+ const canToggleInstanceMCPAccess = computed(() => isOwner.value || isAdmin.value);
202
+ const availableActions = computed(() => {
203
+ if (props.workflow.activeVersionId === null || workflowsCache.isCacheLoading.value) return [];
204
+ const actions = [];
205
+ const suggestedActionSettings = cachedSettings.value?.suggestedActions ?? {};
206
+ if (!suggestedActionSettings.errorWorkflow?.ignored) actions.push({
207
+ id: "errorWorkflow",
208
+ title: i18n.baseText("workflowProductionChecklist.errorWorkflow.title"),
209
+ description: i18n.baseText("workflowProductionChecklist.errorWorkflow.description"),
210
+ moreInfoLink: ERROR_WORKFLOW_DOCS_URL,
211
+ completed: hasErrorWorkflow.value
212
+ });
213
+ if (hasAINode.value && evaluationStore.isEvaluationEnabled && !suggestedActionSettings.evaluations?.ignored) actions.push({
214
+ id: "evaluations",
215
+ title: i18n.baseText("workflowProductionChecklist.evaluations.title"),
216
+ description: i18n.baseText("workflowProductionChecklist.evaluations.description"),
217
+ moreInfoLink: EVALUATIONS_DOCS_URL,
218
+ completed: hasEvaluationSetOutputsNode.value
219
+ });
220
+ if (!suggestedActionSettings.timeSaved?.ignored) actions.push({
221
+ id: "timeSaved",
222
+ title: i18n.baseText("workflowProductionChecklist.timeSaved.title"),
223
+ description: i18n.baseText("workflowProductionChecklist.timeSaved.description"),
224
+ moreInfoLink: TIME_SAVED_DOCS_URL,
225
+ completed: hasTimeSaved.value
226
+ });
227
+ const mcpAction = getMcpAction();
228
+ if (mcpAction) actions.push(mcpAction);
229
+ return actions;
230
+ function getMcpAction() {
231
+ if (!isMcpModuleEnabled.value || !isWorkflowEligibleForMcpAccess.value) return null;
232
+ const baseAction = {
233
+ title: i18n.baseText("mcp.productionChecklist.title"),
234
+ moreInfoLink: MCP_DOCS_PAGE_URL
235
+ };
236
+ if (!isMcpAccessEnabled.value) {
237
+ if (!canToggleInstanceMCPAccess.value || suggestedActionSettings["instance-mcp-access"]?.ignored) return null;
238
+ return {
239
+ ...baseAction,
240
+ id: "instance-mcp-access",
241
+ description: i18n.baseText("mcp.productionChecklist.instance.description"),
242
+ completed: false
243
+ };
244
+ }
245
+ if (suggestedActionSettings["workflow-mcp-access"]?.ignored) return null;
246
+ return {
247
+ ...baseAction,
248
+ id: "workflow-mcp-access",
249
+ description: i18n.baseText("mcp.productionChecklist.workflow.description"),
250
+ completed: props.workflow.settings?.availableInMCP ?? false
251
+ };
252
+ }
253
+ });
254
+ async function loadWorkflowSettings() {
255
+ if (props.workflow.id) cachedSettings.value = await workflowsCache.getMergedWorkflowSettings(props.workflow.id);
256
+ }
257
+ async function handleActionClick(actionId) {
258
+ switch (actionId) {
259
+ case "evaluations":
260
+ await router.push({
261
+ name: VIEWS.EVALUATION_EDIT,
262
+ params: { name: props.workflow.id }
263
+ });
264
+ break;
265
+ case "errorWorkflow":
266
+ case "timeSaved":
267
+ case "workflow-mcp-access":
268
+ uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
269
+ break;
270
+ case "instance-mcp-access":
271
+ await router.push({ name: MCP_SETTINGS_VIEW });
272
+ break;
273
+ default: break;
274
+ }
275
+ isPopoverOpen.value = false;
276
+ }
277
+ function isValidAction(action) {
278
+ return [
279
+ "evaluations",
280
+ "errorWorkflow",
281
+ "timeSaved",
282
+ "workflow-mcp-access",
283
+ "instance-mcp-access"
284
+ ].includes(action);
285
+ }
286
+ async function handleIgnoreClick(actionId) {
287
+ if (!isValidAction(actionId)) return;
288
+ await workflowsCache.ignoreSuggestedAction(props.workflow.id, actionId);
289
+ await loadWorkflowSettings();
290
+ telemetry$1.track("user clicked ignore suggested action", { actionId });
291
+ }
292
+ async function handleIgnoreAll() {
293
+ if (await message.confirm(i18n.baseText("workflowProductionChecklist.ignoreAllConfirmation.description"), i18n.baseText("workflowProductionChecklist.ignoreAllConfirmation.title"), { confirmButtonText: i18n.baseText("workflowProductionChecklist.ignoreAllConfirmation.confirm") }) === "confirm") {
294
+ await workflowsCache.ignoreAllSuggestedActionsForAllWorkflows(availableActions.value.map((action) => action.id));
295
+ await loadWorkflowSettings();
296
+ telemetry$1.track("user clicked ignore suggested actions for all workflows");
297
+ }
298
+ }
299
+ function openSuggestedActions() {
300
+ isPopoverOpen.value = true;
301
+ }
302
+ function onPopoverOpened() {
303
+ telemetry$1.track("user opened suggested actions checklist");
304
+ }
305
+ function handlePopoverOpenChange(open) {
306
+ if (open) {
307
+ isPopoverOpen.value = true;
308
+ onPopoverOpened();
309
+ } else if (!isActivationModalOpen.value) isPopoverOpen.value = false;
310
+ }
311
+ watch(() => !!props.workflow.activeVersionId, async (isActive, wasActive) => {
312
+ if (isActive && !wasActive) {
313
+ if (!cachedSettings.value?.firstActivatedAt) setTimeout(() => {
314
+ openSuggestedActions();
315
+ }, 0);
316
+ await workflowsCache.updateFirstActivatedAt(props.workflow.id);
317
+ }
318
+ });
319
+ onMounted(async () => {
320
+ await loadWorkflowSettings();
321
+ });
322
+ return (_ctx, _cache) => {
323
+ return availableActions.value.length > 0 ? (openBlock(), createBlock(unref(SuggestedActions_default), {
324
+ key: 0,
325
+ open: isPopoverOpen.value,
326
+ title: unref(i18n).baseText("workflowProductionChecklist.title"),
327
+ actions: availableActions.value,
328
+ "ignore-all-label": unref(i18n).baseText("workflowProductionChecklist.turnOffWorkflowSuggestions"),
329
+ notice: isProtectedEnvironment.value ? unref(i18n).baseText("workflowProductionChecklist.readOnlyNotice") : "",
330
+ "popover-alignment": "end",
331
+ onActionClick: handleActionClick,
332
+ onIgnoreClick: handleIgnoreClick,
333
+ onIgnoreAll: handleIgnoreAll,
334
+ "onUpdate:open": handlePopoverOpenChange
335
+ }, null, 8, [
336
+ "open",
337
+ "title",
338
+ "actions",
339
+ "ignore-all-label",
340
+ "notice"
341
+ ])) : createCommentVNode("", true);
342
+ };
343
+ }
344
+ });
345
+ var IntersectionObserver_default = /* @__PURE__ */ defineComponent({
346
+ __name: "IntersectionObserver",
347
+ props: {
348
+ threshold: { default: 0 },
349
+ enabled: {
350
+ type: Boolean,
351
+ default: false
352
+ },
353
+ eventBus: {}
354
+ },
355
+ emits: ["observed"],
356
+ setup(__props, { emit: __emit }) {
357
+ const props = __props;
358
+ const emit = __emit;
359
+ const observer = ref(null);
360
+ const root = ref(null);
361
+ onBeforeUnmount(() => {
362
+ if (props.enabled && observer.value) observer.value.disconnect();
363
+ });
364
+ onMounted(() => {
365
+ if (!props.enabled) return;
366
+ const options = {
367
+ root: root.value,
368
+ rootMargin: "0px",
369
+ threshold: props.threshold
370
+ };
371
+ const intersectionObserver = new IntersectionObserver((entries) => {
372
+ entries.forEach(({ target, isIntersecting }) => {
373
+ emit("observed", {
374
+ el: target,
375
+ isIntersecting
376
+ });
377
+ });
378
+ }, options);
379
+ observer.value = intersectionObserver;
380
+ props.eventBus.on("observe", (observed) => {
381
+ if (observed) intersectionObserver.observe(observed);
382
+ });
383
+ props.eventBus.on("unobserve", (observed) => {
384
+ intersectionObserver.unobserve(observed);
385
+ });
386
+ });
387
+ return (_ctx, _cache) => {
388
+ return openBlock(), createElementBlock("div", {
389
+ ref_key: "root",
390
+ ref: root
391
+ }, [renderSlot(_ctx.$slots, "default")], 512);
392
+ };
393
+ }
394
+ });
395
+ var IntersectionObserved_default = /* @__PURE__ */ defineComponent({
396
+ __name: "IntersectionObserved",
397
+ props: {
398
+ enabled: {
399
+ type: Boolean,
400
+ default: false
401
+ },
402
+ eventBus: {}
403
+ },
404
+ setup(__props) {
405
+ const props = __props;
406
+ const observed = ref(null);
407
+ onMounted(async () => {
408
+ if (!props.enabled) return;
409
+ await nextTick();
410
+ props.eventBus.emit("observe", observed.value);
411
+ });
412
+ onBeforeUnmount(() => {
413
+ if (props.enabled) props.eventBus.emit("unobserve", observed.value);
414
+ });
415
+ return (_ctx, _cache) => {
416
+ return openBlock(), createElementBlock("span", {
417
+ ref_key: "observed",
418
+ ref: observed
419
+ }, [renderSlot(_ctx.$slots, "default")], 512);
420
+ };
421
+ }
422
+ });
423
+ var import_debounce = /* @__PURE__ */ __toESM(require_debounce());
424
+ var _hoisted_1$2 = { class: "tags" };
425
+ var _hoisted_2$2 = ["onClick"];
426
+ var TagsContainer_default = /* @__PURE__ */ __plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
427
+ __name: "TagsContainer",
428
+ props: {
429
+ tagIds: {},
430
+ tagsById: {},
431
+ limit: { default: 20 },
432
+ clickable: {
433
+ type: Boolean,
434
+ default: false
435
+ },
436
+ responsive: {
437
+ type: Boolean,
438
+ default: false
439
+ }
440
+ },
441
+ emits: ["click"],
442
+ setup(__props, { emit: __emit }) {
443
+ const props = __props;
444
+ const emit = __emit;
445
+ const maxWidth = ref(320);
446
+ const intersectionEventBus = createEventBus();
447
+ const visibility = ref({});
448
+ const tagsContainer = ref();
449
+ const style = computed(() => ({ "max-width": `${maxWidth.value}px` }));
450
+ const tags = computed(() => {
451
+ const allTags = props.tagIds.map((tagId) => props.tagsById[tagId]).filter(Boolean);
452
+ let toDisplay = props.limit ? allTags.slice(0, props.limit) : allTags;
453
+ toDisplay = toDisplay.map((tag) => ({
454
+ ...tag,
455
+ hidden: props.responsive && !visibility.value[tag.id]
456
+ }));
457
+ let visibleCount = toDisplay.length;
458
+ if (props.responsive) visibleCount = Object.values(visibility.value).reduce((accu, val) => val ? accu + 1 : accu, 0);
459
+ if (visibleCount < allTags.length) {
460
+ const hidden = allTags.slice(visibleCount);
461
+ const hiddenTitle = hidden.reduce((accu, tag) => accu ? `${accu}, ${tag.name}` : tag.name, "");
462
+ const countTag = {
463
+ id: "count",
464
+ name: `+${hidden.length}`,
465
+ title: hiddenTitle,
466
+ isCount: true
467
+ };
468
+ toDisplay.splice(visibleCount, 0, countTag);
469
+ }
470
+ return toDisplay;
471
+ });
472
+ const setMaxWidth = () => {
473
+ const parent = (tagsContainer.value?.$el)?.parentNode;
474
+ if (parent) {
475
+ maxWidth.value = 0;
476
+ nextTick(() => {
477
+ maxWidth.value = parent.clientWidth;
478
+ });
479
+ }
480
+ };
481
+ const debouncedSetMaxWidth = (0, import_debounce.default)(setMaxWidth, 100);
482
+ const onObserved = ({ el, isIntersecting }) => {
483
+ if (el.dataset.id) visibility.value = {
484
+ ...visibility.value,
485
+ [el.dataset.id]: isIntersecting
486
+ };
487
+ };
488
+ const onClick = (e, tag) => {
489
+ if (props.clickable) e.stopPropagation();
490
+ if (!tag.hidden) emit("click", tag.id);
491
+ };
492
+ onMounted(() => {
493
+ setMaxWidth();
494
+ window.addEventListener("resize", debouncedSetMaxWidth);
495
+ });
496
+ onBeforeUnmount(() => {
497
+ window.removeEventListener("resize", debouncedSetMaxWidth);
498
+ });
499
+ return (_ctx, _cache) => {
500
+ return openBlock(), createBlock(IntersectionObserver_default, {
501
+ ref_key: "tagsContainer",
502
+ ref: tagsContainer,
503
+ threshold: 1,
504
+ class: "tags-container",
505
+ style: normalizeStyle(style.value),
506
+ enabled: _ctx.responsive,
507
+ "event-bus": unref(intersectionEventBus),
508
+ onObserved
509
+ }, {
510
+ default: withCtx(() => [createBaseVNode("span", _hoisted_1$2, [(openBlock(true), createElementBlock(Fragment, null, renderList(tags.value, (tag) => {
511
+ return openBlock(), createElementBlock("span", {
512
+ key: tag.id,
513
+ class: normalizeClass({ clickable: !tag.hidden }),
514
+ onClick: (e) => onClick(e, tag)
515
+ }, [tag.isCount ? (openBlock(), createBlock(unref(N8nTag_default), {
516
+ key: 0,
517
+ title: tag.title,
518
+ text: tag.name,
519
+ clickable: false,
520
+ class: "count-container"
521
+ }, null, 8, ["title", "text"])) : (openBlock(), createBlock(IntersectionObserved_default, {
522
+ key: 1,
523
+ class: normalizeClass({ hideTag: tag.hidden }),
524
+ "data-id": tag.id,
525
+ enabled: _ctx.responsive,
526
+ "event-bus": unref(intersectionEventBus)
527
+ }, {
528
+ default: withCtx(() => [createVNode(unref(N8nTag_default), {
529
+ title: tag.name,
530
+ text: tag.name,
531
+ clickable: _ctx.clickable
532
+ }, null, 8, [
533
+ "title",
534
+ "text",
535
+ "clickable"
536
+ ])]),
537
+ _: 2
538
+ }, 1032, [
539
+ "class",
540
+ "data-id",
541
+ "enabled",
542
+ "event-bus"
543
+ ]))], 10, _hoisted_2$2);
544
+ }), 128))])]),
545
+ _: 1
546
+ }, 8, [
547
+ "style",
548
+ "enabled",
549
+ "event-bus"
550
+ ]);
551
+ };
552
+ }
553
+ }), [["__scopeId", "data-v-2e7ba899"]]);
554
+ var WorkflowTagsContainer_default = /* @__PURE__ */ defineComponent({
555
+ __name: "WorkflowTagsContainer",
556
+ props: {
557
+ tagIds: {},
558
+ limit: {},
559
+ clickable: { type: Boolean },
560
+ responsive: { type: Boolean }
561
+ },
562
+ emits: ["click"],
563
+ setup(__props, { emit: __emit }) {
564
+ const emit = __emit;
565
+ const annotationTagsStore = useTagsStore();
566
+ const tagsById = computed(() => annotationTagsStore.tagsById);
567
+ function onClick(tagId) {
568
+ emit("click", tagId);
569
+ }
570
+ return (_ctx, _cache) => {
571
+ return openBlock(), createBlock(TagsContainer_default, {
572
+ "tag-ids": _ctx.tagIds,
573
+ "tags-by-id": tagsById.value,
574
+ limit: _ctx.limit,
575
+ clickable: _ctx.clickable,
576
+ responsive: _ctx.responsive,
577
+ onClick
578
+ }, null, 8, [
579
+ "tag-ids",
580
+ "tags-by-id",
581
+ "limit",
582
+ "clickable",
583
+ "responsive"
584
+ ]);
585
+ };
586
+ }
587
+ });
588
+ var HEARTBEAT_INTERVAL = 5 * TIME.MINUTE;
589
+ const useCollaborationStore = defineStore(STORES.COLLABORATION, () => {
590
+ const pushStore = usePushConnectionStore();
591
+ const workflowsStore = useWorkflowsStore();
592
+ const usersStore = useUsersStore();
593
+ const uiStore = useUIStore();
594
+ const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings, addBeforeUnloadHandler } = useBeforeUnload({ route: useRoute() });
595
+ const unloadTimeout = ref(null);
596
+ addBeforeUnloadHandler(() => {
597
+ notifyWorkflowClosed();
598
+ if (uiStore.stateIsDirty) unloadTimeout.value = setTimeout(() => notifyWorkflowOpened, 5 * TIME.SECOND);
599
+ });
600
+ const collaborators = ref([]);
601
+ const heartbeatTimer = ref(null);
602
+ const startHeartbeat = () => {
603
+ stopHeartbeat();
604
+ heartbeatTimer.value = window.setInterval(notifyWorkflowOpened, HEARTBEAT_INTERVAL);
605
+ };
606
+ const stopHeartbeat = () => {
607
+ if (heartbeatTimer.value !== null) {
608
+ clearInterval(heartbeatTimer.value);
609
+ heartbeatTimer.value = null;
610
+ }
611
+ };
612
+ const pushStoreEventListenerRemovalFn = ref(null);
613
+ function initialize() {
614
+ if (pushStoreEventListenerRemovalFn.value) return;
615
+ pushStoreEventListenerRemovalFn.value = pushStore.addEventListener((event) => {
616
+ if (event.type === "collaboratorsChanged" && event.data.workflowId === workflowsStore.workflowId) collaborators.value = event.data.collaborators;
617
+ });
618
+ addBeforeUnloadEventBindings();
619
+ notifyWorkflowOpened();
620
+ startHeartbeat();
621
+ }
622
+ function terminate() {
623
+ if (typeof pushStoreEventListenerRemovalFn.value === "function") {
624
+ pushStoreEventListenerRemovalFn.value();
625
+ pushStoreEventListenerRemovalFn.value = null;
626
+ }
627
+ notifyWorkflowClosed();
628
+ stopHeartbeat();
629
+ pushStore.clearQueue();
630
+ removeBeforeUnloadEventBindings();
631
+ if (unloadTimeout.value) clearTimeout(unloadTimeout.value);
632
+ }
633
+ function notifyWorkflowOpened() {
634
+ if (!workflowsStore.isWorkflowSaved[workflowsStore.workflowId]) return;
635
+ pushStore.send({
636
+ type: "workflowOpened",
637
+ workflowId: workflowsStore.workflowId
638
+ });
639
+ }
640
+ function notifyWorkflowClosed() {
641
+ if (!workflowsStore.isWorkflowSaved[workflowsStore.workflowId]) return;
642
+ pushStore.send({
643
+ type: "workflowClosed",
644
+ workflowId: workflowsStore.workflowId
645
+ });
646
+ collaborators.value = collaborators.value.filter(({ user }) => user.id !== usersStore.currentUserId);
647
+ }
648
+ return {
649
+ collaborators,
650
+ initialize,
651
+ terminate,
652
+ startHeartbeat,
653
+ stopHeartbeat
654
+ };
655
+ });
656
+ var CollaborationPane_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
657
+ __name: "CollaborationPane",
658
+ setup(__props) {
659
+ const collaborationStore = useCollaborationStore();
660
+ const usersStore = useUsersStore();
661
+ watch(useDocumentVisibility(), (visibilityState) => {
662
+ if (visibilityState === "hidden") collaborationStore.stopHeartbeat();
663
+ else collaborationStore.startHeartbeat();
664
+ });
665
+ const showUserStack = computed(() => collaborationStore.collaborators.length > 1);
666
+ const collaboratorsSorted = computed(() => {
667
+ const users = collaborationStore.collaborators.map(({ user }) => user);
668
+ const index = users.findIndex((user) => user.id === usersStore.currentUser?.id);
669
+ if (index < 1) return { defaultGroup: users };
670
+ const [currentUser] = users.splice(index, 1);
671
+ return { defaultGroup: [currentUser, ...users] };
672
+ });
673
+ const currentUserEmail = computed(() => usersStore.currentUser?.email);
674
+ onMounted(() => {
675
+ collaborationStore.initialize();
676
+ });
677
+ onBeforeUnmount(() => {
678
+ collaborationStore.terminate();
679
+ });
680
+ return (_ctx, _cache) => {
681
+ return showUserStack.value ? (openBlock(), createElementBlock("div", {
682
+ key: 0,
683
+ class: normalizeClass(`collaboration-pane-container ${_ctx.$style.container}`),
684
+ "data-test-id": "collaboration-pane"
685
+ }, [createVNode(unref(N8nUserStack_default), {
686
+ users: collaboratorsSorted.value,
687
+ "current-user-email": currentUserEmail.value
688
+ }, null, 8, ["users", "current-user-email"])], 2)) : createCommentVNode("", true);
689
+ };
690
+ }
691
+ });
692
+ var CollaborationPane_vue_vue_type_style_index_0_lang_module_default = { container: "_container_dsr9f_123" };
693
+ var CollaborationPane_default = /* @__PURE__ */ __plugin_vue_export_helper_default(CollaborationPane_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": CollaborationPane_vue_vue_type_style_index_0_lang_module_default }]]);
694
+ var _hoisted_1$1 = { key: 0 };
695
+ var _hoisted_2$1 = { key: 1 };
696
+ var WorkflowHistoryButton_default = /* @__PURE__ */ defineComponent({
697
+ __name: "WorkflowHistoryButton",
698
+ props: {
699
+ workflowId: {},
700
+ isNewWorkflow: { type: Boolean }
701
+ },
702
+ setup(__props) {
703
+ const locale = useI18n();
704
+ const props = __props;
705
+ const workflowHistoryRoute = computed(() => ({
706
+ name: VIEWS.WORKFLOW_HISTORY,
707
+ params: { workflowId: props.workflowId }
708
+ }));
709
+ return (_ctx, _cache) => {
710
+ const _component_RouterLink = resolveComponent("RouterLink");
711
+ return _ctx.workflowId ? (openBlock(), createBlock(unref(N8nTooltip_default), {
712
+ key: 0,
713
+ placement: "bottom"
714
+ }, {
715
+ content: withCtx(() => [_ctx.isNewWorkflow ? (openBlock(), createElementBlock("span", _hoisted_1$1, toDisplayString(unref(locale).baseText("workflowHistory.button.tooltip.empty")), 1)) : (openBlock(), createElementBlock("span", _hoisted_2$1, toDisplayString(unref(locale).baseText("workflowHistory.button.tooltip")), 1))]),
716
+ default: withCtx(() => [createVNode(_component_RouterLink, { to: workflowHistoryRoute.value }, {
717
+ default: withCtx(() => [createVNode(unref(N8nIconButton_default), {
718
+ disabled: _ctx.isNewWorkflow,
719
+ "data-test-id": "workflow-history-button",
720
+ type: "highlight",
721
+ icon: "history",
722
+ size: "medium"
723
+ }, null, 8, ["disabled"])]),
724
+ _: 1
725
+ }, 8, ["to"])]),
726
+ _: 1
727
+ })) : createCommentVNode("", true);
728
+ };
729
+ }
730
+ });
731
+ var INVALID_CHARS_REGEX = /[<>:"/\\|?*\u0000-\u001F\u007F-\u009F]/g;
732
+ var ZERO_WIDTH_CHARS_REGEX = /[\u200B-\u200D\u2060\uFEFF]/g;
733
+ var UNICODE_SPACES_REGEX = /[\u00A0\u2000-\u200A]/g;
734
+ var LEADING_TRAILING_DOTS_SPACES_REGEX = /^[\s.]+|[\s.]+$/g;
735
+ var WINDOWS_RESERVED_NAMES = new Set([
736
+ "CON",
737
+ "PRN",
738
+ "AUX",
739
+ "NUL",
740
+ "COM1",
741
+ "COM2",
742
+ "COM3",
743
+ "COM4",
744
+ "COM5",
745
+ "COM6",
746
+ "COM7",
747
+ "COM8",
748
+ "COM9",
749
+ "LPT1",
750
+ "LPT2",
751
+ "LPT3",
752
+ "LPT4",
753
+ "LPT5",
754
+ "LPT6",
755
+ "LPT7",
756
+ "LPT8",
757
+ "LPT9"
758
+ ]);
759
+ var DEFAULT_FALLBACK_NAME = "untitled";
760
+ var MAX_FILENAME_LENGTH = 200;
761
+ var sanitizeFilename = (filename, maxLength = MAX_FILENAME_LENGTH) => {
762
+ if (!filename) return DEFAULT_FALLBACK_NAME;
763
+ let baseName = filename.trim().replace(INVALID_CHARS_REGEX, "_").replace(ZERO_WIDTH_CHARS_REGEX, "").replace(UNICODE_SPACES_REGEX, " ").replace(LEADING_TRAILING_DOTS_SPACES_REGEX, "");
764
+ if (!baseName) baseName = DEFAULT_FALLBACK_NAME;
765
+ if (WINDOWS_RESERVED_NAMES.has(baseName.toUpperCase())) baseName = `_${baseName}`;
766
+ if (baseName.length > maxLength) baseName = baseName.slice(0, maxLength);
767
+ return baseName;
768
+ };
769
+ var import_FileSaver_min = /* @__PURE__ */ __toESM(require_FileSaver_min());
770
+ const getWorkflowId = (propId, routeName) => {
771
+ return propId ?? (typeof routeName === "string" ? routeName : void 0);
772
+ };
773
+ var ActionsDropdownMenu_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
774
+ __name: "ActionsDropdownMenu",
775
+ props: {
776
+ workflowPermissions: {},
777
+ isNewWorkflow: { type: Boolean },
778
+ readOnly: { type: Boolean },
779
+ isArchived: { type: Boolean },
780
+ id: {},
781
+ name: {},
782
+ tags: {},
783
+ currentFolder: {},
784
+ meta: {}
785
+ },
786
+ emits: ["workflow:saved"],
787
+ setup(__props, { expose: __expose, emit: __emit }) {
788
+ const props = __props;
789
+ const emit = __emit;
790
+ const importFileRef = ref();
791
+ const toast = useToast();
792
+ const locale = useI18n();
793
+ const route = useRoute();
794
+ const projectsStore = useProjectsStore();
795
+ const sourceControlStore = useSourceControlStore();
796
+ const workflowsStore = useWorkflowsStore();
797
+ const uiStore = useUIStore();
798
+ const $style = useCssModule();
799
+ const rootStore = useRootStore();
800
+ const tagsStore = useTagsStore();
801
+ const settingsStore = useSettingsStore();
802
+ const usersStore = useUsersStore();
803
+ const workflowHelpers = useWorkflowHelpers();
804
+ const workflowActivate = useWorkflowActivate();
805
+ const changeOwnerEventBus = createEventBus();
806
+ const workflowTelemetry = useTelemetry();
807
+ const onWorkflowPage = computed(() => {
808
+ return route.meta && (route.meta.nodeView || route.meta.keepWorkflowAlive === true);
809
+ });
810
+ const onExecutionsTab = computed(() => {
811
+ return [
812
+ VIEWS.EXECUTION_HOME.toString(),
813
+ VIEWS.WORKFLOW_EXECUTIONS.toString(),
814
+ VIEWS.EXECUTION_PREVIEW
815
+ ].includes(route.name || "");
816
+ });
817
+ const activeVersion = computed(() => workflowsStore.workflow.activeVersion);
818
+ const isSharingEnabled = computed(() => settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]);
819
+ function handleFileImport() {
820
+ const inputRef = importFileRef.value;
821
+ if (inputRef?.files && inputRef.files.length !== 0) {
822
+ const reader = new FileReader();
823
+ reader.onload = () => {
824
+ let workflowData;
825
+ try {
826
+ workflowData = JSON.parse(reader.result);
827
+ } catch (error) {
828
+ toast.showMessage({
829
+ title: locale.baseText("mainSidebar.showMessage.handleFileImport.title"),
830
+ message: locale.baseText("mainSidebar.showMessage.handleFileImport.message"),
831
+ type: "error"
832
+ });
833
+ return;
834
+ } finally {
835
+ reader.onload = null;
836
+ inputRef.value = "";
837
+ }
838
+ nodeViewEventBus.emit("importWorkflowData", { data: workflowData });
839
+ };
840
+ reader.readAsText(inputRef.files[0]);
841
+ }
842
+ }
843
+ const workflowMenuItems = computed(() => {
844
+ const actions = [{
845
+ id: WORKFLOW_MENU_ACTIONS.DOWNLOAD,
846
+ label: locale.baseText("menuActions.download"),
847
+ disabled: !onWorkflowPage.value
848
+ }];
849
+ if (isSharingEnabled.value) actions.push({
850
+ id: WORKFLOW_MENU_ACTIONS.SHARE,
851
+ label: locale.baseText("workflowDetails.share"),
852
+ disabled: !onWorkflowPage.value
853
+ });
854
+ if (props.workflowPermissions.move && projectsStore.isTeamProjectFeatureEnabled) actions.push({
855
+ id: WORKFLOW_MENU_ACTIONS.CHANGE_OWNER,
856
+ label: locale.baseText("workflows.item.changeOwner"),
857
+ disabled: props.isNewWorkflow
858
+ });
859
+ if (!props.readOnly && !props.isArchived) actions.push({
860
+ id: WORKFLOW_MENU_ACTIONS.RENAME,
861
+ label: locale.baseText("generic.rename"),
862
+ disabled: !onWorkflowPage.value || props.workflowPermissions.update !== true
863
+ });
864
+ if (props.workflowPermissions.update === true && !props.readOnly && !props.isArchived || props.isNewWorkflow) {
865
+ actions.unshift({
866
+ id: WORKFLOW_MENU_ACTIONS.DUPLICATE,
867
+ label: locale.baseText("menuActions.duplicate"),
868
+ disabled: !onWorkflowPage.value || !props.id
869
+ });
870
+ actions.unshift({
871
+ id: WORKFLOW_MENU_ACTIONS.EDIT_DESCRIPTION,
872
+ label: locale.baseText("menuActions.editDescription"),
873
+ disabled: !onWorkflowPage.value || !props.id
874
+ });
875
+ actions.push({
876
+ id: WORKFLOW_MENU_ACTIONS.IMPORT_FROM_URL,
877
+ label: locale.baseText("menuActions.importFromUrl"),
878
+ disabled: !onWorkflowPage.value || onExecutionsTab.value
879
+ }, {
880
+ id: WORKFLOW_MENU_ACTIONS.IMPORT_FROM_FILE,
881
+ label: locale.baseText("menuActions.importFromFile"),
882
+ disabled: !onWorkflowPage.value || onExecutionsTab.value
883
+ });
884
+ }
885
+ if (hasPermission(["rbac"], { rbac: { scope: "sourceControl:push" } })) actions.push({
886
+ id: WORKFLOW_MENU_ACTIONS.PUSH,
887
+ label: locale.baseText("menuActions.push"),
888
+ disabled: !sourceControlStore.isEnterpriseSourceControlEnabled || !onWorkflowPage.value || onExecutionsTab.value || sourceControlStore.preferences.branchReadOnly
889
+ });
890
+ actions.push({
891
+ id: WORKFLOW_MENU_ACTIONS.SETTINGS,
892
+ label: locale.baseText("generic.settings"),
893
+ disabled: !onWorkflowPage.value || props.isNewWorkflow
894
+ });
895
+ if (activeVersion.value && props.workflowPermissions.publish && !props.readOnly) actions.push({
896
+ id: WORKFLOW_MENU_ACTIONS.UNPUBLISH,
897
+ label: locale.baseText("menuActions.unpublish"),
898
+ disabled: !onWorkflowPage.value
899
+ });
900
+ if (props.workflowPermissions.delete === true && !props.readOnly || props.isNewWorkflow) if (props.isArchived) {
901
+ actions.push({
902
+ id: WORKFLOW_MENU_ACTIONS.UNARCHIVE,
903
+ label: locale.baseText("menuActions.unarchive"),
904
+ disabled: !onWorkflowPage.value || props.isNewWorkflow
905
+ });
906
+ actions.push({
907
+ id: WORKFLOW_MENU_ACTIONS.DELETE,
908
+ label: locale.baseText("menuActions.delete"),
909
+ disabled: !onWorkflowPage.value || props.isNewWorkflow,
910
+ customClass: $style.deleteItem,
911
+ divided: true
912
+ });
913
+ } else actions.push({
914
+ id: WORKFLOW_MENU_ACTIONS.ARCHIVE,
915
+ label: locale.baseText("menuActions.archive"),
916
+ disabled: !onWorkflowPage.value || props.isNewWorkflow,
917
+ customClass: $style.deleteItem,
918
+ divided: true
919
+ });
920
+ return actions;
921
+ });
922
+ function onUnpublishWorkflow() {
923
+ const workflowId = getWorkflowId(props.id, route.params.name);
924
+ if (!workflowId || !activeVersion.value) {
925
+ toast.showMessage({
926
+ title: locale.baseText("workflowHistory.action.unpublish.notAvailable"),
927
+ type: "warning"
928
+ });
929
+ return;
930
+ }
931
+ const unpublishEventBus = createEventBus();
932
+ unpublishEventBus.once("unpublish", async () => {
933
+ const success = await workflowActivate.unpublishWorkflowFromHistory(workflowId);
934
+ uiStore.closeModal(WORKFLOW_HISTORY_VERSION_UNPUBLISH);
935
+ if (success) toast.showMessage({
936
+ title: locale.baseText("workflowHistory.action.unpublish.success.title"),
937
+ type: "success"
938
+ });
939
+ });
940
+ uiStore.openModalWithData({
941
+ name: WORKFLOW_HISTORY_VERSION_UNPUBLISH,
942
+ data: {
943
+ versionName: activeVersion.value.name,
944
+ eventBus: unpublishEventBus
945
+ }
946
+ });
947
+ }
948
+ async function onWorkflowMenuSelect(action) {
949
+ switch (action) {
950
+ case WORKFLOW_MENU_ACTIONS.EDIT_DESCRIPTION: {
951
+ const workflowId = getWorkflowId(props.id, route.params.name);
952
+ if (!workflowId) return;
953
+ const workflowDescription = workflowsStore.getWorkflowById(workflowId).description;
954
+ uiStore.openModalWithData({
955
+ name: WORKFLOW_DESCRIPTION_MODAL_KEY,
956
+ data: {
957
+ workflowId,
958
+ workflowDescription
959
+ }
960
+ });
961
+ break;
962
+ }
963
+ case WORKFLOW_MENU_ACTIONS.DUPLICATE:
964
+ uiStore.openModalWithData({
965
+ name: DUPLICATE_MODAL_KEY,
966
+ data: {
967
+ id: props.id,
968
+ name: props.name,
969
+ tags: props.tags,
970
+ parentFolderId: props.currentFolder?.id
971
+ }
972
+ });
973
+ break;
974
+ case WORKFLOW_MENU_ACTIONS.RENAME:
975
+ nodeViewEventBus.emit("renameWorkflow");
976
+ break;
977
+ case WORKFLOW_MENU_ACTIONS.DOWNLOAD: {
978
+ const workflowData = await workflowHelpers.getWorkflowDataToSave();
979
+ const { tags,...data } = workflowData;
980
+ const exportData = {
981
+ ...data,
982
+ meta: {
983
+ ...props.meta,
984
+ instanceId: rootStore.instanceId
985
+ },
986
+ tags: (tags ?? []).map((tagId) => {
987
+ const { usageCount,...tag } = tagsStore.tagsById[tagId];
988
+ return tag;
989
+ })
990
+ };
991
+ const blob = new Blob([JSON.stringify(exportData, null, 2)], { type: "application/json;charset=utf-8" });
992
+ let name = props.name || "unsaved_workflow";
993
+ name = sanitizeFilename(name);
994
+ telemetry.track("User exported workflow", { workflow_id: workflowData.id });
995
+ (0, import_FileSaver_min.default)(blob, name + ".json");
996
+ break;
997
+ }
998
+ case WORKFLOW_MENU_ACTIONS.IMPORT_FROM_URL:
999
+ uiStore.openModal(IMPORT_WORKFLOW_URL_MODAL_KEY);
1000
+ break;
1001
+ case WORKFLOW_MENU_ACTIONS.IMPORT_FROM_FILE:
1002
+ nodeViewEventBus.emit("importWorkflowFromFile");
1003
+ break;
1004
+ case WORKFLOW_MENU_ACTIONS.PUSH:
1005
+ try {
1006
+ emit("workflow:saved");
1007
+ router_default.push({ query: {
1008
+ ...route.query,
1009
+ sourceControl: "push"
1010
+ } });
1011
+ } catch (error) {
1012
+ switch (error.message) {
1013
+ case "source_control_not_connected":
1014
+ toast.showError({
1015
+ ...error,
1016
+ message: ""
1017
+ }, locale.baseText("settings.sourceControl.error.not.connected.title"), locale.baseText("settings.sourceControl.error.not.connected.message"));
1018
+ break;
1019
+ default: toast.showError(error, locale.baseText("error"));
1020
+ }
1021
+ }
1022
+ break;
1023
+ case WORKFLOW_MENU_ACTIONS.SETTINGS:
1024
+ uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
1025
+ break;
1026
+ case WORKFLOW_MENU_ACTIONS.SHARE:
1027
+ uiStore.openModalWithData({
1028
+ name: WORKFLOW_SHARE_MODAL_KEY,
1029
+ data: { id: props.id }
1030
+ });
1031
+ workflowTelemetry.track("User opened sharing modal", {
1032
+ workflow_id: props.id,
1033
+ user_id_sharer: usersStore.currentUser?.id,
1034
+ sub_view: route.name === VIEWS.WORKFLOWS ? "Workflows listing" : "Workflow editor"
1035
+ });
1036
+ break;
1037
+ case WORKFLOW_MENU_ACTIONS.ARCHIVE:
1038
+ nodeViewEventBus.emit("archiveWorkflow");
1039
+ break;
1040
+ case WORKFLOW_MENU_ACTIONS.UNARCHIVE:
1041
+ nodeViewEventBus.emit("unarchiveWorkflow");
1042
+ break;
1043
+ case WORKFLOW_MENU_ACTIONS.DELETE:
1044
+ nodeViewEventBus.emit("deleteWorkflow");
1045
+ break;
1046
+ case WORKFLOW_MENU_ACTIONS.CHANGE_OWNER: {
1047
+ const workflowId = getWorkflowId(props.id, route.params.name);
1048
+ if (!workflowId) return;
1049
+ changeOwnerEventBus.once("resource-moved", async () => await router_default.push({ name: VIEWS.WORKFLOWS }));
1050
+ uiStore.openModalWithData({
1051
+ name: PROJECT_MOVE_RESOURCE_MODAL,
1052
+ data: {
1053
+ resource: workflowsStore.workflowsById[workflowId],
1054
+ resourceType: ResourceType.Workflow,
1055
+ resourceTypeLabel: locale.baseText("generic.workflow").toLowerCase(),
1056
+ eventBus: changeOwnerEventBus
1057
+ }
1058
+ });
1059
+ break;
1060
+ }
1061
+ case WORKFLOW_MENU_ACTIONS.UNPUBLISH:
1062
+ onUnpublishWorkflow();
1063
+ break;
1064
+ default: break;
1065
+ }
1066
+ }
1067
+ onMounted(() => {
1068
+ nodeViewEventBus.on("unpublishWorkflow", onUnpublishWorkflow);
1069
+ });
1070
+ onBeforeUnmount(() => {
1071
+ nodeViewEventBus.off("unpublishWorkflow", onUnpublishWorkflow);
1072
+ });
1073
+ __expose({ importFileRef });
1074
+ return (_ctx, _cache) => {
1075
+ return openBlock(), createElementBlock("div", { class: normalizeClass([unref($style).group]) }, [createBaseVNode("input", {
1076
+ ref_key: "importFileRef",
1077
+ ref: importFileRef,
1078
+ class: normalizeClass(unref($style).hiddenInput),
1079
+ type: "file",
1080
+ "data-test-id": "workflow-import-input",
1081
+ onChange: _cache[0] || (_cache[0] = ($event) => handleFileImport())
1082
+ }, null, 34), createVNode(unref(N8nActionDropdown_default), {
1083
+ items: workflowMenuItems.value,
1084
+ "data-test-id": "workflow-menu",
1085
+ onSelect: onWorkflowMenuSelect
1086
+ }, null, 8, ["items"])], 2);
1087
+ };
1088
+ }
1089
+ });
1090
+ var ActionsDropdownMenu_vue_vue_type_style_index_0_lang_module_default = {
1091
+ deleteItem: "_deleteItem_ntqfl_123",
1092
+ group: "_group_ntqfl_127",
1093
+ hiddenInput: "_hiddenInput_ntqfl_132"
1094
+ };
1095
+ var ActionsDropdownMenu_default = /* @__PURE__ */ __plugin_vue_export_helper_default(ActionsDropdownMenu_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": ActionsDropdownMenu_vue_vue_type_style_index_0_lang_module_default }]]);
1096
+ var WorkflowHeaderActions_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
1097
+ __name: "WorkflowHeaderActions",
1098
+ props: {
1099
+ readOnly: { type: Boolean },
1100
+ id: {},
1101
+ tags: {},
1102
+ name: {},
1103
+ meta: {},
1104
+ active: { type: Boolean },
1105
+ currentFolder: {},
1106
+ isArchived: { type: Boolean },
1107
+ isNewWorkflow: { type: Boolean },
1108
+ workflowPermissions: {}
1109
+ },
1110
+ emits: ["workflow:deactivated", "workflow:saved"],
1111
+ setup(__props, { expose: __expose, emit: __emit }) {
1112
+ const i18n = useI18n();
1113
+ const uiStore = useUIStore();
1114
+ const telemetry$1 = useTelemetry();
1115
+ const usersStore = useUsersStore();
1116
+ const route = useRoute();
1117
+ const pageRedirectionHelper = usePageRedirectionHelper();
1118
+ const $style = useCssModule();
1119
+ const props = __props;
1120
+ const emit = __emit;
1121
+ const isWorkflowSaving = computed(() => {
1122
+ return uiStore.isActionActive.workflowSaving;
1123
+ });
1124
+ const actionsMenuRef = useTemplateRef("actionsMenu");
1125
+ const importFileRef = computed(() => actionsMenuRef.value?.importFileRef);
1126
+ const onWorkflowActiveToggle = async (value) => {
1127
+ if (!value.active) emit("workflow:deactivated");
1128
+ };
1129
+ function onShareButtonClick() {
1130
+ uiStore.openModalWithData({
1131
+ name: WORKFLOW_SHARE_MODAL_KEY,
1132
+ data: { id: props.id }
1133
+ });
1134
+ telemetry$1.track("User opened sharing modal", {
1135
+ workflow_id: props.id,
1136
+ user_id_sharer: usersStore.currentUser?.id,
1137
+ sub_view: route.name === VIEWS.WORKFLOWS ? "Workflows listing" : "Workflow editor"
1138
+ });
1139
+ }
1140
+ function goToUpgrade() {
1141
+ pageRedirectionHelper.goToUpgrade("workflow_sharing", "upgrade-workflow-sharing");
1142
+ }
1143
+ __expose({ importFileRef });
1144
+ return (_ctx, _cache) => {
1145
+ return openBlock(), createElementBlock("div", { class: normalizeClass(unref($style).container) }, [
1146
+ createBaseVNode("span", { class: normalizeClass([unref($style).activator, unref($style).group]) }, [createVNode(WorkflowActivator_default, {
1147
+ "is-archived": _ctx.isArchived,
1148
+ "workflow-active": _ctx.active,
1149
+ "workflow-id": _ctx.id,
1150
+ "workflow-permissions": _ctx.workflowPermissions,
1151
+ "onUpdate:workflowActive": onWorkflowActiveToggle
1152
+ }, null, 8, [
1153
+ "is-archived",
1154
+ "workflow-active",
1155
+ "workflow-id",
1156
+ "workflow-permissions"
1157
+ ])], 2),
1158
+ createVNode(EnterpriseEdition_ee_default, { features: [unref(EnterpriseEditionFeature).Sharing] }, {
1159
+ fallback: withCtx(() => [createVNode(unref(N8nTooltip_default), null, {
1160
+ content: withCtx(() => [createVNode(unref(I18nT), {
1161
+ keypath: unref(uiStore).contextBasedTranslationKeys.workflows.sharing.unavailable.description.tooltip,
1162
+ tag: "span",
1163
+ scope: "global"
1164
+ }, {
1165
+ action: withCtx(() => [createBaseVNode("a", { onClick: goToUpgrade }, toDisplayString(unref(i18n).baseText(unref(uiStore).contextBasedTranslationKeys.workflows.sharing.unavailable.button)), 1)]),
1166
+ _: 1
1167
+ }, 8, ["keypath"])]),
1168
+ default: withCtx(() => [createVNode(unref(N8nButton_default), {
1169
+ type: "secondary",
1170
+ class: normalizeClass(["mr-2xs", unref($style).disabledShareButton])
1171
+ }, {
1172
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("workflowDetails.share")), 1)]),
1173
+ _: 1
1174
+ }, 8, ["class"])]),
1175
+ _: 1
1176
+ })]),
1177
+ default: withCtx(() => [createBaseVNode("div", { class: normalizeClass(unref($style).group) }, [!_ctx.isNewWorkflow ? (openBlock(), createBlock(CollaborationPane_default, { key: 0 })) : createCommentVNode("", true), createVNode(unref(N8nButton_default), {
1178
+ type: "secondary",
1179
+ "data-test-id": "workflow-share-button",
1180
+ onClick: onShareButtonClick
1181
+ }, {
1182
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("workflowDetails.share")), 1)]),
1183
+ _: 1
1184
+ })], 2)]),
1185
+ _: 1
1186
+ }, 8, ["features"]),
1187
+ createBaseVNode("div", { class: normalizeClass(unref($style).group) }, [
1188
+ createVNode(SaveButton_default, {
1189
+ type: "primary",
1190
+ saved: !unref(uiStore).stateIsDirty && !_ctx.isNewWorkflow,
1191
+ disabled: isWorkflowSaving.value || _ctx.readOnly || _ctx.isArchived || !_ctx.isNewWorkflow && !_ctx.workflowPermissions.update,
1192
+ "is-saving": isWorkflowSaving.value,
1193
+ "with-shortcut": !_ctx.readOnly && !_ctx.isArchived && _ctx.workflowPermissions.update,
1194
+ "shortcut-tooltip": unref(i18n).baseText("saveWorkflowButton.hint"),
1195
+ "data-test-id": "workflow-save-button",
1196
+ onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("workflow:saved"))
1197
+ }, null, 8, [
1198
+ "saved",
1199
+ "disabled",
1200
+ "is-saving",
1201
+ "with-shortcut",
1202
+ "shortcut-tooltip"
1203
+ ]),
1204
+ createVNode(WorkflowHistoryButton_default, {
1205
+ "workflow-id": props.id,
1206
+ "is-new-workflow": _ctx.isNewWorkflow
1207
+ }, null, 8, ["workflow-id", "is-new-workflow"]),
1208
+ createVNode(ActionsDropdownMenu_default, {
1209
+ id: _ctx.id,
1210
+ ref: "actionsMenu",
1211
+ "workflow-permissions": _ctx.workflowPermissions,
1212
+ "is-new-workflow": _ctx.isNewWorkflow,
1213
+ "read-only": _ctx.readOnly,
1214
+ "is-archived": _ctx.isArchived,
1215
+ name: _ctx.name,
1216
+ tags: _ctx.tags,
1217
+ "current-folder": _ctx.currentFolder,
1218
+ meta: _ctx.meta,
1219
+ "onWorkflow:saved": _cache[1] || (_cache[1] = ($event) => _ctx.$emit("workflow:saved"))
1220
+ }, null, 8, [
1221
+ "id",
1222
+ "workflow-permissions",
1223
+ "is-new-workflow",
1224
+ "read-only",
1225
+ "is-archived",
1226
+ "name",
1227
+ "tags",
1228
+ "current-folder",
1229
+ "meta"
1230
+ ])
1231
+ ], 2)
1232
+ ], 2);
1233
+ };
1234
+ }
1235
+ });
1236
+ var WorkflowHeaderActions_vue_vue_type_style_index_0_lang_module_default = {
1237
+ container: "_container_uqc1z_123",
1238
+ activator: "_activator_uqc1z_127",
1239
+ group: "_group_uqc1z_138",
1240
+ disabledShareButton: "_disabledShareButton_uqc1z_143"
1241
+ };
1242
+ var WorkflowHeaderActions_default = /* @__PURE__ */ __plugin_vue_export_helper_default(WorkflowHeaderActions_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": WorkflowHeaderActions_vue_vue_type_style_index_0_lang_module_default }]]);
1243
+ var WorkflowHeaderDraftPublishActions_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
1244
+ __name: "WorkflowHeaderDraftPublishActions",
1245
+ props: {
1246
+ readOnly: { type: Boolean },
1247
+ id: {},
1248
+ tags: {},
1249
+ name: {},
1250
+ meta: {},
1251
+ currentFolder: {},
1252
+ isArchived: { type: Boolean },
1253
+ isNewWorkflow: { type: Boolean },
1254
+ workflowPermissions: {}
1255
+ },
1256
+ emits: ["workflow:saved"],
1257
+ setup(__props, { expose: __expose }) {
1258
+ const props = __props;
1259
+ const actionsMenuRef = useTemplateRef("actionsMenu");
1260
+ const locale = useI18n();
1261
+ const uiStore = useUIStore();
1262
+ const workflowsStore = useWorkflowsStore();
1263
+ const i18n = useI18n();
1264
+ const { saveCurrentWorkflow } = useWorkflowSaving({ router: useRouter() });
1265
+ const autoSaveForPublish = ref(false);
1266
+ const isWorkflowSaving = computed(() => {
1267
+ return uiStore.isActionActive.workflowSaving && !autoSaveForPublish.value;
1268
+ });
1269
+ const importFileRef = computed(() => actionsMenuRef.value?.importFileRef);
1270
+ const onPublishButtonClick = async () => {
1271
+ if (uiStore.stateIsDirty || props.isNewWorkflow) {
1272
+ autoSaveForPublish.value = true;
1273
+ const saved = await saveCurrentWorkflow({}, true);
1274
+ autoSaveForPublish.value = false;
1275
+ if (!saved) return;
1276
+ }
1277
+ uiStore.openModalWithData({
1278
+ name: WORKFLOW_PUBLISH_MODAL_KEY,
1279
+ data: {}
1280
+ });
1281
+ };
1282
+ const foundTriggers = computed(() => getActivatableTriggerNodes(workflowsStore.workflowTriggerNodes));
1283
+ const containsTrigger = computed(() => {
1284
+ return foundTriggers.value.length > 0;
1285
+ });
1286
+ const isWorkflowSaved = computed(() => {
1287
+ return !uiStore.stateIsDirty && !props.isNewWorkflow;
1288
+ });
1289
+ const publishButtonEnabled = computed(() => {
1290
+ if (!props.workflowPermissions.publish) return false;
1291
+ if (!containsTrigger.value) return false;
1292
+ if (workflowsStore.nodesIssuesExist) return false;
1293
+ return workflowsStore.workflow.versionId && workflowsStore.workflow.versionId !== workflowsStore.workflow.activeVersion?.versionId || uiStore.stateIsDirty;
1294
+ });
1295
+ const publishTooltipText = computed(() => {
1296
+ if (!props.workflowPermissions.publish) return i18n.baseText("workflows.publish.permissionDenied");
1297
+ const wfHasAnyChanges = workflowsStore.workflow.versionId !== workflowsStore.workflow.activeVersion?.versionId;
1298
+ if (!containsTrigger.value) return i18n.baseText("workflows.publishModal.noTriggerMessage");
1299
+ if (workflowsStore.nodesIssuesExist) return i18n.baseText("workflowActivator.showMessage.activeChangedNodesIssuesExistTrue.title", {
1300
+ interpolate: { count: workflowsStore.nodesWithIssues.length },
1301
+ adjustToNumber: workflowsStore.nodesWithIssues.length
1302
+ });
1303
+ if (!wfHasAnyChanges && !uiStore.stateIsDirty) return i18n.baseText("workflows.publishModal.noChanges");
1304
+ return "";
1305
+ });
1306
+ const activeVersion = computed(() => workflowsStore.workflow.activeVersion);
1307
+ const activeVersionName = computed(() => {
1308
+ if (!activeVersion.value) return "";
1309
+ return activeVersion.value.name || generateVersionName(activeVersion.value.versionId);
1310
+ });
1311
+ const latestPublishDate = computed(() => {
1312
+ return getLastPublishedVersion(activeVersion.value?.workflowPublishHistory ?? [])?.createdAt;
1313
+ });
1314
+ onMounted(() => {
1315
+ nodeViewEventBus.on("publishWorkflow", onPublishButtonClick);
1316
+ });
1317
+ onBeforeUnmount(() => {
1318
+ nodeViewEventBus.off("publishWorkflow", onPublishButtonClick);
1319
+ });
1320
+ __expose({ importFileRef });
1321
+ return (_ctx, _cache) => {
1322
+ return openBlock(), createElementBlock("div", { class: normalizeClass(_ctx.$style.container) }, [
1323
+ !_ctx.isNewWorkflow ? (openBlock(), createBlock(CollaborationPane_default, { key: 0 })) : createCommentVNode("", true),
1324
+ activeVersion.value ? (openBlock(), createElementBlock("div", {
1325
+ key: 1,
1326
+ class: normalizeClass(_ctx.$style.activeVersionIndicator),
1327
+ "data-test-id": "workflow-active-version-indicator"
1328
+ }, [createVNode(unref(N8nTooltip_default), null, {
1329
+ content: withCtx(() => [
1330
+ createTextVNode(toDisplayString(activeVersionName.value), 1),
1331
+ _cache[2] || (_cache[2] = createBaseVNode("br", null, null, -1)),
1332
+ createTextVNode(toDisplayString(unref(i18n).baseText("workflowHistory.item.active")) + " ", 1),
1333
+ latestPublishDate.value ? (openBlock(), createBlock(TimeAgo_default, {
1334
+ key: 0,
1335
+ date: latestPublishDate.value
1336
+ }, null, 8, ["date"])) : createCommentVNode("", true)
1337
+ ]),
1338
+ default: withCtx(() => [createVNode(unref(N8nIcon_default), {
1339
+ icon: "circle-check",
1340
+ color: "success",
1341
+ size: "xlarge",
1342
+ class: normalizeClass(_ctx.$style.icon)
1343
+ }, null, 8, ["class"])]),
1344
+ _: 1
1345
+ })], 2)) : createCommentVNode("", true),
1346
+ !_ctx.isArchived && (_ctx.workflowPermissions.update || _ctx.workflowPermissions.publish) ? (openBlock(), createElementBlock("div", {
1347
+ key: 2,
1348
+ class: normalizeClass(_ctx.$style.publishButtonWrapper)
1349
+ }, [createVNode(unref(N8nTooltip_default), { disabled: !publishTooltipText.value }, {
1350
+ content: withCtx(() => [createTextVNode(toDisplayString(publishTooltipText.value), 1)]),
1351
+ default: withCtx(() => [createVNode(unref(N8nButton_default), {
1352
+ loading: autoSaveForPublish.value,
1353
+ disabled: !publishButtonEnabled.value || isWorkflowSaving.value,
1354
+ type: "secondary",
1355
+ "data-test-id": "workflow-open-publish-modal-button",
1356
+ onClick: onPublishButtonClick
1357
+ }, {
1358
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(locale).baseText("workflows.publish")), 1)]),
1359
+ _: 1
1360
+ }, 8, ["loading", "disabled"])]),
1361
+ _: 1
1362
+ }, 8, ["disabled"])], 2)) : createCommentVNode("", true),
1363
+ createVNode(SaveButton_default, {
1364
+ type: "primary",
1365
+ saved: isWorkflowSaved.value,
1366
+ disabled: isWorkflowSaving.value || _ctx.readOnly || _ctx.isArchived || !_ctx.isNewWorkflow && !_ctx.workflowPermissions.update,
1367
+ "is-saving": isWorkflowSaving.value,
1368
+ "with-shortcut": !_ctx.readOnly && !_ctx.isArchived && _ctx.workflowPermissions.update,
1369
+ "shortcut-tooltip": unref(i18n).baseText("saveWorkflowButton.hint"),
1370
+ "data-test-id": "workflow-save-button",
1371
+ onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("workflow:saved"))
1372
+ }, null, 8, [
1373
+ "saved",
1374
+ "disabled",
1375
+ "is-saving",
1376
+ "with-shortcut",
1377
+ "shortcut-tooltip"
1378
+ ]),
1379
+ createVNode(WorkflowHistoryButton_default, {
1380
+ "workflow-id": props.id,
1381
+ "is-new-workflow": _ctx.isNewWorkflow
1382
+ }, null, 8, ["workflow-id", "is-new-workflow"]),
1383
+ createVNode(ActionsDropdownMenu_default, {
1384
+ id: _ctx.id,
1385
+ ref: "actionsMenu",
1386
+ "workflow-permissions": _ctx.workflowPermissions,
1387
+ "is-new-workflow": _ctx.isNewWorkflow,
1388
+ "read-only": _ctx.readOnly,
1389
+ "is-archived": _ctx.isArchived,
1390
+ name: _ctx.name,
1391
+ tags: _ctx.tags,
1392
+ "current-folder": _ctx.currentFolder,
1393
+ meta: _ctx.meta,
1394
+ "onWorkflow:saved": _cache[1] || (_cache[1] = ($event) => _ctx.$emit("workflow:saved"))
1395
+ }, null, 8, [
1396
+ "id",
1397
+ "workflow-permissions",
1398
+ "is-new-workflow",
1399
+ "read-only",
1400
+ "is-archived",
1401
+ "name",
1402
+ "tags",
1403
+ "current-folder",
1404
+ "meta"
1405
+ ])
1406
+ ], 2);
1407
+ };
1408
+ }
1409
+ });
1410
+ var WorkflowHeaderDraftPublishActions_vue_vue_type_style_index_0_lang_module_default = {
1411
+ container: "_container_p6bf9_123",
1412
+ activeVersionIndicator: "_activeVersionIndicator_p6bf9_127",
1413
+ icon: "_icon_p6bf9_131",
1414
+ publishButtonWrapper: "_publishButtonWrapper_p6bf9_135"
1415
+ };
1416
+ var WorkflowHeaderDraftPublishActions_default = /* @__PURE__ */ __plugin_vue_export_helper_default(WorkflowHeaderDraftPublishActions_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": WorkflowHeaderDraftPublishActions_vue_vue_type_style_index_0_lang_module_default }]]);
1417
+ var _hoisted_1 = {
1418
+ class: "tags",
1419
+ "data-test-id": "workflow-tags-container"
1420
+ };
1421
+ var _hoisted_2 = { key: 1 };
1422
+ var WorkflowDetails_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
1423
+ __name: "WorkflowDetails",
1424
+ props: {
1425
+ readOnly: { type: Boolean },
1426
+ id: {},
1427
+ tags: {},
1428
+ name: {},
1429
+ meta: {},
1430
+ scopes: {},
1431
+ active: { type: Boolean },
1432
+ currentFolder: {},
1433
+ isArchived: { type: Boolean },
1434
+ description: {}
1435
+ },
1436
+ emits: ["workflow:deactivated"],
1437
+ setup(__props, { emit: __emit }) {
1438
+ const WORKFLOW_NAME_BP_TO_WIDTH = {
1439
+ XS: 150,
1440
+ SM: 200,
1441
+ MD: 250,
1442
+ LG: 500,
1443
+ XL: 1e3
1444
+ };
1445
+ const props = __props;
1446
+ const emit = __emit;
1447
+ const $style = useCssModule();
1448
+ const settingsStore = useSettingsStore();
1449
+ const uiStore = useUIStore();
1450
+ const workflowsStore = useWorkflowsStore();
1451
+ const projectsStore = useProjectsStore();
1452
+ const foldersStore = useFoldersStore();
1453
+ const npsSurveyStore = useNpsSurveyStore();
1454
+ const i18n = useI18n();
1455
+ const router = useRouter();
1456
+ const route = useRoute();
1457
+ const locale = useI18n();
1458
+ const telemetry$1 = useTelemetry();
1459
+ const message = useMessage();
1460
+ const toast = useToast();
1461
+ const documentTitle = useDocumentTitle();
1462
+ const workflowSaving = useWorkflowSaving({ router });
1463
+ const isTagsEditEnabled = ref(false);
1464
+ const appliedTagIds = ref([]);
1465
+ const tagsSaving = ref(false);
1466
+ const workflowHeaderActionsRef = useTemplateRef("workflowHeaderActions");
1467
+ const tagsEventBus = createEventBus();
1468
+ const hasChanged = (prev, curr) => {
1469
+ if (prev.length !== curr.length) return true;
1470
+ const set = new Set(prev);
1471
+ return curr.reduce((acc, val) => acc || !set.has(val), false);
1472
+ };
1473
+ const isNewWorkflow = computed(() => {
1474
+ return !workflowsStore.isWorkflowSaved[props.id];
1475
+ });
1476
+ const isWorkflowSaving = computed(() => {
1477
+ return uiStore.isActionActive.workflowSaving;
1478
+ });
1479
+ const workflowPermissions = computed(() => getResourcePermissions(props.scopes).workflow);
1480
+ const workflowTagIds = computed(() => {
1481
+ return (props.tags ?? []).map((tag) => typeof tag === "string" ? tag : tag.id);
1482
+ });
1483
+ const currentProjectName = computed(() => {
1484
+ if (projectsStore.currentProject?.type === ProjectTypes.Personal) return locale.baseText("projects.menu.personal");
1485
+ return projectsStore.currentProject?.name;
1486
+ });
1487
+ const currentFolderForBreadcrumbs = computed(() => {
1488
+ if (!isNewWorkflow.value && props.currentFolder) return props.currentFolder;
1489
+ const folderId = route.query.parentFolderId;
1490
+ if (folderId) return foldersStore.getCachedFolder(folderId);
1491
+ return null;
1492
+ });
1493
+ watch(() => props.id, () => {
1494
+ isTagsEditEnabled.value = false;
1495
+ renameInput.value?.forceCancel();
1496
+ });
1497
+ async function onSaveButtonClick() {
1498
+ if (isWorkflowSaving.value) return;
1499
+ const id = getWorkflowId(props.id, route.params.name);
1500
+ const name = props.name;
1501
+ const tags = props.tags;
1502
+ const wasNewWorkflow = !workflowsStore.isWorkflowSaved[props.id];
1503
+ if (await workflowSaving.saveCurrentWorkflow({
1504
+ id,
1505
+ name,
1506
+ tags
1507
+ })) {
1508
+ showCreateWorkflowSuccessToast(id, wasNewWorkflow);
1509
+ await npsSurveyStore.fetchPromptsData();
1510
+ if (route.name === VIEWS.EXECUTION_DEBUG) await router.replace({
1511
+ name: VIEWS.WORKFLOW,
1512
+ params: { name: props.id }
1513
+ });
1514
+ }
1515
+ }
1516
+ function onTagsEditEnable() {
1517
+ appliedTagIds.value = props.tags ?? [];
1518
+ isTagsEditEnabled.value = true;
1519
+ setTimeout(() => {
1520
+ renameInput.value?.forceCancel();
1521
+ tagsEventBus.emit("focus");
1522
+ }, 0);
1523
+ }
1524
+ async function onTagsBlur() {
1525
+ const current = props.tags ?? [];
1526
+ const tags = appliedTagIds.value;
1527
+ if (!hasChanged(current, tags)) {
1528
+ isTagsEditEnabled.value = false;
1529
+ return;
1530
+ }
1531
+ if (tagsSaving.value) return;
1532
+ tagsSaving.value = true;
1533
+ const saved = await workflowSaving.saveCurrentWorkflow({ tags });
1534
+ telemetry$1.track("User edited workflow tags", {
1535
+ workflow_id: props.id,
1536
+ new_tag_count: tags.length
1537
+ });
1538
+ tagsSaving.value = false;
1539
+ if (saved) isTagsEditEnabled.value = false;
1540
+ }
1541
+ function onTagsEditEsc() {
1542
+ isTagsEditEnabled.value = false;
1543
+ }
1544
+ const renameInput = useTemplateRef("renameInput");
1545
+ function onNameToggle() {
1546
+ if (renameInput.value?.forceFocus) renameInput.value.forceFocus();
1547
+ }
1548
+ async function onNameSubmit(name) {
1549
+ const newName = name.trim();
1550
+ if (!newName) {
1551
+ toast.showMessage({
1552
+ title: locale.baseText("renameAction.emptyName.title"),
1553
+ message: locale.baseText("renameAction.emptyName.message"),
1554
+ type: "error"
1555
+ });
1556
+ renameInput.value?.forceCancel();
1557
+ return;
1558
+ }
1559
+ if (newName === props.name) {
1560
+ renameInput.value?.forceCancel();
1561
+ return;
1562
+ }
1563
+ uiStore.addActiveAction("workflowSaving");
1564
+ const id = getWorkflowId(props.id, route.params.name);
1565
+ const wasNewWorkflow = !workflowsStore.isWorkflowSaved[props.id];
1566
+ if (await workflowSaving.saveCurrentWorkflow({ name })) {
1567
+ showCreateWorkflowSuccessToast(id, wasNewWorkflow);
1568
+ documentTitle.setDocumentTitle(newName, "IDLE");
1569
+ }
1570
+ uiStore.removeActiveAction("workflowSaving");
1571
+ renameInput.value?.forceCancel();
1572
+ }
1573
+ async function handleArchiveWorkflow() {
1574
+ if (props.active) {
1575
+ if (await message.confirm(locale.baseText("mainSidebar.confirmMessage.workflowArchive.message", { interpolate: { workflowName: props.name } }), locale.baseText("mainSidebar.confirmMessage.workflowArchive.headline"), {
1576
+ type: "warning",
1577
+ confirmButtonText: locale.baseText("mainSidebar.confirmMessage.workflowArchive.confirmButtonText"),
1578
+ cancelButtonText: locale.baseText("mainSidebar.confirmMessage.workflowArchive.cancelButtonText")
1579
+ }) !== "confirm") return;
1580
+ }
1581
+ try {
1582
+ await workflowsStore.archiveWorkflow(props.id);
1583
+ } catch (error) {
1584
+ toast.showError(error, locale.baseText("generic.archiveWorkflowError"));
1585
+ return;
1586
+ }
1587
+ uiStore.stateIsDirty = false;
1588
+ toast.showMessage({
1589
+ title: locale.baseText("mainSidebar.showMessage.handleArchive.title", { interpolate: { workflowName: props.name } }),
1590
+ type: "success"
1591
+ });
1592
+ const workflow = workflowsStore.getWorkflowById(props.id);
1593
+ if (workflow?.homeProject?.type === ProjectTypes.Team) await router.push({
1594
+ name: VIEWS.PROJECTS_WORKFLOWS,
1595
+ params: { projectId: workflow.homeProject.id }
1596
+ });
1597
+ else await router.push({ name: VIEWS.WORKFLOWS });
1598
+ }
1599
+ async function handleUnarchiveWorkflow() {
1600
+ await workflowsStore.unarchiveWorkflow(props.id);
1601
+ toast.showMessage({
1602
+ title: locale.baseText("mainSidebar.showMessage.handleUnarchive.title", { interpolate: { workflowName: props.name } }),
1603
+ type: "success"
1604
+ });
1605
+ }
1606
+ async function handleDeleteWorkflow() {
1607
+ if (await message.confirm(locale.baseText("mainSidebar.confirmMessage.workflowDelete.message", { interpolate: { workflowName: props.name } }), locale.baseText("mainSidebar.confirmMessage.workflowDelete.headline"), {
1608
+ type: "warning",
1609
+ confirmButtonText: locale.baseText("mainSidebar.confirmMessage.workflowDelete.confirmButtonText"),
1610
+ cancelButtonText: locale.baseText("mainSidebar.confirmMessage.workflowDelete.cancelButtonText")
1611
+ }) !== "confirm") return;
1612
+ const workflow = workflowsStore.getWorkflowById(props.id);
1613
+ const isTeamProject = workflow?.homeProject?.type === ProjectTypes.Team;
1614
+ try {
1615
+ await workflowsStore.deleteWorkflow(props.id);
1616
+ } catch (error) {
1617
+ toast.showError(error, locale.baseText("generic.deleteWorkflowError"));
1618
+ return;
1619
+ }
1620
+ uiStore.stateIsDirty = false;
1621
+ documentTitle.reset();
1622
+ toast.showMessage({
1623
+ title: locale.baseText("mainSidebar.showMessage.handleSelect1.title", { interpolate: { workflowName: props.name } }),
1624
+ type: "success"
1625
+ });
1626
+ if (isTeamProject && workflow?.homeProject) await router.push({
1627
+ name: VIEWS.PROJECTS_WORKFLOWS,
1628
+ params: { projectId: workflow.homeProject.id }
1629
+ });
1630
+ else await router.push({ name: VIEWS.WORKFLOWS });
1631
+ }
1632
+ function getPersonalProjectToastContent() {
1633
+ const title = locale.baseText("workflows.create.personal.toast.title");
1634
+ if (!props.currentFolder) return { title };
1635
+ return {
1636
+ title,
1637
+ toastMessage: locale.baseText("workflows.create.folder.toast.title", { interpolate: {
1638
+ projectName: "Personal",
1639
+ folderName: props.currentFolder.name
1640
+ } })
1641
+ };
1642
+ }
1643
+ function getToastContent() {
1644
+ const currentProject = projectsStore.currentProject;
1645
+ const isPersonalProject = !projectsStore.currentProject || currentProject?.id === projectsStore.personalProject?.id;
1646
+ const projectName = currentProjectName.value ?? "";
1647
+ if (isPersonalProject) return getPersonalProjectToastContent();
1648
+ const titleKey = props.currentFolder ? "workflows.create.folder.toast.title" : "workflows.create.project.toast.title";
1649
+ const interpolateData = props.currentFolder ? {
1650
+ projectName,
1651
+ folderName: props.currentFolder.name ?? ""
1652
+ } : { projectName };
1653
+ return {
1654
+ title: locale.baseText(titleKey, { interpolate: interpolateData }),
1655
+ toastMessage: locale.baseText("workflows.create.project.toast.text", { interpolate: { projectName } })
1656
+ };
1657
+ }
1658
+ function showCreateWorkflowSuccessToast(id, wasNewWorkflow) {
1659
+ if (!id) return;
1660
+ if (!(wasNewWorkflow ?? false)) return;
1661
+ const { title, toastMessage } = getToastContent();
1662
+ toast.showMessage({
1663
+ title,
1664
+ message: toastMessage,
1665
+ type: "success"
1666
+ });
1667
+ }
1668
+ const onBreadcrumbsItemSelected = (item) => {
1669
+ if (item.href) router.push(item.href).catch((error) => {
1670
+ toast.showError(error, i18n.baseText("folders.open.error.title"));
1671
+ });
1672
+ };
1673
+ const handleImportWorkflowFromFile = () => {
1674
+ if (workflowHeaderActionsRef.value?.importFileRef) workflowHeaderActionsRef.value.importFileRef.click();
1675
+ };
1676
+ onMounted(() => {
1677
+ nodeViewEventBus.on("importWorkflowFromFile", handleImportWorkflowFromFile);
1678
+ nodeViewEventBus.on("archiveWorkflow", handleArchiveWorkflow);
1679
+ nodeViewEventBus.on("unarchiveWorkflow", handleUnarchiveWorkflow);
1680
+ nodeViewEventBus.on("deleteWorkflow", handleDeleteWorkflow);
1681
+ nodeViewEventBus.on("renameWorkflow", onNameToggle);
1682
+ nodeViewEventBus.on("addTag", onTagsEditEnable);
1683
+ });
1684
+ onBeforeUnmount(() => {
1685
+ nodeViewEventBus.off("importWorkflowFromFile", handleImportWorkflowFromFile);
1686
+ nodeViewEventBus.off("archiveWorkflow", handleArchiveWorkflow);
1687
+ nodeViewEventBus.off("unarchiveWorkflow", handleUnarchiveWorkflow);
1688
+ nodeViewEventBus.off("deleteWorkflow", handleDeleteWorkflow);
1689
+ nodeViewEventBus.off("renameWorkflow", onNameToggle);
1690
+ nodeViewEventBus.off("addTag", onTagsEditEnable);
1691
+ });
1692
+ return (_ctx, _cache) => {
1693
+ return openBlock(), createElementBlock("div", { class: normalizeClass(unref($style).container) }, [
1694
+ createVNode(BreakpointsObserver_default, {
1695
+ "value-x-s": 15,
1696
+ "value-s-m": 25,
1697
+ "value-m-d": 50,
1698
+ class: "name-container",
1699
+ "data-test-id": "canvas-breadcrumbs"
1700
+ }, {
1701
+ default: withCtx(({ bp }) => [createVNode(FolderBreadcrumbs_default, {
1702
+ "current-folder": currentFolderForBreadcrumbs.value,
1703
+ "current-folder-as-link": true,
1704
+ onItemSelected: onBreadcrumbsItemSelected
1705
+ }, {
1706
+ append: withCtx(() => [unref(projectsStore).currentProject ?? unref(projectsStore).personalProject ? (openBlock(), createElementBlock("span", {
1707
+ key: 0,
1708
+ class: normalizeClass(unref($style)["path-separator"])
1709
+ }, "/", 2)) : createCommentVNode("", true), (openBlock(), createBlock(unref(N8nInlineTextEdit_default), {
1710
+ ref_key: "renameInput",
1711
+ ref: renameInput,
1712
+ key: _ctx.id,
1713
+ placeholder: "Workflow name",
1714
+ "data-test-id": "workflow-name-input",
1715
+ class: "name",
1716
+ "model-value": _ctx.name,
1717
+ "max-length": unref(128),
1718
+ "max-width": WORKFLOW_NAME_BP_TO_WIDTH[bp],
1719
+ "read-only": _ctx.readOnly || _ctx.isArchived || !isNewWorkflow.value && !workflowPermissions.value.update,
1720
+ disabled: _ctx.readOnly || _ctx.isArchived || !isNewWorkflow.value && !workflowPermissions.value.update,
1721
+ "onUpdate:modelValue": onNameSubmit
1722
+ }, null, 8, [
1723
+ "model-value",
1724
+ "max-length",
1725
+ "max-width",
1726
+ "read-only",
1727
+ "disabled"
1728
+ ]))]),
1729
+ _: 2
1730
+ }, 1032, ["current-folder"])]),
1731
+ _: 1
1732
+ }),
1733
+ createBaseVNode("span", _hoisted_1, [unref(settingsStore).areTagsEnabled ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [isTagsEditEnabled.value && !(_ctx.readOnly || _ctx.isArchived) && (isNewWorkflow.value || workflowPermissions.value.update) ? (openBlock(), createBlock(WorkflowTagsDropdown_default, {
1734
+ key: 0,
1735
+ ref: "dropdown",
1736
+ modelValue: appliedTagIds.value,
1737
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => appliedTagIds.value = $event),
1738
+ "event-bus": unref(tagsEventBus),
1739
+ placeholder: unref(i18n).baseText("workflowDetails.chooseOrCreateATag"),
1740
+ class: "tags-edit",
1741
+ "data-test-id": "workflow-tags-dropdown",
1742
+ onBlur: onTagsBlur,
1743
+ onEsc: onTagsEditEsc
1744
+ }, null, 8, [
1745
+ "modelValue",
1746
+ "event-bus",
1747
+ "placeholder"
1748
+ ])) : (_ctx.tags ?? []).length === 0 && !(_ctx.readOnly || _ctx.isArchived) && (isNewWorkflow.value || workflowPermissions.value.update) ? (openBlock(), createElementBlock("div", _hoisted_2, [createBaseVNode("span", {
1749
+ class: "add-tag clickable",
1750
+ "data-test-id": "new-tag-link",
1751
+ onClick: onTagsEditEnable
1752
+ }, " + " + toDisplayString(unref(i18n).baseText("workflowDetails.addTag")), 1)])) : (openBlock(), createBlock(WorkflowTagsContainer_default, {
1753
+ key: _ctx.id,
1754
+ "tag-ids": workflowTagIds.value,
1755
+ clickable: true,
1756
+ responsive: true,
1757
+ "data-test-id": "workflow-tags",
1758
+ onClick: onTagsEditEnable
1759
+ }, null, 8, ["tag-ids"]))], 64)) : createCommentVNode("", true), createBaseVNode("span", { class: normalizeClass(unref($style)["header-controls"]) }, [_ctx.isArchived ? (openBlock(), createBlock(unref(N8nBadge_default), {
1760
+ key: 0,
1761
+ class: "ml-3xs",
1762
+ theme: "tertiary",
1763
+ bold: "",
1764
+ "data-test-id": "workflow-archived-tag"
1765
+ }, {
1766
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(locale).baseText("workflows.item.archived")), 1)]),
1767
+ _: 1
1768
+ })) : createCommentVNode("", true)], 2)]),
1769
+ createVNode(PushConnectionTracker_default, { class: "actions" }, {
1770
+ default: withCtx(() => [!isNewWorkflow.value ? (openBlock(), createBlock(WorkflowProductionChecklist_default, {
1771
+ key: 0,
1772
+ workflow: unref(workflowsStore).workflow
1773
+ }, null, 8, ["workflow"])) : createCommentVNode("", true), unref(true) ? (openBlock(), createBlock(WorkflowHeaderDraftPublishActions_default, {
1774
+ key: 1,
1775
+ id: _ctx.id,
1776
+ ref: "workflowHeaderActions",
1777
+ tags: _ctx.tags,
1778
+ name: _ctx.name,
1779
+ meta: _ctx.meta,
1780
+ "read-only": _ctx.readOnly,
1781
+ "is-archived": _ctx.isArchived,
1782
+ "is-new-workflow": isNewWorkflow.value,
1783
+ "workflow-permissions": workflowPermissions.value,
1784
+ "onWorkflow:saved": onSaveButtonClick
1785
+ }, null, 8, [
1786
+ "id",
1787
+ "tags",
1788
+ "name",
1789
+ "meta",
1790
+ "read-only",
1791
+ "is-archived",
1792
+ "is-new-workflow",
1793
+ "workflow-permissions"
1794
+ ])) : (openBlock(), createBlock(WorkflowHeaderActions_default, {
1795
+ key: 2,
1796
+ id: _ctx.id,
1797
+ ref: "workflowHeaderActions",
1798
+ name: _ctx.name,
1799
+ tags: _ctx.tags,
1800
+ "current-folder": _ctx.currentFolder,
1801
+ meta: _ctx.meta,
1802
+ "read-only": _ctx.readOnly,
1803
+ "is-archived": _ctx.isArchived,
1804
+ active: _ctx.active,
1805
+ "is-new-workflow": isNewWorkflow.value,
1806
+ "workflow-permissions": workflowPermissions.value,
1807
+ "onWorkflow:saved": onSaveButtonClick,
1808
+ "onWorkflow:deactivated": _cache[1] || (_cache[1] = ($event) => emit("workflow:deactivated"))
1809
+ }, null, 8, [
1810
+ "id",
1811
+ "name",
1812
+ "tags",
1813
+ "current-folder",
1814
+ "meta",
1815
+ "read-only",
1816
+ "is-archived",
1817
+ "active",
1818
+ "is-new-workflow",
1819
+ "workflow-permissions"
1820
+ ]))]),
1821
+ _: 1
1822
+ })
1823
+ ], 2);
1824
+ };
1825
+ }
1826
+ });
1827
+ const container$1 = "_container_7bao3_123";
1828
+ const closeNodeViewDiscovery = "_closeNodeViewDiscovery_7bao3_138";
1829
+ var WorkflowDetails_vue_vue_type_style_index_1_lang_module_default = {
1830
+ container: container$1,
1831
+ "path-separator": "_path-separator_7bao3_132",
1832
+ closeNodeViewDiscovery,
1833
+ "header-controls": "_header-controls_7bao3_145"
1834
+ };
1835
+ var WorkflowDetails_default = /* @__PURE__ */ __plugin_vue_export_helper_default(WorkflowDetails_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": WorkflowDetails_vue_vue_type_style_index_1_lang_module_default }], ["__scopeId", "data-v-22fed76c"]]);
1836
+ init_shared_esm_bundler();
1837
+ var vue_github_button_default = defineComponent({
1838
+ name: "github-button",
1839
+ props: {
1840
+ href: String,
1841
+ ariaLabel: String,
1842
+ title: String,
1843
+ dataIcon: String,
1844
+ dataColorScheme: String,
1845
+ dataSize: String,
1846
+ dataShowCount: String,
1847
+ dataText: String
1848
+ },
1849
+ render: function() {
1850
+ const props = { ref: "_" };
1851
+ for (const key in this.$props) props[hyphenate(key)] = this.$props[key];
1852
+ return h("span", [hasOwn(this.$slots, "default") ? h("a", props, this.$slots.default()) : h("a", props)]);
1853
+ },
1854
+ mounted: function() {
1855
+ this.paint();
1856
+ },
1857
+ beforeUpdate: function() {
1858
+ this.reset();
1859
+ },
1860
+ updated: function() {
1861
+ this.paint();
1862
+ },
1863
+ beforeUnmount: function() {
1864
+ this.reset();
1865
+ },
1866
+ methods: {
1867
+ paint: function() {
1868
+ if (this.$el.lastChild !== this.$refs._) return;
1869
+ const _ = this.$el.appendChild(document.createElement("span"));
1870
+ const _this = this;
1871
+ __vitePreload(() => import(
1872
+ /* webpackMode: "eager" */
1873
+ "./buttons.esm-yintpW2E.js"
1874
+ ), [], import.meta.url).then(function(module) {
1875
+ if (_this.$el.lastChild !== _) return;
1876
+ module.render(_.appendChild(_this.$refs._), function(el) {
1877
+ if (_this.$el.lastChild !== _) return;
1878
+ _.parentNode.replaceChild(el, _);
1879
+ });
1880
+ });
1881
+ },
1882
+ reset: function() {
1883
+ if (this.$refs._ == null) return;
1884
+ this.$el.replaceChild(this.$refs._, this.$el.lastChild);
1885
+ }
1886
+ }
1887
+ });
1888
+ var MainHeader_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
1889
+ __name: "MainHeader",
1890
+ setup(__props) {
1891
+ const router = useRouter();
1892
+ const route = useRoute();
1893
+ const locale = useI18n();
1894
+ const pushConnection = usePushConnection({ router });
1895
+ const toast = useToast();
1896
+ const ndvStore = useNDVStore();
1897
+ const uiStore = useUIStore();
1898
+ const sourceControlStore = useSourceControlStore();
1899
+ const workflowsStore = useWorkflowsStore();
1900
+ const executionsStore = useExecutionsStore();
1901
+ const settingsStore = useSettingsStore();
1902
+ const activeHeaderTab = ref(MAIN_HEADER_TABS.WORKFLOW);
1903
+ const workflowToReturnTo = ref("");
1904
+ const executionToReturnTo = ref("");
1905
+ const dirtyState = ref(false);
1906
+ const githubButtonHidden = useLocalStorage(LOCAL_STORAGE_HIDE_GITHUB_STAR_BUTTON, false);
1907
+ const evaluationRoutes = [VIEWS.EVALUATION_EDIT, VIEWS.EVALUATION_RUNS_DETAIL];
1908
+ const workflowRoutes = [
1909
+ VIEWS.WORKFLOW,
1910
+ VIEWS.NEW_WORKFLOW,
1911
+ VIEWS.EXECUTION_DEBUG
1912
+ ];
1913
+ const executionRoutes = [
1914
+ VIEWS.EXECUTION_HOME,
1915
+ VIEWS.WORKFLOW_EXECUTIONS,
1916
+ VIEWS.EXECUTION_PREVIEW
1917
+ ];
1918
+ const tabBarItems = computed(() => {
1919
+ return [
1920
+ {
1921
+ value: MAIN_HEADER_TABS.WORKFLOW,
1922
+ label: locale.baseText("generic.editor")
1923
+ },
1924
+ {
1925
+ value: MAIN_HEADER_TABS.EXECUTIONS,
1926
+ label: locale.baseText("generic.executions")
1927
+ },
1928
+ {
1929
+ value: MAIN_HEADER_TABS.EVALUATION,
1930
+ label: locale.baseText("generic.tests")
1931
+ }
1932
+ ];
1933
+ });
1934
+ const activeNode = computed(() => ndvStore.activeNode);
1935
+ const hideMenuBar = computed(() => Boolean(activeNode.value && activeNode.value.type !== "n8n-nodes-base.stickyNote"));
1936
+ const workflow = computed(() => workflowsStore.workflow);
1937
+ const workflowId = computed(() => String(route.params.name || workflowsStore.workflowId));
1938
+ const onWorkflowPage = computed(() => !!(route.meta.nodeView || route.meta.keepWorkflowAlive));
1939
+ const readOnly = computed(() => sourceControlStore.preferences.branchReadOnly);
1940
+ const isEnterprise = computed(() => settingsStore.isQueueModeEnabled && settingsStore.isWorkerViewAvailable);
1941
+ const isTelemetryEnabled = computed(() => {
1942
+ return settingsStore.isTelemetryEnabled;
1943
+ });
1944
+ const showGitHubButton = computed(() => !isEnterprise.value && !settingsStore.settings.inE2ETests && !githubButtonHidden.value && isTelemetryEnabled.value);
1945
+ const parentFolderForBreadcrumbs = computed(() => {
1946
+ if (!workflow.value.parentFolder) return;
1947
+ return {
1948
+ id: workflow.value.parentFolder.id,
1949
+ name: workflow.value.parentFolder.name,
1950
+ parentFolder: workflow.value.parentFolder.parentFolderId ?? void 0
1951
+ };
1952
+ });
1953
+ watch(route, (to, from) => {
1954
+ syncTabsWithRoute(to, from);
1955
+ });
1956
+ onBeforeMount(() => {
1957
+ pushConnection.initialize();
1958
+ });
1959
+ onBeforeUnmount(() => {
1960
+ pushConnection.terminate();
1961
+ });
1962
+ onMounted(async () => {
1963
+ dirtyState.value = uiStore.stateIsDirty;
1964
+ syncTabsWithRoute(route);
1965
+ });
1966
+ function isViewRoute(name) {
1967
+ return typeof name === "string" && [
1968
+ evaluationRoutes,
1969
+ workflowRoutes,
1970
+ executionRoutes
1971
+ ].flat().includes(name);
1972
+ }
1973
+ function syncTabsWithRoute(to, from) {
1974
+ const routeTabMapping = [
1975
+ {
1976
+ routes: evaluationRoutes,
1977
+ tab: MAIN_HEADER_TABS.EVALUATION
1978
+ },
1979
+ {
1980
+ routes: executionRoutes,
1981
+ tab: MAIN_HEADER_TABS.EXECUTIONS
1982
+ },
1983
+ {
1984
+ routes: workflowRoutes,
1985
+ tab: MAIN_HEADER_TABS.WORKFLOW
1986
+ }
1987
+ ];
1988
+ if (to.name && isViewRoute(to.name)) {
1989
+ const matchingTab = routeTabMapping.find(({ routes }) => routes.includes(to.name));
1990
+ if (matchingTab) activeHeaderTab.value = matchingTab.tab;
1991
+ }
1992
+ if (typeof to.params.name === "string") workflowToReturnTo.value = to.params.name;
1993
+ if (from?.name === VIEWS.EXECUTION_PREVIEW && to.params.name === from.params.name && typeof from.params.executionId === "string") executionToReturnTo.value = from.params.executionId;
1994
+ }
1995
+ function onTabSelected(tab, event) {
1996
+ const openInNewTab = event.ctrlKey || event.metaKey;
1997
+ switch (tab) {
1998
+ case MAIN_HEADER_TABS.WORKFLOW:
1999
+ navigateToWorkflowView(openInNewTab);
2000
+ break;
2001
+ case MAIN_HEADER_TABS.EXECUTIONS:
2002
+ navigateToExecutionsView(openInNewTab);
2003
+ break;
2004
+ case MAIN_HEADER_TABS.EVALUATION:
2005
+ navigateToEvaluationsView(openInNewTab);
2006
+ break;
2007
+ default: break;
2008
+ }
2009
+ }
2010
+ async function navigateToWorkflowView(openInNewTab) {
2011
+ let routeToNavigateTo;
2012
+ if (workflowToReturnTo.value && workflowToReturnTo.value !== "") routeToNavigateTo = {
2013
+ name: VIEWS.WORKFLOW,
2014
+ params: { name: workflowToReturnTo.value },
2015
+ query: route.query
2016
+ };
2017
+ else routeToNavigateTo = {
2018
+ name: VIEWS.NEW_WORKFLOW,
2019
+ query: route.query
2020
+ };
2021
+ if (openInNewTab) {
2022
+ const { href } = router.resolve(routeToNavigateTo);
2023
+ window.open(href, "_blank");
2024
+ } else if (route.name !== routeToNavigateTo.name) {
2025
+ if (route.name === VIEWS.NEW_WORKFLOW) uiStore.stateIsDirty = dirtyState.value;
2026
+ activeHeaderTab.value = MAIN_HEADER_TABS.WORKFLOW;
2027
+ await router.push(routeToNavigateTo);
2028
+ }
2029
+ }
2030
+ async function navigateToExecutionsView(openInNewTab) {
2031
+ const executionToReturnToValue = executionsStore.activeExecution?.id || executionToReturnTo.value;
2032
+ const routeToNavigateTo = executionToReturnToValue ? {
2033
+ name: VIEWS.EXECUTION_PREVIEW,
2034
+ params: {
2035
+ name: workflowId.value,
2036
+ executionId: executionToReturnToValue
2037
+ },
2038
+ query: route.query
2039
+ } : {
2040
+ name: VIEWS.EXECUTION_HOME,
2041
+ params: { name: workflowId.value },
2042
+ query: route.query
2043
+ };
2044
+ if (openInNewTab) {
2045
+ const { href } = router.resolve(routeToNavigateTo);
2046
+ window.open(href, "_blank");
2047
+ } else if (route.name !== routeToNavigateTo.name) {
2048
+ dirtyState.value = uiStore.stateIsDirty;
2049
+ workflowToReturnTo.value = workflowId.value;
2050
+ activeHeaderTab.value = MAIN_HEADER_TABS.EXECUTIONS;
2051
+ await router.push(routeToNavigateTo);
2052
+ }
2053
+ }
2054
+ async function navigateToEvaluationsView(openInNewTab) {
2055
+ const routeToNavigateTo = {
2056
+ name: VIEWS.EVALUATION_EDIT,
2057
+ params: { name: workflowId.value },
2058
+ query: route.query
2059
+ };
2060
+ if (openInNewTab) {
2061
+ const { href } = router.resolve(routeToNavigateTo);
2062
+ window.open(href, "_blank");
2063
+ } else if (route.name !== routeToNavigateTo.name) {
2064
+ dirtyState.value = uiStore.stateIsDirty;
2065
+ workflowToReturnTo.value = workflowId.value;
2066
+ activeHeaderTab.value = MAIN_HEADER_TABS.EXECUTIONS;
2067
+ await router.push(routeToNavigateTo);
2068
+ }
2069
+ }
2070
+ function hideGithubButton() {
2071
+ githubButtonHidden.value = true;
2072
+ }
2073
+ async function onWorkflowDeactivated() {
2074
+ if (settingsStore.isModuleActive("mcp") && workflow.value.settings?.availableInMCP) try {
2075
+ const updatedWorkflow = await workflowsStore.fetchWorkflow(workflow.value.id);
2076
+ workflowsStore.setWorkflow(updatedWorkflow);
2077
+ toast.showToast({
2078
+ title: locale.baseText("mcp.workflowDeactivated.title"),
2079
+ message: locale.baseText("mcp.workflowDeactivated.message"),
2080
+ type: "info"
2081
+ });
2082
+ } catch (error) {
2083
+ toast.showError(error, locale.baseText("workflowSettings.showError.fetchSettings.title"));
2084
+ }
2085
+ }
2086
+ return (_ctx, _cache) => {
2087
+ return openBlock(), createElementBlock("div", { class: normalizeClass(_ctx.$style.container) }, [createBaseVNode("div", { class: normalizeClass({
2088
+ [_ctx.$style["main-header"]]: true,
2089
+ [_ctx.$style.expanded]: !unref(uiStore).sidebarMenuCollapsed
2090
+ }) }, [withDirectives(createBaseVNode("div", { class: normalizeClass(_ctx.$style["top-menu"]) }, [workflow.value?.name ? (openBlock(), createBlock(WorkflowDetails_default, {
2091
+ key: 0,
2092
+ id: workflow.value.id,
2093
+ tags: workflow.value.tags,
2094
+ name: workflow.value.name,
2095
+ meta: workflow.value.meta,
2096
+ scopes: workflow.value.scopes,
2097
+ active: workflow.value.active,
2098
+ "read-only": readOnly.value,
2099
+ "current-folder": parentFolderForBreadcrumbs.value,
2100
+ "is-archived": workflow.value.isArchived,
2101
+ description: workflow.value.description,
2102
+ "onWorkflow:deactivated": onWorkflowDeactivated
2103
+ }, null, 8, [
2104
+ "id",
2105
+ "tags",
2106
+ "name",
2107
+ "meta",
2108
+ "scopes",
2109
+ "active",
2110
+ "read-only",
2111
+ "current-folder",
2112
+ "is-archived",
2113
+ "description"
2114
+ ])) : createCommentVNode("", true), showGitHubButton.value ? (openBlock(), createElementBlock("div", {
2115
+ key: 1,
2116
+ class: normalizeClass([_ctx.$style["github-button"], "hidden-sm-and-down"])
2117
+ }, [createBaseVNode("div", { class: normalizeClass(_ctx.$style["github-button-container"]) }, [createVNode(unref(vue_github_button_default), {
2118
+ href: unref(N8N_MAIN_GITHUB_REPO_URL),
2119
+ "data-color-scheme": unref(uiStore).appliedTheme,
2120
+ "data-size": "large",
2121
+ "data-show-count": "true",
2122
+ "aria-label": unref(locale).baseText("editor.mainHeader.githubButton.label")
2123
+ }, {
2124
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(locale).baseText("generic.star")), 1)]),
2125
+ _: 1
2126
+ }, 8, [
2127
+ "href",
2128
+ "data-color-scheme",
2129
+ "aria-label"
2130
+ ]), createVNode(unref(N8nIcon_default), {
2131
+ class: normalizeClass(_ctx.$style["close-github-button"]),
2132
+ icon: "circle-x",
2133
+ size: "medium",
2134
+ onClick: hideGithubButton
2135
+ }, null, 8, ["class"])], 2)], 2)) : createCommentVNode("", true)], 2), [[vShow, !hideMenuBar.value]]), onWorkflowPage.value ? (openBlock(), createBlock(TabBar_default, {
2136
+ key: 0,
2137
+ items: tabBarItems.value,
2138
+ "model-value": activeHeaderTab.value,
2139
+ "onUpdate:modelValue": onTabSelected
2140
+ }, null, 8, ["items", "model-value"])) : createCommentVNode("", true)], 2)], 2);
2141
+ };
2142
+ }
2143
+ });
2144
+ var MainHeader_vue_vue_type_style_index_0_lang_module_default = {
2145
+ container: "_container_4ekmy_123",
2146
+ "main-header": "_main-header_4ekmy_130",
2147
+ "top-menu": "_top-menu_4ekmy_138",
2148
+ "github-button": "_github-button_4ekmy_149",
2149
+ "close-github-button": "_close-github-button_4ekmy_158",
2150
+ "github-button-container": "_github-button-container_4ekmy_173"
2151
+ };
2152
+ var MainHeader_default = /* @__PURE__ */ __plugin_vue_export_helper_default(MainHeader_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": MainHeader_vue_vue_type_style_index_0_lang_module_default }]]);
2153
+ export { MainHeader_default as default };