@conduction/nextcloud-vue 2.98.0 → 2.100.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 (141) hide show
  1. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js +12 -0
  2. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +11 -2
  4. package/dist/esm/components/CnActionsMenu/CnActionsMenu.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 +6 -1
  7. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +2 -1
  9. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  10. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -1
  11. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
  12. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +1 -1
  13. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +25 -8
  15. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +7 -4
  17. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  19. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -8
  20. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  21. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +13 -4
  22. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  23. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  24. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +54 -3
  25. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  26. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +16 -2
  27. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  28. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
  29. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +42 -7
  30. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
  31. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +121 -57
  32. package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js +10 -0
  34. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue2.js.map +1 -1
  35. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js +2 -1
  36. package/dist/esm/components/CnFlowsPage/CnFlowEditorPage.vue3.js.map +1 -1
  37. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +136 -7
  38. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  39. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  40. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue.js +1 -1
  41. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js +26 -7
  42. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue2.js.map +1 -1
  43. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js +78 -17
  44. package/dist/esm/components/CnOrderedListField/CnOrderedListField.vue3.js.map +1 -1
  45. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  46. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +68 -7
  47. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +256 -240
  49. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +9 -0
  51. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js.map +1 -0
  52. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +265 -0
  53. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -0
  54. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +191 -0
  55. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -0
  56. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js +9 -0
  57. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue.js.map +1 -0
  58. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js +537 -0
  59. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue2.js.map +1 -0
  60. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js +99 -0
  61. package/dist/esm/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue3.js.map +1 -0
  62. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  63. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +18 -70
  64. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +6 -44
  66. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  67. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
  68. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +16 -2
  69. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  70. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +40 -25
  71. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  72. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  73. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  74. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue.js +1 -1
  75. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +7 -7
  76. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
  77. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
  78. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js +9 -0
  79. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue.js.map +1 -0
  80. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js +472 -0
  81. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue2.js.map +1 -0
  82. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js +231 -0
  83. package/dist/esm/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue3.js.map +1 -0
  84. package/dist/esm/components/CnWorkingCalendarWidget/index.js +27 -0
  85. package/dist/esm/components/CnWorkingCalendarWidget/index.js.map +1 -0
  86. package/dist/esm/composables/useFlowStore.js +2 -1
  87. package/dist/esm/composables/useFlowStore.js.map +1 -1
  88. package/dist/esm/index.js +3 -0
  89. package/dist/esm/index.js.map +1 -1
  90. package/dist/esm/l10n/en.json.js +101 -1
  91. package/dist/esm/l10n/en.json.js.map +1 -1
  92. package/dist/esm/l10n/nl.json.js +115 -1
  93. package/dist/esm/l10n/nl.json.js.map +1 -1
  94. package/dist/esm/library-style.js +1 -1
  95. package/dist/esm/nextcloud-vue.css +999 -233
  96. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  97. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  98. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  99. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  100. package/dist/esm/utils/workingCalendarMonth.js +85 -0
  101. package/dist/esm/utils/workingCalendarMonth.js.map +1 -0
  102. package/dist/nextcloud-vue.cjs.js +10314 -7778
  103. package/dist/nextcloud-vue.cjs.js.map +2 -2
  104. package/dist/nextcloud-vue.css +999 -233
  105. package/l10n/en.json +101 -1
  106. package/l10n/nl.json +115 -1
  107. package/package.json +1 -1
  108. package/src/components/CnActionsMenu/CnActionsMenu.vue +14 -1
  109. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +7 -1
  110. package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +1 -0
  111. package/src/components/CnDetailPage/CnDetailPage.vue +29 -9
  112. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +13 -4
  113. package/src/components/CnFactsWidget/CnFactsWidget.vue +65 -3
  114. package/src/components/CnFlowsPage/CnFlowBoard.vue +77 -2
  115. package/src/components/CnFlowsPage/CnFlowEditorPage.vue +11 -0
  116. package/src/components/CnIndexPage/CnIndexPage.vue +136 -7
  117. package/src/components/CnOrderedListField/CnOrderedListField.vue +81 -9
  118. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +114 -7
  119. package/src/components/CnSettingsField/CnSettingsField.vue +449 -0
  120. package/src/components/CnSettingsField/index.js +4 -0
  121. package/src/components/CnSettingsFieldsSection/CnSettingsFieldsSection.vue +642 -0
  122. package/src/components/CnSettingsFieldsSection/index.js +4 -0
  123. package/src/components/CnSettingsPage/CnSettingsPage.vue +6 -86
  124. package/src/components/CnSetupWizard/CnSetupWizard.vue +37 -3
  125. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  126. package/src/components/CnWizardDialog/CnWizardDialog.vue +7 -7
  127. package/src/components/CnWorkingCalendarWidget/CnWorkingCalendarWidget.vue +725 -0
  128. package/src/components/CnWorkingCalendarWidget/index.js +26 -0
  129. package/src/components/index.js +3 -0
  130. package/src/composables/useFlowStore.js +2 -1
  131. package/src/css/badge.css +32 -16
  132. package/src/css/detail-page.css +15 -0
  133. package/src/css/dialog.css +48 -0
  134. package/src/css/look-board-detail.css +80 -8
  135. package/src/css/look-board-index.css +52 -8
  136. package/src/css/look-board.css +301 -1
  137. package/src/index.js +3 -0
  138. package/src/schemas/app-manifest-v2.schema.json +25 -1
  139. package/src/utils/libraryWidgetKeys.js +1 -0
  140. package/src/utils/validateManifestV2.compiled.js +3 -3
  141. package/src/utils/workingCalendarMonth.js +82 -0
@@ -10,61 +10,65 @@ const _hoisted_4 = {
10
10
  key: 0,
11
11
  class: "cn-flow-board__actions"
12
12
  };
