Flowfile 0.5.3__py3-none-any.whl → 0.5.6__py3-none-any.whl

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 (153) hide show
  1. flowfile/__init__.py +16 -0
  2. flowfile/__main__.py +94 -1
  3. flowfile/web/static/assets/{AdminView-49392a9a.js → AdminView-c2c7942b.js} +1 -1
  4. flowfile/web/static/assets/{CloudConnectionView-f13f202b.js → CloudConnectionView-7a3042c6.js} +4 -4
  5. flowfile/web/static/assets/{CloudConnectionView-36bcd6df.css → CloudConnectionView-cf85f943.css} +17 -17
  6. flowfile/web/static/assets/{CloudStorageReader-0023d4a5.js → CloudStorageReader-709c4037.js} +8 -8
  7. flowfile/web/static/assets/{CloudStorageWriter-8e781e11.js → CloudStorageWriter-604c51a8.js} +8 -8
  8. flowfile/web/static/assets/ColumnActionInput-c44b7aee.css +159 -0
  9. flowfile/web/static/assets/ColumnActionInput-d63d6746.js +330 -0
  10. flowfile/web/static/assets/{ColumnSelector-8ad68ea9.js → ColumnSelector-0c8cd1cd.js} +1 -1
  11. flowfile/web/static/assets/ContextMenu-366bf1b4.js +9 -0
  12. flowfile/web/static/assets/ContextMenu-85cf5b44.js +9 -0
  13. flowfile/web/static/assets/ContextMenu-9d28ae6d.js +9 -0
  14. flowfile/web/static/assets/ContextMenu.vue_vue_type_script_setup_true_lang-774c517c.js +59 -0
  15. flowfile/web/static/assets/{CrossJoin-03df6938.js → CrossJoin-38e5b99a.js} +9 -9
  16. flowfile/web/static/assets/{CustomNode-8479239b.js → CustomNode-76e8f3f5.js} +27 -20
  17. flowfile/web/static/assets/CustomNode-edb9b939.css +42 -0
  18. flowfile/web/static/assets/{DatabaseConnectionSettings-869e3efd.js → DatabaseConnectionSettings-38155669.js} +4 -4
  19. flowfile/web/static/assets/{DatabaseConnectionSettings-e91df89a.css → DatabaseConnectionSettings-c20a1e16.css} +22 -20
  20. flowfile/web/static/assets/{DatabaseReader-c58b9552.js → DatabaseReader-2e549c8f.js} +13 -13
  21. flowfile/web/static/assets/{DatabaseReader-36898a00.css → DatabaseReader-5bf8c75b.css} +39 -44
  22. flowfile/web/static/assets/{DatabaseView-d26a9140.js → DatabaseView-dc877c29.js} +2 -2
  23. flowfile/web/static/assets/{DatabaseWriter-217a99f1.css → DatabaseWriter-bdcf2c8b.css} +27 -25
  24. flowfile/web/static/assets/{DatabaseWriter-4d05ddc7.js → DatabaseWriter-ffb91864.js} +12 -12
  25. flowfile/web/static/assets/{DesignerView-a6d0ee84.css → DesignerView-71d4e9a1.css} +429 -376
  26. flowfile/web/static/assets/{DesignerView-e6f5c0e8.js → DesignerView-a4466dab.js} +338 -183
  27. flowfile/web/static/assets/{DocumentationView-2e78ef1b.js → DocumentationView-979afc84.js} +3 -3
  28. flowfile/web/static/assets/{DocumentationView-fd46c656.css → DocumentationView-9ea6e871.css} +9 -9
  29. flowfile/web/static/assets/{ExploreData-7b54caca.js → ExploreData-e4b92aaf.js} +7 -7
  30. flowfile/web/static/assets/{ExternalSource-47ab05a3.css → ExternalSource-7ac7373f.css} +17 -17
  31. flowfile/web/static/assets/{ExternalSource-3fa399b2.js → ExternalSource-d08e7227.js} +9 -9
  32. flowfile/web/static/assets/{Filter-8cbbdbf3.js → Filter-7add806d.js} +9 -9
  33. flowfile/web/static/assets/{Formula-aac42b1e.js → Formula-36ab24d2.js} +9 -9
  34. flowfile/web/static/assets/{FuzzyMatch-cd9bbfca.js → FuzzyMatch-cc01bb04.js} +10 -10
  35. flowfile/web/static/assets/{GraphSolver-c24dec17.css → GraphSolver-4b4d7db9.css} +4 -4
  36. flowfile/web/static/assets/{GraphSolver-c7e6780e.js → GraphSolver-4fb98f3b.js} +11 -11
  37. flowfile/web/static/assets/GroupBy-5792782d.css +9 -0
  38. flowfile/web/static/assets/{GroupBy-93c5d22b.js → GroupBy-b3c8f429.js} +9 -9
  39. flowfile/web/static/assets/{Join-a19b2de2.js → Join-096b7b26.js} +10 -10
  40. flowfile/web/static/assets/{LoginView-0df4ed0a.js → LoginView-c33a246a.js} +1 -1
  41. flowfile/web/static/assets/{ManualInput-3702e677.css → ManualInput-39111f19.css} +48 -48
  42. flowfile/web/static/assets/{ManualInput-8d3374b2.js → ManualInput-7307e9b1.js} +55 -13
  43. flowfile/web/static/assets/{MultiSelect-ad1b6243.js → MultiSelect-14822c48.js} +2 -2
  44. flowfile/web/static/assets/{MultiSelect.vue_vue_type_script_setup_true_lang-e278950d.js → MultiSelect.vue_vue_type_script_setup_true_lang-90c4d340.js} +1 -1
  45. flowfile/web/static/assets/{NodeDesigner-40b647c9.js → NodeDesigner-5036c392.js} +171 -69
  46. flowfile/web/static/assets/{NodeDesigner-5f53be3f.css → NodeDesigner-94cd4dd3.css} +190 -190
  47. flowfile/web/static/assets/{NumericInput-7100234c.js → NumericInput-15cf3b72.js} +2 -2
  48. flowfile/web/static/assets/{NumericInput.vue_vue_type_script_setup_true_lang-5130219f.js → NumericInput.vue_vue_type_script_setup_true_lang-91e679d7.js} +1 -1
  49. flowfile/web/static/assets/{Output-f5efd2aa.js → Output-1f8ed42c.js} +13 -12
  50. flowfile/web/static/assets/{Output-35e97000.css → Output-692dd25d.css} +10 -10
  51. flowfile/web/static/assets/{Pivot-d981d23c.js → Pivot-0e153f4e.js} +10 -10
  52. flowfile/web/static/assets/{PivotValidation-63de1f73.js → PivotValidation-5a4f7c79.js} +1 -1
  53. flowfile/web/static/assets/{PivotValidation-39386e95.js → PivotValidation-81ec2a33.js} +1 -1
  54. flowfile/web/static/assets/{PolarsCode-f9d69217.js → PolarsCode-a39f15ac.js} +7 -7
  55. flowfile/web/static/assets/PopOver-ddcfe4f6.js +138 -0
  56. flowfile/web/static/assets/{Read-aec2e377.js → Read-39b63932.js} +15 -14
  57. flowfile/web/static/assets/{Read-36e7bd51.css → Read-90f366bc.css} +13 -13
  58. flowfile/web/static/assets/{RecordCount-78ed6845.js → RecordCount-e9048ccd.js} +6 -6
  59. flowfile/web/static/assets/{RecordId-2156e890.js → RecordId-ad02521d.js} +9 -9
  60. flowfile/web/static/assets/{SQLQueryComponent-48c72f5b.js → SQLQueryComponent-2eeecf0b.js} +3 -3
  61. flowfile/web/static/assets/SQLQueryComponent-edb90b98.css +29 -0
  62. flowfile/web/static/assets/{Sample-1352ca74.js → Sample-9a68c23d.js} +6 -6
  63. flowfile/web/static/assets/{SecretSelector-22b5ff89.js → SecretSelector-2429f35a.js} +2 -2
  64. flowfile/web/static/assets/{SecretsView-17df66ee.js → SecretsView-c6afc915.js} +2 -2
  65. flowfile/web/static/assets/{Select-0aee4c54.js → Select-fcd002b6.js} +9 -9
  66. flowfile/web/static/assets/{SettingsSection-cd341bb6.js → SettingsSection-5ce15962.js} +1 -1
  67. flowfile/web/static/assets/{SettingsSection-0784e157.js → SettingsSection-c6b1362c.js} +1 -1
  68. flowfile/web/static/assets/{SettingsSection-f2002a6d.js → SettingsSection-cebb91d5.js} +1 -1
  69. flowfile/web/static/assets/SetupView-2d12e01f.js +160 -0
  70. flowfile/web/static/assets/SetupView-ec26f76a.css +230 -0
  71. flowfile/web/static/assets/{SingleSelect-460cc0ea.js → SingleSelect-b67de4eb.js} +2 -2
  72. flowfile/web/static/assets/{SingleSelect.vue_vue_type_script_setup_true_lang-30741bb2.js → SingleSelect.vue_vue_type_script_setup_true_lang-eedb70eb.js} +1 -1
  73. flowfile/web/static/assets/{SliderInput-5d926864.js → SliderInput-fd8134ac.js} +1 -1
  74. flowfile/web/static/assets/Sort-4abb7fae.css +9 -0
  75. flowfile/web/static/assets/{Sort-3cdc971b.js → Sort-c005a573.js} +9 -9
  76. flowfile/web/static/assets/{TextInput-a2d0bfbd.js → TextInput-1bb31dab.js} +2 -2
  77. flowfile/web/static/assets/{TextInput.vue_vue_type_script_setup_true_lang-abad1ca2.js → TextInput.vue_vue_type_script_setup_true_lang-a51fe730.js} +1 -1
  78. flowfile/web/static/assets/{TextToRows-918945f7.js → TextToRows-4f363753.js} +9 -9
  79. flowfile/web/static/assets/{ToggleSwitch-f0ef5196.js → ToggleSwitch-ca0f2e5e.js} +2 -2
  80. flowfile/web/static/assets/{ToggleSwitch.vue_vue_type_script_setup_true_lang-5605c793.js → ToggleSwitch.vue_vue_type_script_setup_true_lang-49aa41d8.js} +1 -1
  81. flowfile/web/static/assets/{UnavailableFields-54d2f518.css → UnavailableFields-394a1f78.css} +13 -13
  82. flowfile/web/static/assets/{UnavailableFields-bdad6144.js → UnavailableFields-f6147968.js} +4 -4
  83. flowfile/web/static/assets/{Union-e8ab8c86.js → Union-c65f17b7.js} +6 -6
  84. flowfile/web/static/assets/Unique-2b705521.css +3 -0
  85. flowfile/web/static/assets/{Unique-8cd4f976.js → Unique-a1d96fb2.js} +12 -12
  86. flowfile/web/static/assets/{Unpivot-710a2948.css → Unpivot-b6ad6427.css} +6 -6
  87. flowfile/web/static/assets/{Unpivot-8da14095.js → Unpivot-c2657ff3.js} +11 -11
  88. flowfile/web/static/assets/{UnpivotValidation-6f7d89ff.js → UnpivotValidation-28e29a3b.js} +1 -1
  89. flowfile/web/static/assets/{VueGraphicWalker-3fb312e1.js → VueGraphicWalker-2fc3ddd4.js} +1 -1
  90. flowfile/web/static/assets/{api-24483f0d.js → api-df48ec50.js} +1 -1
  91. flowfile/web/static/assets/{api-8b81fa73.js → api-ee542cf7.js} +1 -1
  92. flowfile/web/static/assets/{dropDown-3d8dc5fa.css → dropDown-1d6acbd9.css} +26 -26
  93. flowfile/web/static/assets/{dropDown-ac0fda9d.js → dropDown-7576a76a.js} +3 -3
  94. flowfile/web/static/assets/{fullEditor-5497a84a.js → fullEditor-7583bef5.js} +3 -3
  95. flowfile/web/static/assets/{fullEditor-a0be62b3.css → fullEditor-fe9f7e18.css} +3 -3
  96. flowfile/web/static/assets/{genericNodeSettings-99014e1d.js → genericNodeSettings-0155288b.js} +2 -3
  97. flowfile/web/static/assets/{index-3ba44389.js → index-057d770d.js} +2 -2
  98. flowfile/web/static/assets/{index-07dda503.js → index-aeec439d.js} +1 -1
  99. flowfile/web/static/assets/{index-fb6493ae.js → index-ca6799de.js} +2293 -196
  100. flowfile/web/static/assets/{index-e6289dd0.css → index-d60c9dd4.css} +560 -10
  101. flowfile/web/static/assets/nodeInput-d478b9ac.js +2 -0
  102. flowfile/web/static/assets/{outputCsv-8f8ba42d.js → outputCsv-c492b15e.js} +3 -3
  103. flowfile/web/static/assets/outputCsv-cc84e09f.css +2499 -0
  104. flowfile/web/static/assets/{outputExcel-393f4fef.js → outputExcel-13bfa10f.js} +1 -1
  105. flowfile/web/static/assets/{outputParquet-07c81f65.js → outputParquet-9be1523a.js} +1 -1
  106. flowfile/web/static/assets/{readCsv-07f6d9ad.js → readCsv-5a49a8c9.js} +1 -1
  107. flowfile/web/static/assets/{readExcel-ed69bc8f.js → readExcel-27c30ad8.js} +3 -3
  108. flowfile/web/static/assets/{readParquet-e3ed4528.js → readParquet-446bde68.js} +1 -1
  109. flowfile/web/static/assets/{secrets.api-002e7d7e.js → secrets.api-34431884.js} +1 -1
  110. flowfile/web/static/assets/{selectDynamic-80b92899.js → selectDynamic-5754a2b1.js} +2 -3
  111. flowfile/web/static/assets/{vue-codemirror.esm-0965f39f.js → vue-codemirror.esm-8f46fb36.js} +1 -1
  112. flowfile/web/static/assets/{vue-content-loader.es-c506ad97.js → vue-content-loader.es-808fe33a.js} +1 -1
  113. flowfile/web/static/index.html +2 -2
  114. {flowfile-0.5.3.dist-info → flowfile-0.5.6.dist-info}/METADATA +2 -2
  115. {flowfile-0.5.3.dist-info → flowfile-0.5.6.dist-info}/RECORD +139 -134
  116. flowfile_core/auth/secrets.py +56 -13
  117. flowfile_core/fileExplorer/funcs.py +26 -4
  118. flowfile_core/flowfile/code_generator/__init__.py +11 -0
  119. flowfile_core/flowfile/code_generator/code_generator.py +347 -2
  120. flowfile_core/flowfile/flow_data_engine/flow_data_engine.py +13 -1
  121. flowfile_core/flowfile/flow_data_engine/subprocess_operations/subprocess_operations.py +12 -0
  122. flowfile_core/flowfile/flow_graph.py +2 -0
  123. flowfile_core/flowfile/flow_node/flow_node.py +52 -28
  124. flowfile_core/flowfile/node_designer/__init__.py +4 -0
  125. flowfile_core/flowfile/node_designer/ui_components.py +144 -1
  126. flowfile_core/main.py +2 -4
  127. flowfile_core/routes/public.py +43 -1
  128. flowfile_core/schemas/cloud_storage_schemas.py +39 -15
  129. flowfile_core/secret_manager/secret_manager.py +107 -6
  130. flowfile_frame/__init__.py +11 -0
  131. flowfile_frame/database/__init__.py +36 -0
  132. flowfile_frame/database/connection_manager.py +205 -0
  133. flowfile_frame/database/frame_helpers.py +249 -0
  134. flowfile_worker/configs.py +31 -15
  135. flowfile_worker/secrets.py +105 -15
  136. flowfile_worker/spawner.py +10 -6
  137. flowfile/web/static/assets/ContextMenu-26d4dd27.css +0 -26
  138. flowfile/web/static/assets/ContextMenu-31ee57f0.js +0 -41
  139. flowfile/web/static/assets/ContextMenu-69a74055.js +0 -41
  140. flowfile/web/static/assets/ContextMenu-8e2051c6.js +0 -41
  141. flowfile/web/static/assets/ContextMenu-8ec1729e.css +0 -26
  142. flowfile/web/static/assets/ContextMenu-9b310c60.css +0 -26
  143. flowfile/web/static/assets/CustomNode-59e99a86.css +0 -32
  144. flowfile/web/static/assets/GroupBy-be7ac0bf.css +0 -51
  145. flowfile/web/static/assets/PopOver-b22f049e.js +0 -939
  146. flowfile/web/static/assets/SQLQueryComponent-1c2f26b4.css +0 -27
  147. flowfile/web/static/assets/Sort-8a871341.css +0 -51
  148. flowfile/web/static/assets/Unique-9fb2f567.css +0 -51
  149. flowfile/web/static/assets/nodeInput-0eb13f1a.js +0 -2
  150. flowfile/web/static/assets/outputCsv-b9a072af.css +0 -2499
  151. {flowfile-0.5.3.dist-info → flowfile-0.5.6.dist-info}/WHEEL +0 -0
  152. {flowfile-0.5.3.dist-info → flowfile-0.5.6.dist-info}/entry_points.txt +0 -0
  153. {flowfile-0.5.3.dist-info → flowfile-0.5.6.dist-info}/licenses/LICENSE +0 -0
@@ -10552,12 +10552,12 @@ const _export_sfc = (sfc, props) => {
10552
10552
  }
10553
10553
  return target;
10554
10554
  };
10555
- const _sfc_main$7 = {};
10556
- const _hoisted_1$X = { class: "logo" };
10555
+ const _sfc_main$a = {};
10556
+ const _hoisted_1$_ = { class: "logo" };
10557
10557
  function _sfc_render$1(_ctx, _cache) {
10558
- return openBlock(), createElementBlock("div", _hoisted_1$X);
10558
+ return openBlock(), createElementBlock("div", _hoisted_1$_);
10559
10559
  }
10560
- const Header = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["render", _sfc_render$1]]);
10560
+ const Header = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["render", _sfc_render$1]]);
10561
10561
  const NavigationRoutes = {
10562
10562
  root: {
10563
10563
  name: "/",
@@ -15633,7 +15633,7 @@ if (__INTLIFY_PROD_DEVTOOLS__) {
15633
15633
  target.__INTLIFY__ = true;
15634
15634
  setDevToolsHook(target.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__);
15635
15635
  }
15636
- const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15636
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
15637
15637
  __name: "MenuAccordion",
15638
15638
  props: {
15639
15639
  items: { default: () => [] },
@@ -15742,14 +15742,14 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
15742
15742
  }
15743
15743
  });
