n8n-editor-ui 1.83.1 → 1.84.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 (110) hide show
  1. package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-Cu5o7-TL.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-78eP7HIe.js} +1 -1
  2. package/dist/assets/{AuthView-mP34ZmnC.js → AuthView-Bn_LB3Kw.js} +2 -2
  3. package/dist/assets/{CanvasChat-CSLR5tKe.css → CanvasChat-CGGQcCRA.css} +45 -30
  4. package/dist/assets/{CanvasChat-cto4xkVD.js → CanvasChat-tuKMnT6J.js} +230 -143
  5. package/dist/assets/{ChangePasswordView-DkwRz1u6.js → ChangePasswordView-aXYIR8zr.js} +3 -3
  6. package/dist/assets/CollectionParameter-DR9e0MGf.js +4 -0
  7. package/dist/assets/{CredentialsView-UBVro_dv.js → CredentialsView-k8CeiyMJ.js} +5 -6
  8. package/dist/assets/{ErrorView-EWPmvugu.js → ErrorView-e-cpk6J7.js} +1 -1
  9. package/dist/assets/{ConcurrentExecutionsHeader-CEBmSYNK.css → ExecutionsTime-BOPJEomw.css} +63 -63
  10. package/dist/assets/{ConcurrentExecutionsHeader-Ul9ROpk0.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-BYacEmlc.js} +114 -114
  11. package/dist/assets/ExecutionsView-CQi8A4ps.js +926 -0
  12. package/dist/assets/{ExecutionsView-CB1tvZfo.css → ExecutionsView-CRTcP3sx.css} +60 -188
  13. package/dist/assets/{FileSaver.min-D6Iix6V9.js → FileSaver.min-DmMmlWYQ.js} +1 -1
  14. package/dist/assets/{FixedCollectionParameter-DBIBAKMF.js → FixedCollectionParameter-BfUPtP5M.js} +1 -1
  15. package/dist/assets/{ForgotMyPasswordView-DOMjwy3H.js → ForgotMyPasswordView-Dzao5PZ9.js} +3 -3
  16. package/dist/assets/{ProjectHeader-BZ6b6lat.css → Logo-DLBj1gMw.css} +23 -17
  17. package/dist/assets/{Logo-CidMx5L1.js → Logo-DVRZ2qRx.js} +8 -19
  18. package/dist/assets/{MainHeader-CpYwrGHe.js → MainHeader-BUw_JG4S.js} +10 -10
  19. package/dist/assets/{MainSidebar-u0kzXS10.js → MainSidebar-C6aXqICd.js} +75 -42
  20. package/dist/assets/{MainSidebar-BRAjTL7J.css → MainSidebar-CKMiDGvH.css} +13 -12
  21. package/dist/assets/{NodeCreation-C3kgMOiP.js → NodeCreation-B9-99kNr.js} +4 -4
  22. package/dist/assets/{NodeCreator-C3jOJmI0.js → NodeCreator-DH90304h.js} +4 -4
  23. package/dist/assets/{NodeDetailsView-CVVfk-zW.css → NodeDetailsView-0RXvy-0D.css} +2 -2
  24. package/dist/assets/{NodeDetailsView-BuAX7b_S.js → NodeDetailsView-Ci-9Cz_w.js} +69 -61
  25. package/dist/assets/{NodeView-CsrK5ExP.js → NodeView-CFUO-Q9X.js} +57 -19
  26. package/dist/assets/{ProjectCardBadge-BYZ4CZ8h.js → ProjectCardBadge-CGqr1_BG.js} +1 -1
  27. package/dist/assets/{ProjectHeader-AVHuknTg.js → ProjectHeader-C8hRwBFC.js} +60 -7
  28. package/dist/assets/ProjectHeader-CQjB5wC7.css +285 -0
  29. package/dist/assets/{ProjectSettings-BBgNR6v0.js → ProjectSettings-motYfWGR.js} +2 -3
  30. package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-oVU1CjGg.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-DzkWenq4.js} +2 -2
  31. package/dist/assets/{ResourcesListLayout-C9w15Q23.js → ResourcesListLayout-BYVhS2j5.js} +14 -13
  32. package/dist/assets/{ResourcesListLayout-Brs7VKUf.css → ResourcesListLayout-BqQI0lCG.css} +29 -22
  33. package/dist/assets/{RunDataAi-DvJKJNYm.js → RunDataAi-pfKF0Nfm.js} +3 -3
  34. package/dist/assets/{RunDataJson-T-tjG8mj.js → RunDataJson-CNT_rM-i.js} +12 -12
  35. package/dist/assets/{RunDataJsonActions-zKxT1j4k.js → RunDataJsonActions-BTLAUv9R.js} +2 -2
  36. package/dist/assets/{RunDataSearch-CYKk6_W2.js → RunDataSearch-BpcbBojC.js} +1 -1
  37. package/dist/assets/{RunDataTable-rs93_vdQ.js → RunDataTable-ZnG9QEzJ.js} +2 -2
  38. package/dist/assets/{SamlOnboarding-gWhQJPLd.js → SamlOnboarding-DjhCWFIr.js} +3 -3
  39. package/dist/assets/{SettingsApiView-QxAEXccw.js → SettingsApiView-C1ClqjeG.js} +1 -1
  40. package/dist/assets/{SettingsCommunityNodesView-BpwvEtUI.js → SettingsCommunityNodesView-D5eLIpQC.js} +5 -5
  41. package/dist/assets/{SettingsExternalSecrets-DXrPZ93O.js → SettingsExternalSecrets-ubf6jijA.js} +1 -1
  42. package/dist/assets/{SettingsLdapView-nAm7w9WO.js → SettingsLdapView-BezV6JLr.js} +1 -1
  43. package/dist/assets/{SettingsLogStreamingView-Dr4ArIl_.js → SettingsLogStreamingView-ETOxA5Tw.js} +1 -1
  44. package/dist/assets/{SettingsPersonalView-DWFlvGTn.js → SettingsPersonalView-DGxUC8Q4.js} +1 -1
  45. package/dist/assets/{SettingsSourceControl-DKLeROzN.js → SettingsSourceControl-1vHHG6W9.js} +1 -1
  46. package/dist/assets/{SettingsSso-BVmlQW_R.js → SettingsSso-CdI26YPF.js} +1 -1
  47. package/dist/assets/{SettingsUsageAndPlan-I5n8xGLd.js → SettingsUsageAndPlan-BmI8cSiq.js} +1 -1
  48. package/dist/assets/{SettingsUsersView-D8uY5rsT.js → SettingsUsersView-90JmT1qM.js} +1 -1
  49. package/dist/assets/{SettingsView-e7XAFpfc.js → SettingsView-i7rE7s3I.js} +1 -1
  50. package/dist/assets/{SetupView-DQq_7fpU.js → SetupView-Lp4ullGE.js} +3 -3
  51. package/dist/assets/{SetupWorkflowCredentialsButton-frwFWfGJ.js → SetupWorkflowCredentialsButton-CoXXUd3B.js} +1 -1
  52. package/dist/assets/{SetupWorkflowFromTemplateView-C3ENxhAx.js → SetupWorkflowFromTemplateView-TVU0-Zq4.js} +3 -3
  53. package/dist/assets/{SigninView-Bq3o_KYj.js → SigninView-BqF8j6-h.js} +3 -3
  54. package/dist/assets/{SignoutView-BYQXAHDT.js → SignoutView-DrYJ9Qe3.js} +1 -1
  55. package/dist/assets/{SignupView-xqJgShbm.js → SignupView-_EKPhYKN.js} +3 -3
  56. package/dist/assets/{TemplateDetails-COPYl_Ch.js → TemplateDetails-DAalg9G2.js} +3 -3
  57. package/dist/assets/{TemplateList-DWGAiMoN.js → TemplateList-BEYMeJMu.js} +1 -1
  58. package/dist/assets/{TemplatesCollectionView-D7C-dsc7.js → TemplatesCollectionView-fMELXCRX.js} +5 -5
  59. package/dist/assets/{TemplatesSearchView-CUFKLHbU.js → TemplatesSearchView-BO-e3IH7.js} +3 -3
  60. package/dist/assets/{TemplatesView-BjZHhHGF.js → TemplatesView-p57nARMp.js} +1 -1
  61. package/dist/assets/{TemplatesWorkflowView-C2OFQoFQ.js → TemplatesWorkflowView-DAbL5S1-.js} +5 -5
  62. package/dist/assets/{TestDefinitionEditView-DjR3gJvA.js → TestDefinitionEditView-BTo9LlAU.js} +244 -252
  63. package/dist/assets/{TestDefinitionEditView-JONL00pA.css → TestDefinitionEditView-BXhOuJrU.css} +128 -116
  64. package/dist/assets/{TestDefinitionListView-BLzGSiMz.js → TestDefinitionListView-D_-DyZDv.js} +1 -1
  65. package/dist/assets/{TestDefinitionNewView-DBs9WSAD.js → TestDefinitionNewView-Crk5OePO.js} +13 -4
  66. package/dist/assets/{TestDefinitionRootView-vaMPai85.js → TestDefinitionRootView-BtiqAWW1.js} +1 -1
  67. package/dist/assets/{VariablesView-B2A18wmf.js → VariablesView-Bg3GI1iE.js} +5 -5
  68. package/dist/assets/{VariablesView-CbTLdNwU.css → VariablesView-BvDpOTm3.css} +7 -11
  69. package/dist/assets/{WorkerView-CfmL9mV2.js → WorkerView-CaTyr1ci.js} +7 -7
  70. package/dist/assets/{WorkflowActivator-Bk7lYyKD.js → WorkflowActivator-BvmRhIkt.js} +2 -2
  71. package/dist/assets/{WorkflowExecutionsInfoAccordion-BJUV_abc.js → WorkflowExecutionsInfoAccordion-BuIbG1kZ.js} +1 -1
  72. package/dist/assets/{WorkflowExecutionsLandingPage-BGJsZkAj.js → WorkflowExecutionsLandingPage-BirtsKx4.js} +2 -2
  73. package/dist/assets/{WorkflowExecutionsPreview-BDVLuC1z.css → WorkflowExecutionsPreview-CPGOOAq2.css} +48 -16
  74. package/dist/assets/{WorkflowExecutionsPreview-C1dnDirp.js → WorkflowExecutionsPreview-DFyHWF9H.js} +253 -119
  75. package/dist/assets/{WorkflowExecutionsView-CeyHBNCa.js → WorkflowExecutionsView-IUjVjxU9.js} +7 -7
  76. package/dist/assets/{WorkflowHistory-BjD7fWBc.js → WorkflowHistory-BqKSxr_5.js} +3 -3
  77. package/dist/assets/{WorkflowOnboardingView-C9XnQ0XZ.js → WorkflowOnboardingView-Bs0Rmm6I.js} +1 -1
  78. package/dist/assets/{WorkflowPreview-DzPoQOB4.js → WorkflowPreview-1jsK9hpV.js} +1 -1
  79. package/dist/assets/{WorkflowsView-DG5J9u8v.js → WorkflowsView-MzPw02jI.js} +482 -347
  80. package/dist/assets/{WorkflowsView-JN0Hvhvt.css → WorkflowsView-Sg6GR5kC.css} +53 -39
  81. package/dist/assets/{easyAiWorkflowUtils-CHIZUcBZ.js → easyAiWorkflowUtils-DlyLBhIZ.js} +1 -1
  82. package/dist/assets/{global-link-actions-DJx6dXwY.js → global-link-actions-DvwtxSrW.js} +1 -1
  83. package/dist/assets/{import-curl-BQvYdAxP.js → import-curl-CbxpR02g.js} +1 -1
  84. package/dist/assets/{index-CFLVCCgm.css → index-74EeM2i2.css} +751 -103
  85. package/dist/assets/{index-BloiTH5y.js → index-CyVlLoqB.js} +3216 -2198
  86. package/dist/assets/{index-Cvcpg6Dy.js → index-tzkIB4Tg.js} +1 -1
  87. package/dist/assets/{pickBy-fjQgBd6D.js → pickBy-DI3cF803.js} +1 -1
  88. package/dist/assets/{polyfills-C7eMRNFe.js → polyfills-CLZ4X0Ad.js} +2342 -1944
  89. package/dist/assets/{pushConnection.store-D5RQY4RP.js → pushConnection.store-BhUCpqAg.js} +1 -1
  90. package/dist/assets/{templateActions-DfmqYUYJ.js → templateActions-BnGO7zdc.js} +1 -1
  91. package/dist/assets/{typescript.worker-DP34mIHW.js → typescript.worker-Bt3bByTc.js} +1158 -695
  92. package/dist/assets/{useBeforeUnload-BTvPg0aq.js → useBeforeUnload-DtKxjKeS.js} +1 -1
  93. package/dist/assets/{useCanvasMapping-CGHW3BxZ.js → useCanvasMapping-BCP7UO9p.js} +10410 -10398
  94. package/dist/assets/{useCanvasMapping-CkNBF2SE.css → useCanvasMapping-CI4ehFWu.css} +579 -579
  95. package/dist/assets/{useCanvasOperations-Cr_vZCiR.js → useCanvasOperations-Ctquo5LL.js} +23 -6
  96. package/dist/assets/{useExecutionDebugging-CTmjDF_B.js → useExecutionDebugging-C0TAc9fj.js} +1 -1
  97. package/dist/assets/{useExecutionHelpers-C8isDFPE.js → useExecutionHelpers-BQHL3OpL.js} +1 -1
  98. package/dist/assets/{useImportCurlCommand-uH3ThHFG.js → useImportCurlCommand-IE8oJ9bp.js} +13 -20
  99. package/dist/assets/{usePinnedData-C5x08fuF.js → usePinnedData-CtRDhd6k.js} +2 -2
  100. package/dist/assets/{usePushConnection-DUixULqA.js → usePushConnection-DXozzPWi.js} +5 -4
  101. package/dist/assets/{useRunWorkflow-CnFMyZFO.js → useRunWorkflow-D9JIEr1s.js} +3 -3
  102. package/dist/assets/{useTestDefinitionForm-DxJcvrhw.js → useTestDefinitionForm-8dJH3v29.js} +1 -1
  103. package/dist/assets/{useWorkflowActivate-Cn5TIR2c.js → useWorkflowActivate-CI3X35ZJ.js} +1 -1
  104. package/dist/index.html +3 -3
  105. package/package.json +1 -1
  106. package/dist/assets/CollectionParameter-DzUDyeJC.js +0 -4
  107. package/dist/assets/ExecutionsView-DCeodQ1s.js +0 -983
  108. package/dist/assets/Logo-DJLTXpXC.css +0 -165
  109. package/dist/assets/ProjectCreateResource-cJSSCcoG.js +0 -56
  110. package/dist/assets/ProjectCreateResource-eYdTamXR.css +0 -139
