n8n-editor-ui 1.93.0 → 1.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/assets/{AnimatedSpinner-hbTZDd93.js → AnimatedSpinner-DlBYfeum.js} +1 -1
  2. package/dist/assets/{AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-CYzc5StE.js → AnnotationTagsDropdown.ee.vue_vue_type_script_setup_true_lang-b_VpBPcV.js} +1 -1
  3. package/dist/assets/{AuthView-8SLMP0H_.js → AuthView-3BmNl_WD.js} +2 -2
  4. package/dist/assets/{CanvasChatSwitch-Dt8TgNJg.js → CanvasChatSwitch-C8GVNbZv.js} +16 -18
  5. package/dist/assets/{ChangePasswordView-DIRyDp89.js → ChangePasswordView-HptU1MSc.js} +3 -3
  6. package/dist/assets/CollectionParameter-DB_Or-wG.js +4 -0
  7. package/dist/assets/{CredentialsView-B6-VxAJ6.js → CredentialsView-Dx5hgaaC.js} +7 -7
  8. package/dist/assets/{DemoFooter-CIHwH5PG.js → DemoFooter-BkSVK4cp.js} +6 -8
  9. package/dist/assets/{ErrorView-C7i0TZwT.js → ErrorView-HDHwqLgc.js} +1 -1
  10. package/dist/assets/EvaluationsRootView-B5AhHo41.css +594 -0
  11. package/dist/assets/EvaluationsRootView-CwzFA39P.js +654 -0
  12. package/dist/assets/{TestDefinitionListView-Di-Edppe.css → EvaluationsView-6l_Invxt.css} +193 -76
  13. package/dist/assets/EvaluationsView-Y_Nzp-LP.js +570 -0
  14. package/dist/assets/{ExecutionsTime.vue_vue_type_script_setup_true_lang--2G21NNR.js → ExecutionsTime.vue_vue_type_script_setup_true_lang-BioZloew.js} +2 -2
  15. package/dist/assets/{ExecutionsView-C_YtciAr.js → ExecutionsView-SVk21vMq.js} +18 -18
  16. package/dist/assets/{FileSaver.min-bgn7Q9Gt.js → FileSaver.min-ZbRn_Jz1.js} +1 -1
  17. package/dist/assets/{FixedCollectionParameter-BPCJ5aaq.js → FixedCollectionParameter-iCfhPCTX.js} +1 -1
  18. package/dist/assets/{ForgotMyPasswordView-DyUaGd6Z.js → ForgotMyPasswordView-DID5un7M.js} +3 -3
  19. package/dist/assets/{InsightsChartAverageRuntime-BB2I2vpV.js → InsightsChartAverageRuntime-Db4OWo7M.js} +4 -4
  20. package/dist/assets/{InsightsChartFailed-CN_Rl3Bl.js → InsightsChartFailed-DjssZ9vc.js} +4 -4
  21. package/dist/assets/{InsightsChartFailureRate-CHKlg6tg.js → InsightsChartFailureRate-C4U_fOhA.js} +4 -4
  22. package/dist/assets/{InsightsChartTimeSaved-Cd05cM8q.js → InsightsChartTimeSaved-DmcamM8z.js} +4 -4
  23. package/dist/assets/{InsightsChartTotal-ChAO7myf.js → InsightsChartTotal-ywrK30zz.js} +4 -4
  24. package/dist/assets/{InsightsDashboard-Bx4vx9gz.css → InsightsDashboard-BSrakbzr.css} +42 -8
  25. package/dist/assets/{InsightsDashboard-BeCfBVUz.js → InsightsDashboard-CM-ieUCq.js} +43 -41
  26. package/dist/assets/{InsightsPaywall-Chz8CDc3.js → InsightsPaywall-D-bIgmwT.js} +1 -1
  27. package/dist/assets/InsightsSummary-CwTpu3sa.js +209 -0
  28. package/dist/assets/{InsightsSummary-CdlaUpAt.css → InsightsSummary-DzGQpM5h.css} +27 -24
  29. package/dist/assets/{InsightsTableWorkflows-5rpYY7YT.js → InsightsTableWorkflows-CVtm_fGN.js} +5 -6
  30. package/dist/assets/{InsightsTableWorkflows-Blv_GPUj.css → InsightsTableWorkflows-DfTZQkWL.css} +3 -4
  31. package/dist/assets/{Logo-DUDCllkm.js → Logo-nyJoHWQJ.js} +1 -1
  32. package/dist/assets/{LogsPanel-mTaFEGk_.css → LogsPanel-D7j-yJQx.css} +14 -14
  33. package/dist/assets/{LogsPanel-D9r5AcQH.js → LogsPanel-mX9Nf6VB.js} +457 -360
  34. package/dist/assets/{MainHeader-DkKOOZ_D.js → MainHeader-DrG-_mAG.js} +35 -25
  35. package/dist/assets/{MainHeader-CEMGASqv.css → MainHeader-Y95RcfHb.css} +18 -18
  36. package/dist/assets/{MainSidebar-ZUBIWeXm.js → MainSidebar-BMWCsLJG.js} +2 -2
  37. package/dist/assets/{NodeCreation-DCfAFuL5.js → NodeCreation-CO1xHNgA.js} +3 -4
  38. package/dist/assets/{NodeCreator-a0YVv1IE.js → NodeCreator-Bcr66G_2.js} +174 -69
  39. package/dist/assets/{NodeCreator-D18StsVZ.css → NodeCreator-Cp8Apzva.css} +38 -21
  40. package/dist/assets/{NodeDetailsView-C5_hVJzj.js → NodeDetailsView-BFW65Lly.js} +42 -19
  41. package/dist/assets/{NodeDetailsView-pYP-34nS.css → NodeDetailsView-BtWGMS7Y.css} +16 -16
  42. package/dist/assets/{useCanvasMapping-CTTq6x8X.js → NodeView-4aDk41Oy.js} +3559 -11337
  43. package/dist/assets/{useCanvasMapping-VtpW_QZA.css → NodeView-U4YkXSfU.css} +309 -6
  44. package/dist/assets/{ProjectCardBadge-DRlDZx3d.js → ProjectCardBadge-CLVVfcVb.js} +1 -1
  45. package/dist/assets/{ProjectHeader-DNm605Kk.js → ProjectHeader-DQk1kmw3.js} +2 -2
  46. package/dist/assets/{ProjectSettings-Dge_6KaR.js → ProjectSettings-BLTHRnTQ.js} +15 -4
  47. package/dist/assets/{PushConnectionTracker.vue_vue_type_script_setup_true_lang-CUf0LkWR.js → PushConnectionTracker.vue_vue_type_script_setup_true_lang-DhLSSpy6.js} +1 -1
  48. package/dist/assets/{ResourcesListLayout-Bbl-1i4l.js → ResourcesListLayout-BlDcQdXw.js} +2 -2
  49. package/dist/assets/{RunData-b0RE2JWc.js → RunData-C67Kx3bc.js} +234 -92
  50. package/dist/assets/{RunData-DQeENuzG.css → RunData-CE5FsU6k.css} +2 -2
  51. package/dist/assets/{RunDataAi-DnWcCR_0.js → RunDataAi-_rd0qTgN.js} +3 -4
  52. package/dist/assets/{RunDataJson-CptVuHuA.js → RunDataJson-BP0x4Zdv.js} +6 -7
  53. package/dist/assets/{RunDataJsonActions-3jjDztw7.js → RunDataJsonActions-Bc0fqS6Y.js} +1 -1
  54. package/dist/assets/{RunDataParsedAiContent-BbXv-NPD.js → RunDataParsedAiContent-l1979DuT.js} +4 -5
  55. package/dist/assets/{RunDataSearch-B90wjsDA.js → RunDataSearch-CCGPQjFW.js} +1 -1
  56. package/dist/assets/{RunDataTable-CpS78GlT.js → RunDataTable-uzdBjxmW.js} +2 -3
  57. package/dist/assets/{SamlOnboarding-Ch9K5rRW.js → SamlOnboarding-D4xkCaRS.js} +3 -3
  58. package/dist/assets/{SettingsApiView-9GU5n_rm.js → SettingsApiView-ijuSJs-i.js} +1 -1
  59. package/dist/assets/{SettingsCommunityNodesView-CPnVRzNX.js → SettingsCommunityNodesView-D3I8P7Ea.js} +4 -4
  60. package/dist/assets/{SettingsExternalSecrets-D7xTMV9h.js → SettingsExternalSecrets-ndwnYVtu.js} +1 -1
  61. package/dist/assets/{SettingsLdapView-OfrjGKkt.js → SettingsLdapView-Dzhh3gD4.js} +1 -1
  62. package/dist/assets/{SettingsLogStreamingView-C_VnOaeX.js → SettingsLogStreamingView-D-Rr-Jph.js} +1 -1
  63. package/dist/assets/{SettingsPersonalView-Dm24akPV.js → SettingsPersonalView-Cf1cBUw8.js} +1 -1
  64. package/dist/assets/{SettingsSourceControl-DDCmL82j.js → SettingsSourceControl-BXRyD_N0.js} +1 -1
  65. package/dist/assets/{SettingsSso-BGGQ0Cpg.js → SettingsSso-DZTsjRCO.js} +1 -1
  66. package/dist/assets/{SettingsUsageAndPlan-BzO_zdkH.js → SettingsUsageAndPlan-BqY4ptNL.js} +1 -1
  67. package/dist/assets/{SettingsUsersView-DHQUqhqB.js → SettingsUsersView-eqXFp615.js} +1 -1
  68. package/dist/assets/{SettingsView-CbtAqjOX.js → SettingsView-CHSTMDKz.js} +1 -1
  69. package/dist/assets/{SetupView-BME1OE6U.js → SetupView-D6-b4i8i.js} +3 -3
  70. package/dist/assets/{SetupWorkflowCredentialsButton-DZr4TCPC.js → SetupWorkflowCredentialsButton-6SWeqGx-.js} +1 -1
  71. package/dist/assets/{SetupWorkflowFromTemplateView-CPkKEY04.js → SetupWorkflowFromTemplateView-DTZ8dEhY.js} +3 -3
  72. package/dist/assets/{SigninView-DUeRvOiY.js → SigninView-B3mpecGJ.js} +3 -3
  73. package/dist/assets/{SignoutView-BC7SBunZ.js → SignoutView-Bq9cEhcZ.js} +1 -1
  74. package/dist/assets/{SignupView-B5ecYJ2q.js → SignupView-BTyAq-gW.js} +3 -3
  75. package/dist/assets/{TemplateDetails-DjanZgC1.js → TemplateDetails-Bf7Xg-KJ.js} +1 -1
  76. package/dist/assets/{TemplateList-8TyNGxY-.js → TemplateList-BmXxTP4v.js} +1 -1
  77. package/dist/assets/{TemplatesCollectionView-BkH4pJCv.js → TemplatesCollectionView-DKwycT_4.js} +5 -5
  78. package/dist/assets/{TemplatesSearchView-Bcdhi1SL.js → TemplatesSearchView-ciluP1sL.js} +3 -3
  79. package/dist/assets/{TemplatesView-De2XB6We.js → TemplatesView-CDdQbnxe.js} +1 -1
  80. package/dist/assets/{TemplatesWorkflowView-BVnwtrMa.js → TemplatesWorkflowView-uQ3eG-nR.js} +5 -5
  81. package/dist/assets/{VariablesView-BZCvPfan.js → VariablesView-Bve2WEng.js} +4 -4
  82. package/dist/assets/{WorkerView-CigxqnWi.js → WorkerView-CUyaAqvY.js} +6 -6
  83. package/dist/assets/{WorkflowActivator-B7jRy4L1.js → WorkflowActivator-DZSvs7Ye.js} +11 -9
  84. package/dist/assets/{WorkflowExecutionsInfoAccordion-C_ZycbsF.js → WorkflowExecutionsInfoAccordion-DTbkpnyq.js} +1 -1
  85. package/dist/assets/{WorkflowExecutionsLandingPage-DOqrfKlC.js → WorkflowExecutionsLandingPage-DNc0pN7t.js} +2 -2
  86. package/dist/assets/{WorkflowExecutionsPreview-B4Cj2gXW.js → WorkflowExecutionsPreview-SdFojcu-.js} +5 -6
  87. package/dist/assets/{WorkflowExecutionsView-RXfP7zkJ.js → WorkflowExecutionsView-CAbXPlyv.js} +10 -11
  88. package/dist/assets/{WorkflowHistory-DrXrRwIS.js → WorkflowHistory-BIFuha5h.js} +3 -3
  89. package/dist/assets/{WorkflowOnboardingView-CXH1vCW2.js → WorkflowOnboardingView-DLRgnF3H.js} +1 -1
  90. package/dist/assets/{WorkflowPreview-B_MuFEV8.js → WorkflowPreview-DRSvh1f-.js} +1 -1
  91. package/dist/assets/{WorkflowsView-D90hfJ35.js → WorkflowsView-DOQhvV_X.js} +9 -9
  92. package/dist/assets/{useClearExecutionButtonVisible-Dwc1_eG9.js → canvas-CdHFQJm7.js} +3 -2
  93. package/dist/assets/{chartjs.utils-DalQn9bk.js → chartjs.utils-hlpJdzhb.js} +2 -2
  94. package/dist/assets/{easyAiWorkflowUtils-kgtpBx2h.js → easyAiWorkflowUtils-GnIqpmRr.js} +1 -1
  95. package/dist/assets/{global-link-actions-CnWOMvqA.js → global-link-actions-CExoAUZJ.js} +1 -1
  96. package/dist/assets/{import-curl-BvX_O56D.js → import-curl-D2S8-TVc.js} +1 -1
  97. package/dist/assets/{index-DZ6VpjNj.js → index-BSlk84mz.js} +79639 -67526
  98. package/dist/assets/{index-yNaoC3fo.css → index-DH8MNLw5.css} +195 -488
  99. package/dist/assets/{index-Bb2NNknG.js → index-lOeP0Jxq.js} +1 -1
  100. package/dist/assets/{pickBy-B_HGYyxS.js → pickBy-BoYQMT9v.js} +1 -1
  101. package/dist/assets/{polyfills-CLZ4X0Ad.js → polyfills-J2x06Gdp.js} +157 -224
  102. package/dist/assets/{templateActions-DQfZ3ni5.js → templateActions-CAEk7dfj.js} +1 -1
  103. package/dist/assets/{typescript.worker-BsxN2afA.js → typescript.worker-DIrCbxuR.js} +2 -2
  104. package/dist/assets/{useBeforeUnload-Cu0LPVWe.js → useBeforeUnload-COWlK6zC.js} +1 -1
  105. package/dist/assets/{useExecutionDebugging-rc72wLIp.js → useExecutionDebugging-DOtIA9Qr.js} +1 -1
  106. package/dist/assets/{useExecutionHelpers-DqwMonFW.js → useExecutionHelpers-q1_8c2Pm.js} +2 -3
  107. package/dist/assets/{useImportCurlCommand-D_onuFvo.js → useImportCurlCommand-CbwqixK0.js} +2 -2
  108. package/dist/assets/{useProjectPages-e8b03-5_.js → useProjectPages-DlqnxMvy.js} +1 -1
  109. package/dist/assets/{usePushConnection-wm-7Id6Q.js → usePushConnection-Bysa9RG-.js} +35 -111
  110. package/dist/assets/{useWorkflowActivate-65xML23U.js → useWorkflowActivate-B1ps647W.js} +1 -1
  111. package/dist/assets/{useWorkflowSaving-CUel20JA.js → useWorkflowSaving-BVNVyvlZ.js} +1 -1
  112. package/dist/index.html +3 -3
  113. package/package.json +1 -1
  114. package/tsconfig.json +1 -0
  115. package/vite.config.mts +4 -0
  116. package/dist/assets/CollectionParameter-Cj4t6-hd.js +0 -4
  117. package/dist/assets/InsightsSummary-MECenLJQ.js +0 -207
  118. package/dist/assets/NodeView-Bk9h8GYy.js +0 -1719
  119. package/dist/assets/NodeView-C3A-bM1O.css +0 -304
  120. package/dist/assets/TestDefinitionEditView-Cwkrz308.css +0 -1189
  121. package/dist/assets/TestDefinitionEditView-DjmPnrTk.js +0 -1464
  122. package/dist/assets/TestDefinitionListView-BL2s_qBZ.js +0 -631
  123. package/dist/assets/TestDefinitionNewView-B9BqJZST.js +0 -75
  124. package/dist/assets/TestDefinitionRootView-AlWyxbc0.js +0 -39
  125. package/dist/assets/TestDefinitionRootView-DFT60fWE.css +0 -126
  126. package/dist/assets/dateFormatter-BPfJSa6q.js +0 -21
  127. package/dist/assets/useCanvasOperations-u8oSDa_u.js +0 -2834
  128. package/dist/assets/useTestDefinitionForm-DlUOnNC0.js +0 -154
