@conduction/nextcloud-vue 2.103.0 → 2.105.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +23 -0
  2. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +94 -72
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  6. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  7. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +18 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +3 -3
  12. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  13. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  14. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
  15. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  16. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  17. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  18. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
  19. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
  21. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  22. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +39 -2
  23. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  24. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +14 -0
  25. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  26. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +99 -3
  27. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  28. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  29. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
  30. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
  31. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
  32. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
  34. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
  35. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
  36. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
  37. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
  38. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
  39. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
  40. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
  41. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
  42. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
  43. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +213 -4
  44. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +105 -85
  46. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  47. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +10 -4
  48. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  49. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
  50. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
  51. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
  52. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
  53. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
  54. package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
  55. package/dist/esm/components/CnObjectRow/CnObjectRow.vue.js +1 -1
  56. package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +57 -5
  57. package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
  58. package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +37 -4
  59. package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
  60. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
  61. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
  62. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
  63. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
  64. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
  65. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  66. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
  67. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  68. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
  69. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
  70. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
  71. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
  72. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
  73. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
  74. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
  75. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
  76. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
  77. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
  78. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  79. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +18 -2
  80. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  81. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  82. package/dist/esm/composables/indexSources.js +7 -7
  83. package/dist/esm/composables/indexSources.js.map +1 -1
  84. package/dist/esm/index.js +1 -0
  85. package/dist/esm/index.js.map +1 -1
  86. package/dist/esm/l10n/en.json.js +8 -1
  87. package/dist/esm/l10n/en.json.js.map +1 -1
  88. package/dist/esm/l10n/nl.json.js +8 -1
  89. package/dist/esm/l10n/nl.json.js.map +1 -1
  90. package/dist/esm/library-style.js +1 -1
  91. package/dist/esm/nextcloud-vue.css +680 -328
  92. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  93. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  94. package/dist/esm/utils/nextcloudApps.js +45 -0
  95. package/dist/esm/utils/nextcloudApps.js.map +1 -0
  96. package/dist/esm/utils/nextcloudDirectory.js +18 -1
  97. package/dist/esm/utils/nextcloudDirectory.js.map +1 -1
  98. package/dist/esm/utils/scopeListLayout.js +9 -2
  99. package/dist/esm/utils/scopeListLayout.js.map +1 -1
  100. package/dist/esm/utils/sortOrder.js +61 -0
  101. package/dist/esm/utils/sortOrder.js.map +1 -0
  102. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  103. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  104. package/dist/esm/utils/visibleWhen.js +12 -4
  105. package/dist/esm/utils/visibleWhen.js.map +1 -1
  106. package/dist/nextcloud-vue.cjs.js +4046 -2999
  107. package/dist/nextcloud-vue.cjs.js.map +2 -2
  108. package/dist/nextcloud-vue.css +680 -328
  109. package/l10n/en.json +8 -1
  110. package/l10n/nl.json +8 -1
  111. package/package.json +1 -1
  112. package/src/components/CnActionsBar/CnActionsBar.md +1 -0
  113. package/src/components/CnActionsBar/CnActionsBar.vue +39 -2
  114. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
  115. package/src/components/CnAppRoot/CnAppRoot.md +1 -1
  116. package/src/components/CnAppRoot/CnAppRoot.vue +21 -4
  117. package/src/components/CnChartWidget/CnChartWidget.md +2 -0
  118. package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
  119. package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
  120. package/src/components/CnDataTable/CnDataTable.md +1 -0
  121. package/src/components/CnDataTable/CnDataTable.vue +49 -0
  122. package/src/components/CnDetailPage/CnDetailPage.md +2 -0
  123. package/src/components/CnDetailPage/CnDetailPage.vue +99 -3
  124. package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
  125. package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
  126. package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
  127. package/src/components/CnIndexPage/CnIndexPage.md +5 -2
  128. package/src/components/CnIndexPage/CnIndexPage.vue +228 -9
  129. package/src/components/CnIndexPage/useSelfFetchList.js +9 -3
  130. package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
  131. package/src/components/CnNoticeWidget/index.js +12 -0
  132. package/src/components/CnObjectRow/CnObjectRow.vue +95 -1
  133. package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
  134. package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
  135. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +7 -2
  136. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
  137. package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
  138. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +18 -2
  139. package/src/components/index.js +1 -0
  140. package/src/composables/indexSources.js +7 -7
  141. package/src/css/dialog.css +20 -2
  142. package/src/css/index-page.css +19 -0
  143. package/src/css/look-board-detail.css +77 -4
  144. package/src/css/look-board-index.css +84 -2
  145. package/src/css/look-board.css +97 -12
  146. package/src/index.js +1 -0
  147. package/src/schemas/app-manifest-v2.schema.json +58 -3
  148. package/src/utils/libraryWidgetKeys.js +1 -0
  149. package/src/utils/nextcloudApps.js +50 -0
  150. package/src/utils/nextcloudDirectory.js +17 -0
  151. package/src/utils/scopeListLayout.js +9 -2
  152. package/src/utils/sortOrder.js +58 -0
  153. package/src/utils/validateManifestV2.compiled.js +3 -3
  154. package/src/utils/visibleWhen.js +12 -4