@@ -1,27 +1,25 @@
1
- import { d as defineComponent, W as useRoute, b as useRouter, q as computed, g9 as ProjectTypes, V as VIEWS, m as resolveComponent, c as openBlock, h as createElementBlock, i as createVNode, w as withCtx, n as normalizeClass, k as createTextVNode, t as toDisplayString, j as createBaseVNode, l as unref, J as withModifiers, aT as createSlots, e as createBlock, f as createCommentVNode, g as useI18n, cB as _sfc_main$4, ga as __unplugin_components_0$1, _ as _export_sfc, a2 as useProjectsStore, a as useToast, p as useSettingsStore, L as useUIStore, u as useUsersStore, U as useWorkflowsStore, am as getResourcePermissions, dS as dateFormat, gb as ResourceType, ax as withDirectives, ay as vShow, ac as WORKFLOW_SHARE_MODAL_KEY, aj as DUPLICATE_MODAL_KEY, af as MODAL_CONFIRM, gc as PROJECT_MOVE_RESOURCE_MODAL, al as useMessage, ak as useTelemetry, S as defineStore, T as STORES, $ as useRootStore, r as ref, gd as createFolder, ge as getFolderPath, gf as getWorkflowsAndFolders, a1 as useSourceControlStore, au as usePostHog, E as useTagsStore, a4 as useDocumentTitle, K as useDebounce, gg as DEFAULT_WORKFLOW_PAGE_SIZE, a9 as EnterpriseEditionFeature, gh as EASY_AI_WORKFLOW_EXPERIMENT, I as watch, o as onMounted, y as onBeforeUnmount, A as debounce, fZ as N8nIcon, cG as N8nHeading, fY as N8nText, gi as N8nCard, cV as N8nInputLabel, a8 as _sfc_main$5, gj as N8nSelect, F as Fragment, B as renderList, gk as _sfc_main$6, D as createEventBus, bI as AI_CREDITS_EXPERIMENT } from "./index-BloiTH5y.js";
2
- import { R as ResourcesListLayout } from "./ResourcesListLayout-C9w15Q23.js";
3
- import { W as WorkflowActivator } from "./WorkflowActivator-Bk7lYyKD.js";
4
- import { P as ProjectCardBadge } from "./ProjectCardBadge-BYZ4CZ8h.js";
5
- import { P as ProjectHeader } from "./ProjectHeader-AVHuknTg.js";
6
- import { g as getEasyAiWorkflowJson } from "./easyAiWorkflowUtils-CHIZUcBZ.js";
7
- import "./useWorkflowActivate-Cn5TIR2c.js";
8
- import "./ProjectCreateResource-cJSSCcoG.js";
1
+ import { d as defineComponent, U as useRoute, b as useRouter, q as computed, gh as ProjectTypes, c as useI18n, V as VIEWS, h as resolveComponent, i as createElementBlock, g as openBlock, j as createVNode, w as withCtx, n as normalizeClass, k as createBaseVNode, f as createCommentVNode, e as createBlock, gi as __unplugin_components_0$1, l as createTextVNode, t as toDisplayString, J as withModifiers, m as unref, cM as _sfc_main$4, _ as _export_sfc, a3 as useProjectsStore, aU as createSlots, a as useToast, p as useSettingsStore, L as useUIStore, u as useUsersStore, T as useWorkflowsStore, a8 as getResourcePermissions, d$ as dateFormat, aA as withDirectives, aB as vShow, gj as ResourceType, af as WORKFLOW_SHARE_MODAL_KEY, ag as useTelemetry, an as DUPLICATE_MODAL_KEY, ai as useMessage, aj as MODAL_CONFIRM, gk as PROJECT_MOVE_RESOURCE_MODAL, a2 as useSourceControlStore, au as usePostHog, E as useTagsStore, gl as useFoldersStore, a5 as useDocumentTitle, K as useDebounce, r as ref, ab as EnterpriseEditionFeature, gm as EASY_AI_WORKFLOW_EXPERIMENT, I as watch, o as onMounted, C as createEventBus, y as onBeforeUnmount, A as debounce, d2 as N8nInputLabel, ad as _sfc_main$5, gn as N8nSelect, F as Fragment, D as renderList, go as _sfc_main$6, cS as N8nHeading, c0 as N8nText, gp as N8nCard, c4 as N8nIcon, gq as DEFAULT_WORKFLOW_PAGE_SIZE, bO as AI_CREDITS_EXPERIMENT, gr as VALID_FOLDER_NAME_REGEX } from "./index-CyVlLoqB.js";
2
+ import { R as ResourcesListLayout } from "./ResourcesListLayout-BYVhS2j5.js";
3
+ import { W as WorkflowActivator } from "./WorkflowActivator-BvmRhIkt.js";
4
+ import { P as ProjectCardBadge } from "./ProjectCardBadge-CGqr1_BG.js";
5
+ import { P as ProjectHeader } from "./ProjectHeader-C8hRwBFC.js";
6
+ import { g as getEasyAiWorkflowJson } from "./easyAiWorkflowUtils-DlyLBhIZ.js";
7
+ import "./useWorkflowActivate-CI3X35ZJ.js";
9
8
  const FOLDER_LIST_ITEM_ACTIONS = {
10
9
  OPEN: "open",
11
10
  CREATE: "create",
12
11
  CREATE_WORKFLOW: "create_workflow",
13
12
  RENAME: "rename",
14
13
  MOVE: "move",
15
- CHOWN: "change_owner",
16
- TAGS: "manage_tags",
17
14
  DELETE: "delete"
18
15
  };