@@ -1,7 +1,6 @@
1
- import { b0 as inject, b1 as isRef, i as createElementBlock, g as openBlock, k as createBaseVNode, d as defineComponent, q as computed, j as createVNode, e as createBlock, f as createCommentVNode, m as unref, t as toDisplayString, b2 as withModifiers, _ as _export_sfc, b3 as toRefs, r as ref, o as onMounted, n as normalizeClass, x as renderSlot, b4 as normalizeProps, b5 as guardReactiveProps, b6 as resolveDynamicComponent, b7 as mergeProps, b8 as VueMarkdown, F as Fragment, D as renderList, b9 as markdownLink, ba as useFileDialog, bb as onUnmounted, B as normalizeStyle, aA as withDirectives, bc as vModelText, bd as withKeys, w as withCtx, X as watch, h as resolveComponent, l as createTextVNode, be as N8nText, bf as useClipboard, a as useToast, c as useI18n$1, aR as N8nTooltip, bg as N8nButton, aT as _sfc_main$i, aV as createSlots, aJ as useStorage, a_ as watchEffect, y as onBeforeUnmount, G as useDebounce, bh as provide, bi as useProvideTooltipAppendTo, bj as IsInPiPWindowSymbol, bk as CHAT_TRIGGER_NODE_TYPE, bl as MANUAL_CHAT_TRIGGER_NODE_TYPE, bm as NodeConnectionTypes, bn as v4, bo as get, bp as isEmpty, bq as usePinnedData, ai as useMessage, aj as MODAL_CONFIRM, br as CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, bs as AI_SUBCATEGORY, bt as AI_CATEGORY_AGENTS, bu as AI_CATEGORY_CHAINS, bv as AI_CODE_NODE_TYPE, bw as getNodeInputs, bx as getConnectionTypes, by as getNodeOutputs, Q as useWorkflowsStore, bz as useNodeTypesStore, b as useRouter, bA as useNodeHelpers, bB as useRunWorkflow, V as VIEWS, aZ as LOGS_PANEL_STATE, bC as _sfc_main$k, bD as I18nT, bE as N8nIcon, bF as upperFirst, as as useNDVStore, bG as useVirtualList, bH as N8nRadioButtons, ag as useTelemetry, z as nextTick, bI as ndvEventBus, aS as N8nLink, av as useLocalStorage, bJ as LOG_DETAILS_CONTENT, aY as useTemplateRef, a$ as N8nResizeWrapper, bK as useStyles, $ as useCanvasStore, bL as Workflow, bM as IN_PROGRESS_EXECUTION_ID, bN as useThrottleFn } from "./index-DZ6VpjNj.js";
2
- import { u as useClearExecutionButtonVisible } from "./useClearExecutionButtonVisible-Dwc1_eG9.js";
3
- import { H as HighlightJS, f as formatTokenUsageCount, _ as _sfc_main$j, g as getSubtreeTotalConsumedTokens, a as getTotalConsumedTokens, b as flattenLogEntries, R as RunData, c as createLogEntries, d as deepToRaw, e as findSelectedLogEntry } from "./RunData-b0RE2JWc.js";
4
- import { t as toTime, a as toDayMonth } from "./dateFormatter-BPfJSa6q.js";
1
+ import { b1 as inject, b2 as isRef, i as createElementBlock, g as openBlock, k as createBaseVNode, d as defineComponent, q as computed, j as createVNode, e as createBlock, f as createCommentVNode, m as unref, t as toDisplayString, b3 as withModifiers, _ as _export_sfc, b4 as toRefs, r as ref, o as onMounted, n as normalizeClass, x as renderSlot, b5 as normalizeProps, b6 as guardReactiveProps, b7 as resolveDynamicComponent, b8 as mergeProps, F as Fragment, D as renderList, b9 as markdownLink, ba as useFileDialog, bb as chatEventBus, bc as onUnmounted, B as normalizeStyle, aA as withDirectives, bd as vModelText, be as withKeys, w as withCtx, X as watch, h as resolveComponent, l as createTextVNode, bf as N8nText, bg as useClipboard, a as useToast, p as useSettingsStore, c as useI18n$1, aR as N8nTooltip, bh as N8nButton, aT as _sfc_main$i, aV as createSlots, aJ as useStorage, a$ as watchEffect, y as onBeforeUnmount, G as useDebounce, bi as provide, bj as useProvideTooltipAppendTo, bk as IsInPiPWindowSymbol, bl as usePinnedData, ai as useMessage, aj as MODAL_CONFIRM, bm as v4, bn as getInputKey, bo as extractBotResponse, bp as isChatNode, bq as CHAIN_SUMMARIZATION_LANGCHAIN_NODE_TYPE, br as AI_SUBCATEGORY, bs as AI_CATEGORY_AGENTS, bt as AI_CATEGORY_CHAINS, bu as AI_CODE_NODE_TYPE, bv as getNodeInputs, bw as getConnectionTypes, bx as getNodeOutputs, by as NodeConnectionTypes, Q as useWorkflowsStore, bz as useNodeTypesStore, aY as useLogsStore, b as useRouter, bA as useNodeHelpers, bB as useRunWorkflow, bC as restoreChatHistory, V as VIEWS, aZ as useTemplateRef, bD as useTimestamp, bE as toTime, bF as toDayMonth, bG as upperFirst, bH as _sfc_main$k, bI as I18nT, bJ as N8nIcon, z as nextTick, bK as useVirtualList, bL as toRef, bM as N8nRadioButtons, as as useNDVStore, bN as resolveDirective, aS as N8nLink, bO as waitingNodeTooltip, av as useLocalStorage, bP as LOG_DETAILS_PANEL_STATE, bQ as KeyboardShortcutTooltip, b0 as N8nResizeWrapper, bR as useStyles, bS as N8nActionDropdown, a_ as LOGS_PANEL_STATE, ag as useTelemetry, bT as Workflow, bU as useThrottleFn, bV as parse, H as useUIStore, $ as useCanvasStore, bW as ndvEventBus } from "./index-BSlk84mz.js";
2
+ import { u as useClearExecutionButtonVisible, c as canvasEventBus } from "./canvas-CdHFQJm7.js";
3
+ import { H as HighlightJS, V as VueMarkdown, f as formatTokenUsageCount, _ as _sfc_main$j, g as getSubtreeTotalConsumedTokens, a as getTotalConsumedTokens, h as hasSubExecution, R as RunData, c as createLogTree, d as deepToRaw, m as mergeStartData, b as findSelectedLogEntry, e as getEntryAtRelativeIndex, i as getDepth, j as findLogEntryRec, k as flattenLogEntries } from "./RunData-C67Kx3bc.js";
5
4
  function bash(hljs) {
6
5
  const regex = hljs.regex;
7
6
  const VAR = {};
@@ -2797,39 +2796,6 @@ function render(_ctx, _cache) {
2797
2796
  ]));
2798
2797
  }
2799
2798
  const IconSend = { name: "mdi-send", render };
2800
- function createEventBus() {
2801
- const handlers = /* @__PURE__ */ new Map();
2802
- function off(eventName, fn) {
2803
- const eventFns = handlers.get(eventName);
2804
- if (eventFns) {
2805
- eventFns.splice(eventFns.indexOf(fn) >>> 0, 1);
2806
- }
2807
- }
2808
- function on(eventName, fn) {
2809
- let eventFns = handlers.get(eventName);
2810
- if (!eventFns) {
2811
- eventFns = [fn];
2812
- } else {
2813
- eventFns.push(fn);
2814
- }
2815
- handlers.set(eventName, eventFns);
2816
- return () => off(eventName, fn);
2817
- }
2818
- function emit(eventName, event) {
2819
- const eventFns = handlers.get(eventName);
2820
- if (eventFns) {
2821
- eventFns.slice().forEach(async (handler) => {
2822
- await handler(event);
2823
- });
2824
- }
2825
- }
2826
- return {
2827
- on,
2828
- off,
2829
- emit
2830
- };
2831
- }
2832
- const chatEventBus = createEventBus();
2833
2799
  const _hoisted_1$4 = { class: "chat-inputs" };