13
- const _hoisted_5 = {
13
+ const _hoisted_5 = { class: "cn-flow-board__test-intro" };
14
+ const _hoisted_6 = {
14
15
  class: "cn-flow-board__path",
15
16
  "data-testid": "flow-board-path"
16
17
  };
17
- const _hoisted_6 = ["href"];
18
18
  const _hoisted_7 = ["href"];
19
- const _hoisted_8 = { key: 1 };
20
- const _hoisted_9 = {
19
+ const _hoisted_8 = ["href"];
20
+ const _hoisted_9 = { key: 1 };
21
+ const _hoisted_10 = {
21
22
  key: 2,
22
23
  class: "cn-flow-board__meta"
23
24
  };
24
- const _hoisted_10 = { class: "cn-flow-board__body" };
25
- const _hoisted_11 = {
25
+ const _hoisted_11 = { class: "cn-flow-board__body" };
26
+ const _hoisted_12 = {
26
27
  key: 0,
27
28
  class: "cn-flow-board__card cn-flow-board__palette",
28
29
  "data-testid": "flow-board-palette"
29
30
  };
30
- const _hoisted_12 = { class: "cn-flow-board__card-title" };
31
- const _hoisted_13 = { class: "cn-flow-board__palette-app" };
32
- const _hoisted_14 = { class: "cn-flow-board__palette-list" };
33
- const _hoisted_15 = ["disabled", "data-testid", "onClick"];
34
- const _hoisted_16 = {
31
+ const _hoisted_13 = { class: "cn-flow-board__card-title" };
32
+ const _hoisted_14 = { class: "cn-flow-board__palette-app" };
33
+ const _hoisted_15 = { class: "cn-flow-board__palette-list" };
34
+ const _hoisted_16 = ["disabled", "data-testid", "onClick"];
35
+ const _hoisted_17 = {
35
36
  key: 0,
36
37
  class: "cn-flow-board__palette-note"
37
38
  };
38
- const _hoisted_17 = ["aria-label"];
39
- const _hoisted_18 = {
39
+ const _hoisted_18 = ["aria-label"];
40
+ const _hoisted_19 = {
40
41
  key: 0,
41
42
  class: "cn-flow-board__legend",
42
43
  "data-testid": "flow-board-legend"
43
44
  };
44
- const _hoisted_19 = {
45
+ const _hoisted_20 = {
45
46
  class: "cn-flow-board__card cn-flow-board__inspector",
46
47
  "data-testid": "flow-board-inspector"
47
48
  };
48
- const _hoisted_20 = {
49
+ const _hoisted_21 = {
49
50
  class: "cn-flow-board__tabs",
50
51
  role: "tablist"
51
52
  };
52
- const _hoisted_21 = ["aria-selected", "data-testid", "onClick"];
53
- const _hoisted_22 = { class: "cn-flow-board__tab-count" };
54
- const _hoisted_23 = { class: "cn-flow-board__eyebrow" };
55
- const _hoisted_24 = {
53
+ const _hoisted_22 = ["aria-selected", "data-testid", "onClick"];
54
+ const _hoisted_23 = { class: "cn-flow-board__tab-count" };
55
+ const _hoisted_24 = { class: "cn-flow-board__eyebrow" };
56
+ const _hoisted_25 = {
56
57
  class: "cn-flow-board__card-title",
57
58
  "data-testid": "flow-board-step-name"
58
59
  };
59
- const _hoisted_25 = { class: "cn-flow-board__step-actions" };
60
- const _hoisted_26 = { class: "cn-flow-board__subtitle" };
61
- const _hoisted_27 = { class: "cn-flow-board__step-footer" };
60
+ const _hoisted_26 = { class: "cn-flow-board__step-actions" };
61
+ const _hoisted_27 = { class: "cn-flow-board__subtitle" };
62
+ const _hoisted_28 = { class: "cn-flow-board__step-footer" };
62
63
 
63
64
  function render(_ctx, _cache, $props, $setup, $data, $options) {
64
65
  const _component_CnStatusBadge = resolveComponent("CnStatusBadge");
65
66
  const _component_NcCheckboxRadioSwitch = resolveComponent("NcCheckboxRadioSwitch");
66
67
  const _component_NcButton = resolveComponent("NcButton");
68
+ const _component_TestTube = resolveComponent("TestTube");
67
69
  const _component_CnBuildiqEditButton = resolveComponent("CnBuildiqEditButton");
70
+ const _component_CnResourceSelect = resolveComponent("CnResourceSelect");
71
+ const _component_CnDialog = resolveComponent("CnDialog");
68
72
  const _component_NcNoteCard = resolveComponent("NcNoteCard");
69
73
  const _component_CnFlowDetail = resolveComponent("CnFlowDetail");
70
74
  const _component_CnFlowRunSummary = resolveComponent("CnFlowRunSummary");
@@ -125,12 +129,28 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
125
129
  _: 1 /* STABLE */
126
130
  }, 8 /* PROPS */, ["disabled"]))
127
131
  : createCommentVNode("v-if", true),
132
+ ($options.testSubjectReady)
133
+ ? (openBlock(), createBlock(_component_NcButton, {
134
+ key: 2,
135
+ disabled: $setup.store.running || !$setup.store.flow.id,
136
+ "data-testid": "flow-board-test",
137
+ onClick: _cache[2] || (_cache[2] = $event => ($data.testOpen = true))
138
+ }, {
139
+ icon: withCtx(() => [
140
+ createVNode(_component_TestTube, { size: 16 })
141
+ ]),
142
+ default: withCtx(() => [
143
+ createTextVNode(" " + toDisplayString($options.testLabel), 1 /* TEXT */)
144
+ ]),
145
+ _: 1 /* STABLE */
146
+ }, 8 /* PROPS */, ["disabled"]))
147
+ : createCommentVNode("v-if", true),
128
148
  createVNode(_component_CnBuildiqEditButton),
129
149
  createVNode(_component_NcButton, {
130
150
  variant: "primary",
131
151
  disabled: $setup.store.saving || !$setup.store.flow.name || $setup.store.graphLocked,
132
152
  "data-testid": "flow-board-save",
133
- onClick: _cache[2] || (_cache[2] = $event => (_ctx.$emit('save')))
153
+ onClick: _cache[3] || (_cache[3] = $event => (_ctx.$emit('save')))
134
154
  }, {
135
155
  default: withCtx(() => [
136
156
  createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Save')), 1 /* TEXT */)
@@ -140,31 +160,75 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
140
160
  ]))
141
161
  : createCommentVNode("v-if", true)
142
162
  ]),
143
- createElementVNode("p", _hoisted_5, [
163
+ ($data.testOpen)
164
+ ? (openBlock(), createBlock(_component_CnDialog, {
165
+ key: 0,
166
+ name: $options.testLabel,
167
+ "data-testid": "flow-board-test-dialog",
168
+ onClosing: _cache[6] || (_cache[6] = $event => ($data.testOpen = false))
169
+ }, {
170
+ actions: withCtx(() => [
171
+ createVNode(_component_NcButton, {
172
+ "data-testid": "flow-board-test-cancel",
173
+ onClick: _cache[5] || (_cache[5] = $event => ($data.testOpen = false))
174
+ }, {
175
+ default: withCtx(() => [
176
+ createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Cancel')), 1 /* TEXT */)
177
+ ]),
178
+ _: 1 /* STABLE */
179
+ }),
180
+ createVNode(_component_NcButton, {
181
+ variant: "primary",
182
+ disabled: !$data.testRecord || $setup.store.running,
183
+ "data-testid": "flow-board-test-run",
184
+ onClick: $options.runTest
185
+ }, {
186
+ default: withCtx(() => [
187
+ createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Run test')), 1 /* TEXT */)
188
+ ]),
189
+ _: 1 /* STABLE */
190
+ }, 8 /* PROPS */, ["disabled", "onClick"])
191
+ ]),
192
+ default: withCtx(() => [
193
+ createElementVNode("p", _hoisted_5, toDisplayString($options.t('nextcloud-vue', 'The saved flow runs once with the record you pick as its subject.')), 1 /* TEXT */),
194
+ createVNode(_component_CnResourceSelect, {
195
+ modelValue: $data.testRecord,
196
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($data.testRecord) = $event)),
197
+ register: $props.testSubject.register,
198
+ schema: $props.testSubject.schema,
199
+ labelField: $props.testSubject.labelField || 'title',
200
+ inputLabel: $options.t('nextcloud-vue', 'Record'),
201
+ "data-testid": "flow-board-test-record"
202
+ }, null, 8 /* PROPS */, ["modelValue", "register", "schema", "labelField", "inputLabel"])
203
+ ]),
204
+ _: 1 /* STABLE */
205
+ }, 8 /* PROPS */, ["name"]))
206
+ : createCommentVNode("v-if", true),
207
+ createElementVNode("p", _hoisted_6, [
144
208
  createElementVNode("a", {
145
209
  href: $options.listHref,
146
210
  class: "cn-flow-board__crumb",
147
- onClick: _cache[3] || (_cache[3] = $event => ($options.onCrumbClick($event, $props.detailRoute)))
148
- }, toDisplayString($options.listText), 9 /* TEXT, PROPS */, _hoisted_6),
149
- _cache[12] || (_cache[12] = createElementVNode("span", { "aria-hidden": "true" }, " / ", -1 /* CACHED */)),
211
+ onClick: _cache[7] || (_cache[7] = $event => ($options.onCrumbClick($event, $props.detailRoute)))
212
+ }, toDisplayString($options.listText), 9 /* TEXT, PROPS */, _hoisted_7),
213
+ _cache[16] || (_cache[16] = createElementVNode("span", { "aria-hidden": "true" }, " / ", -1 /* CACHED */)),
150
214
  ($setup.store.inRunView)
151
215
  ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
152
216
  createElementVNode("a", {
153
217
  href: $options.flowHref,
154
218
  class: "cn-flow-board__crumb",
155
- onClick: _cache[4] || (_cache[4] = $event => ($options.onCrumbClick($event, $options.flowPath)))
156
- }, toDisplayString($options.flowName), 9 /* TEXT, PROPS */, _hoisted_7),
157
- _cache[11] || (_cache[11] = createElementVNode("span", { "aria-hidden": "true" }, " / ", -1 /* CACHED */)),
219
+ onClick: _cache[8] || (_cache[8] = $event => ($options.onCrumbClick($event, $options.flowPath)))
220
+ }, toDisplayString($options.flowName), 9 /* TEXT, PROPS */, _hoisted_8),
221
+ _cache[15] || (_cache[15] = createElementVNode("span", { "aria-hidden": "true" }, " / ", -1 /* CACHED */)),
158
222
  createElementVNode("span", null, toDisplayString($options.runCrumb), 1 /* TEXT */)
159
223
  ], 64 /* STABLE_FRAGMENT */))