15744
15744
  const MenuAccordion_vue_vue_type_style_index_0_scoped_04b48d7c_lang = "";
15745
- const MenuAccordion = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__scopeId", "data-v-04b48d7c"]]);
15745
+ const MenuAccordion = /* @__PURE__ */ _export_sfc(_sfc_main$9, [["__scopeId", "data-v-04b48d7c"]]);
15746
15746
  const _imports_1 = "/images/flowfile.svg";
15747
- const _hoisted_1$W = ["alt"];
15748
- const _hoisted_2$N = {
15747
+ const _hoisted_1$Z = ["alt"];
15748
+ const _hoisted_2$P = {
15749
15749
  key: 0,
15750
15750
  class: "app-name"
15751
15751
  };
15752
- const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15752
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
15753
15753
  __name: "Logo",
15754
15754
  props: {
15755
15755
  width: {
@@ -15793,14 +15793,14 @@ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
15793
15793
  src: _imports_1,
15794
15794
  alt: __props.altText,
15795
15795
  style: normalizeStyle({ width: __props.width, height: __props.height })
15796
- }, null, 12, _hoisted_1$W),
15797
- __props.appName ? (openBlock(), createElementBlock("span", _hoisted_2$N, toDisplayString$1(__props.appName), 1)) : createCommentVNode("", true)
15796
+ }, null, 12, _hoisted_1$Z),
15797
+ __props.appName ? (openBlock(), createElementBlock("span", _hoisted_2$P, toDisplayString$1(__props.appName), 1)) : createCommentVNode("", true)
15798
15798
  ], 2);
15799
15799
  };
15800
15800
  }
15801
15801
  });
15802
15802
  const Logo_vue_vue_type_style_index_0_scoped_a736f53d_lang = "";
15803
- const Logo = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-a736f53d"]]);
15803
+ const Logo = /* @__PURE__ */ _export_sfc(_sfc_main$8, [["__scopeId", "data-v-a736f53d"]]);
15804
15804
  const THEME_STORAGE_KEY = "flowfile-theme-preference";
15805
15805
  function getSystemPreference() {
15806
15806
  if (typeof window !== "undefined" && window.matchMedia) {
@@ -15908,16 +15908,16 @@ function useTheme() {
15908
15908
  toggleTheme
15909
15909
  };
15910
15910
  }
15911
- const _hoisted_1$V = ["title"];
15912
- const _hoisted_2$M = {
15911
+ const _hoisted_1$Y = ["title"];
15912
+ const _hoisted_2$O = {
15913
15913
  key: 0,
15914
15914
  class: "fas fa-sun"
15915
15915
  };
15916
- const _hoisted_3$F = {
15916
+ const _hoisted_3$H = {
15917
15917
  key: 1,
15918
15918
  class: "fas fa-moon"
15919
15919
  };
15920
- const _sfc_main$4 = /* @__PURE__ */ defineComponent({
15920
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
15921
15921
  __name: "ThemeToggle",
15922
15922
  setup(__props) {
15923
15923
  const { isDark, toggleTheme } = useTheme();
@@ -15928,13 +15928,13 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
15928
15928
  onClick: _cache[0] || (_cache[0] = //@ts-ignore
15929
15929
  (...args) => unref(toggleTheme) && unref(toggleTheme)(...args))
15930
15930
  }, [
15931
- unref(isDark) ? (openBlock(), createElementBlock("i", _hoisted_2$M)) : (openBlock(), createElementBlock("i", _hoisted_3$F))
15932
- ], 8, _hoisted_1$V);
15931
+ unref(isDark) ? (openBlock(), createElementBlock("i", _hoisted_2$O)) : (openBlock(), createElementBlock("i", _hoisted_3$H))
15932
+ ], 8, _hoisted_1$Y);
15933
15933
  };
15934
15934
  }
15935
15935
  });
15936
15936
  const ThemeToggle_vue_vue_type_style_index_0_scoped_c436efe9_lang = "";