2834
2800
  const _hoisted_2$2 = {
2835
2801
  key: 0,
@@ -3268,7 +3234,7 @@ const cssModules$a = {
3268
3234
  };
3269
3235
  const MessageOptionAction = /* @__PURE__ */ _export_sfc(_sfc_main$b, [["__cssModules", cssModules$a]]);
3270
3236
  const _sfc_main$a = /* @__PURE__ */ defineComponent({
3271
- __name: "PanelHeader",
3237
+ __name: "LogsPanelHeader",
3272
3238
  props: {
3273
3239
  title: {}
3274
3240
  },
@@ -3312,7 +3278,7 @@ const style0$9 = {
3312
3278
  const cssModules$9 = {
3313
3279
  "$style": style0$9
3314
3280
  };
3315
- const PanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__cssModules", cssModules$9]]);
3281
+ const LogsPanelHeader = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__cssModules", cssModules$9]]);
3316
3282
  const _hoisted_1$2 = ["onClick"];
3317
3283
  const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3318
3284
  __name: "ChatMessagesPanel",
@@ -3332,6 +3298,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3332
3298
  const clipboard = useClipboard();
3333
3299
  const locale = useI18n$1();
3334
3300
  const toast = useToast();
3301
+ const settingsStore = useSettingsStore();
3335
3302
  const previousMessageIndex = ref(0);
3336
3303
  const sessionIdText = computed(
3337
3304
  () => locale.baseText("chat.window.session.id", {
@@ -3398,7 +3365,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3398
3365
  watch(
3399
3366
  () => props.isOpen,
3400
3367
  (isOpen) => {
3401
- if (isOpen) {
3368
+ if (isOpen && !settingsStore.isNewLogsEnabled) {
3402
3369
  setTimeout(() => {
3403
3370
  chatEventBus.emit("focusInput");
3404
3371
  }, 0);
@@ -3408,10 +3375,11 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
3408
3375
  );
3409
3376
  return (_ctx, _cache) => {
3410
3377
  return openBlock(), createElementBlock("div", {
3411
- class: normalizeClass(_ctx.$style.chat),
3412
- "data-test-id": "workflow-lm-chat-dialog"
3378
+ class: normalizeClass([_ctx.$style.chat, "ignore-key-press-canvas"]),
3379
+ "data-test-id": "workflow-lm-chat-dialog",
3380
+ tabindex: "0"
3413
3381
  }, [
3414
- _ctx.isNewLogsEnabled ? (openBlock(), createBlock(PanelHeader, {
3382
+ _ctx.isNewLogsEnabled ? (openBlock(), createBlock(LogsPanelHeader, {
3415
3383
  key: 0,
3416
3384
  "data-test-id": "chat-header",
3417
3385
  title: unref(locale).baseText("chat.window.title"),
@@ -3775,85 +3743,6 @@ function usePiPWindow({
3775
3743
  });
3776
3744
  return { canPopOut, isPoppedOut, pipWindow };
3777
3745
  }
3778
- function isChatNode(node) {
3779
- return [CHAT_TRIGGER_NODE_TYPE, MANUAL_CHAT_TRIGGER_NODE_TYPE].includes(node.type);
3780
- }
3781
- function getInputKey(node) {
3782
- if (node.type === MANUAL_CHAT_TRIGGER_NODE_TYPE && node.typeVersion < 1.1) {
3783
- return "input";
3784
- }
3785
- if (node.type === CHAT_TRIGGER_NODE_TYPE) {
3786
- return "chatInput";
3787
- }
3788
- return "chatInput";
3789
- }
3790
- function extractChatInput(workflow, resultData) {
3791
- const chatTrigger = workflow.nodes.find(isChatNode);
3792
- if (chatTrigger === void 0) {
3793
- return void 0;
3794
- }
3795
- const inputKey = getInputKey(chatTrigger);
3796
- const runData = (resultData.runData[chatTrigger.name] ?? [])[0];
3797
- const message = runData?.data?.[NodeConnectionTypes.Main]?.[0]?.[0]?.json?.[inputKey];
3798
- if (runData === void 0 || typeof message !== "string") {
3799
- return void 0;
3800
- }
3801
- return {
3802
- text: message,
3803
- sender: "user",
3804
- id: v4()
3805
- };
3806
- }
3807
- function extractBotResponse(resultData, executionId, emptyText2) {
3808
- const lastNodeExecuted = resultData.lastNodeExecuted;
3809
- if (!lastNodeExecuted) return void 0;
3810
- const nodeResponseDataArray = get(resultData.runData, lastNodeExecuted) ?? [];
3811
- const nodeResponseData = nodeResponseDataArray[nodeResponseDataArray.length - 1];
3812
- let responseMessage;
3813
- if (get(nodeResponseData, "error")) {
3814
- responseMessage = "[ERROR: " + get(nodeResponseData, "error.message") + "]";
3815
- } else {
3816
- const responseData = get(nodeResponseData, "data.main[0][0].json");
3817
- const text = extractResponseText(responseData) ?? emptyText2;
3818
- if (!text) {
3819
- return void 0;
3820
- }
3821
- responseMessage = text;
3822
- }
3823
- return {
3824
- text: responseMessage,
3825
- sender: "bot",
3826
- id: executionId ?? v4()
3827
- };
3828
- }
3829
- function extractResponseText(responseData) {
3830
- if (!responseData || isEmpty(responseData)) {
3831
- return void 0;
3832
- }
3833
- const paths = ["output", "text", "response.text"];
3834
- const matchedPath = paths.find((path) => get(responseData, path));
3835
- if (!matchedPath) return JSON.stringify(responseData, null, 2);
3836
- const matchedOutput = get(responseData, matchedPath);
3837
- if (typeof matchedOutput === "object") {
3838
- return "```json\n" + JSON.stringify(matchedOutput, null, 2) + "\n```";
3839
- }
3840
- return matchedOutput?.toString() ?? "";
3841
- }
3842
- function restoreChatHistory(workflowExecutionData, emptyText2) {
3843
- if (!workflowExecutionData?.data) {
3844
- return [];
3845
- }
3846
- const userMessage = extractChatInput(
3847
- workflowExecutionData.workflowData,
3848
- workflowExecutionData.data.resultData
3849
- );
3850
- const botMessage = extractBotResponse(
3851
- workflowExecutionData.data.resultData,
3852
- workflowExecutionData.id,
3853
- emptyText2
3854
- );
3855
- return [...userMessage ? [userMessage] : [], ...botMessage ? [botMessage] : []];
3856
- }
3857
3746
  function useChatMessaging({
3858
3747
  chatTrigger,
3859
3748
  messages: messages2,
@@ -4046,13 +3935,13 @@ function useChatState(isReadOnly) {
4046
3935
  const locale = useI18n$1();
4047
3936
  const workflowsStore = useWorkflowsStore();
4048
3937
  const nodeTypesStore = useNodeTypesStore();
3938
+ const logsStore = useLogsStore();
4049
3939
  const router = useRouter();
4050
3940
  const nodeHelpers = useNodeHelpers();
4051
3941
  const { runWorkflow } = useRunWorkflow({ router });
4052
3942
  const messages2 = ref([]);
4053
3943
  const currentSessionId = ref(v4().replace(/-/g, ""));
4054
3944
  const previousChatMessages = computed(() => workflowsStore.getPastChatMessages);
4055
- const logsPanelState = computed(() => workflowsStore.logsPanelState);
4056
3945
  const workflow = computed(() => workflowsStore.getCurrentWorkflow());
4057
3946
  const { chatTriggerNode, connectedNode, allowFileUploads, allowedFilesMimeTypes } = useChatTrigger({
4058
3947
  workflow,
@@ -4146,7 +4035,7 @@ function useChatState(isReadOnly) {
4146
4035
  nodeHelpers.updateNodesExecutionIssues();
4147
4036
  messages2.value = [];
4148
4037
  currentSessionId.value = v4().replace(/-/g, "");
4149
- if (logsPanelState.value !== LOGS_PANEL_STATE.CLOSED) {
4038
+ if (logsStore.isOpen) {
4150
4039
  chatEventBus.emit("focusInput");
4151
4040
  }
4152
4041
  }
@@ -4169,7 +4058,7 @@ function useChatState(isReadOnly) {
4169
4058
  };
4170
4059
  }
4171
4060
  const _sfc_main$8 = /* @__PURE__ */ defineComponent({
4172
- __name: "ConsumedTokenCountText",
4061
+ __name: "LogsViewConsumedTokenCountText",
4173
4062
  props: {
4174
4063
  consumedTokens: {}
4175
4064
  },
@@ -4199,7 +4088,7 @@ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
4199
4088
  const _hoisted_1$1 = { key: 0 };
4200
4089
  const _hoisted_2 = { key: 1 };
4201
4090
  const _sfc_main$7 = /* @__PURE__ */ defineComponent({
4202
- __name: "NodeName",
4091
+ __name: "LogsViewNodeName",
4203
4092
  props: {
4204
4093
  name: {},
4205
4094
  latestName: {},
@@ -4231,7 +4120,7 @@ const style0$7 = {
4231
4120
  const cssModules$7 = {
4232
4121
  "$style": style0$7
4233
4122
  };
4234
- const NodeName = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__cssModules", cssModules$7]]);
4123
+ const LogsViewNodeName = /* @__PURE__ */ _export_sfc(_sfc_main$7, [["__cssModules", cssModules$7]]);
4235
4124
  const _hoisted_1 = ["aria-expanded", "aria-selected"];
4236
4125
  const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4237
4126
  __name: "LogsOverviewRow",
@@ -4239,20 +4128,23 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4239
4128
  data: {},
4240
4129
  isSelected: { type: Boolean },
4241
4130
  isReadOnly: { type: Boolean },
4242
- shouldShowConsumedTokens: { type: Boolean },
4131
+ shouldShowTokenCountColumn: { type: Boolean },
4243
4132
  isCompact: { type: Boolean },
4244
4133
  latestInfo: {},
4245
- expanded: { type: Boolean }
4134
+ expanded: { type: Boolean },
4135
+ canOpenNdv: { type: Boolean }
4246
4136
  },
4247
- emits: ["toggleExpanded", "triggerPartialExecution", "openNdv"],
4137
+ emits: ["toggleExpanded", "toggleSelected", "triggerPartialExecution", "openNdv"],
4248
4138
  setup(__props, { emit: __emit }) {
4249
4139
  const props = __props;
4250
4140
  const emit = __emit;
4141
+ const container2 = useTemplateRef("containerRef");
4251
4142
  const locale = useI18n$1();
4143
+ const now = useTimestamp({ interval: 1e3 });
4252
4144
  const nodeTypeStore = useNodeTypesStore();
4253
4145
  const type = computed(() => nodeTypeStore.getNodeType(props.data.node.type));
4254
4146
  const isSettled = computed(
4255
- () => props.data.runData.executionStatus && ["crashed", "error", "success"].includes(props.data.runData.executionStatus)
4147
+ () => props.data.runData.executionStatus && !["running", "waiting"].includes(props.data.runData.executionStatus)
4256
4148
  );
4257
4149
  const isError = computed(() => !!props.data.runData.error);
4258
4150
  const startedAtText = computed(() => {
@@ -4263,8 +4155,18 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4263
4155
  }
4264
4156
  });
4265
4157
  });
4158
+ const statusText = computed(() => upperFirst(props.data.runData.executionStatus));
4159
+ const timeText = computed(
4160
+ () => locale.displayTimer(
4161
+ isSettled.value ? props.data.runData.executionTime : Math.floor((now.value - props.data.runData.startTime) / 1e3) * 1e3,
4162
+ true
4163
+ )
4164
+ );
4266
4165
  const subtreeConsumedTokens = computed(
4267
- () => props.shouldShowConsumedTokens ? getSubtreeTotalConsumedTokens(props.data) : void 0
4166
+ () => props.shouldShowTokenCountColumn ? getSubtreeTotalConsumedTokens(props.data, false) : void 0
4167
+ );
4168
+ const hasChildren = computed(
4169
+ () => props.data.children.length > 0 || !!props.data.runData.metadata?.subExecution
4268
4170
  );
4269
4171
  function isLastChild(level) {
4270
4172
  let parent = props.data.parent;
@@ -4277,11 +4179,23 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4277
4179
  const lastSibling = siblings[siblings.length - 1];
4278
4180
  return data === void 0 && lastSibling === void 0 || data?.node === lastSibling?.node && data?.runIndex === lastSibling?.runIndex;
4279
4181
  }
4182
+ watch(
4183
+ () => props.isSelected,
4184
+ (isSelected) => {
4185
+ void nextTick(() => {
4186
+ if (isSelected) {
4187
+ container2.value?.focus();
4188
+ }
4189
+ });
4190
+ },
4191
+ { immediate: true }
4192
+ );
4280
4193
  return (_ctx, _cache) => {
4281
4194
  const _component_NodeIcon = _sfc_main$k;
4282
4195
  return openBlock(), createElementBlock("div", {
4196
+ ref: "containerRef",
4283
4197
  role: "treeitem",
4284
- tabindex: "0",
4198
+ tabindex: "-1",
4285
4199
  "aria-expanded": props.data.children.length > 0 && props.expanded,
4286
4200
  "aria-selected": props.isSelected,
4287
4201
  class: normalizeClass({
@@ -4289,7 +4203,8 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4289
4203
  [_ctx.$style.compact]: props.isCompact,
4290
4204
  [_ctx.$style.error]: isError.value,
4291
4205
  [_ctx.$style.selected]: props.isSelected
4292
- })
4206
+ }),
4207
+ onClick: _cache[3] || (_cache[3] = withModifiers(($event) => emit("toggleSelected"), ["stop"]))
4293
4208
  }, [
4294
4209
  (openBlock(true), createElementBlock(Fragment, null, renderList(props.data.depth, (level) => {
4295
4210
  return openBlock(), createElementBlock("div", {
@@ -4310,7 +4225,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4310
4225
  size: 16,
4311
4226
  class: normalizeClass(_ctx.$style.icon)
4312
4227
  }, null, 8, ["node-type", "class"]),
4313
- createVNode(NodeName, {
4228
+ createVNode(LogsViewNodeName, {
4314
4229
  class: normalizeClass(_ctx.$style.name),
4315
4230
  "latest-name": _ctx.latestInfo?.name ?? props.data.node.name,
4316
4231
  name: props.data.node.name,
@@ -4327,7 +4242,7 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4327
4242
  default: withCtx(() => [
4328
4243
  isSettled.value ? (openBlock(), createBlock(unref(I18nT), {
4329
4244
  key: 0,
4330
- keypath: "logs.overview.body.summaryText"
4245
+ keypath: "logs.overview.body.summaryText.in"
4331
4246
  }, {
4332
4247
  status: withCtx(() => [
4333
4248
  isError.value ? (openBlock(), createBlock(unref(N8nText), {
@@ -4341,19 +4256,21 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4341
4256
  icon: "exclamation-triangle",
4342
4257
  class: normalizeClass(_ctx.$style.errorIcon)
4343
4258
  }, null, 8, ["class"]),
4344
- createTextVNode(toDisplayString(unref(upperFirst)(props.data.runData.executionStatus)), 1)
4259
+ createTextVNode(" " + toDisplayString(statusText.value), 1)
4345
4260
  ]),
4346
4261
  _: 1
4347
4262
  })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
4348
- createTextVNode(toDisplayString(unref(upperFirst)(props.data.runData.executionStatus)), 1)
4263
+ createTextVNode(toDisplayString(statusText.value), 1)
4349
4264
  ], 64))
4350
4265
  ]),
4351
4266
  time: withCtx(() => [
4352
- createTextVNode(toDisplayString(unref(locale).displayTimer(props.data.runData.executionTime, true)), 1)
4267
+ createTextVNode(toDisplayString(timeText.value), 1)
4353
4268
  ]),
4354
4269
  _: 1
4355
4270
  })) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
4356
- createTextVNode(toDisplayString(unref(upperFirst)(props.data.runData.executionStatus)), 1)
4271
+ createTextVNode(toDisplayString(unref(locale).baseText("logs.overview.body.summaryText.for", {
4272
+ interpolate: { status: statusText.value, time: timeText.value }
4273
+ })), 1)
4357
4274
  ], 64))
4358
4275
  ]),
4359
4276
  _: 1
@@ -4397,12 +4314,15 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4397
4314
  type: "secondary",
4398
4315
  size: "medium",
4399
4316
  icon: "edit",
4400
- style: { "color": "var(--color-text-base)" },
4317
+ style: normalizeStyle([{ "color": "var(--color-text-base)" }, {
4318
+ visibility: props.canOpenNdv ? "" : "hidden",
4319
+ color: "var(--color-text-base)"
4320
+ }]),
4401
4321
  disabled: props.latestInfo?.deleted,
4402
4322
  class: normalizeClass(_ctx.$style.openNdvButton),
4403
4323
  "aria-label": unref(locale).baseText("logs.overview.body.open"),
4404
- onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("openNdv", props.data), ["stop"]))
4405
- }, null, 8, ["disabled", "class", "aria-label"])) : createCommentVNode("", true),
4324
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("openNdv"), ["stop"]))
4325
+ }, null, 8, ["style", "disabled", "class", "aria-label"])) : createCommentVNode("", true),
4406
4326
  !_ctx.isCompact || !props.isReadOnly && !props.latestInfo?.deleted && !props.latestInfo?.disabled ? (openBlock(), createBlock(unref(_sfc_main$i), {
4407
4327
  key: 5,
4408
4328
  type: "secondary",
@@ -4412,21 +4332,21 @@ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
4412
4332
  "aria-label": unref(locale).baseText("logs.overview.body.run"),
4413
4333
  class: normalizeClass([_ctx.$style.partialExecutionButton, props.data.depth > 0 ? _ctx.$style.unavailable : ""]),
4414
4334
  disabled: props.latestInfo?.deleted || props.latestInfo?.disabled,
4415
- onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("triggerPartialExecution", props.data), ["stop"]))
4335
+ onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("triggerPartialExecution"), ["stop"]))
4416
4336
  }, null, 8, ["aria-label", "class", "disabled"])) : createCommentVNode("", true),
4417
- !_ctx.isCompact || props.data.children.length > 0 ? (openBlock(), createBlock(unref(N8nButton), {
4337
+ !_ctx.isCompact || hasChildren.value ? (openBlock(), createBlock(unref(N8nButton), {
4418
4338
  key: 6,
4419
4339
  type: "secondary",
4420
4340
  size: "small",
4421
4341
  square: true,
4422
4342
  style: normalizeStyle({
4423
- visibility: props.data.children.length === 0 ? "hidden" : "",
4343
+ visibility: hasChildren.value ? "" : "hidden",
4424
4344
  color: "var(--color-text-base)"
4425
4345
  // give higher specificity than the style from the component itself
4426
4346
  }),
4427
4347
  class: normalizeClass(_ctx.$style.toggleButton),
4428
4348
  "aria-label": unref(locale).baseText("logs.overview.body.toggleRow"),
4429
- onClick: _cache[2] || (_cache[2] = withModifiers(($event) => emit("toggleExpanded", props.data), ["stop"]))
4349
+ onClick: _cache[2] || (_cache[2] = withModifiers(($event) => emit("toggleExpanded"), ["stop"]))
4430
4350
  }, {
4431
4351
  default: withCtx(() => [
4432
4352
  createVNode(unref(N8nIcon), {
@@ -4485,16 +4405,23 @@ const cssModules$6 = {
4485
4405
  };
4486
4406
  const LogsOverviewRow = /* @__PURE__ */ _export_sfc(_sfc_main$6, [["__cssModules", cssModules$6]]);
4487
4407
  const _sfc_main$5 = /* @__PURE__ */ defineComponent({
4488
- __name: "ExecutionSummary",
4408
+ __name: "LogsViewExecutionSummary",
4489
4409
  props: {
4490
4410
  status: {},
4491
4411
  consumedTokens: {},
4412
+ startTime: {},
4492
4413
  timeTook: {}
4493
4414
  },
4494
4415
  setup(__props) {
4495
4416
  const locale = useI18n$1();
4417
+ const now = useTimestamp({ interval: 1e3 });
4496
4418
  const executionStatusText = computed(
4497
- () => __props.timeTook === void 0 ? upperFirst(__props.status) : locale.baseText("logs.overview.body.summaryText", {
4419
+ () => __props.status === "running" || __props.status === "waiting" ? locale.baseText("logs.overview.body.summaryText.for", {
4420
+ interpolate: {
4421
+ status: upperFirst(__props.status),
4422
+ time: locale.displayTimer(Math.floor((now.value - __props.startTime) / 1e3) * 1e3, true)
4423
+ }
4424
+ }) : __props.timeTook === void 0 ? upperFirst(__props.status) : locale.baseText("logs.overview.body.summaryText.in", {
4498
4425
  interpolate: {
4499
4426
  status: upperFirst(__props.status),
4500
4427
  time: locale.displayTimer(__props.timeTook, true)
@@ -4527,7 +4454,7 @@ const style0$5 = {
4527
4454
  const cssModules$5 = {
4528
4455
  "$style": style0$5
4529
4456
  };
4530
- const ExecutionSummary = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$5]]);
4457
+ const LogsViewExecutionSummary = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$5]]);
4531
4458
  const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4532
4459
  __name: "LogsOverviewPanel",
4533
4460
  props: {
@@ -4536,62 +4463,49 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4536
4463
  isReadOnly: { type: Boolean },
4537
4464
  isCompact: { type: Boolean },
4538
4465
  execution: {},
4539
- latestNodeInfo: {},
4540
- scrollToSelection: { type: Boolean }
4466
+ entries: {},
4467
+ flatLogEntries: {},
4468
+ latestNodeInfo: {}
4541
4469
  },
4542
- emits: ["clickHeader", "select", "clearExecutionData"],
4470
+ emits: ["clickHeader", "select", "clearExecutionData", "openNdv", "toggleExpanded", "loadSubExecution"],
4543
4471
  setup(__props, { emit: __emit }) {
4544
4472
  const emit = __emit;
4545
4473
  const locale = useI18n$1();
4546
- const telemetry = useTelemetry();
4547
4474
  const router = useRouter();
4548
4475
  const runWorkflow = useRunWorkflow({ router });
4549
- const ndvStore = useNDVStore();
4550
4476
  const isClearExecutionButtonVisible = useClearExecutionButtonVisible();
4551
- const isEmpty2 = computed(() => __props.execution === void 0);
4477
+ const isEmpty = computed(() => __props.flatLogEntries.length === 0 || __props.execution === void 0);
4552
4478
  const switchViewOptions = computed(() => [
4553
4479
  { label: locale.baseText("logs.overview.header.switch.overview"), value: "overview" },
4554
4480
  { label: locale.baseText("logs.overview.header.switch.details"), value: "details" }
4555
4481
  ]);
4556
4482
  const consumedTokens2 = computed(
4557
- () => getTotalConsumedTokens(...(__props.execution?.tree ?? []).map(getSubtreeTotalConsumedTokens))
4483
+ () => getTotalConsumedTokens(
4484
+ ...__props.entries.map(
4485
+ (entry) => getSubtreeTotalConsumedTokens(
4486
+ entry,
4487
+ false
4488
+ // Exclude token usages from sub workflow which is loaded only after expanding the row
4489
+ )
4490
+ )
4491
+ )
4558
4492
  );
4559
- const collapsedEntries = ref({});
4560
- const flatLogEntries = computed(
4561
- () => flattenLogEntries(__props.execution?.tree ?? [], collapsedEntries.value)
4493
+ const shouldShowTokenCountColumn = computed(
4494
+ () => consumedTokens2.value.totalTokens > 0 || __props.entries.some((entry) => getSubtreeTotalConsumedTokens(entry, true).totalTokens > 0)
4495
+ );
4496
+ const virtualList = useVirtualList(
4497
+ toRef(() => __props.flatLogEntries),
4498
+ { itemHeight: 32 }
4562
4499
  );
4563
- const virtualList = useVirtualList(flatLogEntries, { itemHeight: 32 });
4564
- function handleClickNode(clicked) {
4565
- if (__props.selected?.node === clicked.node && __props.selected?.runIndex === clicked.runIndex) {
4566
- emit("select", void 0);
4567
- return;
4568
- }
4569
- emit("select", clicked);
4570
- telemetry.track("User selected node in log view", {
4571
- node_type: clicked.node.type,
4572
- node_id: clicked.node.id,
4573
- execution_id: __props.execution?.id,
4574
- workflow_id: __props.execution?.workflowData.id
4575
- });
4576
- }
4577
4500
  function handleSwitchView(value) {
4578
- emit(
4579
- "select",
4580
- value === "overview" || (__props.execution?.tree ?? []).length === 0 ? void 0 : __props.execution?.tree[0]
4581
- );
4501
+ emit("select", value === "overview" ? void 0 : __props.flatLogEntries[0]);
4582
4502
  }
4583
4503
  function handleToggleExpanded(treeNode) {
4584
- collapsedEntries.value[treeNode.id] = !collapsedEntries.value[treeNode.id];
4585
- }
4586
- async function handleOpenNdv(treeNode) {
4587
- ndvStore.setActiveNodeName(treeNode.node.name);
4588
- await nextTick(() => {
4589
- const source = treeNode.runData.source[0];
4590
- const inputBranch = source?.previousNodeOutput ?? 0;
4591
- ndvEventBus.emit("updateInputNodeName", source?.previousNode);
4592
- ndvEventBus.emit("setInputBranchIndex", inputBranch);
4593
- ndvStore.setOutputRunIndex(treeNode.runIndex);
4594
- });
4504
+ if (hasSubExecution(treeNode) && treeNode.children.length === 0) {
4505
+ emit("loadSubExecution", treeNode);
4506
+ return;
4507
+ }
4508
+ emit("toggleExpanded", treeNode);
4595
4509
  }
4596
4510
  async function handleTriggerPartialExecution(treeNode) {
4597
4511
  const latestName = __props.latestNodeInfo[treeNode.node.id]?.name ?? treeNode.node.name;
@@ -4600,10 +4514,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4600
4514
  }
4601
4515
  }
4602
4516
  watch(
4603
- () => __props.scrollToSelection ? __props.selected : void 0,
4604
- async (entry) => {
4605
- if (entry) {
4606
- const index = flatLogEntries.value.findIndex((e) => e.id === entry.id);
4517
+ () => __props.selected,
4518
+ async (selection) => {
4519
+ if (selection && virtualList.list.value.every((e) => e.data.id !== selection.id)) {
4520
+ const index = __props.flatLogEntries.findIndex((e) => e.id === selection?.id);
4607
4521
  if (index >= 0) {
4608
4522
  await nextTick(() => virtualList.scrollTo(index));
4609
4523
  }
@@ -4616,7 +4530,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4616
4530
  class: normalizeClass(_ctx.$style.container),
4617
4531
  "data-test-id": "logs-overview"
4618
4532
  }, [
4619
- createVNode(PanelHeader, {
4533
+ createVNode(LogsPanelHeader, {
4620
4534
  title: unref(locale).baseText("logs.overview.header.title"),
4621
4535
  "data-test-id": "logs-overview-header",
4622
4536
  onClick: _cache[1] || (_cache[1] = ($event) => emit("clickHeader"))
@@ -4632,6 +4546,7 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4632
4546
  type: "secondary",
4633
4547
  icon: "trash",
4634
4548
  "icon-size": "medium",
4549
+ "data-test-id": "clear-execution-data-button",
4635
4550
  class: normalizeClass(_ctx.$style.clearButton),
4636
4551
  onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("clearExecutionData"), ["stop"]))
4637
4552
  }, {
@@ -4649,10 +4564,10 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4649
4564
  }, 8, ["title"]),
4650
4565
  _ctx.isOpen ? (openBlock(), createElementBlock("div", {
4651
4566
  key: 0,
4652
- class: normalizeClass([_ctx.$style.content, isEmpty2.value ? _ctx.$style.empty : ""]),
4567
+ class: normalizeClass([_ctx.$style.content, isEmpty.value ? _ctx.$style.empty : ""]),
4653
4568
  "data-test-id": "logs-overview-body"
4654
4569
  }, [
4655
- isEmpty2.value ? (openBlock(), createBlock(unref(N8nText), {
4570
+ isEmpty.value || _ctx.execution === void 0 ? (openBlock(), createBlock(unref(N8nText), {
4656
4571
  key: 0,
4657
4572
  tag: "p",
4658
4573
  size: "medium",
@@ -4665,14 +4580,14 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4665
4580
  ]),
4666
4581
  _: 1
4667
4582
  }, 8, ["class"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
4668
- _ctx.execution ? (openBlock(), createBlock(ExecutionSummary, {
4669
- key: 0,
4583
+ createVNode(LogsViewExecutionSummary, {
4670
4584
  "data-test-id": "logs-overview-status",
4671
4585
  class: normalizeClass(_ctx.$style.summary),
4672
4586
  status: _ctx.execution.status,
4673
4587
  "consumed-tokens": consumedTokens2.value,
4588
+ "start-time": +new Date(_ctx.execution.startedAt),
4674
4589
  "time-took": _ctx.execution.startedAt && _ctx.execution.stoppedAt ? +new Date(_ctx.execution.stoppedAt) - +new Date(_ctx.execution.startedAt) : void 0
4675
- }, null, 8, ["class", "status", "consumed-tokens", "time-took"])) : createCommentVNode("", true),
4590
+ }, null, 8, ["class", "status", "consumed-tokens", "start-time", "time-took"]),
4676
4591
  createBaseVNode("div", mergeProps({
4677
4592
  class: _ctx.$style.tree
4678
4593
  }, unref(virtualList).containerProps), [
@@ -4682,16 +4597,17 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4682
4597
  key: index,
4683
4598
  data,
4684
4599
  "is-read-only": _ctx.isReadOnly,
4685
- "is-selected": data.node.name === _ctx.selected?.node.name && data.runIndex === _ctx.selected?.runIndex,
4600
+ "is-selected": data.id === _ctx.selected?.id,
4686
4601
  "is-compact": _ctx.isCompact,
4687
- "should-show-consumed-tokens": consumedTokens2.value.totalTokens > 0,
4602
+ "should-show-token-count-column": shouldShowTokenCountColumn.value,
4688
4603
  "latest-info": _ctx.latestNodeInfo[data.node.id],
4689
- expanded: !collapsedEntries.value[data.id],
4690
- onClick: withModifiers(($event) => handleClickNode(data), ["stop"]),
4691
- onToggleExpanded: handleToggleExpanded,
4692
- onOpenNdv: handleOpenNdv,
4693
- onTriggerPartialExecution: handleTriggerPartialExecution
4694
- }, null, 8, ["data", "is-read-only", "is-selected", "is-compact", "should-show-consumed-tokens", "latest-info", "expanded", "onClick"]);
4604
+ expanded: unref(virtualList).list.value[index + 1]?.data.parent?.id === data.id,
4605
+ "can-open-ndv": data.executionId === _ctx.execution?.id,
4606
+ onToggleExpanded: ($event) => handleToggleExpanded(data),
4607
+ onOpenNdv: ($event) => emit("openNdv", data),
4608
+ onTriggerPartialExecution: ($event) => handleTriggerPartialExecution(data),
4609
+ onToggleSelected: ($event) => emit("select", _ctx.selected?.id === data.id ? void 0 : data)
4610
+ }, null, 8, ["data", "is-read-only", "is-selected", "is-compact", "should-show-token-count-column", "latest-info", "expanded", "can-open-ndv", "onToggleExpanded", "onOpenNdv", "onTriggerPartialExecution", "onToggleSelected"]);
4695
4611
  }), 128))
4696
4612
  ], 16)
4697
4613
  ], 16),
@@ -4708,14 +4624,14 @@ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
4708
4624
  };
4709
4625
  }
4710
4626
  });
4711
- const container$3 = "_container_acxst_123";
4712
- const clearButton = "_clearButton_acxst_133";
4713
- const content$1 = "_content_acxst_139";
4714
- const empty = "_empty_acxst_148";
4715
- const emptyText = "_emptyText_acxst_153";
4716
- const summary = "_summary_acxst_158";
4717
- const tree = "_tree_acxst_162";
4718
- const switchViewButtons = "_switchViewButtons_acxst_169";
4627
+ const container$3 = "_container_fcgc7_123";
4628
+ const clearButton = "_clearButton_fcgc7_133";
4629
+ const content$1 = "_content_fcgc7_139";
4630
+ const empty = "_empty_fcgc7_148";
4631
+ const emptyText = "_emptyText_fcgc7_153";
4632
+ const summary = "_summary_fcgc7_158";
4633
+ const tree = "_tree_fcgc7_162";
4634
+ const switchViewButtons = "_switchViewButtons_fcgc7_170";
4719
4635
  const style0$4 = {
4720
4636
  container: container$3,
4721
4637
  clearButton,
@@ -4731,13 +4647,11 @@ const cssModules$4 = {
4731
4647
  };
4732
4648
  const LogsOverviewPanel = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__cssModules", cssModules$4]]);
4733
4649
  const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4734
- __name: "RunDataView",
4650
+ __name: "LogsViewRunData",
4735
4651
  props: {
4736
4652
  title: {},
4737
4653
  paneType: {},
4738
- logEntry: {},
4739
- workflow: {},
4740
- execution: {}
4654
+ logEntry: {}
4741
4655
  },
4742
4656
  setup(__props) {
4743
4657
  const locale = useI18n$1();
@@ -4749,7 +4663,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4749
4663
  return { node: __props.logEntry.node, runIndex: __props.logEntry.runIndex };
4750
4664
  }
4751
4665
  const source = __props.logEntry.runData.source[0];
4752
- const node = source && __props.workflow.getNode(source.previousNode);
4666
+ const node = source && __props.logEntry.workflow.getNode(source.previousNode);
4753
4667
  if (!source || !node) {
4754
4668
  return void 0;
4755
4669
  }
@@ -4763,6 +4677,9 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4763
4677
  overrideOutputs: [source.previousNodeOutput ?? 0]
4764
4678
  };
4765
4679
  });
4680
+ const isExecuting = computed(
4681
+ () => __props.paneType === "output" && (__props.logEntry.runData.executionStatus === "running" || __props.logEntry.runData.executionStatus === "waiting")
4682
+ );
4766
4683
  function handleClickOpenNdv() {
4767
4684
  ndvStore.setActiveNodeName(__props.logEntry.node.name);
4768
4685
  }
@@ -4770,9 +4687,10 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4770
4687
  displayMode.value = value;
4771
4688
  }
4772
4689
  return (_ctx, _cache) => {
4690
+ const _directive_n8n_html = resolveDirective("n8n-html");
4773
4691
  return runDataProps.value ? (openBlock(), createBlock(RunData, mergeProps({ key: 0 }, runDataProps.value, {
4774
- workflow: _ctx.workflow,
4775
- "workflow-execution": _ctx.execution,
4692
+ workflow: _ctx.logEntry.workflow,
4693
+ "workflow-execution": _ctx.logEntry.execution,
4776
4694
  "too-much-data-title": unref(locale).baseText("ndv.output.tooMuchData.title"),
4777
4695
  "no-data-in-branch-message": unref(locale).baseText("ndv.output.noOutputDataInBranch"),
4778
4696
  "executing-message": unref(locale).baseText("ndv.output.executing"),
@@ -4784,6 +4702,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4784
4702
  "disable-hover-highlight": true,
4785
4703
  "display-mode": displayMode.value,
4786
4704
  "disable-ai-content": _ctx.logEntry.depth === 0,
4705
+ "is-executing": isExecuting.value,
4787
4706
  "table-header-bg-color": "light",
4788
4707
  onDisplayModeChange: handleChangeDisplayMode
4789
4708
  }), createSlots({
@@ -4812,6 +4731,21 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4812
4731
  _: 1
4813
4732
  })
4814
4733
  ]),
4734
+ "node-waiting": withCtx(() => [
4735
+ createVNode(unref(N8nText), {
4736
+ bold: true,
4737
+ color: "text-dark",
4738
+ size: "large"
4739
+ }, {
4740
+ default: withCtx(() => [
4741
+ createTextVNode(toDisplayString(unref(locale).baseText("ndv.output.waitNodeWaiting.title")), 1)
4742
+ ]),
4743
+ _: 1
4744
+ }),
4745
+ withDirectives(createVNode(unref(N8nText), null, null, 512), [
4746
+ [_directive_n8n_html, unref(waitingNodeTooltip)(_ctx.logEntry.node)]
4747
+ ])
4748
+ ]),
4815
4749
  _: 2
4816
4750
  }, [
4817
4751
  isMultipleInput.value ? {
@@ -4839,7 +4773,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
4839
4773
  ]),
4840
4774
  key: "1"
4841
4775
  } : void 0
4842
- ]), 1040, ["workflow", "workflow-execution", "too-much-data-title", "no-data-in-branch-message", "executing-message", "pane-type", "display-mode", "disable-ai-content"])) : createCommentVNode("", true);
4776
+ ]), 1040, ["workflow", "workflow-execution", "too-much-data-title", "no-data-in-branch-message", "executing-message", "pane-type", "display-mode", "disable-ai-content", "is-executing"])) : createCommentVNode("", true);
4843
4777
  };
4844
4778
  }
4845
4779
  });
@@ -4850,7 +4784,7 @@ const style0$3 = {
4850
4784
  const cssModules$3 = {
4851
4785
  "$style": style0$3
4852
4786
  };
4853
- const RunDataView = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__cssModules", cssModules$3]]);
4787
+ const LogsViewRunData = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__cssModules", cssModules$3]]);
4854
4788
  function useResizablePanel(localStorageKey, {
4855
4789
  container: container2,
4856
4790
  defaultSize,
@@ -4948,24 +4882,17 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
4948
4882
  props: {
4949
4883
  isOpen: { type: Boolean },
4950
4884
  logEntry: {},
4951
- workflow: {},
4952
- execution: {},
4953
4885
  window: {},
4954
- latestInfo: {}
4886
+ latestInfo: {},
4887
+ panels: {}
4955
4888
  },
4956
- emits: ["clickHeader"],
4889
+ emits: ["clickHeader", "toggleInputOpen", "toggleOutputOpen"],
4957
4890
  setup(__props, { emit: __emit }) {
4958
4891
  const emit = __emit;
4959
4892
  const locale = useI18n$1();
4960
- const telemetry = useTelemetry();
4961
4893
  const nodeTypeStore = useNodeTypesStore();
4962
- const content2 = useLocalStorage(
4963
- "N8N_LOGS_DETAIL_PANEL_CONTENT",
4964
- LOG_DETAILS_CONTENT.OUTPUT,
4965
- { writeDefaults: false }
4966
- );
4967
4894
  const type = computed(() => nodeTypeStore.getNodeType(__props.logEntry.node.type));
4968
- const consumedTokens2 = computed(() => getSubtreeTotalConsumedTokens(__props.logEntry));
4895
+ const consumedTokens2 = computed(() => getSubtreeTotalConsumedTokens(__props.logEntry, false));
4969
4896
  const isTriggerNode = computed(() => type.value?.group.includes("trigger"));
4970
4897
  const container2 = useTemplateRef("container");
4971
4898
  const resizer = useResizablePanel("N8N_LOGS_INPUT_PANEL_WIDTH", {
@@ -4976,35 +4903,13 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
4976
4903
  allowCollapse: true,
4977
4904
  allowFullSize: true
4978
4905
  });
4979
- const shouldResize = computed(() => content2.value === LOG_DETAILS_CONTENT.BOTH);
4980
- function handleToggleInput(open) {
4981
- const wasOpen = [LOG_DETAILS_CONTENT.INPUT, LOG_DETAILS_CONTENT.BOTH].includes(content2.value);
4982
- if (open === wasOpen) {
4983
- return;
4984
- }
4985
- content2.value = wasOpen ? LOG_DETAILS_CONTENT.OUTPUT : LOG_DETAILS_CONTENT.BOTH;
4986
- telemetry.track("User toggled log view sub pane", {
4987
- pane: "input",
4988
- newState: wasOpen ? "hidden" : "visible"
4989
- });
4990
- }
4991
- function handleToggleOutput(open) {
4992
- const wasOpen = [LOG_DETAILS_CONTENT.OUTPUT, LOG_DETAILS_CONTENT.BOTH].includes(content2.value);
4993
- if (open === wasOpen) {
4994
- return;
4995
- }
4996
- content2.value = wasOpen ? LOG_DETAILS_CONTENT.INPUT : LOG_DETAILS_CONTENT.BOTH;
4997
- telemetry.track("User toggled log view sub pane", {
4998
- pane: "output",
4999
- newState: wasOpen ? "hidden" : "visible"
5000
- });
5001
- }
4906
+ const shouldResize = computed(() => __props.panels === LOG_DETAILS_PANEL_STATE.BOTH);
5002
4907
  function handleResizeEnd() {
5003
4908
  if (resizer.isCollapsed.value) {
5004
- handleToggleInput(false);
4909
+ emit("toggleInputOpen", false);
5005
4910
  }
5006
4911
  if (resizer.isFullSize.value) {
5007
- handleToggleOutput(false);
4912
+ emit("toggleOutputOpen", false);
5008
4913
  }
5009
4914
  resizer.onResizeEnd();
5010
4915
  }
@@ -5015,10 +4920,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5015
4920
  class: normalizeClass(_ctx.$style.container),
5016
4921
  "data-test-id": "log-details"
5017
4922
  }, [
5018
- createVNode(PanelHeader, {
4923
+ createVNode(LogsPanelHeader, {
5019
4924
  "data-test-id": "log-details-header",
5020
4925
  class: normalizeClass(_ctx.$style.header),
5021
- onClick: _cache[0] || (_cache[0] = ($event) => emit("clickHeader"))
4926
+ onClick: _cache[2] || (_cache[2] = ($event) => emit("clickHeader"))
5022
4927
  }, {
5023
4928
  title: withCtx(() => [
5024
4929
  createBaseVNode("div", {
@@ -5029,18 +4934,19 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5029
4934
  size: 16,
5030
4935
  class: normalizeClass(_ctx.$style.icon)
5031
4936
  }, null, 8, ["node-type", "class"]),
5032
- createVNode(NodeName, {
4937
+ createVNode(LogsViewNodeName, {
5033
4938
  "latest-name": _ctx.latestInfo?.name ?? _ctx.logEntry.node.name,
5034
4939
  name: _ctx.logEntry.node.name,
5035
4940
  "is-deleted": _ctx.latestInfo?.deleted ?? false
5036
4941
  }, null, 8, ["latest-name", "name", "is-deleted"]),
5037
- _ctx.isOpen ? (openBlock(), createBlock(ExecutionSummary, {
4942
+ _ctx.isOpen ? (openBlock(), createBlock(LogsViewExecutionSummary, {
5038
4943
  key: 0,
5039
4944
  class: normalizeClass(_ctx.$style.executionSummary),
5040
4945
  status: _ctx.logEntry.runData.executionStatus ?? "unknown",
5041
4946
  "consumed-tokens": consumedTokens2.value,
4947
+ "start-time": _ctx.logEntry.runData.startTime,
5042
4948
  "time-took": _ctx.logEntry.runData.executionTime
5043
- }, null, 8, ["class", "status", "consumed-tokens", "time-took"])) : createCommentVNode("", true)
4949
+ }, null, 8, ["class", "status", "consumed-tokens", "start-time", "time-took"])) : createCommentVNode("", true)
5044
4950
  ], 2)
5045
4951
  ]),
5046
4952
  actions: withCtx(() => [
@@ -5048,28 +4954,44 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5048
4954
  key: 0,
5049
4955
  class: normalizeClass(_ctx.$style.actions)
5050
4956
  }, [
5051
- createVNode(unref(N8nButton), {
5052
- size: "mini",
5053
- type: "secondary",
5054
- class: normalizeClass(unref(content2) === unref(LOG_DETAILS_CONTENT).OUTPUT ? "" : _ctx.$style.pressed),
5055
- onClick: withModifiers(handleToggleInput, ["stop"])
4957
+ createVNode(KeyboardShortcutTooltip, {
4958
+ label: unref(locale).baseText("generic.shortcutHint"),
4959
+ shortcut: { keys: ["i"] }
5056
4960
  }, {
5057
4961
  default: withCtx(() => [
5058
- createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.input")), 1)
4962
+ createVNode(unref(N8nButton), {
4963
+ size: "mini",
4964
+ type: "secondary",
4965
+ class: normalizeClass(_ctx.panels === unref(LOG_DETAILS_PANEL_STATE).OUTPUT ? "" : _ctx.$style.pressed),
4966
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => emit("toggleInputOpen"), ["stop"]))
4967
+ }, {
4968
+ default: withCtx(() => [
4969
+ createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.input")), 1)
4970
+ ]),
4971
+ _: 1
4972
+ }, 8, ["class"])
5059
4973
  ]),
5060
4974
  _: 1
5061
- }, 8, ["class"]),
5062
- createVNode(unref(N8nButton), {
5063
- size: "mini",
5064
- type: "secondary",
5065
- class: normalizeClass(unref(content2) === unref(LOG_DETAILS_CONTENT).INPUT ? "" : _ctx.$style.pressed),
5066
- onClick: withModifiers(handleToggleOutput, ["stop"])
4975
+ }, 8, ["label"]),
4976
+ createVNode(KeyboardShortcutTooltip, {
4977
+ label: unref(locale).baseText("generic.shortcutHint"),
4978
+ shortcut: { keys: ["o"] }
5067
4979
  }, {
5068
4980
  default: withCtx(() => [
5069
- createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.output")), 1)
4981
+ createVNode(unref(N8nButton), {
4982
+ size: "mini",
4983
+ type: "secondary",
4984
+ class: normalizeClass(_ctx.panels === unref(LOG_DETAILS_PANEL_STATE).INPUT ? "" : _ctx.$style.pressed),
4985
+ onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("toggleOutputOpen"), ["stop"]))
4986
+ }, {
4987
+ default: withCtx(() => [
4988
+ createTextVNode(toDisplayString(unref(locale).baseText("logs.details.header.actions.output")), 1)
4989
+ ]),
4990
+ _: 1
4991
+ }, 8, ["class"])
5070
4992
  ]),
5071
4993
  _: 1
5072
- }, 8, ["class"])
4994
+ }, 8, ["label"])
5073
4995
  ], 2)) : createCommentVNode("", true),
5074
4996
  renderSlot(_ctx.$slots, "actions")
5075
4997
  ]),
@@ -5080,7 +5002,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5080
5002
  class: normalizeClass(_ctx.$style.content),
5081
5003
  "data-test-id": "logs-details-body"
5082
5004
  }, [
5083
- !isTriggerNode.value && unref(content2) !== unref(LOG_DETAILS_CONTENT).OUTPUT ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
5005
+ !isTriggerNode.value && _ctx.panels !== unref(LOG_DETAILS_PANEL_STATE).OUTPUT ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
5084
5006
  key: 0,
5085
5007
  class: normalizeClass({
5086
5008
  [_ctx.$style.inputResizer]: true,
@@ -5096,27 +5018,23 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5096
5018
  onResizeend: handleResizeEnd
5097
5019
  }, {
5098
5020
  default: withCtx(() => [
5099
- createVNode(RunDataView, {
5021
+ createVNode(LogsViewRunData, {
5100
5022
  "data-test-id": "log-details-input",
5101
5023
  "pane-type": "input",
5102
5024
  title: unref(locale).baseText("logs.details.header.actions.input"),
5103
- "log-entry": _ctx.logEntry,
5104
- workflow: _ctx.workflow,
5105
- execution: _ctx.execution
5106
- }, null, 8, ["title", "log-entry", "workflow", "execution"])
5025
+ "log-entry": _ctx.logEntry
5026
+ }, null, 8, ["title", "log-entry"])
5107
5027
  ]),
5108
5028
  _: 1
5109
5029
  }, 8, ["class", "width", "style", "is-resizing-enabled", "window", "onResize"])) : createCommentVNode("", true),
5110
- isTriggerNode.value || unref(content2) !== unref(LOG_DETAILS_CONTENT).INPUT ? (openBlock(), createBlock(RunDataView, {
5030
+ isTriggerNode.value || _ctx.panels !== unref(LOG_DETAILS_PANEL_STATE).INPUT ? (openBlock(), createBlock(LogsViewRunData, {
5111
5031
  key: 1,
5112
5032
  "data-test-id": "log-details-output",
5113
5033
  "pane-type": "output",
5114
5034
  class: normalizeClass(_ctx.$style.outputPanel),
5115
5035
  title: unref(locale).baseText("logs.details.header.actions.output"),
5116
- "log-entry": _ctx.logEntry,
5117
- workflow: _ctx.workflow,
5118
- execution: _ctx.execution
5119
- }, null, 8, ["class", "title", "log-entry", "workflow", "execution"])) : createCommentVNode("", true)
5036
+ "log-entry": _ctx.logEntry
5037
+ }, null, 8, ["class", "title", "log-entry"])) : createCommentVNode("", true)
5120
5038
  ], 2)) : createCommentVNode("", true)
5121
5039
  ], 2);
5122
5040
  };
@@ -5156,10 +5074,11 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5156
5074
  __name: "LogsPanelActions",
5157
5075
  props: {
5158
5076
  isOpen: { type: Boolean },
5077
+ isSyncSelectionEnabled: { type: Boolean },
5159
5078
  showToggleButton: { type: Boolean },
5160
5079
  showPopOutButton: { type: Boolean }
5161
5080
  },
5162
- emits: ["popOut", "toggleOpen"],
5081
+ emits: ["popOut", "toggleOpen", "toggleSyncSelection"],
5163
5082
  setup(__props, { emit: __emit }) {
5164
5083
  const emit = __emit;
5165
5084
  const appStyles = useStyles();
@@ -5169,11 +5088,30 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5169
5088
  const toggleButtonText = computed(
5170
5089
  () => locales.baseText(__props.isOpen ? "runData.panel.actions.collapse" : "runData.panel.actions.open")
5171
5090
  );
5091
+ const menuItems = computed(() => [
5092
+ {
5093
+ id: "toggleSyncSelection",
5094
+ label: locales.baseText("runData.panel.actions.sync"),
5095
+ checked: __props.isSyncSelectionEnabled
5096
+ },
5097
+ ...__props.showPopOutButton ? [{ id: "popOut", label: popOutButtonText.value }] : []
5098
+ ]);
5099
+ function handleSelectMenuItem(selected2) {
5100
+ switch (selected2) {
5101
+ case "popOut":
5102
+ emit(selected2);
5103
+ return;
5104
+ case "toggleSyncSelection":
5105
+ emit(selected2);
5106
+ return;
5107
+ }
5108
+ }
5172
5109
  return (_ctx, _cache) => {
5110
+ const _component_N8nTooltip = resolveComponent("N8nTooltip");
5173
5111
  return openBlock(), createElementBlock("div", {
5174
5112
  class: normalizeClass(_ctx.$style.container)
5175
5113
  }, [
5176
- _ctx.showPopOutButton ? (openBlock(), createBlock(unref(N8nTooltip), {
5114
+ !_ctx.isOpen && _ctx.showPopOutButton ? (openBlock(), createBlock(_component_N8nTooltip, {
5177
5115
  key: 0,
5178
5116
  "z-index": tooltipZIndex.value,
5179
5117
  content: popOutButtonText.value
@@ -5181,7 +5119,8 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5181
5119
  default: withCtx(() => [
5182
5120
  createVNode(unref(_sfc_main$i), {
5183
5121
  icon: "pop-out",
5184
- type: "secondary",
5122
+ type: "tertiary",
5123
+ text: "",
5185
5124
  size: "small",
5186
5125
  "icon-size": "medium",
5187
5126
  "aria-label": popOutButtonText.value,
@@ -5190,29 +5129,39 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5190
5129
  ]),
5191
5130
  _: 1
5192
5131
  }, 8, ["z-index", "content"])) : createCommentVNode("", true),
5193
- _ctx.showToggleButton ? (openBlock(), createBlock(unref(N8nTooltip), {
5132
+ _ctx.isOpen ? (openBlock(), createBlock(unref(N8nActionDropdown), {
5194
5133
  key: 1,
5195
- "z-index": tooltipZIndex.value,
5196
- content: toggleButtonText.value
5134
+ "icon-size": "small",
5135
+ "activator-icon": "ellipsis-h",
5136
+ "activator-size": "small",
5137
+ items: menuItems.value,
5138
+ teleported: false,
5139
+ onSelect: handleSelectMenuItem
5140
+ }, null, 8, ["items"])) : createCommentVNode("", true),
5141
+ _ctx.showToggleButton ? (openBlock(), createBlock(KeyboardShortcutTooltip, {
5142
+ key: 2,
5143
+ label: unref(locales).baseText("generic.shortcutHint"),
5144
+ shortcut: { keys: ["l"] },
5145
+ "z-index": tooltipZIndex.value
5197
5146
  }, {
5198
5147
  default: withCtx(() => [
5199
5148
  createVNode(unref(_sfc_main$i), {
5200
- type: "secondary",
5149
+ type: "tertiary",
5150
+ text: "",
5201
5151
  size: "small",
5202
5152
  "icon-size": "medium",
5203
5153
  icon: _ctx.isOpen ? "chevron-down" : "chevron-up",
5204
5154
  "aria-label": toggleButtonText.value,
5205
- style: { "color": "var(--color-text-base)" },
5206
5155
  onClick: _cache[1] || (_cache[1] = withModifiers(($event) => emit("toggleOpen"), ["stop"]))
5207
5156
  }, null, 8, ["icon", "aria-label"])
5208
5157
  ]),
5209
5158
  _: 1
5210
- }, 8, ["z-index", "content"])) : createCommentVNode("", true)
5159
+ }, 8, ["label", "z-index"])) : createCommentVNode("", true)
5211
5160
  ], 2);
5212
5161
  };
5213
5162
  }
5214
5163
  });
5215
- const container$1 = "_container_1qwjg_123";
5164
+ const container$1 = "_container_xdwf0_123";
5216
5165
  const style0$1 = {
5217
5166
  container: container$1
5218
5167
  };
@@ -5220,11 +5169,9 @@ const cssModules$1 = {
5220
5169
  "$style": style0$1
5221
5170
  };
5222
5171
  const LogsPanelActions = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__cssModules", cssModules$1]]);
5223
- function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5224
- const canvasStore = useCanvasStore();
5172
+ function useLogsPanelLayout(pipContainer, pipContent2, container2, logsContainer2) {
5173
+ const logsStore = useLogsStore();
5225
5174
  const telemetry = useTelemetry();
5226
- const workflowsStore = useWorkflowsStore();
5227
- const panelState = computed(() => workflowsStore.logsPanelState);
5228
5175
  const resizer = useResizablePanel(LOCAL_STORAGE_PANEL_HEIGHT, {
5229
5176
  container: document.body,
5230
5177
  position: "bottom",
@@ -5248,7 +5195,7 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5248
5195
  allowFullSize: true
5249
5196
  });
5250
5197
  const isOpen = computed(
5251
- () => panelState.value === LOGS_PANEL_STATE.CLOSED ? resizer.isResizing.value && resizer.size.value > 0 : !resizer.isCollapsed.value
5198
+ () => logsStore.isOpen ? !resizer.isCollapsed.value : resizer.isResizing.value && resizer.size.value > 0
5252
5199
  );
5253
5200
  const isCollapsingDetailsPanel = computed(() => overviewPanelResizer.isFullSize.value);
5254
5201
  const { canPopOut, isPoppedOut, pipWindow } = usePiPWindow({
@@ -5256,32 +5203,32 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5256
5203
  initialWidth: window.document.body.offsetWidth * 0.8,
5257
5204
  container: pipContainer,
5258
5205
  content: pipContent2,
5259
- shouldPopOut: computed(() => panelState.value === LOGS_PANEL_STATE.FLOATING),
5206
+ shouldPopOut: computed(() => logsStore.state === LOGS_PANEL_STATE.FLOATING),
5260
5207
  onRequestClose: () => {
5261
5208
  if (!isOpen.value) {
5262
5209
  return;
5263
5210
  }
5264
5211
  telemetry.track("User toggled log view", { new_state: "attached" });
5265
- workflowsStore.setPreferPoppedOutLogsView(false);
5212
+ logsStore.setPreferPoppedOut(false);
5266
5213
  }
5267
5214
  });
5268
5215
  function handleToggleOpen(open) {
5269
- const wasOpen = panelState.value !== LOGS_PANEL_STATE.CLOSED;
5216
+ const wasOpen = logsStore.isOpen;
5270
5217
  if (open === wasOpen) {
5271
5218
  return;
5272
5219
  }
5273
- workflowsStore.toggleLogsPanelOpen(open);
5220
+ logsStore.toggleOpen(open);
5274
5221
  telemetry.track("User toggled log view", {
5275
5222
  new_state: wasOpen ? "collapsed" : "attached"
5276
5223
  });
5277
5224
  }
5278
5225
  function handlePopOut() {
5279
5226
  telemetry.track("User toggled log view", { new_state: "floating" });
5280
- workflowsStore.toggleLogsPanelOpen(true);
5281
- workflowsStore.setPreferPoppedOutLogsView(true);
5227
+ logsStore.toggleOpen(true);
5228
+ logsStore.setPreferPoppedOut(true);
5282
5229
  }
5283
5230
  function handleResizeEnd() {
5284
- if (panelState.value === LOGS_PANEL_STATE.CLOSED && !resizer.isCollapsed.value) {
5231
+ if (!logsStore.isOpen && !resizer.isCollapsed.value) {
5285
5232
  handleToggleOpen(true);
5286
5233
  }
5287
5234
  if (resizer.isCollapsed.value) {
@@ -5290,9 +5237,9 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5290
5237
  resizer.onResizeEnd();
5291
5238
  }
5292
5239
  watch(
5293
- [panelState, resizer.size],
5240
+ [() => logsStore.state, resizer.size],
5294
5241
  ([state, height]) => {
5295
- canvasStore.setPanelHeight(
5242
+ logsStore.setHeight(
5296
5243
  state === LOGS_PANEL_STATE.FLOATING ? 0 : state === LOGS_PANEL_STATE.ATTACHED ? height : 32
5297
5244
  );
5298
5245
  },
@@ -5318,10 +5265,13 @@ function useLayout(pipContainer, pipContent2, container2, logsContainer2) {
5318
5265
  onOverviewPanelResizeEnd: overviewPanelResizer.onResizeEnd
5319
5266
  };
5320
5267
  }
5321
- function useExecutionData() {
5268
+ function useLogsExecutionData() {
5322
5269
  const nodeHelpers = useNodeHelpers();
5323
5270
  const workflowsStore = useWorkflowsStore();
5271
+ const toast = useToast();
5324
5272
  const execData = ref();
5273
+ const subWorkflowExecData = ref({});
5274
+ const subWorkflows = ref({});
5325
5275
  const workflow = computed(
5326
5276
  () => execData.value ? new Workflow({
5327
5277
  ...execData.value?.workflowData,
@@ -5347,35 +5297,65 @@ function useExecutionData() {
5347
5297
  (nodes) => nodes.some(isChatNode)
5348
5298
  )
5349
5299
  );
5350
- const execution = computed(() => {
5351
- if (!execData.value || !workflow.value) {
5352
- return void 0;
5300
+ const entries = computed(() => {
5301
+ if (!execData.value?.data || !workflow.value) {
5302
+ return [];
5353
5303
  }
5354
- return {
5355
- ...execData.value,
5356
- tree: createLogEntries(workflow.value, execData.value.data?.resultData.runData ?? {})
5357
- };
5304
+ return createLogTree(
5305
+ workflow.value,
5306
+ execData.value,
5307
+ subWorkflows.value,
5308
+ subWorkflowExecData.value
5309
+ );
5358
5310
  });
5359
- const updateInterval = computed(() => (execution.value?.tree.length ?? 0) > 10 ? 300 : 0);
5360
- const runStatusList = computed(
5361
- () => workflowsStore.workflowExecutionData?.id === IN_PROGRESS_EXECUTION_ID ? Object.values(workflowsStore.workflowExecutionData?.data?.resultData.runData ?? {}).flatMap((tasks) => tasks.map((task) => task.executionStatus ?? "")).join("|") : ""
5362
- );
5311
+ const updateInterval = computed(() => (entries.value?.length ?? 0) > 10 ? 300 : 0);
5363
5312
  function resetExecutionData() {
5364
5313
  execData.value = void 0;
5365
5314
  workflowsStore.setWorkflowExecutionData(null);
5366
5315
  nodeHelpers.updateNodesExecutionIssues();
5367
5316
  }
5317
+ async function loadSubExecution(logEntry) {
5318
+ const executionId = logEntry.runData.metadata?.subExecution?.executionId;
5319
+ const workflowId = logEntry.runData.metadata?.subExecution?.workflowId;
5320
+ if (!execData.value?.data || !executionId || !workflowId) {
5321
+ return;
5322
+ }
5323
+ try {
5324
+ const subExecution = await workflowsStore.fetchExecutionDataById(executionId);
5325
+ const data = subExecution?.data ? parse(subExecution.data) : void 0;
5326
+ if (!data || !subExecution) {
5327
+ throw Error("Data is missing");
5328
+ }
5329
+ subWorkflowExecData.value[executionId] = data;
5330
+ subWorkflows.value[workflowId] = new Workflow({
5331
+ ...subExecution.workflowData,
5332
+ nodeTypes: workflowsStore.getNodeTypes()
5333
+ });
5334
+ } catch (e) {
5335
+ toast.showError(e, "Unable to load sub execution");
5336
+ }
5337
+ }
5368
5338
  watch(
5369
5339
  // Fields that should trigger update
5370
5340
  [
5371
5341
  () => workflowsStore.workflowExecutionData?.id,
5372
5342
  () => workflowsStore.workflowExecutionData?.workflowData.id,
5373
5343
  () => workflowsStore.workflowExecutionData?.status,
5374
- runStatusList
5344
+ () => workflowsStore.workflowExecutionResultDataLastUpdate,
5345
+ () => workflowsStore.workflowExecutionStartedData
5375
5346
  ],
5376
5347
  useThrottleFn(
5377
- () => {
5378
- execData.value = deepToRaw(workflowsStore.workflowExecutionData ?? void 0);
5348
+ ([executionId], [previousExecutionId]) => {
5349
+ execData.value = workflowsStore.workflowExecutionData === null ? void 0 : deepToRaw(
5350
+ mergeStartData(
5351
+ workflowsStore.workflowExecutionStartedData?.[1] ?? {},
5352
+ workflowsStore.workflowExecutionData
5353
+ )
5354
+ );
5355
+ if (executionId !== previousExecutionId) {
5356
+ subWorkflowExecData.value = {};
5357
+ subWorkflows.value = {};
5358
+ }
5379
5359
  },
5380
5360
  updateInterval,
5381
5361
  true,
@@ -5383,7 +5363,84 @@ function useExecutionData() {
5383
5363
  ),
5384
5364
  { immediate: true }
5385
5365
  );
5386
- return { execution, workflow, hasChat, latestNodeNameById, resetExecutionData };
5366
+ return {
5367
+ execution: computed(() => execData.value),
5368
+ entries,
5369
+ hasChat,
5370
+ latestNodeNameById,
5371
+ resetExecutionData,
5372
+ loadSubExecution
5373
+ };
5374
+ }
5375
+ function useLogsSelection(execution, tree2, flatLogEntries, toggleExpand) {
5376
+ const telemetry = useTelemetry();
5377
+ const manualLogEntrySelection = ref({ type: "initial" });
5378
+ const selected2 = computed(() => findSelectedLogEntry(manualLogEntrySelection.value, tree2.value));
5379
+ const logsStore = useLogsStore();
5380
+ const uiStore = useUIStore();
5381
+ const canvasStore = useCanvasStore();
5382
+ function syncSelectionToCanvasIfEnabled(value) {
5383
+ if (!logsStore.isLogSelectionSyncedWithCanvas) {
5384
+ return;
5385
+ }
5386
+ canvasEventBus.emit("nodes:select", { ids: [value.node.id], panIntoView: true });
5387
+ }
5388
+ function select(value) {
5389
+ manualLogEntrySelection.value = value === void 0 ? { type: "none" } : { type: "selected", id: value.id };
5390
+ if (value) {
5391
+ syncSelectionToCanvasIfEnabled(value);
5392
+ telemetry.track("User selected node in log view", {
5393
+ node_type: value.node.type,
5394
+ node_id: value.node.id,
5395
+ execution_id: execution.value?.id,
5396
+ workflow_id: execution.value?.workflowData.id,
5397
+ subworkflow_depth: getDepth(value)
5398
+ });
5399
+ }
5400
+ }
5401
+ function selectPrev() {
5402
+ const entries = flatLogEntries.value;
5403
+ const prevEntry = selected2.value ? getEntryAtRelativeIndex(entries, selected2.value.id, -1) ?? entries[0] : entries[entries.length - 1];
5404
+ manualLogEntrySelection.value = { type: "selected", id: prevEntry.id };
5405
+ syncSelectionToCanvasIfEnabled(prevEntry);
5406
+ }
5407
+ function selectNext() {
5408
+ const entries = flatLogEntries.value;
5409
+ const nextEntry = selected2.value ? getEntryAtRelativeIndex(entries, selected2.value.id, 1) ?? entries[entries.length - 1] : entries[0];
5410
+ manualLogEntrySelection.value = { type: "selected", id: nextEntry.id };
5411
+ syncSelectionToCanvasIfEnabled(nextEntry);
5412
+ }
5413
+ watch(
5414
+ [() => uiStore.lastSelectedNode, () => logsStore.isLogSelectionSyncedWithCanvas],
5415
+ ([selectedOnCanvas, shouldSync]) => {
5416
+ if (!shouldSync || !selectedOnCanvas || canvasStore.hasRangeSelection || selected2.value?.node.name === selectedOnCanvas) {
5417
+ return;
5418
+ }
5419
+ const entry = findLogEntryRec((e) => e.node.name === selectedOnCanvas, tree2.value);
5420
+ if (!entry) {
5421
+ return;
5422
+ }
5423
+ manualLogEntrySelection.value = { type: "selected", id: entry.id };
5424
+ let parent = entry.parent;
5425
+ while (parent !== void 0) {
5426
+ toggleExpand(parent, true);
5427
+ parent = parent.parent;
5428
+ }
5429
+ },
5430
+ { immediate: true }
5431
+ );
5432
+ return { selected: selected2, select, selectPrev, selectNext };
5433
+ }
5434
+ function useLogsTreeExpand(entries) {
5435
+ const collapsedEntries = ref({});
5436
+ const flatLogEntries = computed(() => flattenLogEntries(entries.value, collapsedEntries.value));
5437
+ function toggleExpanded(treeNode, expand) {
5438
+ collapsedEntries.value[treeNode.id] = expand === void 0 ? !collapsedEntries.value[treeNode.id] : !expand;
5439
+ }
5440
+ return {
5441
+ flatLogEntries,
5442
+ toggleExpanded
5443
+ };
5387
5444
  }
5388
5445
  const _sfc_main = /* @__PURE__ */ defineComponent({
5389
5446
  __name: "LogsPanel",
@@ -5396,6 +5453,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5396
5453
  const logsContainer2 = useTemplateRef("logsContainer");
5397
5454
  const pipContainer = useTemplateRef("pipContainer");
5398
5455
  const pipContent2 = useTemplateRef("pipContent");
5456
+ const logsStore = useLogsStore();
5457
+ const ndvStore = useNDVStore();
5399
5458
  const {
5400
5459
  height,
5401
5460
  chatPanelWidth,
@@ -5414,7 +5473,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5414
5473
  onChatPanelResizeEnd,
5415
5474
  onOverviewPanelResize,
5416
5475
  onOverviewPanelResizeEnd
5417
- } = useLayout(pipContainer, pipContent2, container2, logsContainer2);
5476
+ } = useLogsPanelLayout(pipContainer, pipContent2, container2, logsContainer2);
5418
5477
  const {
5419
5478
  currentSessionId,
5420
5479
  messages: messages2,
@@ -5423,35 +5482,43 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5423
5482
  refreshSession,
5424
5483
  displayExecution
5425
5484
  } = useChatState(props.isReadOnly);
5426
- const { workflow, execution, hasChat, latestNodeNameById, resetExecutionData } = useExecutionData();
5427
- const manualLogEntrySelection = ref({ type: "initial" });
5428
- const selectedLogEntry = computed(
5429
- () => findSelectedLogEntry(manualLogEntrySelection.value, execution.value)
5485
+ const { entries, execution, hasChat, latestNodeNameById, resetExecutionData, loadSubExecution } = useLogsExecutionData();
5486
+ const { flatLogEntries, toggleExpanded } = useLogsTreeExpand(entries);
5487
+ const { selected: selected2, select, selectNext, selectPrev } = useLogsSelection(
5488
+ execution,
5489
+ entries,
5490
+ flatLogEntries,
5491
+ toggleExpanded
5430
5492
  );
5431
- const isLogDetailsOpen = computed(() => isOpen.value && selectedLogEntry.value !== void 0);
5493
+ const isLogDetailsOpen = computed(() => isOpen.value && selected2.value !== void 0);
5432
5494
  const isLogDetailsVisuallyOpen = computed(
5433
5495
  () => isLogDetailsOpen.value && !isCollapsingDetailsPanel.value
5434
5496
  );
5435
5497
  const logsPanelActionsProps = computed(() => ({
5436
5498
  isOpen: isOpen.value,
5499
+ isSyncSelectionEnabled: logsStore.isLogSelectionSyncedWithCanvas,
5437
5500
  showToggleButton: !isPoppedOut.value,
5438
5501
  showPopOutButton: canPopOut.value && !isPoppedOut.value,
5439
5502
  onPopOut,
5440
- onToggleOpen
5503
+ onToggleOpen,
5504
+ onToggleSyncSelection: logsStore.toggleLogSelectionSync
5441
5505
  }));
5442
- function handleSelectLogEntry(selected2) {
5443
- const workflowId = execution.value?.workflowData.id;
5444
- if (!workflowId) {
5445
- return;
5446
- }
5447
- manualLogEntrySelection.value = selected2 === void 0 ? { type: "none", workflowId } : { type: "selected", workflowId, data: selected2 };
5448
- }
5449
5506
  function handleResizeOverviewPanelEnd() {
5450
5507
  if (isOverviewPanelFullWidth.value) {
5451
- handleSelectLogEntry(void 0);
5508
+ select(void 0);
5452
5509
  }
5453
5510
  onOverviewPanelResizeEnd();
5454
5511
  }
5512
+ async function handleOpenNdv(treeNode) {
5513
+ ndvStore.setActiveNodeName(treeNode.node.name);
5514
+ await nextTick(() => {
5515
+ const source = treeNode.runData.source[0];
5516
+ const inputBranch = source?.previousNodeOutput ?? 0;
5517
+ ndvEventBus.emit("updateInputNodeName", source?.previousNode);
5518
+ ndvEventBus.emit("setInputBranchIndex", inputBranch);
5519
+ ndvStore.setOutputRunIndex(treeNode.runIndex);
5520
+ });
5521
+ }
5455
5522
  return (_ctx, _cache) => {
5456
5523
  return openBlock(), createElementBlock("div", {
5457
5524
  ref_key: "pipContainer",
@@ -5475,8 +5542,33 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5475
5542
  createBaseVNode("div", {
5476
5543
  ref_key: "container",
5477
5544
  ref: container2,
5478
- class: normalizeClass([_ctx.$style.container, "ignore-key-press-canvas"]),
5479
- tabindex: "0"
5545
+ class: normalizeClass(_ctx.$style.container),
5546
+ tabindex: "-1",
5547
+ onKeydown: [
5548
+ _cache[3] || (_cache[3] = withKeys(withModifiers(($event) => unref(select)(void 0), ["stop"]), ["esc"])),
5549
+ _cache[4] || (_cache[4] = withKeys(withModifiers(
5550
+ //@ts-ignore
5551
+ (...args) => unref(selectNext) && unref(selectNext)(...args),
5552
+ ["stop"]
5553
+ ), ["j"])),
5554
+ _cache[5] || (_cache[5] = withKeys(withModifiers(
5555
+ //@ts-ignore
5556
+ (...args) => unref(selectNext) && unref(selectNext)(...args),
5557
+ ["stop", "prevent"]
5558
+ ), ["down"])),
5559
+ _cache[6] || (_cache[6] = withKeys(withModifiers(
5560
+ //@ts-ignore
5561
+ (...args) => unref(selectPrev) && unref(selectPrev)(...args),
5562
+ ["stop"]
5563
+ ), ["k"])),
5564
+ _cache[7] || (_cache[7] = withKeys(withModifiers(
5565
+ //@ts-ignore
5566
+ (...args) => unref(selectPrev) && unref(selectPrev)(...args),
5567
+ ["stop", "prevent"]
5568
+ ), ["up"])),
5569
+ _cache[8] || (_cache[8] = withKeys(withModifiers(($event) => unref(selected2) && unref(toggleExpanded)(unref(selected2)), ["stop"]), ["space"])),
5570
+ _cache[9] || (_cache[9] = withKeys(withModifiers(($event) => unref(selected2) && handleOpenNdv(unref(selected2)), ["stop"]), ["enter"]))
5571
+ ]
5480
5572
  }, [
5481
5573
  unref(hasChat) && (!props.isReadOnly || unref(messages2).length > 0) ? (openBlock(), createBlock(unref(N8nResizeWrapper), {
5482
5574
  key: 0,
@@ -5530,40 +5622,45 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5530
5622
  "is-open": unref(isOpen),
5531
5623
  "is-read-only": _ctx.isReadOnly,
5532
5624
  "is-compact": isLogDetailsVisuallyOpen.value,
5533
- selected: selectedLogEntry.value,
5625
+ selected: unref(selected2),
5534
5626
  execution: unref(execution),
5535
- "scroll-to-selection": manualLogEntrySelection.value.type !== "selected" || manualLogEntrySelection.value.data.id !== selectedLogEntry.value?.id,
5627
+ entries: unref(entries),
5536
5628
  "latest-node-info": unref(latestNodeNameById),
5629
+ "flat-log-entries": unref(flatLogEntries),
5537
5630
  onClickHeader: _cache[1] || (_cache[1] = ($event) => unref(onToggleOpen)(true)),
5538
- onSelect: handleSelectLogEntry,
5539
- onClearExecutionData: unref(resetExecutionData)
5631
+ onSelect: unref(select),
5632
+ onClearExecutionData: unref(resetExecutionData),
5633
+ onToggleExpanded: unref(toggleExpanded),
5634
+ onOpenNdv: handleOpenNdv,
5635
+ onLoadSubExecution: unref(loadSubExecution)
5540
5636
  }, {
5541
5637
  actions: withCtx(() => [
5542
5638
  !isLogDetailsVisuallyOpen.value ? (openBlock(), createBlock(LogsPanelActions, normalizeProps(mergeProps({ key: 0 }, logsPanelActionsProps.value)), null, 16)) : createCommentVNode("", true)
5543
5639
  ]),
5544
5640
  _: 1
5545
- }, 8, ["class", "is-open", "is-read-only", "is-compact", "selected", "execution", "scroll-to-selection", "latest-node-info", "onClearExecutionData"]))
5641
+ }, 8, ["class", "is-open", "is-read-only", "is-compact", "selected", "execution", "entries", "latest-node-info", "flat-log-entries", "onSelect", "onClearExecutionData", "onToggleExpanded", "onLoadSubExecution"]))
5546
5642
  ]),
5547
5643
  _: 1
5548
5644
  }, 8, ["class", "width", "style", "is-resizing-enabled", "window", "onResize"]),
5549
- isLogDetailsVisuallyOpen.value && selectedLogEntry.value && unref(workflow) && unref(execution) ? (openBlock(), createBlock(LogsDetailsPanel, {
5645
+ isLogDetailsVisuallyOpen.value && unref(selected2) ? (openBlock(), createBlock(LogsDetailsPanel, {
5550
5646
  key: 0,
5551
5647
  class: normalizeClass(_ctx.$style.logDetails),
5552
5648
  "is-open": unref(isOpen),
5553
- "log-entry": selectedLogEntry.value,
5554
- workflow: unref(workflow),
5555
- execution: unref(execution),
5649
+ "log-entry": unref(selected2),
5556
5650
  window: unref(pipWindow),
5557
- "latest-info": unref(latestNodeNameById)[selectedLogEntry.value.node.id],
5558
- onClickHeader: _cache[2] || (_cache[2] = ($event) => unref(onToggleOpen)(true))
5651
+ "latest-info": unref(latestNodeNameById)[unref(selected2).id],
5652
+ panels: unref(logsStore).detailsState,
5653
+ onClickHeader: _cache[2] || (_cache[2] = ($event) => unref(onToggleOpen)(true)),
5654
+ onToggleInputOpen: unref(logsStore).toggleInputOpen,
5655
+ onToggleOutputOpen: unref(logsStore).toggleOutputOpen
5559
5656
  }, {
5560
5657
  actions: withCtx(() => [
5561
5658
  isLogDetailsVisuallyOpen.value ? (openBlock(), createBlock(LogsPanelActions, normalizeProps(mergeProps({ key: 0 }, logsPanelActionsProps.value)), null, 16)) : createCommentVNode("", true)
5562
5659
  ]),
5563
5660
  _: 1
5564
- }, 8, ["class", "is-open", "log-entry", "workflow", "execution", "window", "latest-info"])) : createCommentVNode("", true)
5661
+ }, 8, ["class", "is-open", "log-entry", "window", "latest-info", "panels", "onToggleInputOpen", "onToggleOutputOpen"])) : createCommentVNode("", true)
5565
5662
  ], 2)
5566
- ], 2)
5663
+ ], 34)
5567
5664
  ]),
5568
5665
  _: 1
5569
5666
  }, 8, ["height", "is-resizing-enabled", "class", "style", "onResize", "onResizeend"])