160
- : (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString($options.flowName), 1 /* TEXT */)),
224
+ : (openBlock(), createElementBlock("span", _hoisted_9, toDisplayString($options.flowName), 1 /* TEXT */)),
161
225
  ($options.metaText)
162
- ? (openBlock(), createElementBlock("span", _hoisted_9, " · " + toDisplayString($options.metaText), 1 /* TEXT */))
226
+ ? (openBlock(), createElementBlock("span", _hoisted_10, " · " + toDisplayString($options.metaText), 1 /* TEXT */))
163
227
  : createCommentVNode("v-if", true)
164
228
  ]),
165
229
  ($props.notice && !$setup.store.inRunView)
166
230
  ? (openBlock(), createBlock(_component_NcNoteCard, {
167
- key: 0,
231
+ key: 1,
168
232
  type: "info",
169
233
  class: "cn-flow-board__notice"
170
234
  }, {
@@ -174,17 +238,17 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
174
238
  _: 1 /* STABLE */
175
239
  }))
176
240
  : createCommentVNode("v-if", true),
177
- createElementVNode("div", _hoisted_10, [
241
+ createElementVNode("div", _hoisted_11, [
178
242
  ($options.showPalette)
179
- ? (openBlock(), createElementBlock("aside", _hoisted_11, [
180
- createElementVNode("h3", _hoisted_12, toDisplayString($options.t('nextcloud-vue', 'Steps')), 1 /* TEXT */),
243
+ ? (openBlock(), createElementBlock("aside", _hoisted_12, [
244
+ createElementVNode("h3", _hoisted_13, toDisplayString($options.t('nextcloud-vue', 'Steps')), 1 /* TEXT */),
181
245
  (openBlock(true), createElementBlock(Fragment, null, renderList($options.paletteGroups, (group) => {
182
246
  return (openBlock(), createElementBlock("section", {
183
247
  key: group.app,
184
248
  class: "cn-flow-board__palette-group"
185
249
  }, [
186
- createElementVNode("h4", _hoisted_13, toDisplayString(group.app), 1 /* TEXT */),
187
- createElementVNode("ul", _hoisted_14, [
250
+ createElementVNode("h4", _hoisted_14, toDisplayString(group.app), 1 /* TEXT */),
251
+ createElementVNode("ul", _hoisted_15, [
188
252
  (openBlock(true), createElementBlock(Fragment, null, renderList(group.entries, (entry) => {
189
253
  return (openBlock(), createElementBlock("li", {
190
254
  key: entry.id
@@ -195,14 +259,14 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
195
259
  disabled: $setup.store.graphLocked,
196
260
  "data-testid": `flow-board-palette-${entry.id}`,
197
261
  onClick: $event => ($setup.store.addNode(entry.id))
198
- }, toDisplayString(entry.displayName || entry.label || entry.id), 9 /* TEXT, PROPS */, _hoisted_15)
262
+ }, toDisplayString(entry.displayName || entry.label || entry.id), 9 /* TEXT, PROPS */, _hoisted_16)
199
263
  ]))
200
264
  }), 128 /* KEYED_FRAGMENT */))
201
265
  ])
202
266
  ]))
203
267
  }), 128 /* KEYED_FRAGMENT */)),
204
268
  ($props.paletteFootnote)
205
- ? (openBlock(), createElementBlock("p", _hoisted_16, toDisplayString($props.paletteFootnote), 1 /* TEXT */))
269
+ ? (openBlock(), createElementBlock("p", _hoisted_17, toDisplayString($props.paletteFootnote), 1 /* TEXT */))
206
270
  : createCommentVNode("v-if", true)
207
271
  ]))
208
272
  : createCommentVNode("v-if", true),
@@ -216,11 +280,11 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
216
280
  run: $props.run,
217
281
  toolbarActions: false,
218
282
  addStep: !$options.showPalette,
219
- onSave: _cache[5] || (_cache[5] = $event => (_ctx.$emit('save'))),
220
- onRun: _cache[6] || (_cache[6] = $event => (_ctx.$emit('run')))
283
+ onSave: _cache[9] || (_cache[9] = $event => (_ctx.$emit('save'))),
284
+ onRun: _cache[10] || (_cache[10] = $event => (_ctx.$emit('run')))
221
285
  }, null, 8 /* PROPS */, ["id", "app", "run", "addStep"]),
222
286
  ($setup.store.inRunView)
223
- ? (openBlock(), createElementBlock("div", _hoisted_18, [
287
+ ? (openBlock(), createElementBlock("div", _hoisted_19, [
224
288
  (openBlock(true), createElementBlock(Fragment, null, renderList($options.legend, (level) => {
225
289
  return (openBlock(), createElementBlock("span", {
226
290
  key: level.id,
@@ -240,8 +304,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
240
304
  role: "status",
241
305
  "data-testid": "flow-board-validity"
242
306
  }, toDisplayString($options.validity.text), 3 /* TEXT, CLASS */))
243
- ], 8 /* PROPS */, _hoisted_17),
244
- createElementVNode("aside", _hoisted_19, [
307
+ ], 8 /* PROPS */, _hoisted_18),
308
+ createElementVNode("aside", _hoisted_20, [
245
309
  ($setup.store.inRunView)
246
310
  ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
247
311
  createVNode(_component_CnFlowRunSummary, {
@@ -251,7 +315,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
251
315
  onBack: $options.onBackToFlow,
252
316
  onRetry: $options.onRetry
253
317
  }, null, 8 /* PROPS */, ["run", "stepsTotal", "canRetry", "onBack", "onRetry"]),
254
- createElementVNode("div", _hoisted_20, [
318
+ createElementVNode("div", _hoisted_21, [
255
319
  (openBlock(true), createElementBlock(Fragment, null, renderList($options.runTabs, (tab) => {
256
320
  return (openBlock(), createElementBlock("button", {
257
321
  key: tab.id,
@@ -263,8 +327,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
263
327
  onClick: $event => ($data.runTab = tab.id)
264
328
  }, [
265
329
  createTextVNode(toDisplayString(tab.label) + " ", 1 /* TEXT */),
266
- createElementVNode("span", _hoisted_22, toDisplayString(tab.count), 1 /* TEXT */)
267
- ], 10 /* CLASS, PROPS */, _hoisted_21))
330
+ createElementVNode("span", _hoisted_23, toDisplayString(tab.count), 1 /* TEXT */)
331
+ ], 10 /* CLASS, PROPS */, _hoisted_22))
268
332
  }), 128 /* KEYED_FRAGMENT */))
269
333
  ]),
270
334
  createVNode(_component_CnFlowStepLog, {
@@ -274,12 +338,12 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
274
338
  ], 64 /* STABLE_FRAGMENT */))
275
339
  : ($setup.store.selectedNode)
276
340
  ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
277
- createElementVNode("p", _hoisted_23, toDisplayString($options.stepTypeLabel), 1 /* TEXT */),
278
- createElementVNode("h3", _hoisted_24, toDisplayString($options.stepName), 1 /* TEXT */),
279
- createElementVNode("div", _hoisted_25, [
341
+ createElementVNode("p", _hoisted_24, toDisplayString($options.stepTypeLabel), 1 /* TEXT */),
342
+ createElementVNode("h3", _hoisted_25, toDisplayString($options.stepName), 1 /* TEXT */),
343
+ createElementVNode("div", _hoisted_26, [
280
344
  createVNode(_component_NcButton, {
281
345
  "data-testid": "flow-board-edit-step",
282
- onClick: _cache[7] || (_cache[7] = $event => ($setup.store.editingNodeId = $setup.store.selectedNodeId))
346
+ onClick: _cache[11] || (_cache[11] = $event => ($setup.store.editingNodeId = $setup.store.selectedNodeId))
283
347
  }, {
284
348
  default: withCtx(() => [
285
349
  createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Edit step')), 1 /* TEXT */)
@@ -291,7 +355,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
291
355
  key: 0,
292
356
  variant: "tertiary",
293
357
  "data-testid": "flow-board-open-last-run",
294
- onClick: _cache[8] || (_cache[8] = $event => ($options.openRun($options.lastRunUuid)))
358
+ onClick: _cache[12] || (_cache[12] = $event => ($options.openRun($options.lastRunUuid)))
295
359
  }, {
296
360
  default: withCtx(() => [
297
361
  createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Open the last run on the canvas')), 1 /* TEXT */)
@@ -300,18 +364,18 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
300
364
  }))
301
365
  : createCommentVNode("v-if", true)
302
366
  ]),
303
- createElementVNode("h4", _hoisted_26, toDisplayString($options.t('nextcloud-vue', 'Recent log lines of this step')), 1 /* TEXT */),
367
+ createElementVNode("h4", _hoisted_27, toDisplayString($options.t('nextcloud-vue', 'Recent log lines of this step')), 1 /* TEXT */),
304
368
  createVNode(_component_CnFlowStepLog, {
305
369
  lines: $options.recentStepLines,
306
370
  withDay: "",
307
371
  emptyText: $options.t('nextcloud-vue', 'This step has not run yet.')
308
372
  }, null, 8 /* PROPS */, ["lines", "emptyText"]),
309
- createElementVNode("div", _hoisted_27, [
373
+ createElementVNode("div", _hoisted_28, [
310
374
  createVNode(_component_NcButton, {
311
375
  variant: "tertiary",
312
376
  disabled: $setup.store.graphLocked,
313
377
  "data-testid": "flow-board-delete-step",
314
- onClick: _cache[9] || (_cache[9] = $event => ($setup.store.removeNode($setup.store.selectedNodeId)))
378
+ onClick: _cache[13] || (_cache[13] = $event => ($setup.store.removeNode($setup.store.selectedNodeId)))
315
379
  }, {
316
380
  default: withCtx(() => [
317
381
  createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Delete step')), 1 /* TEXT */)
@@ -320,7 +384,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
320
384
  }, 8 /* PROPS */, ["disabled"]),
321
385
  createVNode(_component_NcButton, {
322
386
  "data-testid": "flow-board-done",
323
- onClick: _cache[10] || (_cache[10] = $event => ($setup.store.selectedNodeId = null))
387
+ onClick: _cache[14] || (_cache[14] = $event => ($setup.store.selectedNodeId = null))
324
388
  }, {
325
389
  default: withCtx(() => [
326
390
  createTextVNode(toDisplayString($options.t('nextcloud-vue', 'Done')), 1 /* TEXT */)
@@ -1 +1 @@
1
- {"version":3,"file":"CnFlowBoard.vue3.js","sources":["../../../../src/components/CnFlowsPage/CnFlowBoard.vue?vue&type=template&id=b3c586ae&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<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<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 CnBuildiqEditButton from '../CnBuildiqEditButton/CnBuildiqEditButton.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 { 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, CnFlowDetail, 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},\n\n\temits: ['save', 'run', 'retried'],\n\n\tsetup() {\n\t\treturn { store: useFlowStore() }\n\t},\n\n\tdata() {\n\t\treturn { runTab: 'step' }\n\t},\n\n\tcomputed: {\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\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__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=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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"}
@@ -98,6 +98,16 @@ var script = {
98
98
  default: '',
99
99
  },
100
100
 
101
+ /**
102
+ * Board look: the records a test run can take as its subject,
103
+ * `{ register, schema, labelField?, label? }`. Manifest key
104
+ * `config.testSubject`; `label` is translated with the app's catalogue.
105
+ */
106
+ testSubject: {
107
+ type: Object,
108
+ default: null,
109
+ },
110
+
101
111
  /**
102
112
  * Board look: an info notice under the path. Manifest key
103
113
  * `config.notice`, translated with the app's catalogue.
@@ -1 +1 @@
1
- {"version":3,"file":"CnFlowEditorPage.vue2.js","sources":["../../../../src/components/CnFlowsPage/CnFlowEditorPage.vue"],"sourcesContent":["<!-- SPDX-License-Identifier: EUPL-1.2 -->\n<!-- Copyright (C) 2026 Conduction B.V. -->\n<template>\n\t<CnFlowBoard v-if=\"isBoard\"\n\t\t:id=\"flowId\"\n\t\t:app=\"app\"\n\t\t:run=\"runUuid\"\n\t\t:detailRoute=\"detailRoute\"\n\t\t:listLabel=\"listLabel ? cnTranslate(listLabel) : ''\"\n\t\t:palette=\"palette\"\n\t\t:paletteFootnote=\"paletteFootnote ? cnTranslate(paletteFootnote) : ''\"\n\t\t:notice=\"notice ? cnTranslate(notice) : ''\"\n\t\t:pill=\"pill ? cnTranslate(pill) : ''\"\n\t\t@save=\"onSave\"\n\t\t@run=\"onRun\" />\n\t<CnFlowDetail v-else\n\t\t:id=\"flowId\"\n\t\t:app=\"app\"\n\t\t:run=\"runUuid\"\n\t\t@save=\"onSave\"\n\t\t@run=\"onRun\" />\n</template>\n\n<script>\nimport CnFlowDetail from '../CnFlowDetail/CnFlowDetail.vue'\nimport CnFlowBoard from './CnFlowBoard.vue'\nimport { useFlowStore } from '../../composables/useFlowStore.js'\nimport { useLook } from '../../composables/useLook.js'\n\n/**\n * The flow canvas — manifest page type `flow-detail`.\n *\n * Mounts the shared `CnFlowDetail` node/edge canvas over OpenRegister's one\n * native flow store (ADR-065, ADR-098), scoped to the owning app. Pair it with\n * a `type: \"flows\"` page at `/flows`; this one takes `/flows/:id`.\n *\n * Controls belong in Nextcloud's app sidebar so the canvas keeps the full\n * width — declare `\"sidebarComponent\"` on the manifest page, or mount\n * `CnFlowSidebar` yourself. Canvas and sidebar share `useFlowStore`, which is\n * why neither needs props from the other.\n *\n * Manifest declaration:\n *\n * { \"id\": \"FlowDetail\", \"route\": \"/flows/:id\", \"type\": \"flow-detail\",\n * \"title\": \"Flow\", \"config\": { \"app\": \"dossiq\" } }\n */\nexport default {\n\tname: 'CnFlowEditorPage',\n\n\tcomponents: { CnFlowBoard, CnFlowDetail },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The owning app id, stamped on a flow created here so the app-scoped\n\t\t * list finds it again. Omit only on the fleet-wide surface.\n\t\t */\n\t\tapp: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The flow id to open. Defaults to the `id` route param, which is the\n\t\t * normal case; pass it explicitly only when mounting outside a route.\n\t\t * The literal `new` opens an unsaved flow.\n\t\t */\n\t\tid: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Route path the editor lives under, used to swap the URL once a new\n\t\t * flow gets its server-assigned id.\n\t\t */\n\t\tdetailRoute: {\n\t\t\ttype: String,\n\t\t\tdefault: '/flows',\n\t\t},\n\n\t\t/**\n\t\t * A run to open on arrival. Defaults to the `run` query parameter,\n\t\t * which is where a run's own address lands: `/flow-runs/{uuid}` reads\n\t\t * the run, finds its flow and redirects to `/flows/{id}?run={uuid}`.\n\t\t * Pass it explicitly only when mounting outside a route.\n\t\t */\n\t\trun: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Draw this page in the `board` look (or `nextcloud`) whatever the app\n\t\t * does. Empty follows the app's look. Manifest key `config.look`.\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: where steps come from. `picker` (default) keeps \"Add a\n\t\t * step\" in the canvas toolbar; `column` draws the palette as a card\n\t\t * beside the canvas, grouped by the app that provides each step.\n\t\t * Manifest key `config.palette`.\n\t\t */\n\t\tpalette: {\n\t\t\ttype: String,\n\t\t\tdefault: 'picker',\n\t\t},\n\n\t\t/**\n\t\t * Board look: a line under the palette card. Manifest key\n\t\t * `config.paletteFootnote`, translated with the app's catalogue.\n\t\t */\n\t\tpaletteFootnote: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: an info notice under the path. Manifest key\n\t\t * `config.notice`, translated with the app's catalogue.\n\t\t */\n\t\tnotice: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: the pill beside the flow's name (\"Case type flow\").\n\t\t * Empty shows the lifecycle for a draft or retired flow. Manifest key\n\t\t * `config.pill`.\n\t\t */\n\t\tpill: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: the list's name at the start of the path (\"Settings /\n\t\t * Flows\"). Empty reads \"Flows\". Manifest key `config.listLabel`.\n\t\t */\n\t\tlistLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\t/**\n\t * Share the one flow store with the toolbar's save/run handlers, and\n\t * resolve the look (`look` is read here, through `useLook`).\n\t *\n\t * @param {object} props The component props.\n\t * @return {object} The setup bindings.\n\t */\n\tsetup(props) {\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { store: useFlowStore(), isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * @return {string} The flow id being edited.\n\t\t */\n\t\tflowId() {\n\t\t\treturn this.id || this.$route?.params?.id || ''\n\t\t},\n\n\t\t/**\n\t\t * @return {string} The run to open on arrival, or an empty string.\n\t\t */\n\t\trunUuid() {\n\t\t\treturn this.run || this.$route?.query?.run || ''\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onSave() {\n\t\t\tconst saved = await this.store.save()\n\t\t\t// A newly created flow gets its id from the server, so the route has\n\t\t\t// to catch up or a reload would land back on `new` and lose it.\n\t\t\tif (saved?.id && this.flowId === 'new') {\n\t\t\t\tthis.$router.replace(`${this.detailRoute}/${saved.id}`)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onRun() {\n\t\t\tawait this.store.run({})\n\t\t},\n\t},\n}\n</script>\n"],"names":["CnFlowBoard","CnFlowDetail"],"mappings":";;;;;AA6BA;AACC;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA;;AAED,aAAe;CACd,IAAI,EAAE,kBAAkB;;AAExB,CAAA,UAAU,EAAE,eAAEA,UAAW,gBAAEC,cAAc;;AAEzC,CAAA,MAAM,EAAE;AACP,EAAA,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,KAAK,KAAK;EAC5C;;AAED,CAAA,KAAK,EAAE;AACN;;;;EAIA,GAAG,EAAE;GACJ,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,IAAI;GACb;;AAED;;;AAGC;;AAED,EAAA,EAAE,EAAE;GACH,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,WAAW,EAAE;GACZ,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,QAAQ;GACjB;;AAED;;;;;;EAMA,GAAG,EAAE;GACJ,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,IAAI,EAAE;GACL,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;;;AAMA,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,QAAQ;GACjB;;AAED;;;;AAIA,EAAA,eAAe,EAAE;GAChB,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;AAIA,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;AAGC;;EAED,IAAI,EAAE;GACL,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,SAAS,EAAE;GACV,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;EACD;;AAED;;;AAGC;AACA;AACA;;CAED,KAAK,CAAC,KAAK,EAAE;EACZ,MAAM,EAAE,OAAQ,EAAA,GAAI,OAAO,CAAC,KAAK,EAAA;AACjC,EAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAQ,EAAA;EACxC;;AAED,CAAA,QAAQ,EAAE;AACT;AACC;;AAED,EAAA,MAAM,GAAG;AACR,GAAA,OAAO,IAAI,CAAC,EAAG,IAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAG,IAAG,EAAC;GAC9C;;AAED;;;AAGA,EAAA,OAAO,GAAG;AACT,GAAA,OAAO,IAAI,CAAC,GAAI,IAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAI,IAAG,EAAC;GAC/C;EACD;;AAED,CAAA,OAAO,EAAE;AACR;;;EAGA,MAAM,MAAM,GAAG;AACd,GAAA,MAAM,KAAM,GAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,GAAC;;;AAGpC,GAAA,IAAI,KAAK,EAAE,EAAC,IAAK,IAAI,CAAC,MAAO,KAAI,KAAK,EAAE;IACvC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,EAAA;AACvD,IAAA;GACA;;AAED;;;EAGA,MAAM,KAAK,GAAG;GACb,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAA;GACvB;EACD;AACF;;;;"}
1
+ {"version":3,"file":"CnFlowEditorPage.vue2.js","sources":["../../../../src/components/CnFlowsPage/CnFlowEditorPage.vue"],"sourcesContent":["<!-- SPDX-License-Identifier: EUPL-1.2 -->\n<!-- Copyright (C) 2026 Conduction B.V. -->\n<template>\n\t<CnFlowBoard v-if=\"isBoard\"\n\t\t:id=\"flowId\"\n\t\t:app=\"app\"\n\t\t:run=\"runUuid\"\n\t\t:detailRoute=\"detailRoute\"\n\t\t:listLabel=\"listLabel ? cnTranslate(listLabel) : ''\"\n\t\t:palette=\"palette\"\n\t\t:paletteFootnote=\"paletteFootnote ? cnTranslate(paletteFootnote) : ''\"\n\t\t:notice=\"notice ? cnTranslate(notice) : ''\"\n\t\t:pill=\"pill ? cnTranslate(pill) : ''\"\n\t\t:testSubject=\"testSubject ? { ...testSubject, label: testSubject.label ? cnTranslate(testSubject.label) : '' } : null\"\n\t\t@save=\"onSave\"\n\t\t@run=\"onRun\" />\n\t<CnFlowDetail v-else\n\t\t:id=\"flowId\"\n\t\t:app=\"app\"\n\t\t:run=\"runUuid\"\n\t\t@save=\"onSave\"\n\t\t@run=\"onRun\" />\n</template>\n\n<script>\nimport CnFlowDetail from '../CnFlowDetail/CnFlowDetail.vue'\nimport CnFlowBoard from './CnFlowBoard.vue'\nimport { useFlowStore } from '../../composables/useFlowStore.js'\nimport { useLook } from '../../composables/useLook.js'\n\n/**\n * The flow canvas — manifest page type `flow-detail`.\n *\n * Mounts the shared `CnFlowDetail` node/edge canvas over OpenRegister's one\n * native flow store (ADR-065, ADR-098), scoped to the owning app. Pair it with\n * a `type: \"flows\"` page at `/flows`; this one takes `/flows/:id`.\n *\n * Controls belong in Nextcloud's app sidebar so the canvas keeps the full\n * width — declare `\"sidebarComponent\"` on the manifest page, or mount\n * `CnFlowSidebar` yourself. Canvas and sidebar share `useFlowStore`, which is\n * why neither needs props from the other.\n *\n * Manifest declaration:\n *\n * { \"id\": \"FlowDetail\", \"route\": \"/flows/:id\", \"type\": \"flow-detail\",\n * \"title\": \"Flow\", \"config\": { \"app\": \"dossiq\" } }\n */\nexport default {\n\tname: 'CnFlowEditorPage',\n\n\tcomponents: { CnFlowBoard, CnFlowDetail },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The owning app id, stamped on a flow created here so the app-scoped\n\t\t * list finds it again. Omit only on the fleet-wide surface.\n\t\t */\n\t\tapp: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The flow id to open. Defaults to the `id` route param, which is the\n\t\t * normal case; pass it explicitly only when mounting outside a route.\n\t\t * The literal `new` opens an unsaved flow.\n\t\t */\n\t\tid: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Route path the editor lives under, used to swap the URL once a new\n\t\t * flow gets its server-assigned id.\n\t\t */\n\t\tdetailRoute: {\n\t\t\ttype: String,\n\t\t\tdefault: '/flows',\n\t\t},\n\n\t\t/**\n\t\t * A run to open on arrival. Defaults to the `run` query parameter,\n\t\t * which is where a run's own address lands: `/flow-runs/{uuid}` reads\n\t\t * the run, finds its flow and redirects to `/flows/{id}?run={uuid}`.\n\t\t * Pass it explicitly only when mounting outside a route.\n\t\t */\n\t\trun: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Draw this page in the `board` look (or `nextcloud`) whatever the app\n\t\t * does. Empty follows the app's look. Manifest key `config.look`.\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: where steps come from. `picker` (default) keeps \"Add a\n\t\t * step\" in the canvas toolbar; `column` draws the palette as a card\n\t\t * beside the canvas, grouped by the app that provides each step.\n\t\t * Manifest key `config.palette`.\n\t\t */\n\t\tpalette: {\n\t\t\ttype: String,\n\t\t\tdefault: 'picker',\n\t\t},\n\n\t\t/**\n\t\t * Board look: a line under the palette card. Manifest key\n\t\t * `config.paletteFootnote`, translated with the app's catalogue.\n\t\t */\n\t\tpaletteFootnote: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: the records a test run can take as its subject,\n\t\t * `{ register, schema, labelField?, label? }`. Manifest key\n\t\t * `config.testSubject`; `label` is translated with the app's catalogue.\n\t\t */\n\t\ttestSubject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: an info notice under the path. Manifest key\n\t\t * `config.notice`, translated with the app's catalogue.\n\t\t */\n\t\tnotice: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: the pill beside the flow's name (\"Case type flow\").\n\t\t * Empty shows the lifecycle for a draft or retired flow. Manifest key\n\t\t * `config.pill`.\n\t\t */\n\t\tpill: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Board look: the list's name at the start of the path (\"Settings /\n\t\t * Flows\"). Empty reads \"Flows\". Manifest key `config.listLabel`.\n\t\t */\n\t\tlistLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\t/**\n\t * Share the one flow store with the toolbar's save/run handlers, and\n\t * resolve the look (`look` is read here, through `useLook`).\n\t *\n\t * @param {object} props The component props.\n\t * @return {object} The setup bindings.\n\t */\n\tsetup(props) {\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { store: useFlowStore(), isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * @return {string} The flow id being edited.\n\t\t */\n\t\tflowId() {\n\t\t\treturn this.id || this.$route?.params?.id || ''\n\t\t},\n\n\t\t/**\n\t\t * @return {string} The run to open on arrival, or an empty string.\n\t\t */\n\t\trunUuid() {\n\t\t\treturn this.run || this.$route?.query?.run || ''\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onSave() {\n\t\t\tconst saved = await this.store.save()\n\t\t\t// A newly created flow gets its id from the server, so the route has\n\t\t\t// to catch up or a reload would land back on `new` and lose it.\n\t\t\tif (saved?.id && this.flowId === 'new') {\n\t\t\t\tthis.$router.replace(`${this.detailRoute}/${saved.id}`)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync onRun() {\n\t\t\tawait this.store.run({})\n\t\t},\n\t},\n}\n</script>\n"],"names":["CnFlowBoard","CnFlowDetail"],"mappings":";;;;;AA8BA;AACC;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA;;AAED,aAAe;CACd,IAAI,EAAE,kBAAkB;;AAExB,CAAA,UAAU,EAAE,eAAEA,UAAW,gBAAEC,cAAc;;AAEzC,CAAA,MAAM,EAAE;AACP,EAAA,WAAW,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,KAAK,KAAK;EAC5C;;AAED,CAAA,KAAK,EAAE;AACN;;;;EAIA,GAAG,EAAE;GACJ,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,IAAI;GACb;;AAED;;;AAGC;;AAED,EAAA,EAAE,EAAE;GACH,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,WAAW,EAAE;GACZ,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,QAAQ;GACjB;;AAED;;;;;;EAMA,GAAG,EAAE;GACJ,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,IAAI,EAAE;GACL,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;;;AAMA,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,QAAQ;GACjB;;AAED;;;;AAIA,EAAA,eAAe,EAAE;GAChB,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;AAGC;;EAED,WAAW,EAAE;GACZ,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,IAAI;GACb;;AAED;;;;AAIA,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;AAGC;;EAED,IAAI,EAAE;GACL,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;;EAIA,SAAS,EAAE;GACV,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;EACD;;AAED;;;AAGC;AACA;AACA;;CAED,KAAK,CAAC,KAAK,EAAE;EACZ,MAAM,EAAE,OAAQ,EAAA,GAAI,OAAO,CAAC,KAAK,EAAA;AACjC,EAAA,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,OAAQ,EAAA;EACxC;;AAED,CAAA,QAAQ,EAAE;AACT;AACC;;AAED,EAAA,MAAM,GAAG;AACR,GAAA,OAAO,IAAI,CAAC,EAAG,IAAG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,EAAG,IAAG,EAAC;GAC9C;;AAED;;;AAGA,EAAA,OAAO,GAAG;AACT,GAAA,OAAO,IAAI,CAAC,GAAI,IAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAI,IAAG,EAAC;GAC/C;EACD;;AAED,CAAA,OAAO,EAAE;AACR;;;EAGA,MAAM,MAAM,GAAG;AACd,GAAA,MAAM,KAAM,GAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,GAAC;;;AAGpC,GAAA,IAAI,KAAK,EAAE,EAAC,IAAK,IAAI,CAAC,MAAO,KAAI,KAAK,EAAE;IACvC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,EAAA;AACvD,IAAA;GACA;;AAED;;;EAGA,MAAM,KAAK,GAAG;GACb,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAA;GACvB;EACD;AACF;;;;"}
@@ -16,9 +16,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
16
16
  paletteFootnote: $props.paletteFootnote ? $options.cnTranslate($props.paletteFootnote) : '',
17
17
  notice: $props.notice ? $options.cnTranslate($props.notice) : '',
18
18
  pill: $props.pill ? $options.cnTranslate($props.pill) : '',
19
+ testSubject: $props.testSubject ? { ...$props.testSubject, label: $props.testSubject.label ? $options.cnTranslate($props.testSubject.label) : '' } : null,
19
20
  onSave: $options.onSave,
20
21
  onRun: $options.onRun
21
- }, null, 8 /* PROPS */, ["id", "app", "run", "detailRoute", "listLabel", "palette", "paletteFootnote", "notice", "pill", "onSave", "onRun"]))
22
+ }, null, 8 /* PROPS */, ["id", "app", "run", "detailRoute", "listLabel", "palette", "paletteFootnote", "notice", "pill", "testSubject", "onSave", "onRun"]))
22
23
  : (openBlock(), createBlock(_component_CnFlowDetail, {
23
24
  key: 1,
24
25
  id: $options.flowId,