15937
- const ThemeToggle = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-c436efe9"]]);
15937
+ const ThemeToggle = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__scopeId", "data-v-c436efe9"]]);
15938
15938
  function bind(fn2, thisArg) {
15939
15939
  return function wrap() {
15940
15940
  return fn2.apply(thisArg, arguments);
@@ -18325,12 +18325,26 @@ class AuthService {
18325
18325
  __publicField(this, "token", ref(null));
18326
18326
  __publicField(this, "tokenExpiration", ref(null));
18327
18327
  __publicField(this, "isElectronMode", ref(false));
18328
+ __publicField(this, "modeInitialized", false);
18328
18329
  __publicField(this, "refreshPromise", null);
18329
18330
  __publicField(this, "currentUsername", ref(null));
18330
18331
  this.isElectronMode.value = this.detectElectronMode();
18331
18332
  this.clearStoredTokens();
18332
18333
  this.loadStoredToken();
18333
18334
  }
18335
+ /**
18336
+ * Update electron mode based on backend status.
18337
+ * This is called when we get the mode from /health/status endpoint.
18338
+ * In "flowfile run ui" mode, electronAPI won't exist but backend mode is "electron".
18339
+ */
18340
+ setModeFromBackend(mode) {
18341
+ if (!this.modeInitialized) {
18342
+ if (!this.detectElectronMode()) {
18343
+ this.isElectronMode.value = mode === "electron";
18344
+ }
18345
+ this.modeInitialized = true;
18346
+ }
18347
+ }
18334
18348
  loadStoredToken() {
18335
18349
  const savedToken = localStorage.getItem("auth_token");
18336
18350
  const savedExpiration = localStorage.getItem("auth_token_expiration");
@@ -18487,6 +18501,7 @@ class AuthService {
18487
18501
  localStorage.removeItem("auth_username");
18488
18502
  }
18489
18503
  }
18504
+ const authService = new AuthService();
18490
18505
  axios$1.interceptors.response.use(
18491
18506
  (response) => response,
18492
18507
  async (error) => {
@@ -18496,13 +18511,11 @@ axios$1.interceptors.response.use(
18496
18511
  const isAuthRequest = requestUrl.includes("/auth/token") || requestUrl.includes("/auth/");
18497
18512
  if (((_a = error.response) == null ? void 0 : _a.status) === 401 && !originalRequest._retry && !isAuthRequest) {
18498
18513
  originalRequest._retry = true;
18499
- const isElectron = !!window.electronAPI;
18500
- if (isElectron) {
18514
+ if (authService.isInElectronMode()) {
18501
18515
  localStorage.removeItem("auth_token");
18502
18516
  localStorage.removeItem("auth_token_expiration");
18503
- const authInstance = new AuthService();
18504
- await authInstance.initialize();
18505
- const newToken = await authInstance.getToken();
18517
+ await authService.initialize();
18518
+ const newToken = await authService.getToken();
18506
18519
  if (newToken) {
18507
18520
  originalRequest.headers["Authorization"] = `Bearer ${newToken}`;
18508
18521
  return axios$1(originalRequest);
@@ -18519,7 +18532,6 @@ axios$1.interceptors.response.use(
18519
18532
  return Promise.reject(error);
18520
18533
  }
18521
18534
  );
18522
- const authService = new AuthService();
18523
18535
  const useAuthStore = /* @__PURE__ */ defineStore("auth", {
18524
18536
  state: () => ({
18525
18537
  user: null,
@@ -18608,20 +18620,20 @@ const useAuthStore = /* @__PURE__ */ defineStore("auth", {
18608
18620
  }
18609
18621
  }
18610
18622
  });
18611
- const _hoisted_1$U = { class: "sidebar" };
18612
- const _hoisted_2$L = { class: "center-container" };
18613
- const _hoisted_3$E = { class: "sidebar-container" };
18614
- const _hoisted_4$v = { class: "sidebar-footer" };
18615
- const _hoisted_5$q = {
18623
+ const _hoisted_1$X = { class: "sidebar" };
18624
+ const _hoisted_2$N = { class: "center-container" };
18625
+ const _hoisted_3$G = { class: "sidebar-container" };
18626
+ const _hoisted_4$x = { class: "sidebar-footer" };
18627
+ const _hoisted_5$s = {
18616
18628
  class: "footer-btn-wrapper",
18617
18629
  "data-tooltip": "Toggle theme"
18618
18630
  };
18619
- const _hoisted_6$l = {
18631
+ const _hoisted_6$n = {
18620
18632
  key: 0,
18621
18633
  class: "footer-btn-wrapper",
18622
18634
  "data-tooltip": "Sign out"
18623
18635
  };
18624
- const _sfc_main$3 = /* @__PURE__ */ defineComponent({
18636
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
18625
18637
  __name: "Sidebar",
18626
18638
  props: {
18627
18639
  isCollapse: {
@@ -18648,25 +18660,25 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
18648
18660
  router2.push({ name: "login" });
18649
18661
  };
18650
18662
  return (_ctx, _cache) => {
18651
- return openBlock(), createElementBlock("div", _hoisted_1$U, [
18652
- createBaseVNode("div", _hoisted_2$L, [
18663
+ return openBlock(), createElementBlock("div", _hoisted_1$X, [
18664
+ createBaseVNode("div", _hoisted_2$N, [
18653
18665
  createVNode(Logo, {
18654
18666
  width: "50px",
18655
18667
  "app-name": "",
18656
18668
  "position-app-name": "left"
18657
18669
  })
18658
18670
  ]),
18659
- createBaseVNode("div", _hoisted_3$E, [
18671
+ createBaseVNode("div", _hoisted_3$G, [
18660
18672
  createVNode(MenuAccordion, {
18661
18673
  items: items.value,
18662
18674
  "is-collapse": true
18663
18675
  }, null, 8, ["items"])
18664
18676
  ]),
18665
- createBaseVNode("div", _hoisted_4$v, [
18666
- createBaseVNode("div", _hoisted_5$q, [
18677
+ createBaseVNode("div", _hoisted_4$x, [
18678
+ createBaseVNode("div", _hoisted_5$s, [
18667
18679
  createVNode(ThemeToggle)
18668
18680
  ]),
18669
- showLogout.value ? (openBlock(), createElementBlock("div", _hoisted_6$l, [
18681
+ showLogout.value ? (openBlock(), createElementBlock("div", _hoisted_6$n, [
18670
18682
  createBaseVNode("button", {
18671
18683
  class: "logout-button",
18672
18684
  onClick: handleLogout
@@ -18680,23 +18692,23 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
18680
18692
  }
18681
18693
  });
18682
18694
  const Sidebar_vue_vue_type_style_index_0_lang = "";
18683
- const _hoisted_1$T = { class: "modal-container" };
18684
- const _hoisted_2$K = { class: "modal-header" };
18685
- const _hoisted_3$D = { class: "modal-title" };
18686
- const _hoisted_4$u = { class: "modal-content" };
18687
- const _hoisted_5$p = {
18695
+ const _hoisted_1$W = { class: "modal-container" };
18696
+ const _hoisted_2$M = { class: "modal-header" };
18697
+ const _hoisted_3$F = { class: "modal-title" };
18698
+ const _hoisted_4$w = { class: "modal-content" };
18699
+ const _hoisted_5$r = {
18688
18700
  key: 0,
18689
18701
  class: "warning-text"
18690
18702
  };
18691
- const _hoisted_6$k = { class: "form-field" };
18692
- const _hoisted_7$d = { class: "password-field" };
18693
- const _hoisted_8$9 = ["type"];
18694
- const _hoisted_9$8 = {
18703
+ const _hoisted_6$m = { class: "form-field" };
18704
+ const _hoisted_7$e = { class: "password-field" };
18705
+ const _hoisted_8$a = ["type"];
18706
+ const _hoisted_9$9 = {
18695
18707
  key: 0,
18696
18708
  class: "form-error"
18697
18709
  };
18698
- const _hoisted_10$8 = { class: "form-field" };
18699
- const _hoisted_11$5 = { class: "password-field" };
18710
+ const _hoisted_10$9 = { class: "form-field" };
18711
+ const _hoisted_11$6 = { class: "password-field" };
18700
18712
  const _hoisted_12$5 = ["type"];
18701
18713
  const _hoisted_13$3 = {
18702
18714
  key: 0,
@@ -18721,7 +18733,7 @@ const _hoisted_23$1 = {
18721
18733
  key: 0,
18722
18734
  class: "fa-solid fa-spinner fa-spin"
18723
18735
  };
18724
- const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18736
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
18725
18737
  __name: "ChangePasswordModal",
18726
18738
  props: {
18727
18739
  show: { type: Boolean },
@@ -18833,9 +18845,9 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18833
18845
  class: "modal-overlay",
18834
18846
  onClick: withModifiers(handleBackdropClick, ["self"])
18835
18847
  }, [
18836
- createBaseVNode("div", _hoisted_1$T, [
18837
- createBaseVNode("div", _hoisted_2$K, [
18838
- createBaseVNode("h3", _hoisted_3$D, [
18848
+ createBaseVNode("div", _hoisted_1$W, [
18849
+ createBaseVNode("div", _hoisted_2$M, [
18850
+ createBaseVNode("h3", _hoisted_3$F, [
18839
18851
  _cache[6] || (_cache[6] = createBaseVNode("i", { class: "fa-solid fa-key" }, null, -1)),
18840
18852
  createTextVNode(" " + toDisplayString$1(_ctx.isForced ? "Password Change Required" : "Change Password"), 1)
18841
18853
  ]),
@@ -18848,18 +18860,18 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18848
18860
  createBaseVNode("i", { class: "fa-solid fa-times" }, null, -1)
18849
18861
  ]))) : createCommentVNode("", true)
18850
18862
  ]),
18851
- createBaseVNode("div", _hoisted_4$u, [
18852
- _ctx.isForced ? (openBlock(), createElementBlock("p", _hoisted_5$p, " You must change your password before continuing. This is required for security purposes. ")) : createCommentVNode("", true),
18863
+ createBaseVNode("div", _hoisted_4$w, [
18864
+ _ctx.isForced ? (openBlock(), createElementBlock("p", _hoisted_5$r, " You must change your password before continuing. This is required for security purposes. ")) : createCommentVNode("", true),
18853
18865
  createBaseVNode("form", {
18854
18866
  class: "form",
18855
18867
  onSubmit: withModifiers(handleSubmit, ["prevent"])
18856
18868
  }, [
18857
- createBaseVNode("div", _hoisted_6$k, [
18869
+ createBaseVNode("div", _hoisted_6$m, [
18858
18870
  _cache[8] || (_cache[8] = createBaseVNode("label", {
18859
18871
  for: "current-password",
18860
18872
  class: "form-label"
18861
18873
  }, "Current Password", -1)),
18862
- createBaseVNode("div", _hoisted_7$d, [
18874
+ createBaseVNode("div", _hoisted_7$e, [
18863
18875
  withDirectives(createBaseVNode("input", {
18864
18876
  id: "current-password",
18865
18877
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => formData.value.currentPassword = $event),
@@ -18867,7 +18879,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18867
18879
  class: normalizeClass(["form-input", { "is-error": errors.value.currentPassword }]),
18868
18880
  placeholder: "Enter current password",
18869
18881
  required: ""
18870
- }, null, 10, _hoisted_8$9), [
18882
+ }, null, 10, _hoisted_8$a), [
18871
18883
  [vModelDynamic, formData.value.currentPassword]
18872
18884
  ]),
18873
18885
  createBaseVNode("button", {
@@ -18881,14 +18893,14 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18881
18893
  }, null, 2)
18882
18894
  ])
18883
18895
  ]),
18884
- errors.value.currentPassword ? (openBlock(), createElementBlock("span", _hoisted_9$8, toDisplayString$1(errors.value.currentPassword), 1)) : createCommentVNode("", true)
18896
+ errors.value.currentPassword ? (openBlock(), createElementBlock("span", _hoisted_9$9, toDisplayString$1(errors.value.currentPassword), 1)) : createCommentVNode("", true)
18885
18897
  ]),
18886
- createBaseVNode("div", _hoisted_10$8, [
18898
+ createBaseVNode("div", _hoisted_10$9, [
18887
18899
  _cache[12] || (_cache[12] = createBaseVNode("label", {
18888
18900
  for: "new-password",
18889
18901
  class: "form-label"
18890
18902
  }, "New Password", -1)),
18891
- createBaseVNode("div", _hoisted_11$5, [
18903
+ createBaseVNode("div", _hoisted_11$6, [
18892
18904
  withDirectives(createBaseVNode("input", {
18893
18905
  id: "new-password",
18894
18906
  "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => formData.value.newPassword = $event),
@@ -18994,7 +19006,2041 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
18994
19006
  }
18995
19007
  });
18996
19008
  const ChangePasswordModal_vue_vue_type_style_index_0_scoped_79657dc0_lang = "";
18997
- const ChangePasswordModal = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-79657dc0"]]);
19009
+ const ChangePasswordModal = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-79657dc0"]]);
19010
+ const useTutorialStore = /* @__PURE__ */ defineStore("tutorial", () => {
19011
+ const isActive = ref(false);
19012
+ const currentTutorial = ref(null);
19013
+ const currentStepIndex = ref(0);
19014
+ const isTransitioning = ref(false);
19015
+ const completedTutorials = ref(/* @__PURE__ */ new Set());
19016
+ const tutorialPaused = ref(false);
19017
+ const currentStep = computed(() => {
19018
+ if (!currentTutorial.value || currentStepIndex.value < 0)
19019
+ return null;
19020
+ return currentTutorial.value.steps[currentStepIndex.value] || null;
19021
+ });
19022
+ const totalSteps = computed(() => {
19023
+ var _a;
19024
+ return ((_a = currentTutorial.value) == null ? void 0 : _a.steps.length) ?? 0;
19025
+ });
19026
+ const progress = computed(() => {
19027
+ if (totalSteps.value === 0)
19028
+ return 0;
19029
+ return (currentStepIndex.value + 1) / totalSteps.value * 100;
19030
+ });
19031
+ const isFirstStep = computed(() => currentStepIndex.value === 0);
19032
+ const isLastStep = computed(() => currentStepIndex.value === totalSteps.value - 1);
19033
+ const hasNextStep = computed(() => currentStepIndex.value < totalSteps.value - 1);
19034
+ const hasPrevStep = computed(() => currentStepIndex.value > 0);
19035
+ async function startTutorial(tutorial) {
19036
+ currentTutorial.value = tutorial;
19037
+ currentStepIndex.value = 0;
19038
+ isActive.value = true;
19039
+ tutorialPaused.value = false;
19040
+ const step = currentTutorial.value.steps[0];
19041
+ if (step == null ? void 0 : step.onEnter) {
19042
+ await step.onEnter();
19043
+ }
19044
+ }
19045
+ async function nextStep() {
19046
+ if (!currentTutorial.value || isTransitioning.value)
19047
+ return;
19048
+ if (currentStepIndex.value >= totalSteps.value - 1) {
19049
+ await completeTutorial();
19050
+ return;
19051
+ }
19052
+ isTransitioning.value = true;
19053
+ const currentStepObj = currentStep.value;
19054
+ if (currentStepObj == null ? void 0 : currentStepObj.onExit) {
19055
+ await currentStepObj.onExit();
19056
+ }
19057
+ currentStepIndex.value++;
19058
+ const nextStepObj = currentStep.value;
19059
+ if (nextStepObj == null ? void 0 : nextStepObj.onEnter) {
19060
+ await nextStepObj.onEnter();
19061
+ }
19062
+ isTransitioning.value = false;
19063
+ }
19064
+ async function prevStep() {
19065
+ if (!currentTutorial.value || isTransitioning.value || currentStepIndex.value <= 0)
19066
+ return;
19067
+ isTransitioning.value = true;
19068
+ const currentStepObj = currentStep.value;
19069
+ if (currentStepObj == null ? void 0 : currentStepObj.onExit) {
19070
+ await currentStepObj.onExit();
19071
+ }
19072
+ currentStepIndex.value--;
19073
+ const prevStepObj = currentStep.value;
19074
+ if (prevStepObj == null ? void 0 : prevStepObj.onEnter) {
19075
+ await prevStepObj.onEnter();
19076
+ }
19077
+ isTransitioning.value = false;
19078
+ }
19079
+ async function goToStep(index2) {
19080
+ if (!currentTutorial.value || isTransitioning.value)
19081
+ return;
19082
+ if (index2 < 0 || index2 >= totalSteps.value)
19083
+ return;
19084
+ isTransitioning.value = true;
19085
+ const currentStepObj = currentStep.value;
19086
+ if (currentStepObj == null ? void 0 : currentStepObj.onExit) {
19087
+ await currentStepObj.onExit();
19088
+ }
19089
+ currentStepIndex.value = index2;
19090
+ const newStepObj = currentStep.value;
19091
+ if (newStepObj == null ? void 0 : newStepObj.onEnter) {
19092
+ await newStepObj.onEnter();
19093
+ }
19094
+ isTransitioning.value = false;
19095
+ }
19096
+ async function completeTutorial() {
19097
+ if (currentTutorial.value) {
19098
+ completedTutorials.value.add(currentTutorial.value.id);
19099
+ const lastStep = currentStep.value;
19100
+ if (lastStep == null ? void 0 : lastStep.onExit) {
19101
+ await lastStep.onExit();
19102
+ }
19103
+ }
19104
+ endTutorial();
19105
+ }
19106
+ function endTutorial() {
19107
+ isActive.value = false;
19108
+ currentTutorial.value = null;
19109
+ currentStepIndex.value = 0;
19110
+ isTransitioning.value = false;
19111
+ tutorialPaused.value = false;
19112
+ }
19113
+ function pauseTutorial() {
19114
+ tutorialPaused.value = true;
19115
+ }
19116
+ function resumeTutorial() {
19117
+ tutorialPaused.value = false;
19118
+ }
19119
+ function isTutorialCompleted(tutorialId) {
19120
+ return completedTutorials.value.has(tutorialId);
19121
+ }
19122
+ function resetCompletedTutorials() {
19123
+ completedTutorials.value.clear();
19124
+ }
19125
+ async function onActionCompleted() {
19126
+ if (!currentStep.value)
19127
+ return;
19128
+ if (currentStep.value.action && currentStep.value.action !== "observe") {
19129
+ await nextStep();
19130
+ }
19131
+ }
19132
+ return {
19133
+ // State
19134
+ isActive,
19135
+ currentTutorial,
19136
+ currentStepIndex,
19137
+ isTransitioning,
19138
+ completedTutorials,
19139
+ tutorialPaused,
19140
+ // Computed
19141
+ currentStep,
19142
+ totalSteps,
19143
+ progress,
19144
+ isFirstStep,
19145
+ isLastStep,
19146
+ hasNextStep,
19147
+ hasPrevStep,
19148
+ // Actions
19149
+ startTutorial,
19150
+ nextStep,
19151
+ prevStep,
19152
+ goToStep,
19153
+ completeTutorial,
19154
+ endTutorial,
19155
+ pauseTutorial,
19156
+ resumeTutorial,
19157
+ isTutorialCompleted,
19158
+ resetCompletedTutorials,
19159
+ onActionCompleted
19160
+ };
19161
+ });
19162
+ const FLOW_ID_STORAGE_KEY = "last_flow_id";
19163
+ const useFlowStore = /* @__PURE__ */ defineStore("flow", {
19164
+ state: () => {
19165
+ const savedFlowId = sessionStorage.getItem(FLOW_ID_STORAGE_KEY);
19166
+ const initialFlowId = savedFlowId ? parseInt(savedFlowId) : -1;
19167
+ return {
19168
+ flowId: initialFlowId,
19169
+ vueFlowInstance: null
19170
+ };
19171
+ },
19172
+ getters: {
19173
+ currentFlowId: (state) => state.flowId
19174
+ },
19175
+ actions: {
19176
+ setFlowId(flowId) {
19177
+ this.flowId = flowId;
19178
+ try {
19179
+ sessionStorage.setItem(FLOW_ID_STORAGE_KEY, flowId.toString());
19180
+ } catch (error) {
19181
+ console.warn("Failed to store flow ID in session storage:", error);
19182
+ }
19183
+ },
19184
+ setVueFlowInstance(vueFlowInstance) {
19185
+ this.vueFlowInstance = vueFlowInstance;
19186
+ },
19187
+ getVueFlowInstance() {
19188
+ return this.vueFlowInstance;
19189
+ }
19190
+ }
19191
+ });
19192
+ const flowfileCorebaseURL = "http://localhost:63578/";
19193
+ axios$1.defaults.baseURL = flowfileCorebaseURL;
19194
+ axios$1.defaults.withCredentials = true;
19195
+ axios$1.interceptors.request.use(
19196
+ async (config) => {
19197
+ if (config.headers && config.headers["X-Skip-Auth-Header"]) {
19198
+ delete config.headers["X-Skip-Auth-Header"];
19199
+ return config;
19200
+ }
19201
+ try {
19202
+ const token = await authService.getToken();
19203
+ if (token) {
19204
+ config.headers = config.headers || {};
19205
+ config.headers.Authorization = `Bearer ${token}`;
19206
+ }
19207
+ return config;
19208
+ } catch (error) {
19209
+ console.error("Error in request interceptor:", error);
19210
+ return config;
19211
+ }
19212
+ },
19213
+ (error) => {
19214
+ return Promise.reject(error);
19215
+ }
19216
+ );
19217
+ axios$1.interceptors.response.use(
19218
+ (response) => {
19219
+ return response;
19220
+ },
19221
+ async (error) => {
19222
+ var _a;
19223
+ const originalRequest = error.config;
19224
+ if (((_a = error.response) == null ? void 0 : _a.status) === 401 && !originalRequest._retry) {
19225
+ originalRequest._retry = true;
19226
+ try {
19227
+ await authService.getToken();
19228
+ return axios$1(originalRequest);
19229
+ } catch (refreshError) {
19230
+ console.error("Token refresh failed:", refreshError);
19231
+ authService.logout();
19232
+ return Promise.reject(error);
19233
+ }
19234
+ }
19235
+ return Promise.reject(error);
19236
+ }
19237
+ );
19238
+ class NodeApi {
19239
+ /**
19240
+ * Get node data for a specific node
19241
+ */
19242
+ static async getNodeData(flowId, nodeId) {
19243
+ const response = await axios$1.get("/node", {
19244
+ params: { flow_id: flowId, node_id: nodeId },
19245
+ headers: { accept: "application/json" }
19246
+ });
19247
+ return response.data;
19248
+ }
19249
+ /**
19250
+ * Get table example/preview data for a node
19251
+ */
19252
+ static async getTableExample(flowId, nodeId) {
19253
+ const response = await axios$1.get("/node/data", {
19254
+ params: { flow_id: flowId, node_id: nodeId },
19255
+ headers: { accept: "application/json" }
19256
+ });
19257
+ return response.data;
19258
+ }
19259
+ /**
19260
+ * Get downstream node IDs for a given node
19261
+ */
19262
+ static async getDownstreamNodeIds(flowId, nodeId) {
19263
+ const response = await axios$1.get("/node/downstream_node_ids", {
19264
+ params: { flow_id: flowId, node_id: nodeId },
19265
+ headers: { accept: "application/json" }
19266
+ });
19267
+ return response.data;
19268
+ }
19269
+ /**
19270
+ * Get node description
19271
+ */
19272
+ static async getNodeDescription(flowId, nodeId) {
19273
+ const response = await axios$1.get("/node/description", {
19274
+ params: { node_id: nodeId, flow_id: flowId }
19275
+ });
19276
+ return response.data;
19277
+ }
19278
+ /**
19279
+ * Set/update node description
19280
+ */
19281
+ static async setNodeDescription(flowId, nodeId, description) {
19282
+ const response = await axios$1.post("/node/description/", JSON.stringify(description), {
19283
+ params: { flow_id: flowId, node_id: nodeId },
19284
+ headers: { "Content-Type": "application/json" }
19285
+ });
19286
+ return response.data;
19287
+ }
19288
+ /**
19289
+ * Update node settings directly
19290
+ */
19291
+ static async updateSettingsDirectly(nodeType, inputData) {
19292
+ const response = await axios$1.post("/update_settings/", inputData, {
19293
+ params: { node_type: nodeType }
19294
+ });
19295
+ return response.data;
19296
+ }
19297
+ /**
19298
+ * Update user-defined node settings
19299
+ */
19300
+ static async updateUserDefinedSettings(nodeType, inputData) {
19301
+ const response = await axios$1.post(
19302
+ "/user_defined_components/update_user_defined_node/",
19303
+ inputData,
19304
+ {
19305
+ params: { node_type: nodeType }
19306
+ }
19307
+ );
19308
+ return response.data;
19309
+ }
19310
+ }
19311
+ class ExpressionsApi {
19312
+ /**
19313
+ * Fetch all available expressions overview/documentation
19314
+ */
19315
+ static async getExpressionsOverview() {
19316
+ const response = await axios$1.get("/editor/expression_doc");
19317
+ return response.data;
19318
+ }
19319
+ }
19320
+ const useResultsStore = /* @__PURE__ */ defineStore("results", {
19321
+ state: () => ({
19322
+ runResults: {},
19323
+ runNodeResults: {},
19324
+ runNodeValidations: {},
19325
+ currentRunResult: null,
19326
+ resultVersion: 0
19327
+ }),
19328
+ getters: {
19329
+ getCurrentRunResult: (state) => state.currentRunResult
19330
+ },
19331
+ actions: {
19332
+ // ========== Result Cache Management ==========
19333
+ initializeResultCache(flowId) {
19334
+ if (!this.runNodeResults[flowId]) {
19335
+ this.runNodeResults[flowId] = {};
19336
+ }
19337
+ },
19338
+ setNodeResult(flowId, nodeId, result) {
19339
+ this.initializeResultCache(flowId);
19340
+ this.runNodeResults[flowId][nodeId] = result;
19341
+ },
19342
+ getNodeResult(flowId, nodeId) {
19343
+ var _a;
19344
+ return (_a = this.runNodeResults[flowId]) == null ? void 0 : _a[nodeId];
19345
+ },
19346
+ resetNodeResult() {
19347
+ console.log("Clearing node results");
19348
+ this.runNodeResults = {};
19349
+ },
19350
+ clearFlowResults(flowId) {
19351
+ if (this.runNodeResults[flowId]) {
19352
+ delete this.runNodeResults[flowId];
19353
+ }
19354
+ },
19355
+ // ========== Validation Cache Management ==========
19356
+ initializeValidationCache(flowId) {
19357
+ if (!this.runNodeValidations[flowId]) {
19358
+ this.runNodeValidations[flowId] = {};
19359
+ }
19360
+ },
19361
+ setNodeValidation(flowId, nodeId, nodeValidationInput) {
19362
+ if (typeof nodeId === "string") {
19363
+ nodeId = parseInt(nodeId);
19364
+ }
19365
+ this.initializeValidationCache(flowId);
19366
+ const nodeValidation = {
19367
+ ...nodeValidationInput,
19368
+ validationTime: Date.now() / 1e3
19369
+ };
19370
+ this.runNodeValidations[flowId][nodeId] = nodeValidation;
19371
+ },
19372
+ resetNodeValidation() {
19373
+ this.runNodeValidations = {};
19374
+ },
19375
+ getNodeValidation(flowId, nodeId) {
19376
+ var _a;
19377
+ return ((_a = this.runNodeValidations[flowId]) == null ? void 0 : _a[nodeId]) || {
19378
+ isValid: true,
19379
+ error: "",
19380
+ validationTime: 0
19381
+ };
19382
+ },
19383
+ // ========== Run Results Management ==========
19384
+ insertRunResult(runResult) {
19385
+ this.currentRunResult = runResult;
19386
+ this.runResults[runResult.flow_id] = runResult;
19387
+ this.initializeResultCache(runResult.flow_id);
19388
+ runResult.node_step_result.forEach((nodeResult) => {
19389
+ this.runNodeResults[runResult.flow_id][nodeResult.node_id] = nodeResult;
19390
+ });
19391
+ this.resultVersion++;
19392
+ },
19393
+ resetRunResults() {
19394
+ this.runNodeResults = {};
19395
+ this.runResults = {};
19396
+ this.currentRunResult = null;
19397
+ },
19398
+ getRunResult(flowId) {
19399
+ return this.runResults[flowId] || null;
19400
+ }
19401
+ }
19402
+ });
19403
+ const useEditorStore = /* @__PURE__ */ defineStore("editor", {
19404
+ state: () => ({
19405
+ // Drawer state
19406
+ isDrawerOpen: false,
19407
+ isAnalysisOpen: false,
19408
+ activeDrawerComponent: shallowRef(null),
19409
+ drawerProps: ref({}),
19410
+ drawCloseFunction: null,
19411
+ // Editor state
19412
+ initialEditorData: "",
19413
+ inputCode: "",
19414
+ // Log viewer state
19415
+ hideLogViewerForThisRun: false,
19416
+ isShowingLogViewer: false,
19417
+ isStreamingLogs: false,
19418
+ displayLogViewer: true,
19419
+ // Code generator state
19420
+ showCodeGenerator: false,
19421
+ // Run state
19422
+ isRunning: false,
19423
+ showFlowResult: false,
19424
+ tableVisible: false
19425
+ }),
19426
+ getters: {
19427
+ drawerOpen() {
19428
+ return !!this.activeDrawerComponent;
19429
+ }
19430
+ },
19431
+ actions: {
19432
+ // ========== Drawer Management ==========
19433
+ async executeDrawCloseFunction() {
19434
+ console.log("Executing draw close function");
19435
+ if (this.drawCloseFunction) {
19436
+ this.drawCloseFunction();
19437
+ }
19438
+ },
19439
+ setCloseFunction(f2) {
19440
+ this.drawCloseFunction = f2;
19441
+ },
19442
+ openDrawer(component2, nodeTitleInfo, props = {}) {
19443
+ this.activeDrawerComponent = component2;
19444
+ this.drawerProps = { ...nodeTitleInfo, ...props };
19445
+ this.isDrawerOpen = true;
19446
+ },
19447
+ closeDrawer() {
19448
+ this.activeDrawerComponent = null;
19449
+ if (this.drawCloseFunction)
19450
+ ;
19451
+ },
19452
+ toggleDrawer() {
19453
+ if (this.isDrawerOpen && this.drawCloseFunction) {
19454
+ this.pushNodeData();
19455
+ }
19456
+ this.isDrawerOpen = !this.isDrawerOpen;
19457
+ },
19458
+ pushNodeData() {
19459
+ if (this.drawCloseFunction && !this.isRunning) {
19460
+ this.drawCloseFunction();
19461
+ this.drawCloseFunction = null;
19462
+ }
19463
+ },
19464
+ openAnalysisDrawer(closeFunction) {
19465
+ console.log("openAnalysisDrawer in editor-store.ts");
19466
+ if (this.isAnalysisOpen) {
19467
+ this.pushNodeData();
19468
+ }
19469
+ if (closeFunction) {
19470
+ this.drawCloseFunction = closeFunction;
19471
+ }
19472
+ this.isAnalysisOpen = true;
19473
+ },
19474
+ closeAnalysisDrawer() {
19475
+ this.isAnalysisOpen = false;
19476
+ if (this.drawCloseFunction) {
19477
+ console.log("closeDrawer in editor-store.ts");
19478
+ this.pushNodeData();
19479
+ }
19480
+ },
19481
+ // ========== Code Generator ==========
19482
+ toggleCodeGenerator() {
19483
+ this.showCodeGenerator = !this.showCodeGenerator;
19484
+ },
19485
+ setCodeGeneratorVisibility(visible) {
19486
+ this.showCodeGenerator = visible;
19487
+ },
19488
+ // ========== Log Viewer ==========
19489
+ showLogViewer() {
19490
+ console.log("triggered show log viewer");
19491
+ this.isShowingLogViewer = this.displayLogViewer;
19492
+ },
19493
+ hideLogViewer() {
19494
+ this.isShowingLogViewer = false;
19495
+ },
19496
+ toggleLogViewer() {
19497
+ console.log("triggered toggle log viewer");
19498
+ this.isShowingLogViewer = !this.isShowingLogViewer;
19499
+ },
19500
+ updateLogViewerVisibility(showResult) {
19501
+ this.isShowingLogViewer = this.displayLogViewer && showResult && !this.hideLogViewerForThisRun;
19502
+ },
19503
+ // ========== Editor Data ==========
19504
+ setInitialEditorData(editorDataString) {
19505
+ this.initialEditorData = editorDataString;
19506
+ },
19507
+ getInitialEditorData() {
19508
+ return this.initialEditorData;
19509
+ },
19510
+ setInputCode(newCode) {
19511
+ this.inputCode = newCode;
19512
+ },
19513
+ // ========== Flow Result Display ==========
19514
+ setShowFlowResult(show) {
19515
+ this.showFlowResult = show;
19516
+ },
19517
+ setTableVisible(visible) {
19518
+ this.tableVisible = visible;
19519
+ },
19520
+ setIsRunning(running) {
19521
+ this.isRunning = running;
19522
+ }
19523
+ }
19524
+ });
19525
+ const useNodeStore = /* @__PURE__ */ defineStore("node", {
19526
+ state: () => ({
19527
+ nodeId: -1,
19528
+ previousNodeId: -1,
19529
+ nodeValidateFuncs: /* @__PURE__ */ new Map(),
19530
+ nodeData: null,
19531
+ nodeExists: false,
19532
+ isLoaded: false,
19533
+ sizeDataPreview: 300,
19534
+ dataTypes: ["String", "Datetime", "Int64", "Int32", "Int16", "Float64", "Float32", "Boolean"],
19535
+ nodeDescriptions: {},
19536
+ allExpressions: null
19537
+ }),
19538
+ getters: {
19539
+ currentNodeId: (state) => state.nodeId,
19540
+ currentNodeData: (state) => state.nodeData,
19541
+ // Backward compatibility: read-only getters (use snake_case for legacy)
19542
+ /** @deprecated Use `nodeId` (camelCase) instead. This getter is read-only. */
19543
+ node_id: (state) => state.nodeId,
19544
+ /** @deprecated Use `isLoaded` (camelCase) instead. This getter is read-only. */
19545
+ is_loaded: (state) => state.isLoaded,
19546
+ // Proxy getters to other stores
19547
+ /** @deprecated Use `useFlowStore().flowId` directly. This getter is read-only. */
19548
+ flow_id() {
19549
+ return useFlowStore().flowId;
19550
+ },
19551
+ /** @deprecated Use `useFlowStore().vueFlowInstance` directly. This getter is read-only. */
19552
+ vueFlowInstance() {
19553
+ return useFlowStore().vueFlowInstance;
19554
+ },
19555
+ /** @deprecated Use `useEditorStore().isRunning` directly. This getter is read-only. */
19556
+ isRunning() {
19557
+ var _a;
19558
+ return ((_a = useEditorStore()) == null ? void 0 : _a.isRunning) || false;
19559
+ },
19560
+ /** @deprecated Use `useEditorStore().isDrawerOpen` directly. This getter is read-only. */
19561
+ isDrawerOpen() {
19562
+ var _a;
19563
+ return ((_a = useEditorStore()) == null ? void 0 : _a.isDrawerOpen) || false;
19564
+ },
19565
+ /** @deprecated Use `useEditorStore().activeDrawerComponent` directly. This getter is read-only. */
19566
+ activeDrawerComponent() {
19567
+ var _a;
19568
+ return (_a = useEditorStore()) == null ? void 0 : _a.activeDrawerComponent;
19569
+ },
19570
+ /** @deprecated Use `useEditorStore().drawerProps` directly. This getter is read-only. */
19571
+ drawerProps() {
19572
+ var _a;
19573
+ return ((_a = useEditorStore()) == null ? void 0 : _a.drawerProps) || {};
19574
+ },
19575
+ /** @deprecated Use `useEditorStore().showCodeGenerator` directly. This getter is read-only. */
19576
+ showCodeGenerator() {
19577
+ var _a;
19578
+ return ((_a = useEditorStore()) == null ? void 0 : _a.showCodeGenerator) || false;
19579
+ },
19580
+ /** @deprecated Use `useEditorStore().showFlowResult` directly. This getter is read-only. */
19581
+ showFlowResult() {
19582
+ var _a;
19583
+ return ((_a = useEditorStore()) == null ? void 0 : _a.showFlowResult) || false;
19584
+ },
19585
+ /** @deprecated Use `useEditorStore().isShowingLogViewer` directly. This getter is read-only. */
19586
+ isShowingLogViewer() {
19587
+ var _a;
19588
+ return ((_a = useEditorStore()) == null ? void 0 : _a.isShowingLogViewer) || false;
19589
+ },
19590
+ /** @deprecated Use `useEditorStore().hideLogViewerForThisRun` directly. This getter is read-only. */
19591
+ hideLogViewerForThisRun() {
19592
+ var _a;
19593
+ return ((_a = useEditorStore()) == null ? void 0 : _a.hideLogViewerForThisRun) || false;
19594
+ },
19595
+ /** @deprecated Use `useEditorStore().displayLogViewer` directly. This getter is read-only. */
19596
+ displayLogViewer() {
19597
+ const editorStore = useEditorStore();
19598
+ return (editorStore == null ? void 0 : editorStore.displayLogViewer) !== void 0 ? editorStore.displayLogViewer : true;
19599
+ },
19600
+ /** @deprecated Use `useEditorStore().inputCode` directly. This getter is read-only. */
19601
+ inputCode() {
19602
+ var _a;
19603
+ return ((_a = useEditorStore()) == null ? void 0 : _a.inputCode) || "";
19604
+ },
19605
+ /** @deprecated Use `useResultsStore().currentRunResult` directly. This getter is read-only. */
19606
+ currentRunResult() {
19607
+ var _a;
19608
+ return (_a = useResultsStore()) == null ? void 0 : _a.currentRunResult;
19609
+ },
19610
+ /** @deprecated Use `useResultsStore().runResults` directly. This getter is read-only. */
19611
+ runResults() {
19612
+ var _a;
19613
+ return ((_a = useResultsStore()) == null ? void 0 : _a.runResults) || {};
19614
+ }
19615
+ },
19616
+ actions: {
19617
+ // ========== Node Data Management ==========
19618
+ async getNodeData(nodeId, useCache2 = true) {
19619
+ const flowStore = useFlowStore();
19620
+ if (this.nodeId === nodeId && useCache2) {
19621
+ if (this.nodeData) {
19622
+ this.isLoaded = true;
19623
+ return this.nodeData;
19624
+ }
19625
+ }
19626
+ try {
19627
+ console.log("Getting node data");
19628
+ const data = await NodeApi.getNodeData(flowStore.flowId, nodeId);
19629
+ this.nodeData = data;
19630
+ this.isLoaded = true;
19631
+ this.nodeExists = true;
19632
+ return this.nodeData;
19633
+ } catch (error) {
19634
+ console.error("Error fetching node data:", error);
19635
+ this.nodeData = null;
19636
+ this.isLoaded = false;
19637
+ this.nodeExists = false;
19638
+ return null;
19639
+ }
19640
+ },
19641
+ async reloadCurrentNodeData() {
19642
+ return this.getNodeData(this.nodeId, false);
19643
+ },
19644
+ getCurrentNodeData() {
19645
+ return this.nodeData;
19646
+ },
19647
+ async getTableExample(flowId, nodeId) {
19648
+ try {
19649
+ return await NodeApi.getTableExample(flowId, nodeId);
19650
+ } catch (error) {
19651
+ console.error("Error fetching table example:", error);
19652
+ return null;
19653
+ }
19654
+ },
19655
+ // ========== Node ID Management ==========
19656
+ setFlowIdAndNodeId(flowId, nodeId) {
19657
+ const flowStore = useFlowStore();
19658
+ if (this.nodeId === nodeId && flowStore.flowId === flowId) {
19659
+ return;
19660
+ }
19661
+ console.log("Automatically pushing the node data");
19662
+ if (flowStore.flowId !== flowId) {
19663
+ flowStore.setFlowId(flowId);
19664
+ }
19665
+ this.nodeId = nodeId;
19666
+ },
19667
+ doReset() {
19668
+ this.isLoaded = false;
19669
+ },
19670
+ // ========== Node Validation ==========
19671
+ setNodeValidateFunc(nodeId, func) {
19672
+ if (typeof nodeId === "string") {
19673
+ nodeId = parseInt(nodeId);
19674
+ }
19675
+ this.nodeValidateFuncs.set(nodeId, func);
19676
+ },
19677
+ async validateNode(nodeId) {
19678
+ if (typeof nodeId === "string") {
19679
+ nodeId = parseInt(nodeId);
19680
+ }
19681
+ const func = this.nodeValidateFuncs.get(nodeId);
19682
+ if (func) {
19683
+ func();
19684
+ }
19685
+ },
19686
+ // ========== Node Descriptions ==========
19687
+ initializeDescriptionCache(flowId) {
19688
+ if (!this.nodeDescriptions[flowId]) {
19689
+ this.nodeDescriptions[flowId] = {};
19690
+ }
19691
+ },
19692
+ cacheNodeDescriptionDict(flowId, nodeId, description) {
19693
+ this.initializeDescriptionCache(flowId);
19694
+ this.nodeDescriptions[flowId][nodeId] = description;
19695
+ if (this.nodeData && this.nodeData.node_id === nodeId && this.nodeData.setting_input) {
19696
+ this.nodeData.setting_input.description = description;
19697
+ }
19698
+ },
19699
+ clearNodeDescriptionCache(flowId, nodeId) {
19700
+ if (this.nodeDescriptions[flowId] && this.nodeDescriptions[flowId][nodeId]) {
19701
+ delete this.nodeDescriptions[flowId][nodeId];
19702
+ }
19703
+ },
19704
+ clearFlowDescriptionCache(flowId) {
19705
+ if (this.nodeDescriptions[flowId]) {
19706
+ delete this.nodeDescriptions[flowId];
19707
+ }
19708
+ },
19709
+ clearAllDescriptionCaches() {
19710
+ this.nodeDescriptions = {};
19711
+ },
19712
+ async getNodeDescription(nodeId, forceRefresh = false) {
19713
+ var _a, _b;
19714
+ const flowStore = useFlowStore();
19715
+ this.initializeDescriptionCache(flowStore.flowId);
19716
+ if (!forceRefresh && ((_a = this.nodeDescriptions[flowStore.flowId]) == null ? void 0 : _a[nodeId])) {
19717
+ return this.nodeDescriptions[flowStore.flowId][nodeId];
19718
+ }
19719
+ try {
19720
+ const description = await NodeApi.getNodeDescription(flowStore.flowId, nodeId);
19721
+ this.cacheNodeDescriptionDict(flowStore.flowId, nodeId, description);
19722
+ return description;
19723
+ } catch (error) {
19724
+ console.info("Error fetching node description:", error);
19725
+ if ((_b = this.nodeDescriptions[flowStore.flowId]) == null ? void 0 : _b[nodeId]) {
19726
+ console.warn("Using cached description due to API error");
19727
+ return this.nodeDescriptions[flowStore.flowId][nodeId];
19728
+ }
19729
+ return "";
19730
+ }
19731
+ },
19732
+ async setNodeDescription(nodeId, description) {
19733
+ const flowStore = useFlowStore();
19734
+ try {
19735
+ this.cacheNodeDescriptionDict(flowStore.flowId, nodeId, description);
19736
+ const result = await NodeApi.setNodeDescription(flowStore.flowId, nodeId, description);
19737
+ if (result === true) {
19738
+ console.log("Description updated successfully");
19739
+ } else {
19740
+ console.warn("Unexpected response:", result);
19741
+ }
19742
+ } catch (error) {
19743
+ if (error.response) {
19744
+ console.error("API error:", error.response.data.message);
19745
+ } else if (error.request) {
19746
+ console.error("The request was made but no response was received");
19747
+ } else {
19748
+ console.error("Error", error.message);
19749
+ }
19750
+ throw error;
19751
+ }
19752
+ },
19753
+ updateNodeDescription(nodeId, description) {
19754
+ const flowStore = useFlowStore();
19755
+ this.cacheNodeDescriptionDict(flowStore.flowId, nodeId, description);
19756
+ },
19757
+ // ========== Node Settings Updates ==========
19758
+ async updateSettingsDirectly(inputData) {
19759
+ var _a, _b;
19760
+ const flowStore = useFlowStore();
19761
+ try {
19762
+ const node = (_a = flowStore.vueFlowInstance) == null ? void 0 : _a.findNode(String(inputData.node_id));
19763
+ inputData.pos_x = node.position.x;
19764
+ inputData.pos_y = node.position.y;
19765
+ const response = await NodeApi.updateSettingsDirectly(
19766
+ node.data.nodeTemplate.item,
19767
+ inputData
19768
+ );
19769
+ const downstreamNodeIds = await NodeApi.getDownstreamNodeIds(
19770
+ flowStore.flowId,
19771
+ inputData.node_id
19772
+ );
19773
+ downstreamNodeIds.map((nodeId) => {
19774
+ this.validateNode(nodeId);
19775
+ });
19776
+ return response;
19777
+ } catch (error) {
19778
+ console.error("Error updating settings directly:", (_b = error.response) == null ? void 0 : _b.data);
19779
+ throw error;
19780
+ }
19781
+ },
19782
+ async updateUserDefinedSettings(inputData) {
19783
+ var _a, _b;
19784
+ const flowStore = useFlowStore();
19785
+ try {
19786
+ const node = (_a = flowStore.vueFlowInstance) == null ? void 0 : _a.findNode(String(inputData.value.node_id));
19787
+ const nodeType = node.data.nodeTemplate.item;
19788
+ inputData.value.pos_x = node.position.x;
19789
+ inputData.value.pos_y = node.position.y;
19790
+ const response = await NodeApi.updateUserDefinedSettings(nodeType, inputData.value);
19791
+ const downstreamNodeIds = await NodeApi.getDownstreamNodeIds(
19792
+ flowStore.flowId,
19793
+ inputData.value.node_id
19794
+ );
19795
+ downstreamNodeIds.map((nodeId) => {
19796
+ this.validateNode(nodeId);
19797
+ });
19798
+ return response;
19799
+ } catch (error) {
19800
+ console.error("Error updating settings:", (_b = error.response) == null ? void 0 : _b.data);
19801
+ throw error;
19802
+ }
19803
+ },
19804
+ async updateSettings(inputData, inputNodeType) {
19805
+ var _a, _b;
19806
+ const flowStore = useFlowStore();
19807
+ try {
19808
+ const node = (_a = flowStore.vueFlowInstance) == null ? void 0 : _a.findNode(String(inputData.value.node_id));
19809
+ const nodeType = inputNodeType ?? node.data.nodeTemplate.item;
19810
+ inputData.value.pos_x = node.position.x;
19811
+ inputData.value.pos_y = node.position.y;
19812
+ const response = await NodeApi.updateSettingsDirectly(nodeType, inputData.value);
19813
+ const downstreamNodeIds = await NodeApi.getDownstreamNodeIds(
19814
+ flowStore.flowId,
19815
+ inputData.value.node_id
19816
+ );
19817
+ downstreamNodeIds.map((nodeId) => {
19818
+ this.validateNode(nodeId);
19819
+ });
19820
+ return response;
19821
+ } catch (error) {
19822
+ console.error("Error updating settings:", (_b = error.response) == null ? void 0 : _b.data);
19823
+ throw error;
19824
+ }
19825
+ },
19826
+ // ========== Expressions ==========
19827
+ async fetchExpressionsOverview() {
19828
+ try {
19829
+ const expressions = await ExpressionsApi.getExpressionsOverview();
19830
+ this.allExpressions = expressions;
19831
+ return this.allExpressions;
19832
+ } catch (error) {
19833
+ console.error("Error fetching expressions overview:", error);
19834
+ return [];
19835
+ }
19836
+ },
19837
+ async getExpressionsOverview() {
19838
+ if (this.allExpressions) {
19839
+ return this.allExpressions;
19840
+ } else {
19841
+ return await this.fetchExpressionsOverview();
19842
+ }
19843
+ },
19844
+ // ========== Utilities ==========
19845
+ getDataTypes() {
19846
+ return this.dataTypes;
19847
+ },
19848
+ getSizeDataPreview() {
19849
+ return this.sizeDataPreview;
19850
+ },
19851
+ setSizeDataPreview(newHeight) {
19852
+ this.sizeDataPreview = newHeight;
19853
+ },
19854
+ getEditorNodeData() {
19855
+ var _a;
19856
+ const flowStore = useFlowStore();
19857
+ if (this.nodeId) {
19858
+ return (_a = flowStore.vueFlowInstance) == null ? void 0 : _a.findNode(String(this.nodeId));
19859
+ }
19860
+ return null;
19861
+ },
19862
+ // ========== Backward Compatibility Actions (Proxy to other stores) ==========
19863
+ /** @deprecated Use `useFlowStore().setFlowId()` directly instead. */
19864
+ setFlowId(flowId) {
19865
+ const flowStore = useFlowStore();
19866
+ flowStore.setFlowId(flowId);
19867
+ },
19868
+ /** @deprecated Use `useFlowStore().setVueFlowInstance()` directly instead. */
19869
+ setVueFlowInstance(vueFlowInstance) {
19870
+ const flowStore = useFlowStore();
19871
+ flowStore.setVueFlowInstance(vueFlowInstance);
19872
+ },
19873
+ /** @deprecated Use `useFlowStore().getVueFlowInstance()` directly instead. */
19874
+ getVueFlowInstance() {
19875
+ const flowStore = useFlowStore();
19876
+ return flowStore.getVueFlowInstance();
19877
+ },
19878
+ /** @deprecated Use `useResultsStore().setNodeResult()` directly instead. */
19879
+ setNodeResult(nodeId, result) {
19880
+ const flowStore = useFlowStore();
19881
+ const resultsStore = useResultsStore();
19882
+ resultsStore.setNodeResult(flowStore.flowId, nodeId, result);
19883
+ },
19884
+ /** @deprecated Use `useResultsStore().getNodeResult()` directly instead. */
19885
+ getNodeResult(nodeId) {
19886
+ const flowStore = useFlowStore();
19887
+ const resultsStore = useResultsStore();
19888
+ return resultsStore.getNodeResult(flowStore.flowId, nodeId);
19889
+ },
19890
+ /** @deprecated Use `useResultsStore().resetNodeResult()` directly instead. */
19891
+ resetNodeResult() {
19892
+ const resultsStore = useResultsStore();
19893
+ resultsStore.resetNodeResult();
19894
+ },
19895
+ /** @deprecated Use `useResultsStore().clearFlowResults()` directly instead. */
19896
+ clearFlowResults(flowId) {
19897
+ const resultsStore = useResultsStore();
19898
+ resultsStore.clearFlowResults(flowId);
19899
+ },
19900
+ /** @deprecated Use `useResultsStore().setNodeValidation()` directly instead. */
19901
+ setNodeValidation(nodeId, nodeValidationInput) {
19902
+ const flowStore = useFlowStore();
19903
+ const resultsStore = useResultsStore();
19904
+ resultsStore.setNodeValidation(flowStore.flowId, nodeId, nodeValidationInput);
19905
+ },
19906
+ /** @deprecated Use `useResultsStore().resetNodeValidation()` directly instead. */
19907
+ resetNodeValidation() {
19908
+ const resultsStore = useResultsStore();
19909
+ resultsStore.resetNodeValidation();
19910
+ },
19911
+ /** @deprecated Use `useResultsStore().getNodeValidation()` directly instead. */
19912
+ getNodeValidation(nodeId) {
19913
+ const flowStore = useFlowStore();
19914
+ const resultsStore = useResultsStore();
19915
+ return resultsStore.getNodeValidation(flowStore.flowId, nodeId);
19916
+ },
19917
+ /** @deprecated Use `useResultsStore().insertRunResult()` directly instead. */
19918
+ insertRunResult(runResult) {
19919
+ const resultsStore = useResultsStore();
19920
+ resultsStore.insertRunResult(runResult);
19921
+ },
19922
+ /** @deprecated Use `useResultsStore().resetRunResults()` directly instead. */
19923
+ resetRunResults() {
19924
+ const resultsStore = useResultsStore();
19925
+ resultsStore.resetRunResults();
19926
+ },
19927
+ /** @deprecated Use `useResultsStore().getRunResult()` directly instead. */
19928
+ getRunResult(flowId) {
19929
+ const resultsStore = useResultsStore();
19930
+ return resultsStore.getRunResult(flowId);
19931
+ },
19932
+ /** @deprecated Use `useEditorStore().openDrawer()` directly instead. */
19933
+ openDrawer(component2, nodeTitleInfo, props = {}) {
19934
+ const editorStore = useEditorStore();
19935
+ editorStore.openDrawer(component2, nodeTitleInfo, props);
19936
+ },
19937
+ /** @deprecated Use `useEditorStore().closeDrawer()` directly instead. */
19938
+ closeDrawer() {
19939
+ const editorStore = useEditorStore();
19940
+ editorStore.closeDrawer();
19941
+ this.nodeId = -1;
19942
+ },
19943
+ /** @deprecated Use `useEditorStore().toggleDrawer()` directly instead. */
19944
+ toggleDrawer() {
19945
+ const editorStore = useEditorStore();
19946
+ editorStore.toggleDrawer();
19947
+ },
19948
+ /** @deprecated Use `useEditorStore().pushNodeData()` directly instead. */
19949
+ pushNodeData() {
19950
+ const editorStore = useEditorStore();
19951
+ editorStore.pushNodeData();
19952
+ },
19953
+ /** @deprecated Use `useEditorStore().setCloseFunction()` directly instead. */
19954
+ setCloseFunction(f2) {
19955
+ const editorStore = useEditorStore();
19956
+ editorStore.setCloseFunction(f2);
19957
+ },
19958
+ /** @deprecated Use `useEditorStore().executeDrawCloseFunction()` directly instead. */
19959
+ executeDrawCloseFunction() {
19960
+ const editorStore = useEditorStore();
19961
+ return editorStore.executeDrawCloseFunction();
19962
+ },
19963
+ /** @deprecated Use `useEditorStore().toggleCodeGenerator()` directly instead. */
19964
+ toggleCodeGenerator() {
19965
+ const editorStore = useEditorStore();
19966
+ editorStore.toggleCodeGenerator();
19967
+ },
19968
+ /** @deprecated Use `useEditorStore().setCodeGeneratorVisibility()` directly instead. */
19969
+ setCodeGeneratorVisibility(visible) {
19970
+ const editorStore = useEditorStore();
19971
+ editorStore.setCodeGeneratorVisibility(visible);
19972
+ },
19973
+ /** @deprecated Use `useEditorStore().showLogViewer()` directly instead. */
19974
+ showLogViewer() {
19975
+ const editorStore = useEditorStore();
19976
+ editorStore.showLogViewer();
19977
+ },
19978
+ /** @deprecated Use `useEditorStore().hideLogViewer()` directly instead. */
19979
+ hideLogViewer() {
19980
+ const editorStore = useEditorStore();
19981
+ editorStore.hideLogViewer();
19982
+ },
19983
+ /** @deprecated Use `useEditorStore().toggleLogViewer()` directly instead. */
19984
+ toggleLogViewer() {
19985
+ const editorStore = useEditorStore();
19986
+ editorStore.toggleLogViewer();
19987
+ },
19988
+ /** @deprecated Use `useEditorStore().setInputCode()` directly instead. */
19989
+ setInputCode(newCode) {
19990
+ const editorStore = useEditorStore();
19991
+ editorStore.setInputCode(newCode);
19992
+ },
19993
+ /** @deprecated Use `useEditorStore().setInitialEditorData()` directly instead. */
19994
+ setInitialEditorData(editorDataString) {
19995
+ const editorStore = useEditorStore();
19996
+ editorStore.setInitialEditorData(editorDataString);
19997
+ },
19998
+ /** @deprecated Use `useEditorStore().getInitialEditorData()` directly instead. */
19999
+ getInitialEditorData() {
20000
+ const editorStore = useEditorStore();
20001
+ return editorStore.getInitialEditorData();
20002
+ }
20003
+ }
20004
+ });
20005
+ const _hoisted_1$V = { class: "tooltip-progress" };
20006
+ const _hoisted_2$L = { class: "progress-bar" };
20007
+ const _hoisted_3$E = { class: "progress-text" };
20008
+ const _hoisted_4$v = { class: "tooltip-content" };
20009
+ const _hoisted_5$q = { class: "tooltip-title" };
20010
+ const _hoisted_6$l = ["innerHTML"];
20011
+ const _hoisted_7$d = {
20012
+ key: 0,
20013
+ class: "tooltip-action-hint"
20014
+ };
20015
+ const _hoisted_8$9 = { class: "tooltip-navigation" };
20016
+ const _hoisted_9$8 = { class: "nav-main" };
20017
+ const _hoisted_10$8 = {
20018
+ key: 0,
20019
+ class: "material-icons"
20020
+ };
20021
+ const _hoisted_11$5 = {
20022
+ key: 1,
20023
+ class: "material-icons"
20024
+ };
20025
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
20026
+ __name: "TutorialTooltip",
20027
+ props: {
20028
+ step: {},
20029
+ position: {},
20030
+ isCenterMode: { type: Boolean },
20031
+ currentStepIndex: {},
20032
+ totalSteps: {},
20033
+ progress: {}
20034
+ },
20035
+ emits: ["next", "prev", "skip", "complete"],
20036
+ setup(__props, { emit: __emit }) {
20037
+ const props = __props;
20038
+ const emit2 = __emit;
20039
+ const tooltipRef = ref(null);
20040
+ const tooltipRect = ref(null);
20041
+ function updateTooltipRect() {
20042
+ if (tooltipRef.value) {
20043
+ tooltipRect.value = tooltipRef.value.getBoundingClientRect();
20044
+ }
20045
+ }
20046
+ watch(
20047
+ () => props.step,
20048
+ () => {
20049
+ setTimeout(updateTooltipRect, 50);
20050
+ },
20051
+ { immediate: true }
20052
+ );
20053
+ onMounted(() => {
20054
+ setTimeout(updateTooltipRect, 50);
20055
+ window.addEventListener("resize", updateTooltipRect);
20056
+ });
20057
+ onUnmounted(() => {
20058
+ window.removeEventListener("resize", updateTooltipRect);
20059
+ });
20060
+ const tooltipStyle = computed(() => {
20061
+ var _a, _b;
20062
+ if (props.isCenterMode) {
20063
+ if (props.step.centerInScreen) {
20064
+ return {
20065
+ position: "fixed",
20066
+ left: "50%",
20067
+ top: "50%",
20068
+ right: "auto",
20069
+ bottom: "auto",
20070
+ transform: "translate(-50%, -50%)"
20071
+ };
20072
+ }
20073
+ return {
20074
+ position: "fixed",
20075
+ right: "24px",
20076
+ bottom: "24px",
20077
+ left: "auto",
20078
+ top: "auto",
20079
+ transform: "none"
20080
+ };
20081
+ }
20082
+ const tooltipWidth = ((_a = tooltipRect.value) == null ? void 0 : _a.width) || 350;
20083
+ const tooltipHeight = ((_b = tooltipRect.value) == null ? void 0 : _b.height) || 200;
20084
+ const padding = 20;
20085
+ const position = props.step.position || "bottom";
20086
+ let x2 = props.position.x;
20087
+ let y = props.position.y;
20088
+ let transform2 = "";
20089
+ switch (position) {
20090
+ case "top":
20091
+ x2 = props.position.x;
20092
+ y = props.position.y;
20093
+ transform2 = "translate(-50%, -100%)";
20094
+ break;
20095
+ case "bottom":
20096
+ x2 = props.position.x;
20097
+ y = props.position.y;
20098
+ transform2 = "translate(-50%, 0)";
20099
+ break;
20100
+ case "left":
20101
+ x2 = props.position.x;
20102
+ y = props.position.y;
20103
+ transform2 = "translate(-100%, -50%)";
20104
+ break;
20105
+ case "right":
20106
+ x2 = props.position.x;
20107
+ y = props.position.y;
20108
+ transform2 = "translate(0, -50%)";
20109
+ break;
20110
+ }
20111
+ let finalX = x2;
20112
+ let finalY = y;
20113
+ let effectiveX = x2;
20114
+ let effectiveY = y;
20115
+ if (transform2.includes("-50%, 0")) {
20116
+ effectiveX = x2 - tooltipWidth / 2;
20117
+ } else if (transform2.includes("-50%, -100%)")) {
20118
+ effectiveX = x2 - tooltipWidth / 2;
20119
+ effectiveY = y - tooltipHeight;
20120
+ } else if (transform2.includes("-100%, -50%")) {
20121
+ effectiveX = x2 - tooltipWidth;
20122
+ effectiveY = y - tooltipHeight / 2;
20123
+ } else if (transform2.includes("0, -50%")) {
20124
+ effectiveY = y - tooltipHeight / 2;
20125
+ }
20126
+ if (effectiveX < padding) {
20127
+ finalX = x2 + (padding - effectiveX);
20128
+ }
20129
+ if (effectiveX + tooltipWidth > window.innerWidth - padding) {
20130
+ finalX = x2 - (effectiveX + tooltipWidth - window.innerWidth + padding);
20131
+ }
20132
+ if (effectiveY < padding) {
20133
+ finalY = y + (padding - effectiveY);
20134
+ }
20135
+ if (effectiveY + tooltipHeight > window.innerHeight - padding) {
20136
+ finalY = y - (effectiveY + tooltipHeight - window.innerHeight + padding);
20137
+ }
20138
+ return {
20139
+ position: "fixed",
20140
+ left: `${finalX}px`,
20141
+ top: `${finalY}px`,
20142
+ transform: transform2
20143
+ };
20144
+ });
20145
+ const isLastStep = computed(() => props.currentStepIndex === props.totalSteps - 1);
20146
+ const showNextButton = computed(() => props.step.showNextButton !== false);
20147
+ const showPrevButton = computed(
20148
+ () => props.step.showPrevButton !== false && props.currentStepIndex > 0
20149
+ );
20150
+ const canSkip = computed(() => props.step.canSkip !== false);
20151
+ const actionHint = computed(() => {
20152
+ switch (props.step.action) {
20153
+ case "click":
20154
+ return "Click the highlighted element to continue";
20155
+ case "drag":
20156
+ return "Drag the highlighted element to the target area";
20157
+ case "input":
20158
+ return "Enter the required information";
20159
+ case "wait":
20160
+ return "Please wait...";
20161
+ default:
20162
+ return null;
20163
+ }
20164
+ });
20165
+ function handleNext() {
20166
+ if (isLastStep.value) {
20167
+ emit2("complete");
20168
+ } else {
20169
+ emit2("next");
20170
+ }
20171
+ }
20172
+ return (_ctx, _cache) => {
20173
+ return openBlock(), createElementBlock("div", {
20174
+ ref_key: "tooltipRef",
20175
+ ref: tooltipRef,
20176
+ class: "tutorial-tooltip",
20177
+ style: normalizeStyle(tooltipStyle.value)
20178
+ }, [
20179
+ createBaseVNode("div", _hoisted_1$V, [
20180
+ createBaseVNode("div", _hoisted_2$L, [
20181
+ createBaseVNode("div", {
20182
+ class: "progress-fill",
20183
+ style: normalizeStyle({ width: `${_ctx.progress}%` })
20184
+ }, null, 4)
20185
+ ]),
20186
+ createBaseVNode("span", _hoisted_3$E, toDisplayString$1(_ctx.currentStepIndex + 1) + " / " + toDisplayString$1(_ctx.totalSteps), 1)
20187
+ ]),
20188
+ createBaseVNode("div", _hoisted_4$v, [
20189
+ createBaseVNode("h3", _hoisted_5$q, toDisplayString$1(_ctx.step.title), 1),
20190
+ createBaseVNode("p", {
20191
+ class: "tooltip-description",
20192
+ innerHTML: _ctx.step.content
20193
+ }, null, 8, _hoisted_6$l),
20194
+ actionHint.value && _ctx.step.action !== "observe" ? (openBlock(), createElementBlock("p", _hoisted_7$d, [
20195
+ _cache[2] || (_cache[2] = createBaseVNode("span", { class: "action-icon material-icons" }, "touch_app", -1)),
20196
+ createTextVNode(" " + toDisplayString$1(actionHint.value), 1)
20197
+ ])) : createCommentVNode("", true)
20198
+ ]),
20199
+ createBaseVNode("div", _hoisted_8$9, [
20200
+ canSkip.value ? (openBlock(), createElementBlock("button", {
20201
+ key: 0,
20202
+ class: "nav-btn skip-btn",
20203
+ onClick: _cache[0] || (_cache[0] = ($event) => emit2("skip"))
20204
+ }, "Skip Tutorial")) : createCommentVNode("", true),
20205
+ createBaseVNode("div", _hoisted_9$8, [
20206
+ showPrevButton.value ? (openBlock(), createElementBlock("button", {
20207
+ key: 0,
20208
+ class: "nav-btn prev-btn",
20209
+ onClick: _cache[1] || (_cache[1] = ($event) => emit2("prev"))
20210
+ }, _cache[3] || (_cache[3] = [
20211
+ createBaseVNode("span", { class: "material-icons" }, "arrow_back", -1),
20212
+ createTextVNode(" Back ")
20213
+ ]))) : createCommentVNode("", true),
20214
+ showNextButton.value ? (openBlock(), createElementBlock("button", {
20215
+ key: 1,
20216
+ class: "nav-btn next-btn",
20217
+ onClick: handleNext
20218
+ }, [
20219
+ createTextVNode(toDisplayString$1(isLastStep.value ? "Finish" : "Next") + " ", 1),
20220
+ !isLastStep.value ? (openBlock(), createElementBlock("span", _hoisted_10$8, "arrow_forward")) : (openBlock(), createElementBlock("span", _hoisted_11$5, "check"))
20221
+ ])) : createCommentVNode("", true)
20222
+ ])
20223
+ ])
20224
+ ], 4);
20225
+ };
20226
+ }
20227
+ });
20228
+ const TutorialTooltip_vue_vue_type_style_index_0_scoped_4c5588cd_lang = "";
20229
+ const TutorialTooltip = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-4c5588cd"]]);
20230
+ const _hoisted_1$U = {
20231
+ key: 0,
20232
+ class: "tutorial-overlay"
20233
+ };
20234
+ const _hoisted_2$K = {
20235
+ key: 0,
20236
+ class: "tutorial-backdrop"
20237
+ };
20238
+ const _hoisted_3$D = {
20239
+ class: "tutorial-mask",
20240
+ width: "100%",
20241
+ height: "100%"
20242
+ };
20243
+ const _hoisted_4$u = { id: "spotlight-mask" };
20244
+ const _hoisted_5$p = ["x", "y", "width", "height", "rx"];
20245
+ const _hoisted_6$k = {
20246
+ key: 1,
20247
+ class: "tutorial-backdrop tutorial-backdrop-full"
20248
+ };
20249
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
20250
+ __name: "TutorialOverlay",
20251
+ setup(__props) {
20252
+ const tutorialStore = useTutorialStore();
20253
+ const nodeStore = useFlowStore();
20254
+ const route = useRoute();
20255
+ const isDesignerPage = computed(() => route.name === "designer");
20256
+ const targetRect = ref(null);
20257
+ const tooltipPosition = ref({ x: 0, y: 0 });
20258
+ const previousNodeCount = ref(0);
20259
+ const spotlightStyle = computed(() => {
20260
+ var _a;
20261
+ if (!targetRect.value || !((_a = tutorialStore.currentStep) == null ? void 0 : _a.target)) {
20262
+ return null;
20263
+ }
20264
+ const padding = tutorialStore.currentStep.highlightPadding ?? 8;
20265
+ const rect = targetRect.value;
20266
+ return {
20267
+ left: `${rect.left - padding}px`,
20268
+ top: `${rect.top - padding}px`,
20269
+ width: `${rect.width + padding * 2}px`,
20270
+ height: `${rect.height + padding * 2}px`,
20271
+ borderRadius: tutorialStore.currentStep.spotlightShape === "circle" ? "50%" : "8px"
20272
+ };
20273
+ });
20274
+ const isCenterMode = computed(() => {
20275
+ var _a;
20276
+ return !((_a = tutorialStore.currentStep) == null ? void 0 : _a.target);
20277
+ });
20278
+ function calculateTooltipPosition() {
20279
+ if (!tutorialStore.currentStep)
20280
+ return;
20281
+ const position = tutorialStore.currentStep.position || "bottom";
20282
+ if (isCenterMode.value || position === "center") {
20283
+ tooltipPosition.value = {
20284
+ x: window.innerWidth / 2,
20285
+ y: window.innerHeight / 2
20286
+ };
20287
+ return;
20288
+ }
20289
+ if (!targetRect.value)
20290
+ return;
20291
+ const rect = targetRect.value;
20292
+ const padding = 16;
20293
+ switch (position) {
20294
+ case "top":
20295
+ tooltipPosition.value = {
20296
+ x: rect.left + rect.width / 2,
20297
+ y: rect.top - padding
20298
+ };
20299
+ break;
20300
+ case "bottom":
20301
+ tooltipPosition.value = {
20302
+ x: rect.left + rect.width / 2,
20303
+ y: rect.bottom + padding
20304
+ };
20305
+ break;
20306
+ case "left":
20307
+ tooltipPosition.value = {
20308
+ x: rect.left - padding - 30,
20309
+ // Extra offset to avoid modal overlap
20310
+ y: rect.top + rect.height / 2
20311
+ };
20312
+ break;
20313
+ case "right":
20314
+ tooltipPosition.value = {
20315
+ x: rect.right + padding,
20316
+ y: rect.top + rect.height / 2
20317
+ };
20318
+ break;
20319
+ }
20320
+ }
20321
+ function updateTargetPosition() {
20322
+ var _a;
20323
+ if (!((_a = tutorialStore.currentStep) == null ? void 0 : _a.target)) {
20324
+ targetRect.value = null;
20325
+ calculateTooltipPosition();
20326
+ return;
20327
+ }
20328
+ const targetElement = document.querySelector(tutorialStore.currentStep.target);
20329
+ if (targetElement) {
20330
+ targetRect.value = targetElement.getBoundingClientRect();
20331
+ calculateTooltipPosition();
20332
+ } else {
20333
+ targetRect.value = null;
20334
+ }
20335
+ }
20336
+ watch(
20337
+ () => tutorialStore.currentStep,
20338
+ async (newStep) => {
20339
+ if (!newStep)
20340
+ return;
20341
+ if (newStep.waitForElement) {
20342
+ const maxAttempts = 50;
20343
+ let attempts = 0;
20344
+ while (attempts < maxAttempts) {
20345
+ const element = document.querySelector(newStep.waitForElement);
20346
+ if (element)
20347
+ break;
20348
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
20349
+ attempts++;
20350
+ }
20351
+ }
20352
+ await nextTick();
20353
+ updateTargetPosition();
20354
+ },
20355
+ { immediate: true }
20356
+ );
20357
+ watch(
20358
+ () => nodeStore.flowId,
20359
+ (newFlowId, oldFlowId) => {
20360
+ var _a;
20361
+ if (!tutorialStore.isActive)
20362
+ return;
20363
+ const currentStepId = (_a = tutorialStore.currentStep) == null ? void 0 : _a.id;
20364
+ if (currentStepId === "confirm-create-flow" && newFlowId && newFlowId > 0 && (!oldFlowId || oldFlowId <= 0)) {
20365
+ setTimeout(() => {
20366
+ tutorialStore.nextStep();
20367
+ }, 500);
20368
+ }
20369
+ }
20370
+ );
20371
+ const nodeSettingsWasVisible = ref(false);
20372
+ function checkForNodeSettings() {
20373
+ var _a;
20374
+ if (!tutorialStore.isActive)
20375
+ return;
20376
+ const currentStepId = (_a = tutorialStore.currentStep) == null ? void 0 : _a.id;
20377
+ const nodeSettings = document.querySelector("#nodeSettings");
20378
+ const nodeSettingsIsVisible = nodeSettings !== null;
20379
+ if (currentStepId === "configure-manual-input" && nodeSettingsIsVisible && !nodeSettingsWasVisible.value) {
20380
+ setTimeout(() => {
20381
+ tutorialStore.nextStep();
20382
+ }, 300);
20383
+ }
20384
+ nodeSettingsWasVisible.value = nodeSettingsIsVisible;
20385
+ }
20386
+ function checkForNewNodes() {
20387
+ var _a;
20388
+ if (!tutorialStore.isActive)
20389
+ return;
20390
+ const currentStepId = (_a = tutorialStore.currentStep) == null ? void 0 : _a.id;
20391
+ const nodes = document.querySelectorAll(".vue-flow__node");
20392
+ const currentNodeCount = nodes.length;
20393
+ if (currentStepId === "drag-manual-input" && currentNodeCount > previousNodeCount.value) {
20394
+ setTimeout(() => {
20395
+ tutorialStore.nextStep();
20396
+ }, 300);
20397
+ }
20398
+ if (currentStepId === "drag-group-by" && currentNodeCount > previousNodeCount.value) {
20399
+ setTimeout(() => {
20400
+ tutorialStore.nextStep();
20401
+ }, 300);
20402
+ }
20403
+ if (currentStepId === "drag-write-data" && currentNodeCount > previousNodeCount.value) {
20404
+ setTimeout(() => {
20405
+ tutorialStore.nextStep();
20406
+ }, 300);
20407
+ }
20408
+ previousNodeCount.value = currentNodeCount;
20409
+ }
20410
+ function handleResize() {
20411
+ updateTargetPosition();
20412
+ }
20413
+ function handleScroll2() {
20414
+ updateTargetPosition();
20415
+ }
20416
+ let mutationObserver = null;
20417
+ function setupMutationObserver() {
20418
+ mutationObserver = new MutationObserver(() => {
20419
+ updateTargetPosition();
20420
+ checkForNodeSettings();
20421
+ checkForNewNodes();
20422
+ });
20423
+ mutationObserver.observe(document.body, {
20424
+ childList: true,
20425
+ subtree: true,
20426
+ attributes: true,
20427
+ attributeFilter: ["class", "style"]
20428
+ });
20429
+ }
20430
+ onMounted(() => {
20431
+ window.addEventListener("resize", handleResize);
20432
+ window.addEventListener("scroll", handleScroll2, true);
20433
+ setupMutationObserver();
20434
+ updateTargetPosition();
20435
+ previousNodeCount.value = document.querySelectorAll(".vue-flow__node").length;
20436
+ });
20437
+ onUnmounted(() => {
20438
+ window.removeEventListener("resize", handleResize);
20439
+ window.removeEventListener("scroll", handleScroll2, true);
20440
+ if (mutationObserver) {
20441
+ mutationObserver.disconnect();
20442
+ }
20443
+ });
20444
+ return (_ctx, _cache) => {
20445
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
20446
+ createVNode(Transition, { name: "tutorial-fade" }, {
20447
+ default: withCtx(() => {
20448
+ var _a;
20449
+ return [
20450
+ isDesignerPage.value && unref(tutorialStore).isActive && !unref(tutorialStore).tutorialPaused ? (openBlock(), createElementBlock("div", _hoisted_1$U, [
20451
+ spotlightStyle.value ? (openBlock(), createElementBlock("div", _hoisted_2$K, [
20452
+ (openBlock(), createElementBlock("svg", _hoisted_3$D, [
20453
+ createBaseVNode("defs", null, [
20454
+ createBaseVNode("mask", _hoisted_4$u, [
20455
+ _cache[0] || (_cache[0] = createBaseVNode("rect", {
20456
+ width: "100%",
20457
+ height: "100%",
20458
+ fill: "white"
20459
+ }, null, -1)),
20460
+ spotlightStyle.value ? (openBlock(), createElementBlock("rect", {
20461
+ key: 0,
20462
+ x: parseInt(spotlightStyle.value.left),
20463
+ y: parseInt(spotlightStyle.value.top),
20464
+ width: parseInt(spotlightStyle.value.width),
20465
+ height: parseInt(spotlightStyle.value.height),
20466
+ rx: spotlightStyle.value.borderRadius === "50%" ? parseInt(spotlightStyle.value.width) / 2 : 8,
20467
+ fill: "black"
20468
+ }, null, 8, _hoisted_5$p)) : createCommentVNode("", true)
20469
+ ])
20470
+ ]),
20471
+ _cache[1] || (_cache[1] = createBaseVNode("rect", {
20472
+ width: "100%",
20473
+ height: "100%",
20474
+ fill: "rgba(0, 0, 0, 0.7)",
20475
+ mask: "url(#spotlight-mask)"
20476
+ }, null, -1))
20477
+ ]))
20478
+ ])) : ((_a = unref(tutorialStore).currentStep) == null ? void 0 : _a.centerInScreen) ? (openBlock(), createElementBlock("div", _hoisted_6$k)) : createCommentVNode("", true),
20479
+ spotlightStyle.value ? (openBlock(), createElementBlock("div", {
20480
+ key: 2,
20481
+ class: "tutorial-spotlight",
20482
+ style: normalizeStyle(spotlightStyle.value)
20483
+ }, _cache[2] || (_cache[2] = [
20484
+ createBaseVNode("div", { class: "spotlight-border" }, null, -1)
20485
+ ]), 4)) : createCommentVNode("", true),
20486
+ unref(tutorialStore).currentStep ? (openBlock(), createBlock(TutorialTooltip, {
20487
+ key: 3,
20488
+ step: unref(tutorialStore).currentStep,
20489
+ position: tooltipPosition.value,
20490
+ "is-center-mode": isCenterMode.value,
20491
+ "current-step-index": unref(tutorialStore).currentStepIndex,
20492
+ "total-steps": unref(tutorialStore).totalSteps,
20493
+ progress: unref(tutorialStore).progress,
20494
+ onNext: unref(tutorialStore).nextStep,
20495
+ onPrev: unref(tutorialStore).prevStep,
20496
+ onSkip: unref(tutorialStore).endTutorial,
20497
+ onComplete: unref(tutorialStore).completeTutorial
20498
+ }, null, 8, ["step", "position", "is-center-mode", "current-step-index", "total-steps", "progress", "onNext", "onPrev", "onSkip", "onComplete"])) : createCommentVNode("", true)
20499
+ ])) : createCommentVNode("", true)
20500
+ ];
20501
+ }),
20502
+ _: 1
20503
+ })
20504
+ ]);
20505
+ };
20506
+ }
20507
+ });
20508
+ const TutorialOverlay_vue_vue_type_style_index_0_scoped_cfeb3afc_lang = "";
20509
+ const TutorialOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-cfeb3afc"]]);
20510
+ const gettingStartedTutorial = {
20511
+ id: "getting-started",
20512
+ name: "Getting Started with Flowfile",
20513
+ description: "Learn how to create your first data flow - from input to output",
20514
+ steps: [
20515
+ // Step 1: Welcome
20516
+ {
20517
+ id: "welcome",
20518
+ title: "Welcome to Flowfile!",
20519
+ content: `
20520
+ <p>In this tutorial, you'll learn how to build your first data flow.</p>
20521
+ <p>We'll cover:</p>
20522
+ <ul style="margin: 12px 0; padding-left: 20px;">
20523
+ <li>Creating a new flow</li>
20524
+ <li>Adding data with Manual Input</li>
20525
+ <li>Transforming data with Group By</li>
20526
+ <li>Writing results to a CSV file</li>
20527
+ <li>Running your flow</li>
20528
+ <li>Saving as YAML</li>
20529
+ </ul>
20530
+ <p>Let's get started!</p>
20531
+ `,
20532
+ position: "center",
20533
+ action: "observe",
20534
+ showNextButton: true,
20535
+ showPrevButton: false
20536
+ },
20537
+ // Step 2: Click Quick Create button
20538
+ {
20539
+ id: "click-quick-create",
20540
+ title: "Create a New Flow",
20541
+ content: `
20542
+ <p>First, let's create a new flow.</p>
20543
+ <p>Click the <strong>Quick Create</strong> button to open the flow creation dialog.</p>
20544
+ `,
20545
+ target: "[data-tutorial='quick-create-btn']",
20546
+ position: "bottom",
20547
+ action: "click",
20548
+ showNextButton: false,
20549
+ highlightPadding: 4
20550
+ },
20551
+ // Step 3: Click Create Flow in modal (no highlight - tooltip stays in corner)
20552
+ {
20553
+ id: "confirm-create-flow",
20554
+ title: "Confirm Flow Creation",
20555
+ content: `
20556
+ <p>A dialog appeared where you can optionally name your flow.</p>
20557
+ <p>Click <strong>Create Flow</strong> in the dialog to continue.</p>
20558
+ `,
20559
+ position: "center",
20560
+ action: "observe",
20561
+ showNextButton: false
20562
+ },
20563
+ // Step 4: Explore the canvas
20564
+ {
20565
+ id: "explore-canvas",
20566
+ title: "Your Flow Canvas",
20567
+ content: `
20568
+ <p>This is your <strong>flow canvas</strong> - the workspace where you'll build your data pipelines.</p>
20569
+ <p>On the left, you'll see the <strong>Data Actions</strong> panel with all available nodes organized by category.</p>
20570
+ `,
20571
+ target: ".vue-flow",
20572
+ position: "center",
20573
+ action: "observe",
20574
+ showNextButton: true,
20575
+ highlightPadding: 0
20576
+ },
20577
+ // Step 5: Explore the node list
20578
+ {
20579
+ id: "node-list",
20580
+ title: "Available Nodes",
20581
+ content: `
20582
+ <p>The <strong>Data Actions</strong> panel contains all the nodes you can use:</p>
20583
+ <ul style="margin: 12px 0; padding-left: 20px;">
20584
+ <li><strong>Input Sources</strong> - Load data from files, databases, or manual input</li>
20585
+ <li><strong>Transformations</strong> - Filter, select, sort, and modify data</li>
20586
+ <li><strong>Combine Operations</strong> - Join and merge datasets</li>
20587
+ <li><strong>Aggregations</strong> - Group and summarize data</li>
20588
+ <li><strong>Output Operations</strong> - Write results to files or databases</li>
20589
+ </ul>
20590
+ `,
20591
+ target: "[data-tutorial='node-list']",
20592
+ position: "right",
20593
+ action: "observe",
20594
+ showNextButton: true,
20595
+ highlightPadding: 4
20596
+ },
20597
+ // Step 5: Find Manual Input
20598
+ {
20599
+ id: "find-manual-input",
20600
+ title: "Input Sources",
20601
+ content: `
20602
+ <p>Let's add some data to work with!</p>
20603
+ <p>The <strong>Input Sources</strong> category contains nodes for bringing data into your flow:</p>
20604
+ <ul style="margin: 12px 0; padding-left: 20px;">
20605
+ <li><strong>Read</strong> - Load CSV, Parquet, or other files</li>
20606
+ <li><strong>Manual Input</strong> - Enter sample data directly</li>
20607
+ <li><strong>Database Reader</strong> - Query databases</li>
20608
+ <li><strong>External Source</strong> - Connect to APIs</li>
20609
+ </ul>
20610
+ `,
20611
+ target: "[data-tutorial-category='input']",
20612
+ position: "right",
20613
+ action: "observe",
20614
+ showNextButton: true,
20615
+ highlightPadding: 4
20616
+ },
20617
+ // Step 6: Highlight Manual Input node
20618
+ {
20619
+ id: "drag-manual-input",
20620
+ title: "Drag Manual Input to Canvas",
20621
+ content: `
20622
+ <p>Find <strong>Manual Input</strong> and <strong>drag it</strong> onto the canvas.</p>
20623
+ <p>This node lets you define sample data directly in the flow - perfect for testing!</p>
20624
+ `,
20625
+ target: "[data-tutorial-node='manual_input']",
20626
+ position: "right",
20627
+ action: "drag",
20628
+ actionTarget: ".vue-flow",
20629
+ showNextButton: true,
20630
+ highlightPadding: 4
20631
+ },
20632
+ // Step 7: Node added - click to configure
20633
+ {
20634
+ id: "configure-manual-input",
20635
+ title: "Configure Your Data",
20636
+ content: `
20637
+ <p>Once you've added the node, <strong>click on it</strong> to open its settings.</p>
20638
+ <p>The settings panel will appear on the right where you can define your data columns and values.</p>
20639
+ `,
20640
+ target: ".vue-flow__node",
20641
+ position: "left",
20642
+ action: "click",
20643
+ waitForElement: ".vue-flow__node",
20644
+ showNextButton: true,
20645
+ highlightPadding: 8
20646
+ },
20647
+ // Step 8: Show node settings with sample data suggestion
20648
+ {
20649
+ id: "node-settings",
20650
+ title: "Add Sample Data",
20651
+ content: `
20652
+ <p>The <strong>Node Settings</strong> panel lets you configure your data.</p>
20653
+ <p><strong>Quick option:</strong> Click <strong>Edit JSON</strong> button, paste this sample data, then click <strong>Apply JSON to table</strong>:</p>
20654
+ <div style="background: var(--color-background-muted); padding: 8px; border-radius: 4px; margin: 8px 0; font-family: monospace; font-size: 11px; max-height: 120px; overflow: auto;">
20655
+ [{"country":"USA","product":"Widget","revenue":1000},<br>
20656
+ {"country":"Germany","product":"Gadget","revenue":2500},<br>
20657
+ {"country":"France","product":"Widget","revenue":1800},<br>
20658
+ {"country":"USA","product":"Gadget","revenue":3200},<br>
20659
+ {"country":"Germany","product":"Widget","revenue":1500},<br>
20660
+ {"country":"France","product":"Gadget","revenue":2100}]
20661
+ </div>
20662
+ <p style="font-size: 12px; color: var(--color-text-secondary);">Or manually add columns (country, product, revenue) and rows. Make sure to change the data type of revenue to "integer".</p>
20663
+ `,
20664
+ target: "#nodeSettings",
20665
+ position: "left",
20666
+ action: "observe",
20667
+ waitForElement: "#nodeSettings",
20668
+ showNextButton: true,
20669
+ highlightPadding: 4,
20670
+ onExit: () => {
20671
+ const nodeStore = useNodeStore();
20672
+ nodeStore.nodeId = -1;
20673
+ }
20674
+ },
20675
+ // Step 9: Explore transformations
20676
+ {
20677
+ id: "transformations-overview",
20678
+ title: "Transformation Nodes",
20679
+ content: `
20680
+ <p>Now let's explore the <strong>transformation</strong> options available:</p>
20681
+ <ul style="margin: 12px 0; padding-left: 20px;">
20682
+ <li><strong>Filter</strong> - Keep only rows matching conditions</li>
20683
+ <li><strong>Select</strong> - Choose and rename columns</li>
20684
+ <li><strong>Sort</strong> - Order rows by column values</li>
20685
+ <li><strong>Formula</strong> - Create calculated columns</li>
20686
+ <li><strong>Polars Code</strong> - Write custom Polars code</li>
20687
+ </ul>
20688
+ `,
20689
+ target: "[data-tutorial-category='transform']",
20690
+ position: "right",
20691
+ action: "observe",
20692
+ showNextButton: true,
20693
+ highlightPadding: 4
20694
+ },
20695
+ // Step 10: Aggregations - More prominent Group By explanation
20696
+ {
20697
+ id: "aggregations-overview",
20698
+ title: "Let's Aggregate Your Data!",
20699
+ content: `
20700
+ <p style="font-size: 15px; margin-bottom: 16px;"><strong>Grouping</strong> is one of the most powerful data operations. It lets you summarize data by categories.</p>
20701
+ <p><strong>Example:</strong> With your sales data, you can answer questions like:</p>
20702
+ <ul style="margin: 12px 0; padding-left: 20px;">
20703
+ <li>"What is the <strong>total revenue per country</strong>?"</li>
20704
+ <li>"How many products were sold in each region?"</li>
20705
+ <li>"What's the average order value by product type?"</li>
20706
+ </ul>
20707
+ `,
20708
+ target: "[data-tutorial-category='aggregate']",
20709
+ position: "right",
20710
+ action: "observe",
20711
+ showNextButton: true,
20712
+ highlightPadding: 4
20713
+ },
20714
+ // Step 11: Drag Group By node
20715
+ {
20716
+ id: "drag-group-by",
20717
+ title: "Add Group By Node",
20718
+ content: `
20719
+ <p style="font-size: 15px; padding: 12px; background: var(--color-accent-subtle); color: #1a1a1a; border-radius: 6px; margin-bottom: 12px;">
20720
+ <strong style="color: inherit;">Drag the Group By node</strong> onto the canvas now!
20721
+ </p>
20722
+ <p>This will let you calculate the <strong>total revenue per country</strong> from your sales data.</p>
20723
+ `,
20724
+ target: "[data-tutorial-node='group_by']",
20725
+ position: "right",
20726
+ action: "drag",
20727
+ actionTarget: ".vue-flow",
20728
+ showNextButton: true,
20729
+ highlightPadding: 4
20730
+ },
20731
+ // Step 12: Connect nodes with grouping context
20732
+ {
20733
+ id: "connect-nodes",
20734
+ title: "Connect Your Nodes",
20735
+ content: `
20736
+ <p>To make data flow between nodes, you need to <strong>connect them</strong>.</p>
20737
+ <p>Look for the small circles (handles) on each node:</p>
20738
+ <ul style="margin: 12px 0; padding-left: 20px;">
20739
+ <li><strong>Right side</strong> - Output handle (data goes out)</li>
20740
+ <li><strong>Left side</strong> - Input handle (data comes in)</li>
20741
+ </ul>
20742
+ <p><strong>Click and drag</strong> from Manual Input's output to Group By's input.</p>
20743
+ <p style="margin-top: 12px;">Once connected, click on Group By to configure it - select <strong>country</strong> as the group column and <strong>sum of revenue</strong> as the aggregation!</p>
20744
+ `,
20745
+ target: ".vue-flow",
20746
+ position: "center",
20747
+ action: "observe",
20748
+ showNextButton: true,
20749
+ highlightPadding: 0,
20750
+ onExit: () => {
20751
+ const nodeStore = useNodeStore();
20752
+ nodeStore.nodeId = -1;
20753
+ }
20754
+ },
20755
+ // Step 13: Write data (output operations)
20756
+ {
20757
+ id: "output-overview",
20758
+ title: "Write Your Results",
20759
+ content: `
20760
+ <p>The <strong>Output Operations</strong> section lets you save your results:</p>
20761
+ <ul style="margin: 12px 0; padding-left: 20px;">
20762
+ <li><strong>Write data</strong> - Save to CSV, Parquet, or Excel files</li>
20763
+ <li><strong>Database Writer</strong> - Save to a database</li>
20764
+ <li><strong>Cloud Storage</strong> - Upload to S3, GCS, etc.</li>
20765
+ </ul>
20766
+ `,
20767
+ target: "[data-tutorial-category='output']",
20768
+ position: "right",
20769
+ action: "observe",
20770
+ showNextButton: true,
20771
+ highlightPadding: 4
20772
+ },
20773
+ // Step 13: Drag Write data node
20774
+ {
20775
+ id: "drag-write-data",
20776
+ title: "Add Write Data Node",
20777
+ content: `
20778
+ <p>Now <strong>drag the Write data node</strong> onto the canvas.</p>
20779
+ <p>This will let you save your aggregated revenue per country to a CSV file!</p>
20780
+ <p>After adding it, connect it to the Group By node's output.</p>
20781
+ `,
20782
+ target: "[data-tutorial-node='output']",
20783
+ position: "right",
20784
+ action: "drag",
20785
+ actionTarget: ".vue-flow",
20786
+ showNextButton: true,
20787
+ highlightPadding: 4
20788
+ },
20789
+ // Step 14: Connect and configure nodes
20790
+ {
20791
+ id: "configure-write-data",
20792
+ title: "Connect and Configure Your Nodes",
20793
+ content: `
20794
+ <p>Now it's time to wire everything together!</p>
20795
+ <p><strong>Steps to complete:</strong></p>
20796
+ <ol style="margin: 12px 0; padding-left: 20px;">
20797
+ <li>Connect <strong>Group By → Write data</strong></li>
20798
+ <li>Click on <strong>Write data</strong> to set the output file path</li>
20799
+ </ol>
20800
+ <p style="font-size: 12px; color: var(--color-text-secondary);">Drag from output handles (right side) to input handles (left side) to connect nodes.</p>
20801
+ `,
20802
+ position: "center",
20803
+ action: "observe",
20804
+ showNextButton: true,
20805
+ onExit: () => {
20806
+ const nodeStore = useNodeStore();
20807
+ nodeStore.nodeId = -1;
20808
+ }
20809
+ },
20810
+ // Step 15: Execution settings
20811
+ {
20812
+ id: "execution-settings",
20813
+ title: "Configure Execution Mode",
20814
+ content: `
20815
+ <p>Before running, let's check the <strong>execution settings</strong>.</p>
20816
+ <p>Click the <strong>Settings</strong> button to open execution options.</p>
20817
+ <p>Make sure <strong>Development</strong> mode is selected - this gives you detailed feedback and is perfect for building and testing flows!</p>
20818
+ `,
20819
+ target: "[data-tutorial='settings-btn']",
20820
+ position: "bottom",
20821
+ action: "observe",
20822
+ showNextButton: true,
20823
+ highlightPadding: 4
20824
+ },
20825
+ // Step 16: Run the flow
20826
+ {
20827
+ id: "run-flow",
20828
+ title: "Run Your Flow",
20829
+ content: `
20830
+ <p>Now click <strong>Run</strong> to execute your flow!</p>
20831
+ <p>Flowfile will process your data through each node in sequence.</p>
20832
+ <p>Watch the nodes change color as they execute:</p>
20833
+ <ul style="margin: 12px 0; padding-left: 20px;">
20834
+ <li><strong>Blue</strong> - Currently running</li>
20835
+ <li><strong>Green</strong> - Completed successfully</li>
20836
+ <li><strong>Red</strong> - Error occurred</li>
20837
+ </ul>
20838
+ `,
20839
+ target: "[data-tutorial='run-btn']",
20840
+ position: "bottom",
20841
+ action: "observe",
20842
+ showNextButton: true,
20843
+ highlightPadding: 4
20844
+ },
20845
+ // Step 16: View results and explore pipeline
20846
+ {
20847
+ id: "view-results",
20848
+ title: "Explore Your Results",
20849
+ content: `
20850
+ <p style="font-size: 15px;">Wait for the success message and then your flow has finished running!</p>
20851
+ <p><strong>Click on any node</strong> to see its output in the Table Preview below.</p>
20852
+ <p>Try clicking on different nodes:</p>
20853
+ <ul style="margin: 12px 0; padding-left: 20px;">
20854
+ <li><strong>Manual Input</strong> - Your raw sales data</li>
20855
+ <li><strong>Group By</strong> - Total revenue per country</li>
20856
+ <li><strong>Write data</strong> - Final output to be saved</li>
20857
+ </ul>
20858
+ <p style="font-size: 12px; color: var(--color-text-secondary);"><strong>Tip:</strong> If you don't see any data, make sure you have set up the flow to run in Development mode.</p>
20859
+ `,
20860
+ position: "center",
20861
+ action: "observe",
20862
+ showNextButton: true
20863
+ },
20864
+ // Step 17: Save the flow
20865
+ {
20866
+ id: "save-flow",
20867
+ title: "Save Your Flow",
20868
+ content: `
20869
+ <p>Let's save your flow so you can use it again!</p>
20870
+ <p>Click the <strong>Save</strong> button to choose where to save your flow file.</p>
20871
+ `,
20872
+ target: "[data-tutorial='save-btn']",
20873
+ position: "bottom",
20874
+ action: "observe",
20875
+ showNextButton: true,
20876
+ highlightPadding: 4
20877
+ },
20878
+ // Step 18: YAML format explanation
20879
+ {
20880
+ id: "yaml-format",
20881
+ title: "Flows are Saved as YAML",
20882
+ content: `
20883
+ <p>Flowfile saves your flows in <strong>YAML format</strong> (.yaml or .yml).</p>
20884
+ <p>This means your flows are:</p>
20885
+ <ul style="margin: 12px 0; padding-left: 20px;">
20886
+ <li><strong>Human-readable</strong> - Open and edit in any text editor</li>
20887
+ <li><strong>Version-control friendly</strong> - Track changes with Git</li>
20888
+ <li><strong>Portable</strong> - Share flows with your team</li>
20889
+ <li><strong>Scriptable</strong> - Run from command line</li>
20890
+ </ul>
20891
+ <p>You can even edit your flows manually if needed!</p>
20892
+ `,
20893
+ position: "center",
20894
+ action: "observe",
20895
+ showNextButton: true,
20896
+ centerInScreen: true
20897
+ },
20898
+ // Step 19: Generate code
20899
+ {
20900
+ id: "generate-code",
20901
+ title: "Generate Python Code",
20902
+ content: `
20903
+ <p>Want to use your flow in Python?</p>
20904
+ <p>Click <strong>Generate Code</strong> to export your flow as Python/Polars code!</p>
20905
+ <p>This is great for:</p>
20906
+ <ul style="margin: 12px 0; padding-left: 20px;">
20907
+ <li>Integrating with Python projects</li>
20908
+ <li>Learning how Polars works</li>
20909
+ <li>Creating production pipelines</li>
20910
+ </ul>
20911
+ `,
20912
+ target: "[data-tutorial='generate-code-btn']",
20913
+ position: "bottom",
20914
+ action: "click",
20915
+ showNextButton: true,
20916
+ highlightPadding: 4
20917
+ },
20918
+ // Step 20: Code preview
20919
+ {
20920
+ id: "code-preview",
20921
+ title: "Your Python Code",
20922
+ content: `
20923
+ <p>Here's your flow as <strong>Python/Polars code</strong>!</p>
20924
+ <p>You can:</p>
20925
+ <ul style="margin: 12px 0; padding-left: 20px;">
20926
+ <li>Click <strong>Export Code</strong> to save as a .py file</li>
20927
+ <li>Copy the code directly from the editor</li>
20928
+ <li>Click <strong>Refresh</strong> to regenerate after changes</li>
20929
+ </ul>
20930
+ <p>The code is fully functional and can run standalone!</p>
20931
+ `,
20932
+ position: "center",
20933
+ action: "observe",
20934
+ showNextButton: true
20935
+ },
20936
+ // Step 21: Keyboard shortcuts
20937
+ {
20938
+ id: "keyboard-shortcuts",
20939
+ title: "Keyboard Shortcuts",
20940
+ content: `
20941
+ <p>Speed up your workflow with keyboard shortcuts:</p>
20942
+ <ul style="margin: 12px 0; padding-left: 20px;">
20943
+ <li><strong>Ctrl+S</strong> - Save flow</li>
20944
+ <li><strong>Ctrl+E</strong> - Run flow</li>
20945
+ <li><strong>Ctrl+G</strong> - Generate code</li>
20946
+ <li><strong>Ctrl+N</strong> - Quick create new flow</li>
20947
+ <li><strong>Ctrl+C/V</strong> - Copy/paste nodes</li>
20948
+ <li><strong>Delete</strong> - Remove selected node</li>
20949
+ </ul>
20950
+ `,
20951
+ position: "center",
20952
+ action: "observe",
20953
+ showNextButton: true
20954
+ },
20955
+ // Step 22: Completion
20956
+ {
20957
+ id: "completion",
20958
+ title: "Congratulations!",
20959
+ content: `
20960
+ <p>You've completed the Getting Started tutorial!</p>
20961
+ <p>You now know how to:</p>
20962
+ <ul style="margin: 12px 0; padding-left: 20px;">
20963
+ <li>Create a new flow</li>
20964
+ <li>Add and configure nodes</li>
20965
+ <li>Connect nodes to build pipelines</li>
20966
+ <li>Run your flow and preview data</li>
20967
+ <li>Save and export your work</li>
20968
+ </ul>
20969
+ <p style="margin-top: 16px;">
20970
+ <strong>Learn more:</strong> Visit our
20971
+ <a href="https://edwardvaneechoud.github.io/Flowfile/" target="_blank" style="color: var(--color-accent); text-decoration: underline;">documentation</a>
20972
+ for advanced features and more tutorials.
20973
+ </p>
20974
+ `,
20975
+ position: "center",
20976
+ action: "observe",
20977
+ showNextButton: true,
20978
+ showPrevButton: false,
20979
+ canSkip: false,
20980
+ centerInScreen: true
20981
+ }
20982
+ ]
20983
+ };
20984
+ const _hoisted_1$T = {
20985
+ key: 0,
20986
+ class: "tutorial-start-container"
20987
+ };
20988
+ const DISMISSED_KEY = "flowfile-tutorial-dismissed";
20989
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
20990
+ __name: "TutorialStartButton",
20991
+ setup(__props) {
20992
+ const tutorialStore = useTutorialStore();
20993
+ const nodeStore = useNodeStore();
20994
+ const route = useRoute();
20995
+ const isDismissed = ref(false);
20996
+ onMounted(() => {
20997
+ isDismissed.value = localStorage.getItem(DISMISSED_KEY) === "true";
20998
+ });
20999
+ const showButton = computed(() => {
21000
+ const isDesignerPage = route.name === "designer";
21001
+ const hasNoFlow = !nodeStore.flow_id || nodeStore.flow_id <= 0;
21002
+ return isDesignerPage && hasNoFlow && !tutorialStore.isActive && !isDismissed.value;
21003
+ });
21004
+ function startTutorial() {
21005
+ tutorialStore.startTutorial(gettingStartedTutorial);
21006
+ }
21007
+ function dismissButton() {
21008
+ isDismissed.value = true;
21009
+ localStorage.setItem(DISMISSED_KEY, "true");
21010
+ }
21011
+ return (_ctx, _cache) => {
21012
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
21013
+ createVNode(Transition, { name: "float-in" }, {
21014
+ default: withCtx(() => [
21015
+ showButton.value ? (openBlock(), createElementBlock("div", _hoisted_1$T, [
21016
+ createBaseVNode("button", {
21017
+ class: "tutorial-dismiss-btn",
21018
+ title: "Dismiss",
21019
+ onClick: dismissButton
21020
+ }, _cache[0] || (_cache[0] = [
21021
+ createBaseVNode("span", { class: "material-icons" }, "close", -1)
21022
+ ])),
21023
+ createBaseVNode("button", {
21024
+ class: "tutorial-start-btn",
21025
+ onClick: startTutorial
21026
+ }, _cache[1] || (_cache[1] = [
21027
+ createBaseVNode("span", { class: "btn-icon material-icons" }, "school", -1),
21028
+ createBaseVNode("div", { class: "btn-content" }, [
21029
+ createBaseVNode("span", { class: "btn-title" }, "New to Flowfile?"),
21030
+ createBaseVNode("span", { class: "btn-subtitle" }, "Start the interactive tutorial")
21031
+ ], -1),
21032
+ createBaseVNode("span", { class: "btn-arrow material-icons" }, "arrow_forward", -1)
21033
+ ]))
21034
+ ])) : createCommentVNode("", true)
21035
+ ]),
21036
+ _: 1
21037
+ })
21038
+ ]);
21039
+ };
21040
+ }
21041
+ });
21042
+ const TutorialStartButton_vue_vue_type_style_index_0_scoped_36f83d99_lang = "";
21043
+ const TutorialStartButton = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-36f83d99"]]);
18998
21044
  const _hoisted_1$S = { class: "app-layout" };
18999
21045
  const _hoisted_2$J = { class: "app-layout__content" };
19000
21046
  const _hoisted_3$C = { class: "app-layout__page" };
@@ -19031,7 +21077,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
19031
21077
  createBaseVNode("div", {
19032
21078
  class: normalizeClass(["app-layout__sidebar-wrapper", { minimized: isCollapse.value }])
19033
21079
  }, [
19034
- createVNode(_sfc_main$3, {
21080
+ createVNode(_sfc_main$6, {
19035
21081
  "is-collapse": isCollapse.value,
19036
21082
  onToggleCollapse: toggleCollapse
19037
21083
  }, null, 8, ["is-collapse"])
@@ -19045,21 +21091,82 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
19045
21091
  "is-forced": true,
19046
21092
  onClose: _cache[0] || (_cache[0] = ($event) => showPasswordModal.value = false),
19047
21093
  onSuccess: handlePasswordChanged
19048
- }, null, 8, ["show"])
21094
+ }, null, 8, ["show"]),
21095
+ createVNode(TutorialOverlay),
21096
+ createVNode(TutorialStartButton)
19049
21097
  ]);
19050
21098
  };
19051
21099
  }
19052
21100
  });
19053
21101
  const AppLayout_vue_vue_type_style_index_0_lang = "";
21102
+ class SetupService {
21103
+ constructor() {
21104
+ __publicField(this, "cachedStatus", null);
21105
+ __publicField(this, "statusPromise", null);
21106
+ }
21107
+ async getSetupStatus(forceRefresh = false) {
21108
+ if (!forceRefresh && this.cachedStatus) {
21109
+ return this.cachedStatus;
21110
+ }
21111
+ if (this.statusPromise) {
21112
+ return this.statusPromise;
21113
+ }
21114
+ this.statusPromise = this.fetchStatus();
21115
+ try {
21116
+ this.cachedStatus = await this.statusPromise;
21117
+ return this.cachedStatus;
21118
+ } finally {
21119
+ this.statusPromise = null;
21120
+ }
21121
+ }
21122
+ async fetchStatus() {
21123
+ const maxRetries = 5;
21124
+ const retryDelay = 1e3;
21125
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
21126
+ try {
21127
+ const response = await axios$1.get("/health/status", {
21128
+ headers: { "X-Skip-Auth-Header": "true" },
21129
+ timeout: 5e3
21130
+ });
21131
+ return response.data;
21132
+ } catch {
21133
+ if (attempt < maxRetries) {
21134
+ await new Promise((resolve2) => setTimeout(resolve2, retryDelay));
21135
+ }
21136
+ }
21137
+ }
21138
+ return {
21139
+ setup_required: true,
21140
+ master_key_configured: false,
21141
+ mode: "unknown"
21142
+ };
21143
+ }
21144
+ async generateKey() {
21145
+ const response = await axios$1.post("/setup/generate-key", null, {
21146
+ headers: { "X-Skip-Auth-Header": "true" }
21147
+ });
21148
+ return response.data;
21149
+ }
21150
+ clearCache() {
21151
+ this.cachedStatus = null;
21152
+ }
21153
+ }
21154
+ const setupService = new SetupService();
19054
21155
  const routes = [
19055
21156
  {
19056
21157
  path: "/",
19057
21158
  redirect: "/main"
19058
21159
  },
21160
+ {
21161
+ path: "/setup",
21162
+ name: "setup",
21163
+ component: () => __vitePreload(() => import("./SetupView-2d12e01f.js"), true ? ["assets/SetupView-2d12e01f.js","assets/SetupView-ec26f76a.css"] : void 0),
21164
+ meta: { requiresAuth: false, isSetupPage: true }
21165
+ },
19059
21166
  {
19060
21167
  path: "/login",
19061
21168
  name: "login",
19062
- component: () => __vitePreload(() => import("./LoginView-0df4ed0a.js"), true ? ["assets/LoginView-0df4ed0a.js","assets/LoginView-d325d632.css"] : void 0),
21169
+ component: () => __vitePreload(() => import("./LoginView-c33a246a.js"), true ? ["assets/LoginView-c33a246a.js","assets/LoginView-d325d632.css"] : void 0),
19063
21170
  meta: { requiresAuth: false }
19064
21171
  },
19065
21172
  {
@@ -19075,42 +21182,42 @@ const routes = [
19075
21182
  {
19076
21183
  path: "designer",
19077
21184
  name: "designer",
19078
- component: () => __vitePreload(() => import("./DesignerView-e6f5c0e8.js").then((n) => n.D), true ? ["assets/DesignerView-e6f5c0e8.js","assets/PopOver-b22f049e.js","assets/PopOver-d96599db.css","assets/index-3ba44389.js","assets/vue-codemirror.esm-0965f39f.js","assets/DesignerView-a6d0ee84.css"] : void 0)
21185
+ component: () => __vitePreload(() => import("./DesignerView-a4466dab.js").then((n) => n.D), true ? ["assets/DesignerView-a4466dab.js","assets/PopOver-ddcfe4f6.js","assets/PopOver-d96599db.css","assets/index-057d770d.js","assets/vue-codemirror.esm-8f46fb36.js","assets/DesignerView-71d4e9a1.css"] : void 0)
19079
21186
  },
19080
21187
  {
19081
21188
  name: "nodeData",
19082
21189
  path: "nodeData",
19083
- component: () => __vitePreload(() => import("./fullEditor-5497a84a.js"), true ? ["assets/fullEditor-5497a84a.js","assets/PopOver-b22f049e.js","assets/PopOver-d96599db.css","assets/vue-codemirror.esm-0965f39f.js","assets/fullEditor-a0be62b3.css"] : void 0)
21190
+ component: () => __vitePreload(() => import("./fullEditor-7583bef5.js"), true ? ["assets/fullEditor-7583bef5.js","assets/PopOver-ddcfe4f6.js","assets/PopOver-d96599db.css","assets/vue-codemirror.esm-8f46fb36.js","assets/fullEditor-fe9f7e18.css"] : void 0)
19084
21191
  },
19085
21192
  {
19086
21193
  name: "documentation",
19087
21194
  path: "documentation",
19088
- component: () => __vitePreload(() => import("./DocumentationView-2e78ef1b.js"), true ? ["assets/DocumentationView-2e78ef1b.js","assets/DocumentationView-fd46c656.css"] : void 0)
21195
+ component: () => __vitePreload(() => import("./DocumentationView-979afc84.js"), true ? ["assets/DocumentationView-979afc84.js","assets/DocumentationView-9ea6e871.css"] : void 0)
19089
21196
  },
19090
21197
  {
19091
21198
  name: "databaseManager",
19092
21199
  path: "databaseManager",
19093
- component: () => __vitePreload(() => import("./DatabaseView-d26a9140.js"), true ? ["assets/DatabaseView-d26a9140.js","assets/api-24483f0d.js","assets/DatabaseView-6655afd6.css"] : void 0)
21200
+ component: () => __vitePreload(() => import("./DatabaseView-dc877c29.js"), true ? ["assets/DatabaseView-dc877c29.js","assets/api-df48ec50.js","assets/DatabaseView-6655afd6.css"] : void 0)
19094
21201
  },
19095
21202
  {
19096
21203
  name: "cloudConnectionManager",
19097
21204
  path: "cloudConnectionManager",
19098
- component: () => __vitePreload(() => import("./CloudConnectionView-f13f202b.js"), true ? ["assets/CloudConnectionView-f13f202b.js","assets/api-8b81fa73.js","assets/CloudConnectionView-36bcd6df.css"] : void 0)
21205
+ component: () => __vitePreload(() => import("./CloudConnectionView-7a3042c6.js"), true ? ["assets/CloudConnectionView-7a3042c6.js","assets/api-ee542cf7.js","assets/CloudConnectionView-cf85f943.css"] : void 0)
19099
21206
  },
19100
21207
  {
19101
21208
  name: "secretManager",
19102
21209
  path: "secretManager",
19103
- component: () => __vitePreload(() => import("./SecretsView-17df66ee.js"), true ? ["assets/SecretsView-17df66ee.js","assets/secrets.api-002e7d7e.js","assets/SecretsView-aa291340.css"] : void 0)
21210
+ component: () => __vitePreload(() => import("./SecretsView-c6afc915.js"), true ? ["assets/SecretsView-c6afc915.js","assets/secrets.api-34431884.js","assets/SecretsView-aa291340.css"] : void 0)
19104
21211
  },
19105
21212
  {
19106
21213
  name: "nodeDesigner",
19107
21214
  path: "nodeDesigner",
19108
- component: () => __vitePreload(() => import("./NodeDesigner-40b647c9.js"), true ? ["assets/NodeDesigner-40b647c9.js","assets/vue-codemirror.esm-0965f39f.js","assets/index-3ba44389.js","assets/NodeDesigner-5f53be3f.css"] : void 0)
21215
+ component: () => __vitePreload(() => import("./NodeDesigner-5036c392.js"), true ? ["assets/NodeDesigner-5036c392.js","assets/vue-codemirror.esm-8f46fb36.js","assets/index-057d770d.js","assets/NodeDesigner-94cd4dd3.css"] : void 0)
19109
21216
  },
19110
21217
  {
19111
21218
  name: "admin",
19112
21219
  path: "admin",
19113
- component: () => __vitePreload(() => import("./AdminView-49392a9a.js"), true ? ["assets/AdminView-49392a9a.js","assets/AdminView-f53bad23.css"] : void 0),
21220
+ component: () => __vitePreload(() => import("./AdminView-c2c7942b.js"), true ? ["assets/AdminView-c2c7942b.js","assets/AdminView-f53bad23.css"] : void 0),
19114
21221
  meta: { requiresAdmin: true, hideInElectron: true }
19115
21222
  }
19116
21223
  ]
@@ -19124,10 +21231,39 @@ const router = createRouter({
19124
21231
  history: createWebHashHistory("/"),
19125
21232
  routes
19126
21233
  });
21234
+ let setupChecked = false;
21235
+ let setupRequired = false;
19127
21236
  router.beforeEach(async (to, _from, next) => {
19128
21237
  const authStore = useAuthStore();
19129
21238
  const requiresAuth = to.matched.some((record) => record.meta.requiresAuth !== false);
19130
21239
  const hideInElectron = to.matched.some((record) => record.meta.hideInElectron);
21240
+ const isSetupPage = to.matched.some((record) => record.meta.isSetupPage);
21241
+ if (!setupChecked || isSetupPage) {
21242
+ try {
21243
+ const status = await setupService.getSetupStatus(isSetupPage);
21244
+ authService.setModeFromBackend(status.mode);
21245
+ setupRequired = status.setup_required;
21246
+ setupChecked = status.mode !== "unknown";
21247
+ } catch {
21248
+ setupRequired = true;
21249
+ setupChecked = false;
21250
+ }
21251
+ }
21252
+ if (!authService.isInElectronMode()) {
21253
+ if (setupRequired && !isSetupPage) {
21254
+ next({ name: "setup" });
21255
+ return;
21256
+ }
21257
+ if (!setupRequired && isSetupPage) {
21258
+ next({ name: "login" });
21259
+ return;
21260
+ }
21261
+ } else {
21262
+ if (isSetupPage) {
21263
+ next({ name: "designer" });
21264
+ return;
21265
+ }
21266
+ }
19131
21267
  if (authService.isAuthenticated() && !authStore.user) {
19132
21268
  await authStore.initialize();
19133
21269
  }
@@ -60499,52 +62635,6 @@ const i18n = createI18n({
60499
62635
  });
60500
62636
  const all2 = "";
60501
62637
  const main = "";
60502
- const flowfileCorebaseURL = "http://localhost:63578/";
60503
- axios$1.defaults.baseURL = flowfileCorebaseURL;
60504
- axios$1.defaults.withCredentials = true;
60505
- axios$1.interceptors.request.use(
60506
- async (config) => {
60507
- if (config.headers && config.headers["X-Skip-Auth-Header"]) {
60508
- delete config.headers["X-Skip-Auth-Header"];
60509
- return config;
60510
- }
60511
- try {
60512
- const token = await authService.getToken();
60513
- if (token) {
60514
- config.headers = config.headers || {};
60515
- config.headers.Authorization = `Bearer ${token}`;
60516
- }
60517
- return config;
60518
- } catch (error) {
60519
- console.error("Error in request interceptor:", error);
60520
- return config;
60521
- }
60522
- },
60523
- (error) => {
60524
- return Promise.reject(error);
60525
- }
60526
- );
60527
- axios$1.interceptors.response.use(
60528
- (response) => {
60529
- return response;
60530
- },
60531
- async (error) => {
60532
- var _a;
60533
- const originalRequest = error.config;
60534
- if (((_a = error.response) == null ? void 0 : _a.status) === 401 && !originalRequest._retry) {
60535
- originalRequest._retry = true;
60536
- try {
60537
- await authService.getToken();
60538
- return axios$1(originalRequest);
60539
- } catch (refreshError) {
60540
- console.error("Token refresh failed:", refreshError);
60541
- authService.logout();
60542
- return Promise.reject(error);
60543
- }
60544
- }
60545
- return Promise.reject(error);
60546
- }
60547
- );
60548
62638
  const app = createApp(App);
60549
62639
  app.directive("click-outside", ClickOutsideDirective);
60550
62640
  app.use(stores);
@@ -60572,92 +62662,99 @@ authService.initialize().then((authenticated) => {
60572
62662
  }
60573
62663
  });
60574
62664
  export {
60575
- onBeforeUnmount as $,
60576
- computed as A,
60577
- watch as B,
60578
- onMounted as C,
60579
- renderList as D,
62665
+ isRef as $,
62666
+ withCtx as A,
62667
+ unref as B,
62668
+ createBlock as C,
62669
+ defineStore as D,
60580
62670
  ElNotification as E,
60581
- Fragment as F,
60582
- withKeys as G,
60583
- ElMessage as H,
60584
- ElMessageBox as I,
60585
- inject as J,
60586
- effectScope as K,
60587
- provide as L,
60588
- getCurrentInstance as M,
60589
- getCurrentScope as N,
60590
- onScopeDispose as O,
60591
- createPropsRestProxy as P,
60592
- toRef as Q,
60593
- renderSlot as R,
60594
- reactive as S,
60595
- useSlots as T,
60596
- isRef as U,
60597
- toRefs as V,
60598
- customRef as W,
60599
- nextTick as X,
60600
- onBeforeMount as Y,
60601
- normalizeStyle as Z,
62671
+ getDefaultExportFromCjs as F,
62672
+ computed as G,
62673
+ watch as H,
62674
+ onActivated as I,
62675
+ onMounted as J,
62676
+ Fragment as K,
62677
+ renderList as L,
62678
+ withKeys as M,
62679
+ ElMessage as N,
62680
+ ElMessageBox as O,
62681
+ inject as P,
62682
+ effectScope as Q,
62683
+ provide as R,
62684
+ getCurrentInstance as S,
62685
+ getCurrentScope as T,
62686
+ onScopeDispose as U,
62687
+ createPropsRestProxy as V,
62688
+ toRef as W,
62689
+ renderSlot as X,
62690
+ reactive as Y,
62691
+ useSlots as Z,
60602
62692
  _imports_1 as _,
60603
- useAuthStore as a,
60604
- isMemoSame as a0,
60605
- toValue as a1,
60606
- shallowRef as a2,
60607
- h$1 as a3,
60608
- markRaw as a4,
60609
- readonly as a5,
60610
- useAttrs$1 as a6,
60611
- mergeProps as a7,
60612
- resolveDynamicComponent as a8,
60613
- watchEffect as a9,
60614
- normalizeProps as aa,
60615
- defineAsyncComponent as ab,
60616
- onErrorCaptured as ac,
60617
- __vitePreload as ad,
60618
- Teleport as ae,
60619
- guardReactiveProps as af,
60620
- Transition as ag,
60621
- render$$ as ah,
60622
- vShow as ai,
60623
- authService as aj,
60624
- flowfileCorebaseURL as ak,
60625
- useCssVars as al,
60626
- vModelSelect as am,
60627
- vModelCheckbox as an,
60628
- ElDialog as ao,
60629
- ElButton as ap,
60630
- toRaw as aq,
60631
- ElRadio as ar,
60632
- useThemeStore as as,
60633
- debounce$2 as at,
60634
- ElIcon as au,
60635
- ElPopover as av,
60636
- ElOption$1 as aw,
60637
- ElSelect as ax,
60638
- createBaseVNode as b,
62693
+ createBaseVNode as a,
62694
+ toRefs as a0,
62695
+ customRef as a1,
62696
+ nextTick as a2,
62697
+ onBeforeMount as a3,
62698
+ normalizeStyle as a4,
62699
+ onBeforeUnmount as a5,
62700
+ isMemoSame as a6,
62701
+ toValue as a7,
62702
+ shallowRef as a8,
62703
+ h$1 as a9,
62704
+ useThemeStore as aA,
62705
+ debounce$2 as aB,
62706
+ ElPopover as aC,
62707
+ ElOption$1 as aD,
62708
+ ElSelect as aE,
62709
+ markRaw as aa,
62710
+ readonly as ab,
62711
+ useAttrs$1 as ac,
62712
+ mergeProps as ad,
62713
+ resolveDynamicComponent as ae,
62714
+ watchEffect as af,
62715
+ normalizeProps as ag,
62716
+ defineAsyncComponent as ah,
62717
+ onErrorCaptured as ai,
62718
+ __vitePreload as aj,
62719
+ useFlowStore as ak,
62720
+ Teleport as al,
62721
+ guardReactiveProps as am,
62722
+ Transition as an,
62723
+ render$$ as ao,
62724
+ vShow as ap,
62725
+ authService as aq,
62726
+ flowfileCorebaseURL as ar,
62727
+ useCssVars as as,
62728
+ vModelSelect as at,
62729
+ vModelCheckbox as au,
62730
+ ElDialog as av,
62731
+ ElButton as aw,
62732
+ toRaw as ax,
62733
+ ElIcon as ay,
62734
+ ElRadio as az,
62735
+ createStaticVNode as b,
60639
62736
  createElementBlock as c,
60640
62737
  defineComponent as d,
60641
- createStaticVNode as e,
60642
- createCommentVNode as f,
60643
- withDirectives as g,
60644
- vModelDynamic as h,
60645
- _export_sfc as i,
60646
- axios$1 as j,
60647
- onUnmounted as k,
60648
- resolveComponent as l,
60649
- createVNode as m,
62738
+ createCommentVNode as e,
62739
+ createTextVNode as f,
62740
+ _export_sfc as g,
62741
+ useAuthStore as h,
62742
+ withDirectives as i,
62743
+ vModelDynamic as j,
62744
+ axios$1 as k,
62745
+ useNodeStore as l,
62746
+ useEditorStore as m,
60650
62747
  normalizeClass as n,
60651
62748
  openBlock as o,
60652
- withCtx as p,
60653
- createTextVNode as q,
62749
+ useResultsStore as p,
62750
+ onUnmounted as q,
60654
62751
  ref as r,
60655
- unref as s,
62752
+ setupService as s,
60656
62753
  toDisplayString$1 as t,
60657
62754
  useRouter as u,
60658
62755
  vModelText as v,
60659
62756
  withModifiers as w,
60660
- createBlock as x,
60661
- defineStore as y,
60662
- getDefaultExportFromCjs as z
62757
+ useTutorialStore as x,
62758
+ resolveComponent as y,
62759
+ createVNode as z
60663
62760
  };