16
+ const _hoisted_1$2 = { "data-test-id": "folder-card" };
19
17
  const _sfc_main$3 = /* @__PURE__ */ defineComponent({
20
18
  __name: "FolderCard",
21
19
  props: {
22
20
  data: {},
23
21
  actions: { default: () => [] },
24
- breadcrumbs: {}
22
+ readOnly: { type: Boolean, default: true }
25
23
  },
26
24
  emits: ["action", "folderOpened"],
27
25
  setup(__props, { emit: __emit }) {
@@ -66,23 +64,18 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
66
64
  }
67
65
  emit("action", { action, folderId: props.data.id });
68
66
  };
69
- const onBreadcrumbsItemClick = async (item) => {
70
- if (item.href) {
71
- await router.push(item.href);
72
- }
73
- };
74
67
  return (_ctx, _cache) => {
75
68
  const _component_n8n_icon = resolveComponent("n8n-icon");
76
69
  const _component_n8n_heading = resolveComponent("n8n-heading");
70
+ const _component_N8nBadge = resolveComponent("N8nBadge");
77
71
  const _component_n8n_text = resolveComponent("n8n-text");
78
72
  const _component_TimeAgo = _sfc_main$4;
79
73
  const _component_ProjectIcon = __unplugin_components_0$1;
80
74
  const _component_n8n_link = resolveComponent("n8n-link");
81
- const _component_n8n_breadcrumbs = resolveComponent("n8n-breadcrumbs");
82
75
  const _component_n8n_action_toggle = resolveComponent("n8n-action-toggle");
83
76
  const _component_n8n_card = resolveComponent("n8n-card");
84
77
  const _component_router_link = resolveComponent("router-link");
85
- return openBlock(), createElementBlock("div", null, [
78
+ return openBlock(), createElementBlock("div", _hoisted_1$2, [
86
79
  createVNode(_component_router_link, {
87
80
  to: cardUrl.value,
88
81
  onClick: _cache[1] || (_cache[1] = () => emit("folderOpened", { folder: props.data }))
@@ -96,37 +89,65 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
96
89
  "data-test-id": "folder-card-icon",
97
90
  class: normalizeClass(_ctx.$style["folder-icon"]),
98
91
  icon: "folder",
99
- size: "large"
92
+ size: "xlarge"
100
93
  }, null, 8, ["class"])
101
94
  ]),
102
95
  header: withCtx(() => [
103
- createVNode(_component_n8n_heading, {
104
- tag: "h2",
105
- bold: "",
106
- size: "small",
107
- "data-test-id": "folder-card-name"
108
- }, {
109
- default: withCtx(() => [
110
- createTextVNode(toDisplayString(_ctx.data.name), 1)
111
- ]),
112
- _: 1
113
- })
96
+ createBaseVNode("div", {
97
+ class: normalizeClass(_ctx.$style["card-header"])
98
+ }, [
99
+ createVNode(_component_n8n_heading, {
100
+ tag: "h2",
101
+ bold: "",
102
+ size: "small",
103
+ "data-test-id": "folder-card-name"
104
+ }, {
105
+ default: withCtx(() => [
106
+ createTextVNode(toDisplayString(_ctx.data.name), 1)
107
+ ]),
108
+ _: 1
109
+ }),
110
+ _ctx.readOnly ? (openBlock(), createBlock(_component_N8nBadge, {
111
+ key: 0,
112
+ class: "ml-3xs",
113
+ theme: "tertiary",
114
+ bold: ""
115
+ }, {
116
+ default: withCtx(() => [
117
+ createTextVNode(toDisplayString(unref(i18n).baseText("workflows.item.readonly")), 1)
118
+ ]),
119
+ _: 1
120
+ })) : createCommentVNode("", true)
121
+ ], 2)
114
122
  ]),
115
123
  footer: withCtx(() => [
116
124
  createBaseVNode("div", {
117
125
  class: normalizeClass(_ctx.$style["card-footer"])
118
126
  }, [
119
- createVNode(_component_n8n_text, {
127
+ _ctx.data.workflowCount > 0 ? (openBlock(), createBlock(_component_n8n_text, {
128
+ key: 0,
129
+ size: "small",
130
+ color: "text-light",
131
+ class: normalizeClass([_ctx.$style["info-cell"], _ctx.$style["info-cell--workflow-count"]]),
132
+ "data-test-id": "folder-card-folder-count"
133
+ }, {
134
+ default: withCtx(() => [
135
+ createTextVNode(toDisplayString(unref(i18n).baseText("generic.workflow", { interpolate: { count: _ctx.data.workflowCount } })), 1)
136
+ ]),
137
+ _: 1
138
+ }, 8, ["class"])) : createCommentVNode("", true),
139
+ _ctx.data.subFolderCount > 0 ? (openBlock(), createBlock(_component_n8n_text, {
140
+ key: 1,
120
141
  size: "small",
121
142
  color: "text-light",
122
143
  class: normalizeClass([_ctx.$style["info-cell"], _ctx.$style["info-cell--workflow-count"]]),
123
144
  "data-test-id": "folder-card-workflow-count"
124
145
  }, {
125
146
  default: withCtx(() => [
126
- createTextVNode(toDisplayString(_ctx.data.workflowCount) + " " + toDisplayString(unref(i18n).baseText("generic.workflows")), 1)
147
+ createTextVNode(toDisplayString(unref(i18n).baseText("generic.folder", { interpolate: { count: _ctx.data.subFolderCount } })), 1)
127
148
  ]),
128
149
  _: 1
129
- }, 8, ["class"]),
150
+ }, 8, ["class"])) : createCommentVNode("", true),
130
151
  createVNode(_component_n8n_text, {
131
152
  size: "small",
132
153
  color: "text-light",
@@ -163,56 +184,41 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
163
184
  onClick: _cache[0] || (_cache[0] = withModifiers(() => {
164
185
  }, ["prevent"]))
165
186
  }, [
166
- createBaseVNode("div", {
167
- class: normalizeClass(_ctx.$style.breadcrumbs)
187
+ _ctx.data.homeProject ? (openBlock(), createElementBlock("div", {
188
+ key: 0,
189
+ class: normalizeClass(_ctx.$style["project-pill"])
168
190
  }, [
169
- createVNode(_component_n8n_breadcrumbs, {
170
- items: _ctx.breadcrumbs.visibleItems,
171
- "hidden-items": _ctx.breadcrumbs.hiddenItems,
172
- "path-truncated": _ctx.breadcrumbs.visibleItems[0]?.parentFolder,
173
- "show-border": true,
174
- "highlight-last-item": false,
175
- theme: "small",
176
- "data-test-id": "folder-card-breadcrumbs",
177
- onItemSelected: onBreadcrumbsItemClick
178
- }, createSlots({ _: 2 }, [
179
- _ctx.data.homeProject ? {
180
- name: "prepend",
181
- fn: withCtx(() => [
182
- createBaseVNode("div", {
183
- class: normalizeClass(_ctx.$style["home-project"])
184
- }, [
185
- createVNode(_component_n8n_link, {
186
- to: `/projects/${_ctx.data.homeProject.id}`
187
- }, {
188
- default: withCtx(() => [
189
- createVNode(_component_ProjectIcon, {
190
- icon: projectIcon.value,
191
- "border-less": true,
192
- size: "mini"
193
- }, null, 8, ["icon"]),
194
- createVNode(_component_n8n_text, {
195
- size: "small",
196
- compact: true,
197
- bold: true,
198
- color: "text-base"
199
- }, {
200
- default: withCtx(() => [
201
- createTextVNode(toDisplayString(projectName.value), 1)
202
- ]),
203
- _: 1
204
- })
205
- ]),
206
- _: 1
207
- }, 8, ["to"])
208
- ], 2)
191
+ createBaseVNode("div", {
192
+ class: normalizeClass(_ctx.$style["home-project"]),
193
+ "data-test-id": "folder-card-home-project"
194
+ }, [
195
+ createVNode(_component_n8n_link, {
196
+ to: `/projects/${_ctx.data.homeProject.id}`
197
+ }, {
198
+ default: withCtx(() => [
199
+ createVNode(_component_ProjectIcon, {
200
+ icon: projectIcon.value,
201
+ "border-less": true,
202
+ size: "mini"
203
+ }, null, 8, ["icon"]),
204
+ createVNode(_component_n8n_text, {
205
+ size: "small",
206
+ compact: true,
207
+ bold: true,
208
+ color: "text-base"
209
+ }, {
210
+ default: withCtx(() => [
211
+ createTextVNode(toDisplayString(projectName.value), 1)
212
+ ]),
213
+ _: 1
214
+ })
209
215
  ]),
210
- key: "0"
211
- } : void 0
212
- ]), 1032, ["items", "hidden-items", "path-truncated"])
213
- ], 2),
216
+ _: 1
217
+ }, 8, ["to"])
218
+ ], 2)
219
+ ], 2)) : createCommentVNode("", true),
214
220
  _ctx.actions.length ? (openBlock(), createBlock(_component_n8n_action_toggle, {
215
- key: 0,
221
+ key: 1,
216
222
  actions: _ctx.actions,
217
223
  theme: "dark",
218
224
  "data-test-id": "folder-card-actions",
@@ -229,15 +235,17 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
229
235
  };
230
236
  }
231
237
  });
232
- const card = "_card_v01dx_123";
238
+ const card = "_card_1ughy_124";
233
239
  const style0$3 = {
234
240
  card,
235
- "folder-icon": "_folder-icon_v01dx_131",
236
- "card-footer": "_card-footer_v01dx_142",
237
- "info-cell": "_info-cell_v01dx_146",
238
- "card-actions": "_card-actions_v01dx_151",
239
- "home-project": "_home-project_v01dx_156",
240
- "info-cell--created": "_info-cell--created_v01dx_176"
241
+ "folder-icon": "_folder-icon_1ughy_132",
242
+ "card-header": "_card-header_1ughy_141",
243
+ "card-footer": "_card-footer_1ughy_149",
244
+ "info-cell": "_info-cell_1ughy_153",
245
+ "card-actions": "_card-actions_1ughy_158",
246
+ "project-pill": "_project-pill_1ughy_163",
247
+ "home-project": "_home-project_1ughy_171",
248
+ "info-cell--created": "_info-cell--created_1ughy_191"
241
249
  };
242
250
  const cssModules$3 = {
243
251
  "$style": style0$3
@@ -281,21 +289,22 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
281
289
  "highlight-last-item": false,
282
290
  "path-truncated": _ctx.breadcrumbs.visibleItems[0].parentFolder,
283
291
  "hidden-items": _ctx.breadcrumbs.hiddenItems,
284
- "data-test-id": "folder-card-breadcrumbs",
292
+ "data-test-id": "folder-list-breadcrumbs",
285
293
  onItemSelected: onItemSelect
286
294
  }, createSlots({ _: 2 }, [
287
295
  currentProject.value ? {
288
296
  name: "prepend",
289
297
  fn: withCtx(() => [
290
298
  createBaseVNode("div", {
291
- class: normalizeClass(_ctx.$style["home-project"])
299
+ class: normalizeClass(_ctx.$style["home-project"]),
300
+ "data-test-id": "home-project"
292
301
  }, [
293
302
  createVNode(_component_n8n_link, {
294
303
  to: `/projects/${currentProject.value.id}`
295
304
  }, {
296
305
  default: withCtx(() => [
297
306
  createVNode(_component_N8nText, {
298
- size: "large",
307
+ size: "medium",
299
308
  color: "text-base"
300
309
  }, {
301
310
  default: withCtx(() => [
@@ -336,18 +345,18 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
336
345
  __name: "WorkflowCard",
337
346
  props: {
338
347
  data: {},
339
- breadcrumbs: {},
340
348
  readOnly: { type: Boolean, default: false },
341
349
  workflowListEventBus: { default: void 0 }
342
350
  },
343
- emits: ["expand:tags", "click:tag", "workflow:deleted", "workflow:active-toggle"],
351
+ emits: ["expand:tags", "click:tag", "workflow:deleted", "workflow:active-toggle", "action:move-to-folder"],
344
352
  setup(__props, { emit: __emit }) {
345
353
  const WORKFLOW_LIST_ITEM_ACTIONS = {
346
354
  OPEN: "open",
347
355
  SHARE: "share",
348
356
  DUPLICATE: "duplicate",
349
357
  DELETE: "delete",
350
- MOVE: "move"
358
+ MOVE: "move",
359
+ MOVE_TO_FOLDER: "moveToFolder"
351
360
  };
352
361
  const props = __props;
353
362
  const emit = __emit;
@@ -355,8 +364,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
355
364
  const message = useMessage();
356
365
  const locale = useI18n();
357
366
  const router = useRouter();
367
+ const route = useRoute();
358
368
  const telemetry = useTelemetry();
359
- const i18n = useI18n();
360
369
  const settingsStore = useSettingsStore();
361
370
  const uiStore = useUIStore();
362
371
  const usersStore = useUsersStore();
@@ -365,6 +374,9 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
365
374
  const resourceTypeLabel = computed(() => locale.baseText("generic.workflow").toLowerCase());
366
375
  const currentUser = computed(() => usersStore.currentUser ?? {});
367
376
  const workflowPermissions = computed(() => getResourcePermissions(props.data.scopes).workflow);
377
+ const showFolders = computed(() => {
378
+ return settingsStore.isFoldersFeatureEnabled && route.name !== VIEWS.WORKFLOWS;
379
+ });
368
380
  const actions = computed(() => {
369
381
  const items = [
370
382
  {
@@ -382,9 +394,15 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
382
394
  value: WORKFLOW_LIST_ITEM_ACTIONS.DUPLICATE
383
395
  });
384
396
  }
397
+ if (workflowPermissions.value.update && !props.readOnly && showFolders.value) {
398
+ items.push({
399
+ label: locale.baseText("folders.actions.moveToFolder"),
400
+ value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE_TO_FOLDER
401
+ });
402
+ }
385
403
  if (workflowPermissions.value.move && projectsStore.isTeamProjectFeatureEnabled) {
386
404
  items.push({
387
- label: locale.baseText("workflows.item.move"),
405
+ label: locale.baseText("workflows.item.changeOwner"),
388
406
  value: WORKFLOW_LIST_ITEM_ACTIONS.MOVE
389
407
  });
390
408
  }
@@ -403,28 +421,13 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
403
421
  `d mmmm${String(props.data.createdAt).startsWith(currentYear) ? "" : ", yyyy"}`
404
422
  );
405
423
  });
406
- const projectIcon = computed(() => {
407
- const defaultIcon = { type: "icon", value: "layer-group" };
408
- if (props.data.homeProject?.type === ProjectTypes.Personal) {
409
- return { type: "icon", value: "user" };
410
- } else if (props.data.homeProject?.type === ProjectTypes.Team) {
411
- return props.data.homeProject.icon ?? defaultIcon;
412
- }
413
- return defaultIcon;
414
- });
415
- const projectName = computed(() => {
416
- if (props.data.homeProject?.type === ProjectTypes.Personal) {
417
- return i18n.baseText("projects.menu.personal");
418
- }
419
- return props.data.homeProject?.name;
420
- });
421
424
  async function onClick(event) {
422
425
  if (event?.ctrlKey || event?.metaKey) {
423
- const route = router.resolve({
426
+ const route2 = router.resolve({
424
427
  name: VIEWS.WORKFLOW,
425
428
  params: { name: props.data.id }
426
429
  });
427
- window.open(route.href, "_blank");
430
+ window.open(route2.href, "_blank");
428
431
  return;
429
432
  }
430
433
  await router.push({
@@ -474,6 +477,13 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
474
477
  case WORKFLOW_LIST_ITEM_ACTIONS.MOVE:
475
478
  moveResource();
476
479
  break;
480
+ case WORKFLOW_LIST_ITEM_ACTIONS.MOVE_TO_FOLDER:
481
+ emit("action:move-to-folder", {
482
+ id: props.data.id,
483
+ name: props.data.name,
484
+ parentFolderId: props.data.parentFolder?.id
485
+ });
486
+ break;
477
487
  }
478
488
  }
479
489
  async function deleteWorkflow() {
@@ -526,9 +536,6 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
526
536
  const _component_n8n_heading = resolveComponent("n8n-heading");
527
537
  const _component_n8n_tags = resolveComponent("n8n-tags");
528
538
  const _component_n8n_text = resolveComponent("n8n-text");
529
- const _component_ProjectIcon = __unplugin_components_0$1;
530
- const _component_n8n_link = resolveComponent("n8n-link");
531
- const _component_n8n_breadcrumbs = resolveComponent("n8n-breadcrumbs");
532
539
  const _component_n8n_action_toggle = resolveComponent("n8n-action-toggle");
533
540
  const _component_n8n_card = resolveComponent("n8n-card");
534
541
  return openBlock(), createBlock(_component_n8n_card, {
@@ -566,61 +573,13 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
566
573
  onClick: _cache[0] || (_cache[0] = withModifiers(() => {
567
574
  }, ["stop"]))
568
575
  }, [
569
- !_ctx.data.parentFolder ? (openBlock(), createBlock(ProjectCardBadge, {
570
- key: 0,
576
+ createVNode(ProjectCardBadge, {
571
577
  class: normalizeClass(_ctx.$style.cardBadge),
572
578
  resource: _ctx.data,
573
579
  "resource-type": unref(ResourceType).Workflow,
574
580
  "resource-type-label": resourceTypeLabel.value,
575
581
  "personal-project": unref(projectsStore).personalProject
576
- }, null, 8, ["class", "resource", "resource-type", "resource-type-label", "personal-project"])) : (openBlock(), createElementBlock("div", {
577
- key: 1,
578
- class: normalizeClass(_ctx.$style.breadcrumbs)
579
- }, [
580
- createVNode(_component_n8n_breadcrumbs, {
581
- items: _ctx.breadcrumbs.visibleItems,
582
- "hidden-items": _ctx.breadcrumbs.hiddenItems,
583
- "path-truncated": _ctx.breadcrumbs.visibleItems[0]?.parentFolder,
584
- "show-border": true,
585
- "highlight-last-item": false,
586
- theme: "small",
587
- "data-test-id": "folder-card-breadcrumbs"
588
- }, createSlots({ _: 2 }, [
589
- _ctx.data.homeProject ? {
590
- name: "prepend",
591
- fn: withCtx(() => [
592
- createBaseVNode("div", {
593
- class: normalizeClass(_ctx.$style["home-project"])
594
- }, [
595
- createVNode(_component_n8n_link, {
596
- to: `/projects/${_ctx.data.homeProject.id}`
597
- }, {
598
- default: withCtx(() => [
599
- createVNode(_component_ProjectIcon, {
600
- icon: projectIcon.value,
601
- "border-less": true,
602
- size: "mini"
603
- }, null, 8, ["icon"]),
604
- createVNode(_component_n8n_text, {
605
- size: "small",
606
- compact: true,
607
- bold: true,
608
- color: "text-base"
609
- }, {
610
- default: withCtx(() => [
611
- createTextVNode(toDisplayString(projectName.value), 1)
612
- ]),
613
- _: 1
614
- })
615
- ]),
616
- _: 1
617
- }, 8, ["to"])
618
- ], 2)
619
- ]),
620
- key: "0"
621
- } : void 0
622
- ]), 1032, ["items", "hidden-items", "path-truncated"])
623
- ], 2)),
582
+ }, null, 8, ["class", "resource", "resource-type", "resource-type-label", "personal-project"]),
624
583
  createVNode(WorkflowActivator, {
625
584
  class: "mr-s",
626
585
  "workflow-active": _ctx.data.active,
@@ -680,18 +639,18 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
680
639
  };
681
640
  }
682
641
  });
683
- const cardLink = "_cardLink_dsqjo_123";
684
- const cardHeading = "_cardHeading_dsqjo_133";
685
- const cardDescription = "_cardDescription_dsqjo_142";
686
- const cardActions = "_cardActions_dsqjo_149";
687
- const cardBadge = "_cardBadge_dsqjo_176";
688
- const breadcrumbs = "_breadcrumbs_dsqjo_177";
642
+ const cardLink = "_cardLink_1mosm_123";
643
+ const cardHeading = "_cardHeading_1mosm_133";
644
+ const cardDescription = "_cardDescription_1mosm_142";
645
+ const cardActions = "_cardActions_1mosm_149";
646
+ const cardBadge = "_cardBadge_1mosm_176";
647
+ const breadcrumbs = "_breadcrumbs_1mosm_177";
689
648
  const style0$1 = {
690
649
  cardLink,
691
650
  cardHeading,
692
651
  cardDescription,
693
652
  cardActions,
694
- "home-project": "_home-project_dsqjo_159",
653
+ "home-project": "_home-project_1mosm_159",
695
654
  cardBadge,
696
655
  breadcrumbs
697
656
  };
@@ -699,73 +658,6 @@ const cssModules$1 = {
699
658
  "$style": style0$1
700
659
  };
701
660
  const WorkflowCard = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__cssModules", cssModules$1]]);
702
- const useFoldersStore = defineStore(STORES.FOLDERS, () => {
703
- const rootStore = useRootStore();
704
- const totalWorkflowCount = ref(0);
705
- const breadcrumbsCache = ref({});
706
- const cacheFolders = (folders) => {
707
- folders.forEach((folder) => {
708
- if (!breadcrumbsCache.value[folder.id]) {
709
- breadcrumbsCache.value[folder.id] = {
710
- id: folder.id,
711
- name: folder.name,
712
- parentFolder: folder.parentFolder
713
- };
714
- }
715
- });
716
- };
717
- const getCachedFolder = (folderId) => {
718
- return breadcrumbsCache.value[folderId];
719
- };
720
- async function createFolder$1(name, projectId, parentFolderId) {
721
- return await createFolder(
722
- rootStore.restApiContext,
723
- projectId,
724
- name,
725
- parentFolderId
726
- );
727
- }
728
- async function getFolderPath$1(projectId, folderId) {
729
- const tree = await getFolderPath(rootStore.restApiContext, projectId, folderId);
730
- const forCache = extractFoldersForCache(tree);
731
- cacheFolders(forCache);
732
- return tree;
733
- }
734
- function extractFoldersForCache(items, parentFolderId) {
735
- let result = [];
736
- items.forEach((item) => {
737
- result.push({
738
- id: item.id,
739
- name: item.name,
740
- parentFolder: parentFolderId
741
- });
742
- if (item.children && item.children.length > 0) {
743
- const childFolders = extractFoldersForCache(item.children, item.id);
744
- result = [...result, ...childFolders];
745
- }
746
- });
747
- return result;
748
- }
749
- async function fetchTotalWorkflowsAndFoldersCount(projectId) {
750
- const { count } = await getWorkflowsAndFolders(
751
- rootStore.restApiContext,
752
- { projectId },
753
- { skip: 0, take: 1 },
754
- true
755
- );
756
- totalWorkflowCount.value = count;
757
- return count;
758
- }
759
- return {
760
- fetchTotalWorkflowsAndFoldersCount,
761
- breadcrumbsCache,
762
- cacheFolders,
763
- getCachedFolder,
764
- createFolder: createFolder$1,
765
- getFolderPath: getFolderPath$1,
766
- totalWorkflowCount
767
- };
768
- });
769
661
  const _hoisted_1 = { class: "text-center mt-s" };
770
662
  const _hoisted_2 = {
771
663
  key: 0,
@@ -818,47 +710,37 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
818
710
  const pageSize = ref(DEFAULT_WORKFLOW_PAGE_SIZE);
819
711
  const currentSort = ref("updatedAt:desc");
820
712
  const currentFolderId = ref(null);
821
- const folderActions = ref([
713
+ const folderActions = computed(() => [
822
714
  {
823
- label: "Open",
715
+ label: i18n.baseText("generic.open"),
824
716
  value: FOLDER_LIST_ITEM_ACTIONS.OPEN,
825
717
  disabled: false,
826
718
  onlyAvailableOn: "card"
827
719
  },
828
720
  {
829
- label: "Create Folder",
721
+ label: i18n.baseText("folders.actions.create"),
830
722
  value: FOLDER_LIST_ITEM_ACTIONS.CREATE,
831
- disabled: false
723
+ disabled: readOnlyEnv.value || !hasPermissionToCreateFolders.value
832
724
  },
833
725
  {
834
- label: "Create Workflow",
726
+ label: i18n.baseText("folders.actions.create.workflow"),
835
727
  value: FOLDER_LIST_ITEM_ACTIONS.CREATE_WORKFLOW,
836
- disabled: false
728
+ disabled: readOnlyEnv.value || !hasPermissionToCreateWorkflows.value
837
729
  },
838
730
  {
839
- label: "Rename",
731
+ label: i18n.baseText("generic.rename"),
840
732
  value: FOLDER_LIST_ITEM_ACTIONS.RENAME,
841
- disabled: true
733
+ disabled: readOnlyEnv.value || !hasPermissionToUpdateFolders.value
842
734
  },
843
735
  {
844
- label: "Move to Folder",
736
+ label: i18n.baseText("folders.actions.moveToFolder"),
845
737
  value: FOLDER_LIST_ITEM_ACTIONS.MOVE,
846
- disabled: true
847
- },
848
- {
849
- label: "Change Owner",
850
- value: FOLDER_LIST_ITEM_ACTIONS.CHOWN,
851
- disabled: true
852
- },
853
- {
854
- label: "Manage Tags",
855
- value: FOLDER_LIST_ITEM_ACTIONS.TAGS,
856
- disabled: true
738
+ disabled: readOnlyEnv.value || !hasPermissionToUpdateFolders.value
857
739
  },
858
740
  {
859
- label: "Delete",
741
+ label: i18n.baseText("generic.delete"),
860
742
  value: FOLDER_LIST_ITEM_ACTIONS.DELETE,
861
- disabled: true
743
+ disabled: readOnlyEnv.value || !hasPermissionToDeleteFolders.value
862
744
  }
863
745
  ]);
864
746
  const folderCardActions = computed(
@@ -872,16 +754,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
872
754
  )
873
755
  );
874
756
  const readOnlyEnv = computed(() => sourceControlStore.preferences.branchReadOnly);
875
- const foldersEnabled = computed(() => settingsStore.settings.folders.enabled);
876
757
  const isOverviewPage = computed(() => route.name === VIEWS.WORKFLOWS);
877
758
  const currentUser = computed(() => usersStore.currentUser ?? {});
878
759
  const isShareable = computed(
879
760
  () => settingsStore.isEnterpriseFeatureEnabled[EnterpriseEditionFeature.Sharing]
880
761
  );
881
- const showFolders = computed(() => foldersEnabled.value && !isOverviewPage.value);
762
+ const showFolders = computed(() => {
763
+ return settingsStore.isFoldersFeatureEnabled && !isOverviewPage.value;
764
+ });
882
765
  const currentFolder = computed(() => {
883
766
  return currentFolderId.value ? foldersStore.breadcrumbsCache[currentFolderId.value] : null;
884
767
  });
768
+ const hasPermissionToCreateFolders = computed(() => {
769
+ if (!currentProject.value) return false;
770
+ return getResourcePermissions(currentProject.value.scopes).folder.create === true;
771
+ });
772
+ const hasPermissionToUpdateFolders = computed(() => {
773
+ if (!currentProject.value) return false;
774
+ return getResourcePermissions(currentProject.value.scopes).folder.update === true;
775
+ });
776
+ const hasPermissionToDeleteFolders = computed(() => {
777
+ if (!currentProject.value) return false;
778
+ return getResourcePermissions(currentProject.value.scopes).folder.delete === true;
779
+ });
780
+ const hasPermissionToCreateWorkflows = computed(() => {
781
+ if (!currentProject.value) return false;
782
+ return getResourcePermissions(currentProject.value.scopes).workflow.create === true;
783
+ });
885
784
  const currentProject = computed(() => projectsStore.currentProject);
886
785
  const projectName = computed(() => {
887
786
  if (currentProject.value?.type === ProjectTypes.Personal) {
@@ -907,6 +806,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
907
806
  homeProject: resource.homeProject,
908
807
  sharedWithProjects: resource.sharedWithProjects,
909
808
  workflowCount: resource.workflowCount,
809
+ subFolderCount: resource.subFolderCount,
910
810
  parentFolder: resource.parentFolder
911
811
  };
912
812
  } else {
@@ -978,22 +878,43 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
978
878
  if (name !== "pullWorkfolder") return;
979
879
  after(async () => await initialize());
980
880
  });
881
+ const onFolderDeleted = async (payload) => {
882
+ const folderInfo = foldersStore.getCachedFolder(payload.folderId);
883
+ foldersStore.deleteFoldersFromCache([payload.folderId, folderInfo?.parentFolder ?? ""]);
884
+ if (currentFolderId.value === payload.folderId) {
885
+ void router.push({
886
+ name: VIEWS.PROJECTS_FOLDERS,
887
+ params: { projectId: route.params.projectId, folderId: folderInfo?.parentFolder ?? "" }
888
+ });
889
+ } else {
890
+ await fetchWorkflows();
891
+ }
892
+ telemetry.track("User deleted folder", {
893
+ folder_id: payload.folderId,
894
+ deleted_sub_folders: payload.folderCount,
895
+ deleted_sub_workflows: payload.workflowCount
896
+ });
897
+ };
981
898
  onMounted(async () => {
982
899
  documentTitle.set(i18n.baseText("workflows.heading"));
983
900
  void usersStore.showPersonalizationSurvey();
984
901
  workflowListEventBus.on("resource-moved", fetchWorkflows);
985
902
  workflowListEventBus.on("workflow-duplicated", fetchWorkflows);
903
+ workflowListEventBus.on("folder-deleted", onFolderDeleted);
904
+ workflowListEventBus.on("folder-moved", moveFolder);
905
+ workflowListEventBus.on("workflow-moved", onWorkflowMoved);
986
906
  });
987
907
  onBeforeUnmount(() => {
988
908
  workflowListEventBus.off("resource-moved", fetchWorkflows);
989
909
  workflowListEventBus.off("workflow-duplicated", fetchWorkflows);
910
+ workflowListEventBus.off("folder-deleted", onFolderDeleted);
911
+ workflowListEventBus.off("folder-moved", moveFolder);
912
+ workflowListEventBus.off("workflow-moved", onWorkflowMoved);
990
913
  });
991
914
  const initialize = async () => {
992
915
  loading.value = true;
993
916
  await setFiltersFromQueryString();
994
- if (!route.params.folderId) {
995
- currentFolderId.value = null;
996
- }
917
+ currentFolderId.value = route.params.folderId;
997
918
  const [, resourcesPage] = await Promise.all([
998
919
  usersStore.fetchUsers(),
999
920
  fetchWorkflows(),
@@ -1010,36 +931,48 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1010
931
  const routeProjectId = route.params?.projectId;
1011
932
  const homeProjectFilter = filters.value.homeProject || void 0;
1012
933
  const parentFolder = route.params?.folderId || void 0;
1013
- const fetchedResources = await workflowsStore.fetchWorkflowsPage(
1014
- routeProjectId ?? homeProjectFilter,
1015
- currentPage.value,
1016
- pageSize.value,
1017
- currentSort.value,
1018
- {
1019
- name: filters.value.search || void 0,
1020
- active: filters.value.status === StatusFilter.ALL ? void 0 : filters.value.status === StatusFilter.ACTIVE,
1021
- tags: filters.value.tags.map((tagId) => tagsStore.tagsById[tagId]?.name),
1022
- parentFolderId: parentFolder ?? "0"
1023
- // 0 is the root folder in the API
1024
- },
1025
- showFolders.value
1026
- );
1027
- foldersStore.cacheFolders(
1028
- fetchedResources.filter((resource) => resource.resource === "folder").map((r) => ({ id: r.id, name: r.name, parentFolder: r.parentFolder?.id }))
1029
- );
1030
- const isCurrentFolderCached = foldersStore.breadcrumbsCache[parentFolder ?? ""] !== void 0;
1031
- const needToFetchFolderPath = parentFolder && !isCurrentFolderCached && routeProjectId;
1032
- if (needToFetchFolderPath) {
1033
- breadcrumbsLoading.value = true;
1034
- await foldersStore.getFolderPath(routeProjectId, parentFolder);
1035
- currentFolderId.value = parentFolder;
1036
- breadcrumbsLoading.value = false;
934
+ const tags = filters.value.tags.length ? filters.value.tags.map((tagId) => tagsStore.tagsById[tagId]?.name) : [];
935
+ const activeFilter = filters.value.status === StatusFilter.ALL ? void 0 : filters.value.status === StatusFilter.ACTIVE;
936
+ const fetchFolders = showFolders.value && !tags.length && activeFilter === void 0;
937
+ try {
938
+ const fetchedResources = await workflowsStore.fetchWorkflowsPage(
939
+ routeProjectId ?? homeProjectFilter,
940
+ currentPage.value,
941
+ pageSize.value,
942
+ currentSort.value,
943
+ {
944
+ name: filters.value.search || void 0,
945
+ active: activeFilter,
946
+ tags: tags.length ? tags : void 0,
947
+ parentFolderId: parentFolder ?? (isOverviewPage.value ? void 0 : "0")
948
+ // Sending 0 will only show one level of folders
949
+ },
950
+ fetchFolders
951
+ );
952
+ foldersStore.cacheFolders(
953
+ fetchedResources.filter((resource) => resource.resource === "folder").map((r) => ({ id: r.id, name: r.name, parentFolder: r.parentFolder?.id }))
954
+ );
955
+ const isCurrentFolderCached = foldersStore.breadcrumbsCache[parentFolder ?? ""] !== void 0;
956
+ const needToFetchFolderPath = parentFolder && !isCurrentFolderCached && routeProjectId;
957
+ if (needToFetchFolderPath) {
958
+ breadcrumbsLoading.value = true;
959
+ await foldersStore.getFolderPath(routeProjectId, parentFolder);
960
+ breadcrumbsLoading.value = false;
961
+ }
962
+ await foldersStore.fetchTotalWorkflowsAndFoldersCount(routeProjectId);
963
+ workflowsAndFolders.value = fetchedResources;
964
+ return fetchedResources;
965
+ } catch (error) {
966
+ toast.showError(error, i18n.baseText("workflows.list.error.fetching"));
967
+ void router.push({ name: VIEWS.PROJECTS_FOLDERS, params: { projectId: routeProjectId } });
968
+ return [];
969
+ } finally {
970
+ delayedLoading.cancel();
971
+ loading.value = false;
972
+ if (breadcrumbsLoading.value) {
973
+ breadcrumbsLoading.value = false;
974
+ }
1037
975
  }
1038
- await foldersStore.fetchTotalWorkflowsAndFoldersCount(routeProjectId);
1039
- delayedLoading.cancel();
1040
- workflowsAndFolders.value = fetchedResources;
1041
- loading.value = false;
1042
- return fetchedResources;
1043
976
  };
1044
977
  const onSortUpdated = async (sort) => {
1045
978
  currentSort.value = WORKFLOWS_SORT_MAP[sort] ?? "updatedAt:desc";
@@ -1053,24 +986,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1053
986
  const onFiltersUpdated = async () => {
1054
987
  currentPage.value = 1;
1055
988
  saveFiltersOnQueryString();
1056
- await fetchWorkflows();
989
+ await callDebounced(fetchWorkflows, { debounceTime: 100, trailing: true });
1057
990
  };
1058
991
  const onSearchUpdated = async (search) => {
1059
992
  currentPage.value = 1;
1060
993
  saveFiltersOnQueryString();
1061
994
  if (search) {
1062
- await callDebounced(fetchWorkflows, { debounceTime: 500, trailing: true });
995
+ await callDebounced(fetchWorkflows, { debounceTime: 100, trailing: true });
1063
996
  } else {
1064
997
  await fetchWorkflows();
1065
998
  }
1066
999
  };
1067
1000
  const setCurrentPage = async (page) => {
1068
1001
  currentPage.value = page;
1069
- await fetchWorkflows();
1002
+ await callDebounced(fetchWorkflows, { debounceTime: 100, trailing: true });
1070
1003
  };
1071
1004
  const setPageSize = async (size) => {
1072
1005
  pageSize.value = size;
1073
- await fetchWorkflows();
1006
+ await callDebounced(fetchWorkflows, { debounceTime: 100, trailing: true });
1074
1007
  };
1075
1008
  const onClickTag = async (tagId) => {
1076
1009
  if (!filters.value.tags.includes(tagId)) {
@@ -1204,6 +1137,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1204
1137
  if (!workflow) return;
1205
1138
  workflow.active = data.active;
1206
1139
  };
1140
+ const getFolderListItem = (folderId) => {
1141
+ return workflowsAndFolders.value.find(
1142
+ (resource) => resource.resource === "folder" && resource.id === folderId
1143
+ );
1144
+ };
1145
+ const getFolderContent = async (folderId) => {
1146
+ const folderListItem = getFolderListItem(folderId);
1147
+ if (folderListItem) {
1148
+ return {
1149
+ workflowCount: folderListItem.workflowCount,
1150
+ subFolderCount: folderListItem.subFolderCount
1151
+ };
1152
+ }
1153
+ try {
1154
+ const content = await foldersStore.fetchFolderContent(currentProject.value?.id ?? "", folderId);
1155
+ return { workflowCount: content.totalWorkflows, subFolderCount: content.totalSubFolders };
1156
+ } catch (error) {
1157
+ toast.showMessage({
1158
+ title: i18n.baseText("folders.delete.error.message"),
1159
+ message: i18n.baseText("folders.not.found.message"),
1160
+ type: "error"
1161
+ });
1162
+ return { workflowCount: 0, subFolderCount: 0 };
1163
+ }
1164
+ };
1207
1165
  const visibleBreadcrumbsItems = computed(() => {
1208
1166
  if (!currentFolder.value) return [];
1209
1167
  const items = [];
@@ -1247,20 +1205,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1247
1205
  hiddenItems: hiddenBreadcrumbsItems.value
1248
1206
  };
1249
1207
  });
1250
- const cardBreadcrumbs = computed(() => {
1251
- const visibleItems = visibleBreadcrumbsItems.value;
1252
- const hiddenItems = hiddenBreadcrumbsItems.value;
1253
- if (visibleItems.length > 1) {
1254
- return {
1255
- visibleItems: [visibleItems[visibleItems.length - 1]],
1256
- hiddenItems: [...hiddenItems, ...visibleItems.slice(0, visibleItems.length - 1)]
1257
- };
1258
- }
1259
- return {
1260
- visibleItems,
1261
- hiddenItems
1262
- };
1263
- });
1264
1208
  const onBreadcrumbItemClick = (item) => {
1265
1209
  if (item.href) {
1266
1210
  loading.value = true;
@@ -1268,7 +1212,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1268
1212
  currentFolderId.value = item.id;
1269
1213
  loading.value = false;
1270
1214
  }).catch((error) => {
1271
- toast.showError(error, "Error navigating to folder");
1215
+ toast.showError(error, i18n.baseText("folders.open.error.title"));
1272
1216
  });
1273
1217
  }
1274
1218
  };
@@ -1278,7 +1222,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1278
1222
  if (!route.params.projectId) return;
1279
1223
  const currentParent = currentFolder.value?.name || projectName.value;
1280
1224
  if (!currentParent) return;
1281
- await createFolder2({
1225
+ await createFolder({
1282
1226
  id: route.params.folderId ?? "-1",
1283
1227
  name: currentParent,
1284
1228
  type: currentFolder.value ? "folder" : "project"
@@ -1287,6 +1231,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1287
1231
  case FOLDER_LIST_ITEM_ACTIONS.CREATE_WORKFLOW:
1288
1232
  addWorkflow();
1289
1233
  break;
1234
+ case FOLDER_LIST_ITEM_ACTIONS.DELETE:
1235
+ if (!route.params.folderId) return;
1236
+ const content = await getFolderContent(route.params.folderId);
1237
+ await deleteFolder(
1238
+ route.params.folderId,
1239
+ content.workflowCount,
1240
+ content.subFolderCount
1241
+ );
1242
+ break;
1243
+ case FOLDER_LIST_ITEM_ACTIONS.RENAME:
1244
+ if (!route.params.folderId) return;
1245
+ await renameFolder(route.params.folderId);
1246
+ break;
1247
+ case FOLDER_LIST_ITEM_ACTIONS.MOVE:
1248
+ if (!currentFolder.value) return;
1249
+ uiStore.openMoveToFolderModal(
1250
+ "folder",
1251
+ {
1252
+ id: currentFolder.value?.id,
1253
+ name: currentFolder.value?.name,
1254
+ parentFolderId: currentFolder.value?.parentFolder
1255
+ },
1256
+ workflowListEventBus
1257
+ );
1258
+ break;
1290
1259
  }
1291
1260
  };
1292
1261
  const onFolderCardAction = async (payload) => {
@@ -1294,7 +1263,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1294
1263
  if (!clickedFolder) return;
1295
1264
  switch (payload.action) {
1296
1265
  case FOLDER_LIST_ITEM_ACTIONS.CREATE:
1297
- await createFolder2({
1266
+ await createFolder({
1298
1267
  id: clickedFolder.id,
1299
1268
  name: clickedFolder.name,
1300
1269
  type: "folder"
@@ -1307,17 +1276,35 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1307
1276
  query: { projectId: route.params?.projectId, parentFolderId: clickedFolder.id }
1308
1277
  });
1309
1278
  break;
1279
+ case FOLDER_LIST_ITEM_ACTIONS.DELETE: {
1280
+ const content = await getFolderContent(clickedFolder.id);
1281
+ await deleteFolder(clickedFolder.id, content.workflowCount, content.subFolderCount);
1282
+ break;
1283
+ }
1284
+ case FOLDER_LIST_ITEM_ACTIONS.RENAME:
1285
+ await renameFolder(clickedFolder.id);
1286
+ break;
1287
+ case FOLDER_LIST_ITEM_ACTIONS.MOVE:
1288
+ uiStore.openMoveToFolderModal(
1289
+ "folder",
1290
+ {
1291
+ id: clickedFolder.id,
1292
+ name: clickedFolder.name,
1293
+ parentFolderId: clickedFolder.parentFolder
1294
+ },
1295
+ workflowListEventBus
1296
+ );
1297
+ break;
1310
1298
  }
1311
1299
  };
1312
- const createFolder2 = async (parent) => {
1300
+ const createFolder = async (parent) => {
1313
1301
  const promptResponsePromise = message.prompt(
1314
1302
  i18n.baseText("folders.add.to.parent.message", { interpolate: { parent: parent.name } }),
1315
1303
  {
1316
1304
  confirmButtonText: i18n.baseText("generic.create"),
1317
1305
  cancelButtonText: i18n.baseText("generic.cancel"),
1318
- inputErrorMessage: i18n.baseText("folders.add.invalidName.message"),
1319
- inputValue: "",
1320
- inputPattern: /^[a-zA-Z0-9-_ ]{1,100}$/,
1306
+ inputErrorMessage: i18n.baseText("folders.invalidName.message"),
1307
+ inputPattern: VALID_FOLDER_NAME_REGEX,
1321
1308
  customClass: "add-folder-modal"
1322
1309
  }
1323
1310
  );
@@ -1330,18 +1317,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1330
1317
  route.params.projectId,
1331
1318
  parent.type === "folder" ? parent.id : void 0
1332
1319
  );
1333
- let newFolderURL = `/projects/${route.params.projectId}`;
1334
- if (newFolder.parentFolder) {
1335
- newFolderURL = `/projects/${route.params.projectId}/folders/${newFolder.id}/workflows`;
1336
- }
1337
- toast.showMessage({
1320
+ const newFolderURL = router.resolve({
1321
+ name: VIEWS.PROJECTS_FOLDERS,
1322
+ params: { projectId: route.params.projectId, folderId: newFolder.id }
1323
+ }).href;
1324
+ toast.showToast({
1338
1325
  title: i18n.baseText("folders.add.success.title"),
1339
1326
  message: i18n.baseText("folders.add.success.message", {
1340
1327
  interpolate: {
1341
1328
  link: newFolderURL,
1342
- name: newFolder.name
1329
+ folderName: newFolder.name
1343
1330
  }
1344
1331
  }),
1332
+ onClick: (event) => {
1333
+ if (event?.target instanceof HTMLAnchorElement) {
1334
+ event.preventDefault();
1335
+ void router.push(newFolderURL);
1336
+ }
1337
+ },
1345
1338
  type: "success"
1346
1339
  });
1347
1340
  if (!workflowsAndFolders.value.length) {
@@ -1354,14 +1347,56 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1354
1347
  updatedAt: newFolder.updatedAt,
1355
1348
  homeProject: projectsStore.currentProject,
1356
1349
  sharedWithProjects: [],
1357
- workflowCount: 0
1350
+ workflowCount: 0,
1351
+ subFolderCount: 0
1358
1352
  }
1359
1353
  ];
1354
+ foldersStore.cacheFolders([
1355
+ { id: newFolder.id, name: newFolder.name, parentFolder: currentFolder.value?.id }
1356
+ ]);
1360
1357
  } else {
1361
1358
  await fetchWorkflows();
1362
1359
  }
1360
+ telemetry.track("User created folder", {
1361
+ folder_id: newFolder.id
1362
+ });
1363
1363
  } catch (error) {
1364
- toast.showError(error, "Error creating folder");
1364
+ toast.showError(error, i18n.baseText("folders.create.error.title"));
1365
+ }
1366
+ }
1367
+ };
1368
+ const renameFolder = async (folderId) => {
1369
+ const folder = foldersStore.getCachedFolder(folderId);
1370
+ if (!folder || !currentProject.value) return;
1371
+ const promptResponsePromise = message.prompt(
1372
+ i18n.baseText("folders.rename.message", { interpolate: { folderName: folder.name } }),
1373
+ {
1374
+ confirmButtonText: i18n.baseText("generic.rename"),
1375
+ cancelButtonText: i18n.baseText("generic.cancel"),
1376
+ inputErrorMessage: i18n.baseText("folders.invalidName.message"),
1377
+ inputValue: folder.name,
1378
+ inputPattern: VALID_FOLDER_NAME_REGEX,
1379
+ customClass: "rename-folder-modal"
1380
+ }
1381
+ );
1382
+ const promptResponse = await promptResponsePromise;
1383
+ if (promptResponse.action === MODAL_CONFIRM) {
1384
+ const newFolderName = promptResponse.value;
1385
+ try {
1386
+ await foldersStore.renameFolder(currentProject.value?.id, folderId, newFolderName);
1387
+ foldersStore.breadcrumbsCache[folderId].name = newFolderName;
1388
+ toast.showMessage({
1389
+ title: i18n.baseText("folders.rename.success.message", {
1390
+ interpolate: { folderName: newFolderName }
1391
+ }),
1392
+ type: "success"
1393
+ });
1394
+ await fetchWorkflows();
1395
+ telemetry.track("User renamed folder", {
1396
+ folder_id: folderId
1397
+ });
1398
+ } catch (error) {
1399
+ toast.showError(error, i18n.baseText("folders.rename.error.title"));
1365
1400
  }
1366
1401
  }
1367
1402
  };
@@ -1369,12 +1404,106 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1369
1404
  if (!route.params.projectId) return;
1370
1405
  const currentParent = currentFolder.value?.name || projectName.value;
1371
1406
  if (!currentParent) return;
1372
- await createFolder2({
1407
+ await createFolder({
1373
1408
  id: route.params.folderId ?? "-1",
1374
1409
  name: currentParent,
1375
1410
  type: currentFolder.value ? "folder" : "project"
1376
1411
  });
1377
1412
  };
1413
+ const deleteFolder = async (folderId, workflowCount, subFolderCount) => {
1414
+ if (subFolderCount || workflowCount) {
1415
+ uiStore.openDeleteFolderModal(folderId, workflowListEventBus, {
1416
+ workflowCount,
1417
+ subFolderCount
1418
+ });
1419
+ } else {
1420
+ await foldersStore.deleteFolder(route.params.projectId, folderId);
1421
+ toast.showMessage({
1422
+ title: i18n.baseText("folders.delete.success.message"),
1423
+ type: "success"
1424
+ });
1425
+ await onFolderDeleted({ folderId, workflowCount, folderCount: subFolderCount });
1426
+ }
1427
+ };
1428
+ const moveFolder = async (payload) => {
1429
+ if (!route.params.projectId) return;
1430
+ try {
1431
+ await foldersStore.moveFolder(
1432
+ route.params.projectId,
1433
+ payload.folder.id,
1434
+ payload.newParent.id
1435
+ );
1436
+ const isCurrentFolder = currentFolderId.value === payload.folder.id;
1437
+ const newFolderURL = router.resolve({
1438
+ name: VIEWS.PROJECTS_FOLDERS,
1439
+ params: { projectId: route.params.projectId, folderId: payload.newParent.id }
1440
+ }).href;
1441
+ if (isCurrentFolder) {
1442
+ void router.push(newFolderURL);
1443
+ } else {
1444
+ toast.showToast({
1445
+ title: i18n.baseText("folders.move.success.title"),
1446
+ message: i18n.baseText("folders.move.success.message", {
1447
+ interpolate: { folderName: payload.folder.name, newFolderName: payload.newParent.name }
1448
+ }),
1449
+ onClick: (event) => {
1450
+ if (event?.target instanceof HTMLAnchorElement) {
1451
+ event.preventDefault();
1452
+ void router.push(newFolderURL);
1453
+ }
1454
+ },
1455
+ type: "success"
1456
+ });
1457
+ await fetchWorkflows();
1458
+ }
1459
+ } catch (error) {
1460
+ toast.showError(error, i18n.baseText("folders.move.error.title"));
1461
+ }
1462
+ };
1463
+ const moveWorkflowToFolder = async (payload) => {
1464
+ uiStore.openMoveToFolderModal(
1465
+ "workflow",
1466
+ { id: payload.id, name: payload.name, parentFolderId: payload.parentFolderId },
1467
+ workflowListEventBus
1468
+ );
1469
+ };
1470
+ const onWorkflowMoved = async (payload) => {
1471
+ if (!route.params.projectId) return;
1472
+ try {
1473
+ const newFolderURL = router.resolve({
1474
+ name: VIEWS.PROJECTS_FOLDERS,
1475
+ params: { projectId: route.params.projectId, folderId: payload.newParent.id }
1476
+ }).href;
1477
+ const workflowResource = workflowsAndFolders.value.find(
1478
+ (resource) => resource.id === payload.workflow.id
1479
+ );
1480
+ await workflowsStore.updateWorkflow(payload.workflow.id, {
1481
+ parentFolderId: payload.newParent.id,
1482
+ versionId: workflowResource?.versionId
1483
+ });
1484
+ await fetchWorkflows();
1485
+ toast.showToast({
1486
+ title: i18n.baseText("folders.move.workflow.success.title"),
1487
+ message: i18n.baseText("folders.move.workflow.success.message", {
1488
+ interpolate: { workflowName: payload.workflow.name, newFolderName: payload.newParent.name }
1489
+ }),
1490
+ onClick: (event) => {
1491
+ if (event?.target instanceof HTMLAnchorElement) {
1492
+ event.preventDefault();
1493
+ void router.push(newFolderURL);
1494
+ }
1495
+ },
1496
+ type: "success"
1497
+ });
1498
+ telemetry.track("User moved content", {
1499
+ workflow_id: payload.workflow.id,
1500
+ source_folder_id: payload.workflow.oldParentId,
1501
+ destination_folder_id: payload.newParent.id
1502
+ });
1503
+ } catch (error) {
1504
+ toast.showError(error, i18n.baseText("folders.move.workflow.error.title"));
1505
+ }
1506
+ };
1378
1507
  return (_ctx, _cache) => {
1379
1508
  const _component_N8nButton = resolveComponent("N8nButton");
1380
1509
  const _component_N8nTooltip = resolveComponent("N8nTooltip");
@@ -1401,6 +1530,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1401
1530
  "custom-page-size": unref(DEFAULT_WORKFLOW_PAGE_SIZE),
1402
1531
  "total-items": unref(workflowsStore).totalWorkflowCount,
1403
1532
  "dont-perform-sorting-and-filtering": true,
1533
+ "has-empty-state": unref(foldersStore).totalWorkflowCount === 0 && !currentFolderId.value,
1404
1534
  "onClick:add": addWorkflow,
1405
1535
  "onUpdate:search": onSearchUpdated,
1406
1536
  "onUpdate:currentPage": setCurrentPage,
@@ -1459,7 +1589,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1459
1589
  }, null, 8, ["loading"])
1460
1590
  ], 2)) : showFolders.value && currentFolder.value ? (openBlock(), createElementBlock("div", {
1461
1591
  key: 1,
1462
- class: normalizeClass(_ctx.$style["breadcrumbs-container"])
1592
+ class: normalizeClass(_ctx.$style["breadcrumbs-container"]),
1593
+ "data-test-id": "main-breadcrumbs"
1463
1594
  }, [
1464
1595
  createVNode(_component_FolderBreadcrumbs, {
1465
1596
  breadcrumbs: mainBreadcrumbs.value,
@@ -1474,23 +1605,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1474
1605
  key: 0,
1475
1606
  data,
1476
1607
  actions: folderCardActions.value,
1477
- breadcrumbs: cardBreadcrumbs.value,
1608
+ "read-only": readOnlyEnv.value || !hasPermissionToDeleteFolders.value && !hasPermissionToCreateFolders.value,
1478
1609
  class: "mb-2xs",
1479
1610
  onAction: onFolderCardAction
1480
- }, null, 8, ["data", "actions", "breadcrumbs"])) : (openBlock(), createBlock(WorkflowCard, {
1611
+ }, null, 8, ["data", "actions", "read-only"])) : (openBlock(), createBlock(WorkflowCard, {
1481
1612
  key: 1,
1482
1613
  "data-test-id": "resources-list-item",
1483
1614
  class: "mb-2xs",
1484
1615
  data,
1485
- breadcrumbs: cardBreadcrumbs.value,
1486
1616
  "workflow-list-event-bus": unref(workflowListEventBus),
1487
1617
  "read-only": readOnlyEnv.value,
1488
1618
  "onClick:tag": onClickTag,
1489
1619
  "onWorkflow:deleted": fetchWorkflows,
1490
1620
  "onWorkflow:moved": fetchWorkflows,
1491
1621
  "onWorkflow:duplicated": fetchWorkflows,
1492
- "onWorkflow:activeToggle": onWorkflowActiveToggle
1493
- }, null, 8, ["data", "breadcrumbs", "workflow-list-event-bus", "read-only"]))
1622
+ "onWorkflow:activeToggle": onWorkflowActiveToggle,
1623
+ "onAction:moveToFolder": moveWorkflowToFolder
1624
+ }, null, 8, ["data", "workflow-list-event-bus", "read-only"]))
1494
1625
  ]),
1495
1626
  empty: withCtx(() => [
1496
1627
  createBaseVNode("div", _hoisted_1, [
@@ -1619,7 +1750,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1619
1750
  showFolders.value ? {
1620
1751
  name: "add-button",
1621
1752
  fn: withCtx(() => [
1622
- createVNode(_component_N8nTooltip, { placement: "top" }, {
1753
+ createVNode(_component_N8nTooltip, {
1754
+ placement: "top",
1755
+ disabled: readOnlyEnv.value || !hasPermissionToCreateFolders.value
1756
+ }, {
1623
1757
  content: withCtx(() => [
1624
1758
  createTextVNode(toDisplayString(currentParentName.value ? unref(i18n).baseText("folders.add.to.parent.message", {
1625
1759
  interpolate: { parent: currentParentName.value }
@@ -1632,30 +1766,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
1632
1766
  type: "tertiary",
1633
1767
  "data-test-id": "add-folder-button",
1634
1768
  class: normalizeClass(_ctx.$style["add-folder-button"]),
1769
+ disabled: readOnlyEnv.value || !hasPermissionToCreateFolders.value,
1635
1770
  onClick: createFolderInCurrent
1636
- }, null, 8, ["class"])
1771
+ }, null, 8, ["class", "disabled"])
1637
1772
  ]),
1638
1773
  _: 1
1639
- })
1774
+ }, 8, ["disabled"])
1640
1775
  ]),
1641
1776
  key: "0"
1642
1777
  } : void 0
1643
- ]), 1032, ["filters", "resources", "shareable", "disabled", "resources-refreshing", "custom-page-size", "total-items"]);
1778
+ ]), 1032, ["filters", "resources", "shareable", "disabled", "resources-refreshing", "custom-page-size", "total-items", "has-empty-state"]);
1644
1779
  };
1645
1780
  }
1646
1781
  });
1647
- const actionsContainer = "_actionsContainer_j58pl_123";
1648
- const emptyStateCard = "_emptyStateCard_j58pl_139";
1649
- const emptyStateCardIcon = "_emptyStateCardIcon_j58pl_152";
1782
+ const actionsContainer = "_actionsContainer_12bsx_123";
1783
+ const emptyStateCard = "_emptyStateCard_12bsx_139";
1784
+ const emptyStateCardIcon = "_emptyStateCardIcon_12bsx_152";
1650
1785
  const style0 = {
1651
1786
  actionsContainer,
1652
- "easy-ai-workflow-callout": "_easy-ai-workflow-callout_j58pl_128",
1653
- "callout-trailing-content": "_callout-trailing-content_j58pl_133",
1787
+ "easy-ai-workflow-callout": "_easy-ai-workflow-callout_12bsx_128",
1788
+ "callout-trailing-content": "_callout-trailing-content_12bsx_133",
1654
1789
  emptyStateCard,
1655
1790
  emptyStateCardIcon,
1656
- "add-folder-button": "_add-folder-button_j58pl_161",
1657
- "breadcrumbs-container": "_breadcrumbs-container_j58pl_165",
1658
- "breadcrumbs-loading": "_breadcrumbs-loading_j58pl_170"
1791
+ "add-folder-button": "_add-folder-button_12bsx_161",
1792
+ "breadcrumbs-container": "_breadcrumbs-container_12bsx_165",
1793
+ "breadcrumbs-loading": "_breadcrumbs-loading_12bsx_171"
1659
1794
  };
1660
1795
  const cssModules = {
1661
1796
  "$style": style0