@@ -1 +1 @@
1
- {"version":3,"file":"CnFlowBoard.vue3.js","sources":["../../../../src/components/CnFlowsPage/CnFlowBoard.vue?vue&type=template&id=5c5d3119&lang.js"],"sourcesContent":["<!--\n CnFlowBoard — the flow editor in the board look: a page header with the\n flow's name, path and actions, then the canvas in a card beside an\n inspector card. Optionally a palette card on the left (`palette: column`).\n The same page shows one run when the route carries `?run=`: the canvas\n paints each step's outcome and the inspector holds the run's card and logs.\n\n The canvas itself is CnFlowDetail; this component only lays it out and adds\n what the board draws around it.\n\n SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-flow-board\" :class=\"{ 'cn-flow-board--with-palette': showPalette }\" data-testid=\"flow-board\">\n\t\t<header class=\"cn-flow-board__header\">\n\t\t\t<div class=\"cn-flow-board__heading\">\n\t\t\t\t<h2 class=\"cn-flow-board__title\" data-testid=\"flow-board-title\">\n\t\t\t\t\t{{ titleText }}\n\t\t\t\t</h2>\n\t\t\t\t<CnStatusBadge v-if=\"pillText\" :label=\"pillText\" variant=\"default\" />\n\t\t\t</div>\n\t\t\t<div v-if=\"!store.inRunView\" class=\"cn-flow-board__actions\">\n\t\t\t\t<NcCheckboxRadioSwitch v-if=\"store.flow.id\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:modelValue=\"store.flow.enabled !== false\"\n\t\t\t\t\tdata-testid=\"flow-board-enabled\"\n\t\t\t\t\t@update:modelValue=\"onEnabledChange\">\n\t\t\t\t\t{{ store.flow.enabled !== false ? t('nextcloud-vue', 'Active') : t('nextcloud-vue', 'Paused') }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton :disabled=\"store.checking || !store.nodes.length\"\n\t\t\t\t\tdata-testid=\"flow-board-check\"\n\t\t\t\t\t@click=\"store.check()\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Check') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton v-if=\"showRun\"\n\t\t\t\t\t:disabled=\"store.running || !store.flow.id\"\n\t\t\t\t\tdata-testid=\"flow-board-run\"\n\t\t\t\t\t@click=\"$emit('run')\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton v-if=\"testSubjectReady\"\n\t\t\t\t\t:disabled=\"store.running || !store.flow.id\"\n\t\t\t\t\tdata-testid=\"flow-board-test\"\n\t\t\t\t\t@click=\"testOpen = true\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<TestTube :size=\"16\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ testLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<CnBuildiqEditButton />\n\t\t\t\t<NcButton variant=\"primary\"\n\t\t\t\t\t:disabled=\"store.saving || !store.flow.name || store.graphLocked\"\n\t\t\t\t\tdata-testid=\"flow-board-save\"\n\t\t\t\t\t@click=\"$emit('save')\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Save') }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</header>\n\n\t\t<CnDialog v-if=\"testOpen\"\n\t\t\t:name=\"testLabel\"\n\t\t\tdata-testid=\"flow-board-test-dialog\"\n\t\t\t@closing=\"testOpen = false\">\n\t\t\t<p class=\"cn-flow-board__test-intro\">\n\t\t\t\t{{ t('nextcloud-vue', 'The saved flow runs once with the record you pick as its subject.') }}\n\t\t\t</p>\n\t\t\t<CnResourceSelect v-model=\"testRecord\"\n\t\t\t\t:register=\"testSubject.register\"\n\t\t\t\t:schema=\"testSubject.schema\"\n\t\t\t\t:labelField=\"testSubject.labelField || 'title'\"\n\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Record')\"\n\t\t\t\tdata-testid=\"flow-board-test-record\" />\n\t\t\t<template #actions>\n\t\t\t\t<NcButton data-testid=\"flow-board-test-cancel\" @click=\"testOpen = false\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton variant=\"primary\"\n\t\t\t\t\t:disabled=\"!testRecord || store.running\"\n\t\t\t\t\tdata-testid=\"flow-board-test-run\"\n\t\t\t\t\t@click=\"runTest\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Run test') }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t</CnDialog>\n\n\t\t<p class=\"cn-flow-board__path\" data-testid=\"flow-board-path\">\n\t\t\t<a :href=\"listHref\" class=\"cn-flow-board__crumb\" @click=\"onCrumbClick($event, detailRoute)\">{{ listText }}</a>\n\t\t\t<span aria-hidden=\"true\"> / </span>\n\t\t\t<template v-if=\"store.inRunView\">\n\t\t\t\t<a :href=\"flowHref\" class=\"cn-flow-board__crumb\" @click=\"onCrumbClick($event, flowPath)\">{{ flowName }}</a>\n\t\t\t\t<span aria-hidden=\"true\"> / </span>\n\t\t\t\t<span>{{ runCrumb }}</span>\n\t\t\t</template>\n\t\t\t<span v-else>{{ flowName }}</span>\n\t\t\t<span v-if=\"metaText\" class=\"cn-flow-board__meta\"> · {{ metaText }}</span>\n\t\t</p>\n\n\t\t<NcNoteCard v-if=\"notice && !store.inRunView\" type=\"info\" class=\"cn-flow-board__notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\n\t\t<div class=\"cn-flow-board__body\">\n\t\t\t<aside v-if=\"showPalette\" class=\"cn-flow-board__card cn-flow-board__palette\" data-testid=\"flow-board-palette\">\n\t\t\t\t<h3 class=\"cn-flow-board__card-title\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Steps') }}\n\t\t\t\t</h3>\n\t\t\t\t<section v-for=\"group in paletteGroups\"\n\t\t\t\t\t:key=\"group.app\"\n\t\t\t\t\tclass=\"cn-flow-board__palette-group\">\n\t\t\t\t\t<h4 class=\"cn-flow-board__palette-app\">\n\t\t\t\t\t\t{{ group.app }}\n\t\t\t\t\t</h4>\n\t\t\t\t\t<ul class=\"cn-flow-board__palette-list\">\n\t\t\t\t\t\t<li v-for=\"entry in group.entries\" :key=\"entry.id\">\n\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-board__palette-step\"\n\t\t\t\t\t\t\t\t:disabled=\"store.graphLocked\"\n\t\t\t\t\t\t\t\t:data-testid=\"`flow-board-palette-${entry.id}`\"\n\t\t\t\t\t\t\t\t@click=\"store.addNode(entry.id)\">\n\t\t\t\t\t\t\t\t{{ entry.displayName || entry.label || entry.id }}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</section>\n\t\t\t\t<p v-if=\"paletteFootnote\" class=\"cn-flow-board__palette-note\">\n\t\t\t\t\t{{ paletteFootnote }}\n\t\t\t\t</p>\n\t\t\t</aside>\n\n\t\t\t<section class=\"cn-flow-board__card cn-flow-board__canvas\" :aria-label=\"t('nextcloud-vue', 'Flow canvas')\">\n\t\t\t\t<CnFlowDetail :id=\"id\"\n\t\t\t\t\t:app=\"app\"\n\t\t\t\t\t:run=\"run\"\n\t\t\t\t\t:toolbarActions=\"false\"\n\t\t\t\t\t:addStep=\"!showPalette\"\n\t\t\t\t\t@save=\"$emit('save')\"\n\t\t\t\t\t@run=\"$emit('run')\" />\n\t\t\t\t<div v-if=\"store.inRunView\"\n\t\t\t\t\tclass=\"cn-flow-board__legend\"\n\t\t\t\t\tdata-testid=\"flow-board-legend\">\n\t\t\t\t\t<span v-for=\"level in legend\" :key=\"level.id\" class=\"cn-flow-board__legend-item\">\n\t\t\t\t\t\t<CnStatusBadge :label=\"level.label\" :variant=\"level.variant\" size=\"small\" />\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t\t<p v-else\n\t\t\t\t\tclass=\"cn-flow-board__validity\"\n\t\t\t\t\t:class=\"`cn-flow-board__validity--${validity.tone}`\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"flow-board-validity\">\n\t\t\t\t\t{{ validity.text }}\n\t\t\t\t</p>\n\t\t\t</section>\n\n\t\t\t<aside class=\"cn-flow-board__card cn-flow-board__inspector\" data-testid=\"flow-board-inspector\">\n\t\t\t\t<template v-if=\"store.inRunView\">\n\t\t\t\t\t<CnFlowRunSummary :run=\"runRecord\"\n\t\t\t\t\t\t:stepsTotal=\"store.nodes.length\"\n\t\t\t\t\t\t:canRetry=\"canRetry\"\n\t\t\t\t\t\t@back=\"onBackToFlow\"\n\t\t\t\t\t\t@retry=\"onRetry\" />\n\t\t\t\t\t<div class=\"cn-flow-board__tabs\" role=\"tablist\">\n\t\t\t\t\t\t<button v-for=\"tab in runTabs\"\n\t\t\t\t\t\t\t:key=\"tab.id\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\t\tclass=\"cn-flow-board__tab\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-flow-board__tab--active': runTab === tab.id }\"\n\t\t\t\t\t\t\t:aria-selected=\"runTab === tab.id ? 'true' : 'false'\"\n\t\t\t\t\t\t\t:data-testid=\"`flow-board-run-tab-${tab.id}`\"\n\t\t\t\t\t\t\t@click=\"runTab = tab.id\">\n\t\t\t\t\t\t\t{{ tab.label }}\n\t\t\t\t\t\t\t<span class=\"cn-flow-board__tab-count\">{{ tab.count }}</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<CnFlowStepLog :lines=\"runTab === 'step' ? selectedRunLines : allRunLines\"\n\t\t\t\t\t\t:emptyText=\"runTab === 'step' && !store.selectedNodeId ? t('nextcloud-vue', 'Select a step on the canvas to see what it did.') : ''\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-else-if=\"store.selectedNode\">\n\t\t\t\t\t<p class=\"cn-flow-board__eyebrow\">\n\t\t\t\t\t\t{{ stepTypeLabel }}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h3 class=\"cn-flow-board__card-title\" data-testid=\"flow-board-step-name\">\n\t\t\t\t\t\t{{ stepName }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<div class=\"cn-flow-board__step-actions\">\n\t\t\t\t\t\t<NcButton data-testid=\"flow-board-edit-step\" @click=\"store.editingNodeId = store.selectedNodeId\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Edit step') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton v-if=\"lastRunUuid\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tdata-testid=\"flow-board-open-last-run\"\n\t\t\t\t\t\t\t@click=\"openRun(lastRunUuid)\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Open the last run on the canvas') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h4 class=\"cn-flow-board__subtitle\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Recent log lines of this step') }}\n\t\t\t\t\t</h4>\n\t\t\t\t\t<CnFlowStepLog :lines=\"recentStepLines\"\n\t\t\t\t\t\twithDay\n\t\t\t\t\t\t:emptyText=\"t('nextcloud-vue', 'This step has not run yet.')\" />\n\t\t\t\t\t<div class=\"cn-flow-board__step-footer\">\n\t\t\t\t\t\t<NcButton variant=\"tertiary\"\n\t\t\t\t\t\t\t:disabled=\"store.graphLocked\"\n\t\t\t\t\t\t\tdata-testid=\"flow-board-delete-step\"\n\t\t\t\t\t\t\t@click=\"store.removeNode(store.selectedNodeId)\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Delete step') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton data-testid=\"flow-board-done\" @click=\"store.selectedNodeId = null\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Done') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t\t<CnFlowSidebar v-else embedded />\n\t\t\t</aside>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport TestTube from 'vue-material-design-icons/TestTube.vue'\nimport CnBuildiqEditButton from '../CnBuildiqEditButton/CnBuildiqEditButton.vue'\nimport CnDialog from '../CnDialog/CnDialog.vue'\nimport CnFlowDetail from '../CnFlowDetail/CnFlowDetail.vue'\nimport CnFlowRunSummary from '../CnFlowDetail/CnFlowRunSummary.vue'\nimport CnFlowSidebar from '../CnFlowDetail/CnFlowSidebar.vue'\nimport CnFlowStepLog from '../CnFlowDetail/CnFlowStepLog.vue'\nimport CnResourceSelect from '../CnResourceSelect/CnResourceSelect.vue'\nimport { FLOW_RUN_ACTIVE_STATUSES, useFlowStore } from '../../composables/useFlowStore.js'\nimport { formatRelativeDate } from '../../utils/boardDate.js'\nimport { flowOutcomeLevels, flowRunDurationMs, flowRunLogLines, flowRunName, formatFlowDuration } from '../../utils/flowRunLog.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\n/**\n * The board-look flow editor and run view. CnFlowEditorPage renders it when\n * the app or page is in the board look; the Nextcloud look keeps the canvas\n * on its own with the app sidebar.\n */\nexport default {\n\tname: 'CnFlowBoard',\n\n\tcomponents: { CnBuildiqEditButton, CnDialog, CnFlowDetail, CnResourceSelect, TestTube, CnFlowRunSummary, CnFlowSidebar, CnFlowStepLog, CnStatusBadge, NcButton, NcCheckboxRadioSwitch, NcNoteCard },\n\n\tprops: {\n\t\t/** The flow uuid, or `new`. */\n\t\tid: { type: String, default: '' },\n\t\t/** The owning app, for a new flow and the list scope. */\n\t\tapp: { type: String, default: null },\n\t\t/** The run to show, or ''. */\n\t\trun: { type: String, default: '' },\n\t\t/** Where the flow list lives; flows open at `<detailRoute>/<id>`. */\n\t\tdetailRoute: { type: String, default: '/flows' },\n\t\t/** The list's name in the path (\"Flows\", \"Settings / Flows\"). */\n\t\tlistLabel: { type: String, default: '' },\n\t\t/** `column` draws the step palette as a card on the left. */\n\t\tpalette: { type: String, default: 'picker' },\n\t\t/** Free text under the path in the palette card. */\n\t\tpaletteFootnote: { type: String, default: '' },\n\t\t/** An info notice under the path. */\n\t\tnotice: { type: String, default: '' },\n\t\t/** The pill beside the title (\"Case type flow\"). */\n\t\tpill: { type: String, default: '' },\n\t\t/**\n\t\t * The records a test run can take as its subject: `{ register, schema,\n\t\t * labelField?, label? }`. Draws a header button (\"Testen met een zaak\",\n\t\t * DqFlow) that runs the saved flow once with a picked record.\n\t\t */\n\t\ttestSubject: { type: Object, default: null },\n\t},\n\n\temits: ['save', 'run', 'retried'],\n\n\tsetup() {\n\t\treturn { store: useFlowStore() }\n\t},\n\n\tdata() {\n\t\treturn { runTab: 'step', testOpen: false, testRecord: null }\n\t},\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether a test subject is declared well enough to pick one. */\n\t\ttestSubjectReady() {\n\t\t\treturn Boolean(this.testSubject && this.testSubject.register && this.testSubject.schema)\n\t\t},\n\n\t\t/** @return {string} The test button's label: the page's own, else the library's. */\n\t\ttestLabel() {\n\t\t\treturn (this.testSubject && this.testSubject.label) || t('nextcloud-vue', 'Test with a record')\n\t\t},\n\n\t\t/** @return {boolean} Whether the palette card is drawn. */\n\t\tshowPalette() {\n\t\t\treturn this.palette === 'column' && !this.store.inRunView\n\t\t},\n\n\t\t/** @return {string} The page title. */\n\t\ttitleText() {\n\t\t\treturn this.store.flow.name || this.t('nextcloud-vue', 'New flow')\n\t\t},\n\n\t\t/** @return {string} The flow's name in the path. */\n\t\tflowName() {\n\t\t\treturn this.store.flow.name || this.t('nextcloud-vue', 'New flow')\n\t\t},\n\n\t\t/** @return {string} The pill text: the page's, else the lifecycle. */\n\t\tpillText() {\n\t\t\tif (this.pill) {\n\t\t\t\treturn this.pill\n\t\t\t}\n\t\t\tconst lifecycle = String(this.store.flow.lifecycleStatus || '')\n\t\t\tif (lifecycle === 'draft') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Draft')\n\t\t\t}\n\t\t\tif (lifecycle === 'deprecated') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Retired')\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/** @return {string} The list label. */\n\t\tlistText() {\n\t\t\treturn this.listLabel || this.t('nextcloud-vue', 'Flows')\n\t\t},\n\n\t\t/** @return {string} The flow's own path. */\n\t\tflowPath() {\n\t\t\treturn `${this.detailRoute}/${this.store.flow.id || this.id}`\n\t\t},\n\n\t\t/** @return {string} The list href. */\n\t\tlistHref() {\n\t\t\treturn this.hrefOf(this.detailRoute)\n\t\t},\n\n\t\t/** @return {string} The flow href. */\n\t\tflowHref() {\n\t\t\treturn this.hrefOf(this.flowPath)\n\t\t},\n\n\t\t/**\n\t\t * What the path says after the name: the trigger, the step count and\n\t\t * the version in the editor; when the run started and how long it\n\t\t * took in the run view.\n\t\t *\n\t\t * @return {string} The meta text.\n\t\t */\n\t\tmetaText() {\n\t\t\tif (this.store.inRunView) {\n\t\t\t\tconst record = this.runRecord\n\t\t\t\tif (!record) {\n\t\t\t\t\treturn ''\n\t\t\t\t}\n\t\t\t\tconst parts = [formatRelativeDate(record.created, { withTime: true })]\n\t\t\t\tconst duration = formatFlowDuration(flowRunDurationMs(record))\n\t\t\t\tif (duration) {\n\t\t\t\t\tparts.push(this.t('nextcloud-vue', 'done in {duration}', { duration }))\n\t\t\t\t}\n\t\t\t\treturn parts.filter(Boolean).join(' · ')\n\t\t\t}\n\t\t\tconst parts = []\n\t\t\tconst trigger = this.triggerText\n\t\t\tif (trigger) {\n\t\t\t\tparts.push(this.t('nextcloud-vue', 'trigger {trigger}', { trigger }))\n\t\t\t}\n\t\t\tconst count = this.store.nodes.length\n\t\t\tparts.push(count === 1 ? this.t('nextcloud-vue', '1 step') : this.t('nextcloud-vue', '{count} steps', { count }))\n\t\t\tif (this.store.flow.version) {\n\t\t\t\tparts.push(this.t('nextcloud-vue', 'version {version}', { version: this.store.flow.version }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/** @return {string} How the flow starts, as the catalogue names it. */\n\t\ttriggerText() {\n\t\t\tconst trigger = String(this.store.flow.trigger || '')\n\t\t\tif (trigger === 'schedule') {\n\t\t\t\treturn this.t('nextcloud-vue', 'On a schedule')\n\t\t\t}\n\t\t\tif (trigger === '' || trigger === 'manual') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Run by hand')\n\t\t\t}\n\t\t\tconst entry = (this.store.eventCatalog || []).find((item) => item && item.id === trigger)\n\t\t\treturn (entry && entry.label) || trigger\n\t\t},\n\n\t\t/** @return {boolean} Whether Run is offered. */\n\t\tshowRun() {\n\t\t\treturn this.store.nodes.some((node) => node?.type === 'openregister.trigger-manual')\n\t\t},\n\n\t\t/**\n\t\t * The engine's verdict on the canvas as one line under it.\n\t\t *\n\t\t * @return {{tone: string, text: string}} The validity bar.\n\t\t */\n\t\tvalidity() {\n\t\t\tconst result = this.store.checkResult\n\t\t\tif (!result) {\n\t\t\t\treturn { tone: 'unknown', text: this.t('nextcloud-vue', 'Not checked yet. Check runs the flow past the engine without saving it.') }\n\t\t\t}\n\t\t\tconst blocking = Array.isArray(result.blocking) ? result.blocking.length : 0\n\t\t\tconst warnings = Array.isArray(result.warnings) ? result.warnings.length : 0\n\t\t\tif (result.valid === false || blocking > 0) {\n\t\t\t\treturn { tone: 'error', text: result.message || this.t('nextcloud-vue', 'The flow cannot run as it is. See the messages on the canvas.') }\n\t\t\t}\n\t\t\tif (warnings > 0) {\n\t\t\t\treturn { tone: 'warning', text: this.t('nextcloud-vue', 'The flow is valid, with {count} warnings.', { count: warnings }) }\n\t\t\t}\n\t\t\treturn { tone: 'success', text: this.t('nextcloud-vue', 'The flow is valid.') }\n\t\t},\n\n\t\t/** @return {Array<object>} The palette grouped by owning app. */\n\t\tpaletteGroups() {\n\t\t\tconst groups = {}\n\t\t\t;(this.store.nodeCatalog || []).forEach((entry) => {\n\t\t\t\tconst app = String(entry?.app || String(entry?.id || '').split('.')[0] || '')\n\t\t\t\tif (!groups[app]) {\n\t\t\t\t\tgroups[app] = { app, entries: [] }\n\t\t\t\t}\n\t\t\t\tgroups[app].entries.push(entry)\n\t\t\t})\n\t\t\treturn Object.values(groups)\n\t\t},\n\n\t\t/** @return {object|null} The run on screen. */\n\t\trunRecord() {\n\t\t\treturn this.store.runDetail\n\t\t\t\t|| (this.store.runs || []).find((item) => item.uuid === this.store.inspectedRunUuid)\n\t\t\t\t|| null\n\t\t},\n\n\t\t/** @return {string} The run's place in the path. */\n\t\trunCrumb() {\n\t\t\treturn this.t('nextcloud-vue', 'Run {id}', { id: flowRunName(this.runRecord) })\n\t\t},\n\n\t\t/** @return {boolean} Whether Run again is offered. */\n\t\tcanRetry() {\n\t\t\treturn !!this.runRecord && !FLOW_RUN_ACTIVE_STATUSES.includes(this.runRecord.status)\n\t\t},\n\n\t\t/** @return {Array<object>} Every line of the run on screen. */\n\t\tallRunLines() {\n\t\t\treturn this.runRecord ? flowRunLogLines(this.runRecord) : []\n\t\t},\n\n\t\t/** @return {Array<object>} The selected step's lines in this run. */\n\t\tselectedRunLines() {\n\t\t\treturn this.runRecord && this.store.selectedNodeId\n\t\t\t\t? flowRunLogLines(this.runRecord, this.store.selectedNodeId)\n\t\t\t\t: []\n\t\t},\n\n\t\t/** @return {Array<object>} The two log tabs with their counts. */\n\t\trunTabs() {\n\t\t\treturn [\n\t\t\t\t{ id: 'step', label: this.t('nextcloud-vue', 'This step'), count: this.selectedRunLines.length },\n\t\t\t\t{ id: 'run', label: this.t('nextcloud-vue', 'Logs of the whole run'), count: this.allRunLines.length },\n\t\t\t]\n\t\t},\n\n\t\t/** @return {Array<object>} The legend of outcomes on the canvas. */\n\t\tlegend() {\n\t\t\tconst levels = flowOutcomeLevels()\n\t\t\treturn ['success', 'warning', 'error', 'info', 'skipped'].map((id) => ({ id, ...levels[id] }))\n\t\t},\n\n\t\t/** @return {string} The selected step's type, as the catalogue names it. */\n\t\tstepTypeLabel() {\n\t\t\tconst node = this.store.selectedNode\n\t\t\tconst entry = node ? this.store.catalogEntry(node.type) : null\n\t\t\treturn entry ? (entry.displayName || entry.id) : String(node?.type || '')\n\t\t},\n\n\t\t/** @return {string} The selected step's name. */\n\t\tstepName() {\n\t\t\tconst node = this.store.selectedNode\n\t\t\treturn (node && (node.name || node.label)) || this.stepTypeLabel\n\t\t},\n\n\t\t/**\n\t\t * The selected step's lines from the flow's recent runs, newest run\n\t\t * first, at most ten.\n\t\t *\n\t\t * @return {Array<object>} The lines.\n\t\t */\n\t\trecentStepLines() {\n\t\t\tconst id = this.store.selectedNodeId\n\t\t\tif (!id) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst lines = []\n\t\t\t;(this.store.runs || []).forEach((item) => {\n\t\t\t\tflowRunLogLines(item, id).forEach((line) => lines.push({ ...line, key: `${item.uuid}-${line.key}` }))\n\t\t\t})\n\t\t\treturn lines.slice(0, 10)\n\t\t},\n\n\t\t/** @return {string} The newest run's uuid, or ''. */\n\t\tlastRunUuid() {\n\t\t\treturn (this.store.runs && this.store.runs[0] && this.store.runs[0].uuid) || ''\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Run the saved flow once with the picked record as its subject, then\n\t\t * close the dialog; the run shows on the canvas as any run does.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync runTest() {\n\t\t\tconst uuid = Array.isArray(this.testRecord) ? this.testRecord[0] : this.testRecord\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.store.run({ uuid, register: this.testSubject.register, schema: this.testSubject.schema })\n\t\t\tthis.testOpen = false\n\t\t\tthis.testRecord = null\n\t\t},\n\n\t\tt,\n\n\t\t/**\n\t\t * @param {string} path An app route path.\n\t\t * @return {string} Its href.\n\t\t */\n\t\threfOf(path) {\n\t\t\tif (this.$router && typeof this.$router.resolve === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst resolved = this.$router.resolve(path)\n\t\t\t\t\tif (resolved && resolved.href) {\n\t\t\t\t\t\treturn resolved.href\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// A path the router does not know stays a plain path.\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn path\n\t\t},\n\n\t\t/**\n\t\t * Follow a path link on the app's router; a modified click keeps the\n\t\t * browser's own behaviour.\n\t\t *\n\t\t * @param {MouseEvent} event The click.\n\t\t * @param {string} path The target path.\n\t\t * @return {void}\n\t\t */\n\t\tonCrumbClick(event, path) {\n\t\t\tif (!this.$router || event.ctrlKey || event.metaKey || event.shiftKey || event.button === 1) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tevent.preventDefault()\n\t\t\tthis.$router.push(path).catch(() => {})\n\t\t},\n\n\t\t/**\n\t\t * Switch the flow on or off. The change is saved with the flow.\n\t\t *\n\t\t * @param {boolean} on The new state.\n\t\t * @return {void}\n\t\t */\n\t\tonEnabledChange(on) {\n\t\t\tthis.store.flow.enabled = on === true\n\t\t\tthis.store.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Open a run of this flow on the canvas.\n\t\t *\n\t\t * @param {string} uuid The run.\n\t\t * @return {void}\n\t\t */\n\t\topenRun(uuid) {\n\t\t\tif (this.$router) {\n\t\t\t\tthis.$router.push({ path: this.flowPath, query: { run: uuid } }).catch(() => {})\n\t\t\t} else {\n\t\t\t\tthis.store.inspectRun(uuid)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Leave the run view for the flow.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonBackToFlow() {\n\t\t\tthis.store.closeRun()\n\t\t\tif (this.$router) {\n\t\t\t\tthis.$router.push({ path: this.flowPath }).catch(() => {})\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Start the shown run again and open the new one.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onRetry() {\n\t\t\tconst retried = await this.store.retryRun(this.runRecord?.uuid)\n\t\t\tthis.$emit('retried', retried)\n\t\t\tif (retried && retried.uuid) {\n\t\t\t\tthis.openRun(retried.uuid)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-board {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tpadding: 20px 24px;\n\tmin-height: 100%;\n\tbox-sizing: border-box;\n}\n\n.cn-flow-board__header {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n}\n\n.cn-flow-board__heading {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-width: 0;\n}\n\n.cn-flow-board__title {\n\tmargin: 0;\n\tfont-size: 24px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__actions {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-board__test-intro {\n\tmargin: 0 0 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__path {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__crumb {\n\tcolor: var(--color-main-text);\n\ttext-decoration: underline;\n}\n\n.cn-flow-board__body {\n\tdisplay: grid;\n\tgrid-template-columns: minmax(0, 1fr) 340px;\n\tgap: 16px;\n\tflex: 1 1 auto;\n\tmin-height: 520px;\n}\n\n.cn-flow-board--with-palette .cn-flow-board__body {\n\tgrid-template-columns: 240px minmax(0, 1fr) 340px;\n}\n\n.cn-flow-board__card {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tmin-width: 0;\n\tpadding: 16px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 12px;\n\tbackground: var(--color-main-background);\n}\n\n.cn-flow-board__canvas {\n\tpadding: 0;\n\toverflow: hidden;\n\tbackground-color: var(--color-background-hover);\n\tbackground-image: radial-gradient(var(--color-border-dark) 1px, transparent 1px);\n\tbackground-size: 16px 16px;\n}\n\n.cn-flow-board__canvas > :first-child {\n\tflex: 1 1 auto;\n\tmin-height: 0;\n}\n\n.cn-flow-board__card-title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__subtitle {\n\tmargin: 4px 0 0;\n\tfont-size: 14px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__eyebrow {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-flow-board__validity,\n.cn-flow-board__legend {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\tmargin: 0;\n\tpadding: 10px 16px;\n\tborder-top: 1px solid var(--color-border);\n\tbackground: var(--color-main-background);\n}\n\n.cn-flow-board__validity--success {\n\tcolor: var(--color-success-text);\n}\n\n.cn-flow-board__validity--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-flow-board__validity--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-flow-board__palette-group {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-board__palette-app {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__palette-list {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-flow-board__palette-step {\n\twidth: 100%;\n\tmin-height: 34px;\n\tpadding: 6px 10px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 8px;\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\ttext-align: start;\n\tcursor: pointer;\n}\n\n.cn-flow-board__palette-step:hover {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-flow-board__palette-note {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-flow-board__tabs {\n\tdisplay: flex;\n\tgap: 4px;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-board__tab {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 8px 10px;\n\tmargin-bottom: -1px;\n\tborder: 1px solid transparent;\n\tborder-radius: 8px 8px 0 0;\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-flow-board__tab--active {\n\tborder-color: var(--color-border);\n\tborder-bottom-color: var(--color-main-background);\n\tfont-weight: 600;\n}\n\n.cn-flow-board__tab-count {\n\tmin-width: 18px;\n\tpadding: 0 5px;\n\tborder-radius: 9px;\n\tbackground: var(--color-background-dark);\n\tfont-size: 12px;\n\tline-height: 18px;\n\ttext-align: center;\n}\n\n.cn-flow-board__step-actions,\n.cn-flow-board__step-footer {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n}\n\n.cn-flow-board__step-footer {\n\tjustify-content: space-between;\n\tmargin-top: auto;\n}\n\n@media (max-width: 1024px) {\n\t.cn-flow-board__body,\n\t.cn-flow-board--with-palette .cn-flow-board__body {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t}\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_createBlock","_createTextVNode","_createVNode","_Fragment","_openBlock","_renderList"],"mappings":"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"}
1
+ {"version":3,"file":"CnFlowBoard.vue3.js","sources":["../../../../src/components/CnFlowsPage/CnFlowBoard.vue?vue&type=template&id=72119172&lang.js"],"sourcesContent":["<!--\n CnFlowBoard — the flow editor in the board look: a page header with the\n flow's name, path and actions, then the canvas in a card beside an\n inspector card. Optionally a palette card on the left (`palette: column`).\n The same page shows one run when the route carries `?run=`: the canvas\n paints each step's outcome and the inspector holds the run's card and logs.\n\n The canvas itself is CnFlowDetail; this component only lays it out and adds\n what the board draws around it.\n\n SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>\n SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-flow-board\" :class=\"{ 'cn-flow-board--with-palette': showPalette }\" data-testid=\"flow-board\">\n\t\t<header class=\"cn-flow-board__header\">\n\t\t\t<div class=\"cn-flow-board__heading\">\n\t\t\t\t<h2 class=\"cn-flow-board__title\" data-testid=\"flow-board-title\">\n\t\t\t\t\t{{ titleText }}\n\t\t\t\t</h2>\n\t\t\t\t<CnStatusBadge v-if=\"pillText\" :label=\"pillText\" variant=\"default\" />\n\t\t\t</div>\n\t\t\t<div v-if=\"!store.inRunView\" class=\"cn-flow-board__actions\">\n\t\t\t\t<NcCheckboxRadioSwitch v-if=\"store.flow.id\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:modelValue=\"store.flow.enabled !== false\"\n\t\t\t\t\tdata-testid=\"flow-board-enabled\"\n\t\t\t\t\t@update:modelValue=\"onEnabledChange\">\n\t\t\t\t\t{{ store.flow.enabled !== false ? t('nextcloud-vue', 'Active') : t('nextcloud-vue', 'Paused') }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<NcButton :disabled=\"store.checking || !store.nodes.length\"\n\t\t\t\t\tdata-testid=\"flow-board-check\"\n\t\t\t\t\t@click=\"store.check()\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Check') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton v-if=\"showRun\"\n\t\t\t\t\t:disabled=\"store.running || !store.flow.id\"\n\t\t\t\t\tdata-testid=\"flow-board-run\"\n\t\t\t\t\t@click=\"onRun\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton v-if=\"testSubjectReady\"\n\t\t\t\t\t:disabled=\"store.running || !store.flow.id\"\n\t\t\t\t\tdata-testid=\"flow-board-test\"\n\t\t\t\t\t@click=\"testOpen = true\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<TestTube :size=\"16\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ testLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<CnBuildiqEditButton />\n\t\t\t\t<NcButton variant=\"primary\"\n\t\t\t\t\t:disabled=\"store.saving || !store.flow.name || store.graphLocked\"\n\t\t\t\t\tdata-testid=\"flow-board-save\"\n\t\t\t\t\t@click=\"$emit('save')\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Save') }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</header>\n\n\t\t<CnDialog v-if=\"testOpen\"\n\t\t\t:name=\"testLabel\"\n\t\t\tdata-testid=\"flow-board-test-dialog\"\n\t\t\t@closing=\"testOpen = false\">\n\t\t\t<p class=\"cn-flow-board__test-intro\">\n\t\t\t\t{{ t('nextcloud-vue', 'The saved flow runs once with the record you pick as its subject.') }}\n\t\t\t</p>\n\t\t\t<CnResourceSelect v-model=\"testRecord\"\n\t\t\t\t:register=\"testSubject.register\"\n\t\t\t\t:schema=\"testSubject.schema\"\n\t\t\t\t:labelField=\"testSubject.labelField || 'title'\"\n\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Record')\"\n\t\t\t\tdata-testid=\"flow-board-test-record\" />\n\t\t\t<template #actions>\n\t\t\t\t<NcButton data-testid=\"flow-board-test-cancel\" @click=\"testOpen = false\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton variant=\"primary\"\n\t\t\t\t\t:disabled=\"!testRecord || store.running\"\n\t\t\t\t\tdata-testid=\"flow-board-test-run\"\n\t\t\t\t\t@click=\"runTest\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Run test') }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t</CnDialog>\n\n\t\t<p class=\"cn-flow-board__path\" data-testid=\"flow-board-path\">\n\t\t\t<a :href=\"listHref\" class=\"cn-flow-board__crumb\" @click=\"onCrumbClick($event, detailRoute)\">{{ listText }}</a>\n\t\t\t<span aria-hidden=\"true\"> / </span>\n\t\t\t<template v-if=\"store.inRunView\">\n\t\t\t\t<a :href=\"flowHref\" class=\"cn-flow-board__crumb\" @click=\"onCrumbClick($event, flowPath)\">{{ flowName }}</a>\n\t\t\t\t<span aria-hidden=\"true\"> / </span>\n\t\t\t\t<span>{{ runCrumb }}</span>\n\t\t\t</template>\n\t\t\t<span v-else>{{ flowName }}</span>\n\t\t\t<span v-if=\"metaText\" class=\"cn-flow-board__meta\"> · {{ metaText }}</span>\n\t\t</p>\n\n\t\t<NcNoteCard v-if=\"notice && !store.inRunView\" type=\"info\" class=\"cn-flow-board__notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\n\t\t<div class=\"cn-flow-board__body\">\n\t\t\t<aside v-if=\"showPalette\" class=\"cn-flow-board__card cn-flow-board__palette\" data-testid=\"flow-board-palette\">\n\t\t\t\t<h3 class=\"cn-flow-board__card-title\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Steps') }}\n\t\t\t\t</h3>\n\t\t\t\t<section v-for=\"group in paletteGroups\"\n\t\t\t\t\t:key=\"group.app\"\n\t\t\t\t\tclass=\"cn-flow-board__palette-group\">\n\t\t\t\t\t<h4 class=\"cn-flow-board__palette-app\">\n\t\t\t\t\t\t{{ group.name }}\n\t\t\t\t\t</h4>\n\t\t\t\t\t<ul class=\"cn-flow-board__palette-list\">\n\t\t\t\t\t\t<li v-for=\"entry in group.entries\" :key=\"entry.id\">\n\t\t\t\t\t\t\t<button type=\"button\"\n\t\t\t\t\t\t\t\tclass=\"cn-flow-board__palette-step\"\n\t\t\t\t\t\t\t\t:disabled=\"store.graphLocked\"\n\t\t\t\t\t\t\t\t:data-testid=\"`flow-board-palette-${entry.id}`\"\n\t\t\t\t\t\t\t\t@click=\"store.addNode(entry.id)\">\n\t\t\t\t\t\t\t\t{{ entry.displayName || entry.label || entry.id }}\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</section>\n\t\t\t\t<p v-if=\"paletteFootnote\" class=\"cn-flow-board__palette-note\">\n\t\t\t\t\t{{ paletteFootnote }}\n\t\t\t\t</p>\n\t\t\t</aside>\n\n\t\t\t<section class=\"cn-flow-board__card cn-flow-board__canvas\" :aria-label=\"t('nextcloud-vue', 'Flow canvas')\">\n\t\t\t\t<CnFlowDetail :id=\"id\"\n\t\t\t\t\t:app=\"app\"\n\t\t\t\t\t:run=\"run\"\n\t\t\t\t\t:toolbarActions=\"false\"\n\t\t\t\t\t:addStep=\"!showPalette\"\n\t\t\t\t\t@save=\"$emit('save')\"\n\t\t\t\t\t@run=\"onRun\" />\n\t\t\t\t<div v-if=\"store.inRunView\"\n\t\t\t\t\tclass=\"cn-flow-board__legend\"\n\t\t\t\t\tdata-testid=\"flow-board-legend\">\n\t\t\t\t\t<span v-for=\"level in legend\" :key=\"level.id\" class=\"cn-flow-board__legend-item\">\n\t\t\t\t\t\t<CnStatusBadge :label=\"level.label\" :variant=\"level.variant\" size=\"small\" />\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t\t<p v-else\n\t\t\t\t\tclass=\"cn-flow-board__validity\"\n\t\t\t\t\t:class=\"`cn-flow-board__validity--${validity.tone}`\"\n\t\t\t\t\trole=\"status\"\n\t\t\t\t\tdata-testid=\"flow-board-validity\">\n\t\t\t\t\t{{ validity.text }}\n\t\t\t\t</p>\n\t\t\t</section>\n\n\t\t\t<aside class=\"cn-flow-board__card cn-flow-board__inspector\" data-testid=\"flow-board-inspector\">\n\t\t\t\t<template v-if=\"store.inRunView\">\n\t\t\t\t\t<CnFlowRunSummary :run=\"runRecord\"\n\t\t\t\t\t\t:stepsTotal=\"store.nodes.length\"\n\t\t\t\t\t\t:canRetry=\"canRetry\"\n\t\t\t\t\t\t@back=\"onBackToFlow\"\n\t\t\t\t\t\t@retry=\"onRetry\" />\n\t\t\t\t\t<div class=\"cn-flow-board__tabs\" role=\"tablist\">\n\t\t\t\t\t\t<button v-for=\"tab in runTabs\"\n\t\t\t\t\t\t\t:key=\"tab.id\"\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\trole=\"tab\"\n\t\t\t\t\t\t\tclass=\"cn-flow-board__tab\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-flow-board__tab--active': runTab === tab.id }\"\n\t\t\t\t\t\t\t:aria-selected=\"runTab === tab.id ? 'true' : 'false'\"\n\t\t\t\t\t\t\t:data-testid=\"`flow-board-run-tab-${tab.id}`\"\n\t\t\t\t\t\t\t@click=\"runTab = tab.id\">\n\t\t\t\t\t\t\t{{ tab.label }}\n\t\t\t\t\t\t\t<span class=\"cn-flow-board__tab-count\">{{ tab.count }}</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</div>\n\t\t\t\t\t<CnFlowStepLog :lines=\"runTab === 'step' ? selectedRunLines : allRunLines\"\n\t\t\t\t\t\t:emptyText=\"runTab === 'step' && !store.selectedNodeId ? t('nextcloud-vue', 'Select a step on the canvas to see what it did.') : ''\" />\n\t\t\t\t</template>\n\t\t\t\t<template v-else-if=\"store.selectedNode\">\n\t\t\t\t\t<p class=\"cn-flow-board__eyebrow\">\n\t\t\t\t\t\t{{ stepTypeLabel }}\n\t\t\t\t\t</p>\n\t\t\t\t\t<h3 class=\"cn-flow-board__card-title\" data-testid=\"flow-board-step-name\">\n\t\t\t\t\t\t{{ stepName }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<dl v-if=\"stepSettings.length > 0\" class=\"cn-flow-board__settings\">\n\t\t\t\t\t\t<div v-for=\"setting in stepSettings\"\n\t\t\t\t\t\t\t:key=\"setting.key\"\n\t\t\t\t\t\t\tclass=\"cn-flow-board__setting\"\n\t\t\t\t\t\t\tdata-testid=\"flow-board-step-setting\">\n\t\t\t\t\t\t\t<dt>{{ setting.label }}</dt>\n\t\t\t\t\t\t\t<dd>{{ setting.value }}</dd>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</dl>\n\t\t\t\t\t<div class=\"cn-flow-board__step-actions\">\n\t\t\t\t\t\t<NcButton data-testid=\"flow-board-edit-step\" @click=\"store.editingNodeId = store.selectedNodeId\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Edit step') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton v-if=\"lastRunUuid\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\tdata-testid=\"flow-board-open-last-run\"\n\t\t\t\t\t\t\t@click=\"openRun(lastRunUuid)\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Open the last run on the canvas') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t\t<h4 class=\"cn-flow-board__subtitle\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Recent log lines of this step') }}\n\t\t\t\t\t</h4>\n\t\t\t\t\t<CnFlowStepLog :lines=\"recentStepLines\"\n\t\t\t\t\t\twithDay\n\t\t\t\t\t\t:emptyText=\"t('nextcloud-vue', 'This step has not run yet.')\" />\n\t\t\t\t\t<div class=\"cn-flow-board__step-footer\">\n\t\t\t\t\t\t<NcButton variant=\"tertiary\"\n\t\t\t\t\t\t\t:disabled=\"store.graphLocked\"\n\t\t\t\t\t\t\tdata-testid=\"flow-board-delete-step\"\n\t\t\t\t\t\t\t@click=\"store.removeNode(store.selectedNodeId)\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Delete step') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton data-testid=\"flow-board-done\" @click=\"store.selectedNodeId = null\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Done') }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t\t<template v-else-if=\"showRuns\">\n\t\t\t\t\t<NcButton variant=\"tertiary\"\n\t\t\t\t\t\tclass=\"cn-flow-board__runs-back\"\n\t\t\t\t\t\tdata-testid=\"flow-board-hide-runs\"\n\t\t\t\t\t\t@click=\"showRuns = false\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Back to the step settings') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<CnFlowSidebar embedded />\n\t\t\t\t</template>\n\t\t\t\t<div v-else class=\"cn-flow-board__inspector-empty\" data-testid=\"flow-board-inspector-empty\">\n\t\t\t\t\t<p>{{ t('nextcloud-vue', 'Select a step on the canvas to see its settings.') }}</p>\n\t\t\t\t\t<NcButton variant=\"secondary\"\n\t\t\t\t\t\tdata-testid=\"flow-board-show-runs\"\n\t\t\t\t\t\t@click=\"showRuns = true\">\n\t\t\t\t\t\t{{ t('nextcloud-vue', 'Show runs') }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t</div>\n\t\t\t</aside>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport TestTube from 'vue-material-design-icons/TestTube.vue'\nimport CnBuildiqEditButton from '../CnBuildiqEditButton/CnBuildiqEditButton.vue'\nimport CnDialog from '../CnDialog/CnDialog.vue'\nimport CnFlowDetail from '../CnFlowDetail/CnFlowDetail.vue'\nimport CnFlowRunSummary from '../CnFlowDetail/CnFlowRunSummary.vue'\nimport CnFlowSidebar from '../CnFlowDetail/CnFlowSidebar.vue'\nimport CnFlowStepLog from '../CnFlowDetail/CnFlowStepLog.vue'\nimport CnResourceSelect from '../CnResourceSelect/CnResourceSelect.vue'\nimport { FLOW_RUN_ACTIVE_STATUSES, useFlowStore } from '../../composables/useFlowStore.js'\nimport { formatRelativeDate } from '../../utils/boardDate.js'\nimport { flowOutcomeLevels, flowRunDurationMs, flowRunLogLines, flowRunName, formatFlowDuration } from '../../utils/flowRunLog.js'\nimport { appDisplayNames } from '../../utils/nextcloudApps.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\n/**\n * The board-look flow editor and run view. CnFlowEditorPage renders it when\n * the app or page is in the board look; the Nextcloud look keeps the canvas\n * on its own with the app sidebar.\n */\nexport default {\n\tname: 'CnFlowBoard',\n\n\tcomponents: { CnBuildiqEditButton, CnDialog, CnFlowDetail, CnResourceSelect, TestTube, CnFlowRunSummary, CnFlowSidebar, CnFlowStepLog, CnStatusBadge, NcButton, NcCheckboxRadioSwitch, NcNoteCard },\n\n\tprops: {\n\t\t/** The flow uuid, or `new`. */\n\t\tid: { type: String, default: '' },\n\t\t/** The owning app, for a new flow and the list scope. */\n\t\tapp: { type: String, default: null },\n\t\t/** The run to show, or ''. */\n\t\trun: { type: String, default: '' },\n\t\t/** Where the flow list lives; flows open at `<detailRoute>/<id>`. */\n\t\tdetailRoute: { type: String, default: '/flows' },\n\t\t/** The list's name in the path (\"Flows\", \"Settings / Flows\"). */\n\t\tlistLabel: { type: String, default: '' },\n\t\t/** `column` draws the step palette as a card on the left. */\n\t\tpalette: { type: String, default: 'picker' },\n\t\t/** Free text under the path in the palette card. */\n\t\tpaletteFootnote: { type: String, default: '' },\n\t\t/** An info notice under the path. */\n\t\tnotice: { type: String, default: '' },\n\t\t/** The pill beside the title (\"Case type flow\"). */\n\t\tpill: { type: String, default: '' },\n\t\t/**\n\t\t * The records a test run can take as its subject: `{ register, schema,\n\t\t * labelField?, label? }`. Draws a header button (\"Testen met een zaak\",\n\t\t * DqFlow) that runs the saved flow once with a picked record.\n\t\t */\n\t\ttestSubject: { type: Object, default: null },\n\t},\n\n\temits: ['save', 'run', 'retried'],\n\n\tsetup() {\n\t\treturn { store: useFlowStore() }\n\t},\n\n\tdata() {\n\t\treturn { runTab: 'step', testOpen: false, testRecord: null, appNames: {}, showRuns: false }\n\t},\n\n\tcomputed: {\n\t\t/** @return {boolean} Whether a test subject is declared well enough to pick one. */\n\t\ttestSubjectReady() {\n\t\t\treturn Boolean(this.testSubject && this.testSubject.register && this.testSubject.schema)\n\t\t},\n\n\t\t/** @return {string} The test button's label: the page's own, else the library's. */\n\t\ttestLabel() {\n\t\t\treturn (this.testSubject && this.testSubject.label) || t('nextcloud-vue', 'Test with a record')\n\t\t},\n\n\t\t/** @return {boolean} Whether the palette card is drawn. */\n\t\tshowPalette() {\n\t\t\treturn this.palette === 'column' && !this.store.inRunView\n\t\t},\n\n\t\t/** @return {string} The page title. */\n\t\ttitleText() {\n\t\t\treturn this.store.flow.name || this.t('nextcloud-vue', 'New flow')\n\t\t},\n\n\t\t/** @return {string} The flow's name in the path. */\n\t\tflowName() {\n\t\t\treturn this.store.flow.name || this.t('nextcloud-vue', 'New flow')\n\t\t},\n\n\t\t/** @return {string} The pill text: the page's, else the lifecycle. */\n\t\tpillText() {\n\t\t\tif (this.pill) {\n\t\t\t\treturn this.pill\n\t\t\t}\n\t\t\tconst lifecycle = String(this.store.flow.lifecycleStatus || '')\n\t\t\tif (lifecycle === 'draft') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Draft')\n\t\t\t}\n\t\t\tif (lifecycle === 'deprecated') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Retired')\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/** @return {string} The list label. */\n\t\tlistText() {\n\t\t\treturn this.listLabel || this.t('nextcloud-vue', 'Flows')\n\t\t},\n\n\t\t/** @return {string} The flow's own path. */\n\t\tflowPath() {\n\t\t\treturn `${this.detailRoute}/${this.store.flow.id || this.id}`\n\t\t},\n\n\t\t/** @return {string} The list href. */\n\t\tlistHref() {\n\t\t\treturn this.hrefOf(this.detailRoute)\n\t\t},\n\n\t\t/** @return {string} The flow href. */\n\t\tflowHref() {\n\t\t\treturn this.hrefOf(this.flowPath)\n\t\t},\n\n\t\t/**\n\t\t * What the path says after the name: the trigger, the step count and\n\t\t * the version in the editor; when the run started and how long it\n\t\t * took in the run view.\n\t\t *\n\t\t * @return {string} The meta text.\n\t\t */\n\t\tmetaText() {\n\t\t\tif (this.store.inRunView) {\n\t\t\t\tconst record = this.runRecord\n\t\t\t\tif (!record) {\n\t\t\t\t\treturn ''\n\t\t\t\t}\n\t\t\t\tconst parts = [formatRelativeDate(record.created, { withTime: true })]\n\t\t\t\tconst duration = formatFlowDuration(flowRunDurationMs(record))\n\t\t\t\tif (duration) {\n\t\t\t\t\tparts.push(this.t('nextcloud-vue', 'done in {duration}', { duration }))\n\t\t\t\t}\n\t\t\t\treturn parts.filter(Boolean).join(' · ')\n\t\t\t}\n\t\t\tconst parts = []\n\t\t\tconst trigger = this.triggerText\n\t\t\tif (trigger) {\n\t\t\t\tparts.push(this.t('nextcloud-vue', 'trigger {trigger}', { trigger }))\n\t\t\t}\n\t\t\tconst count = this.store.nodes.length\n\t\t\tparts.push(count === 1 ? this.t('nextcloud-vue', '1 step') : this.t('nextcloud-vue', '{count} steps', { count }))\n\t\t\tif (this.store.flow.version) {\n\t\t\t\tparts.push(this.t('nextcloud-vue', 'version {version}', { version: this.store.flow.version }))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/** @return {string} How the flow starts, as the catalogue names it. */\n\t\ttriggerText() {\n\t\t\tconst trigger = String(this.store.flow.trigger || '')\n\t\t\tif (trigger === 'schedule') {\n\t\t\t\treturn this.t('nextcloud-vue', 'On a schedule')\n\t\t\t}\n\t\t\tif (trigger === '' || trigger === 'manual') {\n\t\t\t\treturn this.t('nextcloud-vue', 'Run by hand')\n\t\t\t}\n\t\t\tconst entry = (this.store.eventCatalog || []).find((item) => item && item.id === trigger)\n\t\t\treturn (entry && entry.label) || trigger\n\t\t},\n\n\t\t/** @return {boolean} Whether Run is offered. */\n\t\tshowRun() {\n\t\t\treturn this.store.nodes.some((node) => node?.type === 'openregister.trigger-manual')\n\t\t},\n\n\t\t/**\n\t\t * The engine's verdict on the canvas as one line under it.\n\t\t *\n\t\t * @return {{tone: string, text: string}} The validity bar.\n\t\t */\n\t\tvalidity() {\n\t\t\tconst result = this.store.checkResult\n\t\t\tif (!result) {\n\t\t\t\treturn { tone: 'unknown', text: this.t('nextcloud-vue', 'Not checked yet. Check runs the flow past the engine without saving it.') }\n\t\t\t}\n\t\t\tconst blocking = Array.isArray(result.blocking) ? result.blocking.length : 0\n\t\t\tconst warnings = Array.isArray(result.warnings) ? result.warnings.length : 0\n\t\t\tif (result.valid === false || blocking > 0) {\n\t\t\t\treturn { tone: 'error', text: result.message || this.t('nextcloud-vue', 'The flow cannot run as it is. See the messages on the canvas.') }\n\t\t\t}\n\t\t\tif (warnings > 0) {\n\t\t\t\treturn { tone: 'warning', text: this.t('nextcloud-vue', 'The flow is valid, with {count} warnings.', { count: warnings }) }\n\t\t\t}\n\t\t\treturn { tone: 'success', text: this.t('nextcloud-vue', 'The flow is valid.') }\n\t\t},\n\n\t\t/**\n\t\t * The palette grouped by owning app, each group named by the app's\n\t\t * display name (its id when Nextcloud names none), the app that owns\n\t\t * this flow first.\n\t\t *\n\t\t * @return {Array<{app: string, name: string, entries: Array<object>}>} The groups.\n\t\t */\n\t\tpaletteGroups() {\n\t\t\tconst groups = {}\n\t\t\t;(this.store.nodeCatalog || []).forEach((entry) => {\n\t\t\t\tconst app = String(entry?.app || String(entry?.id || '').split('.')[0] || '')\n\t\t\t\tif (!groups[app]) {\n\t\t\t\t\tgroups[app] = { app, name: this.appNames[app] || app, entries: [] }\n\t\t\t\t}\n\t\t\t\tgroups[app].entries.push(entry)\n\t\t\t})\n\t\t\tconst list = Object.values(groups)\n\t\t\tconst host = list.findIndex((group) => group.app === this.app)\n\t\t\treturn host > 0 ? [list[host], ...list.slice(0, host), ...list.slice(host + 1)] : list\n\t\t},\n\n\t\t/** @return {object|null} The run on screen. */\n\t\trunRecord() {\n\t\t\treturn this.store.runDetail\n\t\t\t\t|| (this.store.runs || []).find((item) => item.uuid === this.store.inspectedRunUuid)\n\t\t\t\t|| null\n\t\t},\n\n\t\t/** @return {string} The run's place in the path. */\n\t\trunCrumb() {\n\t\t\treturn this.t('nextcloud-vue', 'Run {id}', { id: flowRunName(this.runRecord) })\n\t\t},\n\n\t\t/** @return {boolean} Whether Run again is offered. */\n\t\tcanRetry() {\n\t\t\treturn !!this.runRecord && !FLOW_RUN_ACTIVE_STATUSES.includes(this.runRecord.status)\n\t\t},\n\n\t\t/** @return {Array<object>} Every line of the run on screen. */\n\t\tallRunLines() {\n\t\t\treturn this.runRecord ? flowRunLogLines(this.runRecord) : []\n\t\t},\n\n\t\t/** @return {Array<object>} The selected step's lines in this run. */\n\t\tselectedRunLines() {\n\t\t\treturn this.runRecord && this.store.selectedNodeId\n\t\t\t\t? flowRunLogLines(this.runRecord, this.store.selectedNodeId)\n\t\t\t\t: []\n\t\t},\n\n\t\t/** @return {Array<object>} The two log tabs with their counts. */\n\t\trunTabs() {\n\t\t\treturn [\n\t\t\t\t{ id: 'step', label: this.t('nextcloud-vue', 'This step'), count: this.selectedRunLines.length },\n\t\t\t\t{ id: 'run', label: this.t('nextcloud-vue', 'Logs of the whole run'), count: this.allRunLines.length },\n\t\t\t]\n\t\t},\n\n\t\t/** @return {Array<object>} The legend of outcomes on the canvas. */\n\t\tlegend() {\n\t\t\tconst levels = flowOutcomeLevels()\n\t\t\treturn ['success', 'warning', 'error', 'info', 'skipped'].map((id) => ({ id, ...levels[id] }))\n\t\t},\n\n\t\t/** @return {string} The selected step's type, as the catalogue names it. */\n\t\tstepTypeLabel() {\n\t\t\tconst node = this.store.selectedNode\n\t\t\tconst entry = node ? this.store.catalogEntry(node.type) : null\n\t\t\treturn entry ? (entry.displayName || entry.id) : String(node?.type || '')\n\t\t},\n\n\t\t/**\n\t\t * The selected step's settings as its owner declares them in the\n\t\t * catalogue's `configForm`: label and value, a select's option label,\n\t\t * Yes or No for a switch. Unset settings are left out.\n\t\t *\n\t\t * @return {Array<{key: string, label: string, value: string}>} The settings.\n\t\t */\n\t\tstepSettings() {\n\t\t\tconst node = this.store.selectedNode\n\t\t\tconst entry = node ? this.store.catalogEntry(node.type) : null\n\t\t\tconst config = (node && node.config) || {}\n\t\t\tconst form = (entry && Array.isArray(entry.configForm)) ? entry.configForm : []\n\t\t\treturn form\n\t\t\t\t.filter((field) => field && field.key && config[field.key] !== undefined && config[field.key] !== null && config[field.key] !== '')\n\t\t\t\t.map((field) => {\n\t\t\t\t\tconst raw = config[field.key]\n\t\t\t\t\tconst option = Array.isArray(field.options) ? field.options.find((o) => o && o.value === raw) : null\n\t\t\t\t\tlet value\n\t\t\t\t\tif (option) {\n\t\t\t\t\t\tvalue = String(option.label ?? option.value)\n\t\t\t\t\t} else if (typeof raw === 'boolean') {\n\t\t\t\t\t\tvalue = raw ? this.t('nextcloud-vue', 'Yes') : this.t('nextcloud-vue', 'No')\n\t\t\t\t\t} else if (typeof raw === 'object') {\n\t\t\t\t\t\tvalue = JSON.stringify(raw)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalue = String(raw)\n\t\t\t\t\t}\n\t\t\t\t\treturn { key: field.key, label: field.label || field.key, value }\n\t\t\t\t})\n\t\t},\n\n\t\t/** @return {string} The selected step's name. */\n\t\tstepName() {\n\t\t\tconst node = this.store.selectedNode\n\t\t\treturn (node && (node.name || node.label)) || this.stepTypeLabel\n\t\t},\n\n\t\t/**\n\t\t * The selected step's lines from the flow's recent runs, newest run\n\t\t * first, at most ten.\n\t\t *\n\t\t * @return {Array<object>} The lines.\n\t\t */\n\t\trecentStepLines() {\n\t\t\tconst id = this.store.selectedNodeId\n\t\t\tif (!id) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst lines = []\n\t\t\t;(this.store.runs || []).forEach((item) => {\n\t\t\t\tflowRunLogLines(item, id).forEach((line) => lines.push({ ...line, key: `${item.uuid}-${line.key}` }))\n\t\t\t})\n\t\t\treturn lines.slice(0, 10)\n\t\t},\n\n\t\t/** @return {string} The newest run's uuid, or ''. */\n\t\tlastRunUuid() {\n\t\t\treturn (this.store.runs && this.store.runs[0] && this.store.runs[0].uuid) || ''\n\t\t},\n\t},\n\n\twatch: {\n\t\t// A selected step takes the panel back from the run history.\n\t\t'store.selectedNodeId': function(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.showRuns = false\n\t\t\t}\n\t\t},\n\t},\n\n\tasync created() {\n\t\t// The palette names its groups by app display name; only the column\n\t\t// palette draws them, so only it reads the names.\n\t\tif (this.palette !== 'column') {\n\t\t\treturn\n\t\t}\n\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\tthis.appNames = await appDisplayNames(axios)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Run the flow, with the run history in the panel to follow it.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonRun() {\n\t\t\tthis.showRuns = true\n\t\t\tthis.$emit('run')\n\t\t},\n\n\t\t/**\n\t\t * Run the saved flow once with the picked record as its subject, then\n\t\t * close the dialog; the run shows on the canvas as any run does.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync runTest() {\n\t\t\tconst uuid = Array.isArray(this.testRecord) ? this.testRecord[0] : this.testRecord\n\t\t\tif (!uuid) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.store.run({ uuid, register: this.testSubject.register, schema: this.testSubject.schema })\n\t\t\tthis.testOpen = false\n\t\t\tthis.testRecord = null\n\t\t},\n\n\t\tt,\n\n\t\t/**\n\t\t * @param {string} path An app route path.\n\t\t * @return {string} Its href.\n\t\t */\n\t\threfOf(path) {\n\t\t\tif (this.$router && typeof this.$router.resolve === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst resolved = this.$router.resolve(path)\n\t\t\t\t\tif (resolved && resolved.href) {\n\t\t\t\t\t\treturn resolved.href\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// A path the router does not know stays a plain path.\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn path\n\t\t},\n\n\t\t/**\n\t\t * Follow a path link on the app's router; a modified click keeps the\n\t\t * browser's own behaviour.\n\t\t *\n\t\t * @param {MouseEvent} event The click.\n\t\t * @param {string} path The target path.\n\t\t * @return {void}\n\t\t */\n\t\tonCrumbClick(event, path) {\n\t\t\tif (!this.$router || event.ctrlKey || event.metaKey || event.shiftKey || event.button === 1) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tevent.preventDefault()\n\t\t\tthis.$router.push(path).catch(() => {})\n\t\t},\n\n\t\t/**\n\t\t * Switch the flow on or off. The change is saved with the flow.\n\t\t *\n\t\t * @param {boolean} on The new state.\n\t\t * @return {void}\n\t\t */\n\t\tonEnabledChange(on) {\n\t\t\tthis.store.flow.enabled = on === true\n\t\t\tthis.store.dirty = true\n\t\t},\n\n\t\t/**\n\t\t * Open a run of this flow on the canvas.\n\t\t *\n\t\t * @param {string} uuid The run.\n\t\t * @return {void}\n\t\t */\n\t\topenRun(uuid) {\n\t\t\tif (this.$router) {\n\t\t\t\tthis.$router.push({ path: this.flowPath, query: { run: uuid } }).catch(() => {})\n\t\t\t} else {\n\t\t\t\tthis.store.inspectRun(uuid)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Leave the run view for the flow.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonBackToFlow() {\n\t\t\tthis.store.closeRun()\n\t\t\tif (this.$router) {\n\t\t\t\tthis.$router.push({ path: this.flowPath }).catch(() => {})\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Start the shown run again and open the new one.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onRetry() {\n\t\t\tconst retried = await this.store.retryRun(this.runRecord?.uuid)\n\t\t\tthis.$emit('retried', retried)\n\t\t\tif (retried && retried.uuid) {\n\t\t\t\tthis.openRun(retried.uuid)\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-flow-board {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tpadding: 20px 24px;\n\tmin-height: 100%;\n\tbox-sizing: border-box;\n}\n\n.cn-flow-board__header {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n}\n\n.cn-flow-board__heading {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-width: 0;\n}\n\n.cn-flow-board__title {\n\tmargin: 0;\n\tfont-size: 24px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__actions {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-flow-board__test-intro {\n\tmargin: 0 0 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__path {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__crumb {\n\tcolor: var(--color-main-text);\n\ttext-decoration: underline;\n}\n\n.cn-flow-board__body {\n\tdisplay: grid;\n\tgrid-template-columns: minmax(0, 1fr) 340px;\n\tgap: 16px;\n\tflex: 1 1 auto;\n\tmin-height: 520px;\n}\n\n.cn-flow-board--with-palette .cn-flow-board__body {\n\tgrid-template-columns: 240px minmax(0, 1fr) 340px;\n}\n\n.cn-flow-board__card {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tmin-width: 0;\n\tpadding: 16px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 12px;\n\tbackground: var(--color-main-background);\n}\n\n.cn-flow-board__canvas {\n\tpadding: 0;\n\toverflow: hidden;\n\tbackground-color: var(--color-background-hover);\n\tbackground-image: radial-gradient(var(--color-border-dark) 1px, transparent 1px);\n\tbackground-size: 16px 16px;\n}\n\n.cn-flow-board__canvas > :first-child {\n\tflex: 1 1 auto;\n\tmin-height: 0;\n}\n\n.cn-flow-board__card-title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__subtitle {\n\tmargin: 4px 0 0;\n\tfont-size: 14px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__eyebrow {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-flow-board__validity,\n.cn-flow-board__legend {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\tmargin: 0;\n\tpadding: 10px 16px;\n\tborder-top: 1px solid var(--color-border);\n\tbackground: var(--color-main-background);\n}\n\n.cn-flow-board__validity--success {\n\tcolor: var(--color-success-text);\n}\n\n.cn-flow-board__validity--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-flow-board__validity--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-flow-board__palette-group {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-flow-board__palette-app {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n\tfont-weight: 600;\n}\n\n.cn-flow-board__palette-list {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-flow-board__palette-step {\n\twidth: 100%;\n\tmin-height: 34px;\n\tpadding: 6px 10px;\n\tborder: 1px solid var(--color-border);\n\tborder-radius: 8px;\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\ttext-align: start;\n\tcursor: pointer;\n}\n\n.cn-flow-board__palette-step:hover {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-flow-board__palette-note {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-flow-board__tabs {\n\tdisplay: flex;\n\tgap: 4px;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-flow-board__tab {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 8px 10px;\n\tmargin-bottom: -1px;\n\tborder: 1px solid transparent;\n\tborder-radius: 8px 8px 0 0;\n\tbackground: transparent;\n\tcolor: var(--color-main-text);\n\tcursor: pointer;\n}\n\n.cn-flow-board__tab--active {\n\tborder-color: var(--color-border);\n\tborder-bottom-color: var(--color-main-background);\n\tfont-weight: 600;\n}\n\n.cn-flow-board__tab-count {\n\tmin-width: 18px;\n\tpadding: 0 5px;\n\tborder-radius: 9px;\n\tbackground: var(--color-background-dark);\n\tfont-size: 12px;\n\tline-height: 18px;\n\ttext-align: center;\n}\n\n.cn-flow-board__settings {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tmargin: 0;\n}\n\n.cn-flow-board__setting dt {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__setting dd {\n\tmargin: 2px 0 0;\n\tfont-weight: 600;\n\toverflow-wrap: anywhere;\n}\n\n.cn-flow-board__inspector-empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: flex-start;\n\tgap: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-flow-board__inspector-empty p {\n\tmargin: 0;\n}\n\n.cn-flow-board__step-actions,\n.cn-flow-board__step-footer {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n}\n\n.cn-flow-board__step-footer {\n\tjustify-content: space-between;\n\tmargin-top: auto;\n}\n\n@media (max-width: 1024px) {\n\t.cn-flow-board__body,\n\t.cn-flow-board--with-palette .cn-flow-board__body {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t}\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_createBlock","_createTextVNode","_createVNode","_Fragment","_openBlock","_renderList"],"mappings":"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"}
@@ -33,6 +33,7 @@ import { columnFieldsOf, refIdOf, buildValueStages, buildReferenceStages, column
33
33
  import { reportBindingProblems } from '../../utils/diagnostics.js';
34
34
  import { fetchGroupedCounts } from '../../utils/fetchAggregate.js';
35
35
  import { fetchListTotal, fetchFilterCounts } from '../../utils/fetchFilterCounts.js';
36
+ import { unwrapAppConfig } from '../../utils/formatMetric.js';
36
37
  import { buildExportUrl } from '../../utils/indexExportHelpers.js';
37
38
  import { lensUnavailableText } from '../../utils/lensAvailability.js';
38
39
  import { isModifiedClick, openRowTarget } from '../../utils/linkNavigation.js';
@@ -55,6 +56,7 @@ import { DEFAULT_ROW_INDICATOR_CAP } from '../../utils/rowIndicators.js';
55
56
  import { viewMatchesScope, extractViewState, buildRouteQueryFromViewState, extractViewStateFromRouteQuery, buildViewCreatePayload, savedViewScope, normalizeSharedWith } from '../../utils/savedViewHelpers.js';
56
57
  import { fieldsFromSchema, columnsFromSchema } from '../../utils/schema.js';
57
58
  import { resolveScopeLayout, resolveScopePresentation } from '../../utils/scopeListLayout.js';
59
+ import { sameSortKeys, orderToSortKeys } from '../../utils/sortOrder.js';
58
60
  import { dispatchObjectCreated } from '../../utils/walkthroughSignals.js';
59
61
  import __sfc_main$7 from '../CnActionButtons/CnActionButtons.vue.js';
60
62
  import __sfc_main$8 from '../CnActionsBar/CnActionsBar.vue.js';
@@ -425,6 +427,8 @@ var script = {
425
427
  cnCustomComponents: { default: () => ({}) },
426
428
  /** The permissions the user holds, provided by CnAppRoot; for gated page tabs. */
427
429
  cnPermissions: { default: () => [] },
430
+ /** The app config an ancestor provides, for `@config.<key>` in quick-filter labels. */
431
+ cnAppConfig: { default: null },
428
432
  /** The app id CnAppRoot provides, for the plural form of `countSubtitle`. */
429
433
  cnAppId: { default: '' },
430
434
  /**
@@ -728,7 +732,10 @@ var script = {
728
732
  * case" (manifest `config.headerButtons`). Each is `{ label?, action,
729
733
  * variant?, icon?, format?, id? }`: `action` is `add` (the Add flow;
730
734
  * its label defaults to the Add label), `export` (the export leaf in
731
- * `format`, `csv` by default, else the export dialog), `import`,
735
+ * `format`, `csv` by default, else the export dialog; with `run` the
736
+ * `headerActions` entry of that id; on an `entitySource` page without
737
+ * `run` and without a `@mass-export` listener it is not drawn),
738
+ * `import`,
732
739
  * `refresh`, `save-view` (the save-current-view dialog: the board's
733
740
  * "Zoekopdracht opslaan", label "Save view" by default), or the id of a
734
741
  * `headerActions` entry; `variant` is
@@ -908,6 +915,20 @@ var script = {
908
915
  validator: (v) => ['', 'toolbar'].includes(v),
909
916
  },
910
917
 
918
+ /**
919
+ * Where the board look's search field sits (manifest
920
+ * `config.searchPlacement`): `''` (the default) opens row 2 with it,
921
+ * `'toolbar'` puts it on row 1 before the Filter button and the view
922
+ * switch (DqTeamwachtrij).
923
+ *
924
+ * @type {''|'toolbar'}
925
+ */
926
+ searchPlacement: {
927
+ type: String,
928
+ default: '',
929
+ validator: (v) => ['', 'toolbar'].includes(v),
930
+ },
931
+
911
932
  /**
912
933
  * How the quick filters render: `'chips'` (pill strip, default) or
913
934
  * `'dropdown'` (a single `NcSelect`). Sourced from the manifest as
@@ -1854,6 +1875,29 @@ var script = {
1854
1875
  default: false,
1855
1876
  },
1856
1877
 
1878
+ /**
1879
+ * `false` draws no inline search in the actions bar, also in the board
1880
+ * look, which otherwise draws one on every index page. Fed from the
1881
+ * manifest as `pages[].config.search`.
1882
+ */
1883
+ search: {
1884
+ type: Boolean,
1885
+ default: true,
1886
+ },
1887
+
1888
+ /**
1889
+ * The app config `@config.<key>` tokens resolve against, in quick-filter
1890
+ * filters and labels (`"Residence @config.municipality"`), as on the
1891
+ * dashboard and detail pages. Merged over a config an ancestor provides
1892
+ * on `cnAppConfig`. Manifest: `config.appConfig`.
1893
+ *
1894
+ * @type {object}
1895
+ */
1896
+ appConfig: {
1897
+ type: Object,
1898
+ default: () => ({}),
1899
+ },
1900
+
1857
1901
  /**
1858
1902
  * Keep the "Showing X of Y" counter visible beside the inline search field,
1859
1903
  * after any `#after-search` controls (only relevant with `inlineSearch`,
@@ -1921,12 +1965,28 @@ var script = {
1921
1965
  default: () => [],
1922
1966
  },
1923
1967
 
1924
- /** Selected value of the standalone sort dropdown (controlled). */
1968
+ /**
1969
+ * Selected value of the standalone sort dropdown. Empty lets a
1970
+ * self-fetch page show the option matching its current order.
1971
+ */
1925
1972
  sortSelectValue: {
1926
1973
  type: String,
1927
1974
  default: '',
1928
1975
  },
1929
1976
 
1977
+ /**
1978
+ * The order a self-fetch page opens on when neither the address nor
1979
+ * `sortKeys`/`sortKey` gives one (manifest `config.defaultOrder`):
1980
+ * `"-createdAt"`, `"priority:desc,title"`, an `_order` map or a
1981
+ * `[{ key, order }]` list.
1982
+ *
1983
+ * @type {string|object|Array}
1984
+ */
1985
+ defaultOrder: {
1986
+ type: [String, Object, Array],
1987
+ default: '',
1988
+ },
1989
+
1930
1990
  /** MDI icon name for the list view-toggle option (manifest `config.listIcon`) */
1931
1991
  listIcon: {
1932
1992
  type: String,
@@ -3655,6 +3715,60 @@ var script = {
3655
3715
  return match || null
3656
3716
  },
3657
3717
 
3718
+ /**
3719
+ * The heading above the list for the selected folder: on a `groups`
3720
+ * pane (or with `folderSidebar.heading: true`), its name and, under
3721
+ * it, its parent folder and its count. The count reads
3722
+ * `folderSidebar.countText` (`{count}`, through the app's translate),
3723
+ * else "{count} members" on a groups pane.
3724
+ *
3725
+ * @return {{name: string, subtitle: string}|null} The heading, or null on All.
3726
+ */
3727
+ scopeHeading() {
3728
+ const cfg = this.folderSidebar;
3729
+ const scope = this.activeScope;
3730
+ if (!cfg || !scope || !(cfg.source === 'groups' || cfg.heading === true)) {
3731
+ return null
3732
+ }
3733
+ const idField = this.folderPassthroughIdField;
3734
+ const name = String(this.getByPath(scope, this.folderPassthroughNameField) ?? this.selectedFolderId);
3735
+ const parentId = scope.parentId ?? scope.parent ?? null;
3736
+ const parent = parentId === null || parentId === undefined
3737
+ ? null
3738
+ : this.folderSidebarFolders.find((f) => f && String(this.getByPath(f, idField)) === String(parentId));
3739
+ const parts = [];
3740
+ if (parent) {
3741
+ parts.push(String(this.getByPath(parent, this.folderPassthroughNameField) ?? parentId));
3742
+ }
3743
+ if (typeof scope.count === 'number') {
3744
+ if (cfg.countText) {
3745
+ parts.push(this.cnTranslate(cfg.countText).replace('{count}', String(scope.count)));
3746
+ } else if (cfg.source === 'groups') {
3747
+ parts.push(translatePlural('nextcloud-vue', '{count} member', '{count} members', scope.count, { count: scope.count }));
3748
+ }
3749
+ }
3750
+ return { name, subtitle: parts.join(' · ') }
3751
+ },
3752
+
3753
+ /**
3754
+ * The sort select's shown value: `sortSelectValue` when the host
3755
+ * controls it, else on a self-fetch page the option whose order is the
3756
+ * list's current order (a header click that matches one shows it).
3757
+ *
3758
+ * @return {string} The option value, or '' when none matches.
3759
+ */
3760
+ effectiveSortSelectValue() {
3761
+ if (this.sortSelectValue) {
3762
+ return this.sortSelectValue
3763
+ }
3764
+ if (!this.isSelfFetchMode || !this.list || !this.list.sortKeys) {
3765
+ return ''
3766
+ }
3767
+ const current = this.list.sortKeys.value || [];
3768
+ const match = (this.sortSelectOptions || []).find((o) => o && sameSortKeys(this.sortSelectKeys(o), current));
3769
+ return match ? match.value : ''
3770
+ },
3771
+
3658
3772
  /**
3659
3773
  * The `x-index` block the active scope's own schema row carries, for a
3660
3774
  * folder list derived from a register. Empty for every other source:
@@ -5329,11 +5443,21 @@ var script = {
5329
5443
  effectiveQuickFilters() {
5330
5444
  const own = withPersonalLenses(this.presented('quickFilters') || this.generatedQuickFilters, this.personalLenses);
5331
5445
  if (own && own.length > 0) {
5332
- return own
5446
+ return own.map((tab) => this.withConfigLabels(tab))
5333
5447
  }
5334
5448
  return (this.isNamedSource && this.namedQuickFilters) || null
5335
5449
  },
5336
5450
 
5451
+ /**
5452
+ * The app config `@config.<key>` tokens resolve against: the `appConfig`
5453
+ * prop over a config an ancestor provides.
5454
+ *
5455
+ * @return {object} The config.
5456
+ */
5457
+ effectiveAppConfig() {
5458
+ return { ...unwrapAppConfig(this.cnAppConfig), ...(this.appConfig || {}) }
5459
+ },
5460
+
5337
5461
  /**
5338
5462
  * Whether the Add button renders. A named source that declares
5339
5463
  * `showAdd: false` suppresses it (a task is created by a flow, never
@@ -5428,6 +5552,7 @@ var script = {
5428
5552
  variant: button.variant === 'primary' ? 'primary' : 'secondary',
5429
5553
  icon,
5430
5554
  format: button.format === 'excel' ? 'excel' : 'csv',
5555
+ run: typeof button.run === 'string' ? button.run : '',
5431
5556
  items: Array.isArray(button.items)
5432
5557
  ? button.items.filter((item) => (typeof item === 'string' && item !== '')
5433
5558
  || (item && typeof item === 'object' && typeof item.heading === 'string' && item.heading !== ''))
@@ -5435,6 +5560,10 @@ var script = {
5435
5560
  }
5436
5561
  })
5437
5562
  .filter((button) => button.label !== '')
5563
+ // An Export with nothing to export through is not drawn: a
5564
+ // named or endpoint source with no `run` and no `@mass-export`
5565
+ // listener.
5566
+ .filter((button) => button.action !== 'export' || this.headerExportAvailable(button))
5438
5567
  // The Actions menu lists the page's header actions (or the
5439
5568
  // entries its `items` name), so a menu with nothing to list
5440
5569
  // is not drawn.
@@ -7223,7 +7352,9 @@ var script = {
7223
7352
  if (button.action === 'add') {
7224
7353
  this.onAddClick();
7225
7354
  } else if (button.action === 'export') {
7226
- if (this.register && this.exportSchemaSlug) {
7355
+ if (button.run) {
7356
+ this.onHeaderAction({ action: button.run, id: button.run });
7357
+ } else if (this.register && this.exportSchemaSlug) {
7227
7358
  this.onExportClick(button.format);
7228
7359
  } else {
7229
7360
  this.showExportDialog = true;
@@ -7239,6 +7370,25 @@ var script = {
7239
7370
  }
7240
7371
  },
7241
7372
 
7373
+ /**
7374
+ * Whether a header Export has something to export through. Any page
7375
+ * listing OpenRegister objects (self-fetch or the consumer's
7376
+ * `objects`) keeps it; a named or endpoint source (`entitySource`)
7377
+ * needs a `run` naming one of the page's header actions, or a
7378
+ * `@mass-export` listener.
7379
+ *
7380
+ * @spec openspec/changes/index-header-export-source/specs/index-page/spec.md#requirement-a-header-export-is-drawn-only-when-it-can-export
7381
+ * @param {{run?: string}} button The resolved header button.
7382
+ * @return {boolean}
7383
+ */
7384
+ headerExportAvailable(button) {
7385
+ if (!this.isNamedSource || (button && button.run)) {
7386
+ return true
7387
+ }
7388
+ const props = this.$ && this.$.vnode && this.$.vnode.props;
7389
+ return Boolean(props && typeof props.onMassExport === 'function')
7390
+ },
7391
+
7242
7392
  /**
7243
7393
  * Click dispatch from CnActionsBar's `@header-action`. Looks
7244
7394
  * up the resolved entry by id, invokes its handler if any,
@@ -7359,6 +7509,65 @@ var script = {
7359
7509
  this.$emit('quick-filter-change', this.selectedQuickFilterIndices);
7360
7510
  },
7361
7511
 
7512
+ /**
7513
+ * The sort keys a sort-select option stands for: its `order` (any
7514
+ * `orderToSortKeys` form), else its `value` read as an order.
7515
+ *
7516
+ * @param {object} option A `sortSelectOptions` entry.
7517
+ * @return {Array<{key: string, order: string}>} The sort keys.
7518
+ */
7519
+ sortSelectKeys(option) {
7520
+ if (!option) {
7521
+ return []
7522
+ }
7523
+ return orderToSortKeys(option.order !== undefined ? option.order : option.value)
7524
+ },
7525
+
7526
+ /**
7527
+ * A choice in the sort select. On a self-fetch page it orders the list
7528
+ * as a header click does (`_order`, kept in the address); every page
7529
+ * also emits `sort-change` with the value.
7530
+ *
7531
+ * @param {string} value The chosen option's value.
7532
+ * @return {void}
7533
+ */
7534
+ onSortSelectChange(value) {
7535
+ const option = (this.sortSelectOptions || []).find((o) => o && o.value === value);
7536
+ const keys = this.sortSelectKeys(option);
7537
+ if (option && keys.length > 0 && this.isSelfFetchMode && typeof this.list.onSort === 'function') {
7538
+ this.list.onSort({ key: keys[0].key, order: keys[0].order, keys });
7539
+ this.persistViewStateToRoute(this.currentViewState());
7540
+ }
7541
+ this.$emit('sort-change', value);
7542
+ },
7543
+
7544
+ /**
7545
+ * A quick filter with `@config.<key>` in its `label` or `activeLabel`
7546
+ * (`"Residence @config.municipality"`): the label translated first, then
7547
+ * each token replaced by its configured value. A key the config does
7548
+ * not hold leaves its token in place. Other tabs pass unchanged.
7549
+ *
7550
+ * @param {object} tab A quick-filter tab.
7551
+ * @return {object} The tab, with its labels resolved.
7552
+ */
7553
+ withConfigLabels(tab) {
7554
+ if (!tab || typeof tab !== 'object') {
7555
+ return tab
7556
+ }
7557
+ const hasToken = (value) => typeof value === 'string' && value.includes('@config.');
7558
+ if (!hasToken(tab.label) && !hasToken(tab.activeLabel)) {
7559
+ return tab
7560
+ }
7561
+ const config = this.effectiveAppConfig;
7562
+ const fill = (value) => (hasToken(value)
7563
+ ? this.cnTranslate(value).replace(/@config\.([A-Za-z0-9_.-]*[A-Za-z0-9_])/g, (token, key) => {
7564
+ const found = this.getByPath(config, key);
7565
+ return found === undefined || found === null || found === '' ? token : String(found)
7566
+ })
7567
+ : value);
7568
+ return { ...tab, label: fill(tab.label), activeLabel: fill(tab.activeLabel) }
7569
+ },
7570
+
7362
7571
  /**
7363
7572
  * @param {{key: string, order: string, keys?: Array<{key: string, order: string}>}} payload Sort change from CnDataTable.
7364
7573
  * @return {void}