@conduction/nextcloud-vue 2.79.0 → 2.81.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 (390) hide show
  1. package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
  2. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
  3. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
  5. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  6. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +13 -11
  7. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +80 -4
  9. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +95 -91
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  12. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +179 -13
  13. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  14. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +52 -16
  15. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  16. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +96 -4
  17. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  18. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +158 -110
  19. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  20. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
  21. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
  22. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
  23. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
  24. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
  25. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
  26. package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
  27. package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
  28. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
  29. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
  30. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
  31. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
  32. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
  33. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
  34. package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
  35. package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
  36. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +1 -1
  37. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +2 -2
  40. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  41. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  42. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +65 -5
  43. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  44. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
  45. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  46. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +19 -11
  47. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  48. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
  49. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  50. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +134 -4
  51. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  52. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +21 -4
  53. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  54. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
  55. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  56. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
  57. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  58. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +1 -1
  59. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -1
  60. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -1
  61. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js +7 -7
  62. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js.map +1 -1
  63. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue3.js.map +1 -1
  64. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
  65. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
  66. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +867 -0
  67. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
  68. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
  69. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
  70. package/dist/esm/components/CnFactsWidget/index.js +30 -0
  71. package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
  72. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
  73. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
  74. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +626 -0
  75. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
  76. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +396 -0
  77. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
  78. package/dist/esm/components/CnFieldListWidget/index.js +29 -0
  79. package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
  80. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +302 -4
  81. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  82. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +417 -244
  83. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  84. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +101 -1
  85. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  86. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +141 -1
  87. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
  88. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
  89. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  90. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
  91. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  92. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +78 -3
  93. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  94. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +74 -49
  95. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  96. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +333 -73
  97. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  98. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +79 -17
  99. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  100. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
  101. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
  102. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
  103. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
  104. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
  105. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
  106. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +7 -7
  107. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  108. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  109. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +1 -1
  110. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -1
  111. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
  112. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  113. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
  114. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  115. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +63 -1
  116. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  117. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +8 -1
  118. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  119. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +14 -0
  120. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  121. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js +5 -1
  122. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  123. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
  124. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
  125. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
  126. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
  127. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
  128. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
  129. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
  130. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
  131. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
  132. package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
  133. package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
  134. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
  135. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
  136. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +411 -0
  137. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
  138. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +178 -0
  139. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
  140. package/dist/esm/components/CnRecordListWidget/index.js +31 -0
  141. package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
  142. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
  143. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
  144. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
  145. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
  146. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
  147. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
  148. package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
  149. package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
  150. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
  151. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
  152. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
  153. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
  154. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
  155. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
  156. package/dist/esm/components/CnSectionsWidget/index.js +35 -0
  157. package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
  158. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  159. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  160. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
  161. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
  162. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
  163. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
  164. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
  165. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
  166. package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
  167. package/dist/esm/components/CnSettingsFormWidget/index.js.map +1 -0
  168. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
  169. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  170. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  171. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +87 -6
  172. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  173. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
  174. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  175. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +84 -1
  176. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  177. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +85 -41
  178. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  179. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
  180. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
  181. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
  182. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
  183. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
  184. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
  185. package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
  186. package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
  187. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +168 -7
  188. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  189. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +86 -23
  190. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  191. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
  192. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  193. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
  194. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  195. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
  196. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
  197. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
  198. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
  199. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
  200. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
  201. package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
  202. package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
  203. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  204. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  205. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +7 -2
  206. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  207. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  208. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  209. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js.map +1 -1
  210. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +301 -6
  211. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  212. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +153 -55
  213. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  214. package/dist/esm/composables/useFormDraft.js +140 -9
  215. package/dist/esm/composables/useFormDraft.js.map +1 -1
  216. package/dist/esm/composables/useListView.js +4 -4
  217. package/dist/esm/composables/useListView.js.map +1 -1
  218. package/dist/esm/index.js +21 -1
  219. package/dist/esm/index.js.map +1 -1
  220. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
  221. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  222. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
  223. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  224. package/dist/esm/integrations/builtin/field-inspection.js +21 -0
  225. package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
  226. package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
  227. package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
  228. package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
  229. package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
  230. package/dist/esm/integrations/offline/index.js +2 -1
  231. package/dist/esm/integrations/offline/index.js.map +1 -1
  232. package/dist/esm/integrations/offline/offlineDb.js +6 -1
  233. package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
  234. package/dist/esm/integrations/offline/syncReplayService.js +8 -2
  235. package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
  236. package/dist/esm/l10n/en.json.js +20 -1
  237. package/dist/esm/l10n/en.json.js.map +1 -1
  238. package/dist/esm/l10n/nl.json.js +70 -2
  239. package/dist/esm/l10n/nl.json.js.map +1 -1
  240. package/dist/esm/nextcloud-vue.css +2192 -222
  241. package/dist/esm/utils/contentHeaderLink.js +51 -0
  242. package/dist/esm/utils/contentHeaderLink.js.map +1 -0
  243. package/dist/esm/utils/detailActionModel.js +60 -3
  244. package/dist/esm/utils/detailActionModel.js.map +1 -1
  245. package/dist/esm/utils/facets.js +75 -3
  246. package/dist/esm/utils/facets.js.map +1 -1
  247. package/dist/esm/utils/fetchFilterCounts.js +40 -5
  248. package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
  249. package/dist/esm/utils/fillTemplate.js +120 -0
  250. package/dist/esm/utils/fillTemplate.js.map +1 -0
  251. package/dist/esm/utils/initials.js +32 -0
  252. package/dist/esm/utils/initials.js.map +1 -0
  253. package/dist/esm/utils/libraryWidgetKeys.js +11 -0
  254. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  255. package/dist/esm/utils/objectWrite.js +59 -0
  256. package/dist/esm/utils/objectWrite.js.map +1 -0
  257. package/dist/esm/utils/pageControls.js +81 -0
  258. package/dist/esm/utils/pageControls.js.map +1 -0
  259. package/dist/esm/utils/personalLenses.js +40 -3
  260. package/dist/esm/utils/personalLenses.js.map +1 -1
  261. package/dist/esm/utils/queryPresets.js +96 -0
  262. package/dist/esm/utils/queryPresets.js.map +1 -0
  263. package/dist/esm/utils/resolveFilterTokens.js +12 -1
  264. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  265. package/dist/esm/utils/resolveManifestTokens.js +2 -0
  266. package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
  267. package/dist/esm/utils/schema.js +21 -0
  268. package/dist/esm/utils/schema.js.map +1 -1
  269. package/dist/esm/utils/sentinelTokens.js +22 -4
  270. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  271. package/dist/esm/utils/userGroupsPeek.js +91 -0
  272. package/dist/esm/utils/userGroupsPeek.js.map +1 -0
  273. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  274. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  275. package/dist/esm/utils/visibleWhen.js +57 -5
  276. package/dist/esm/utils/visibleWhen.js.map +1 -1
  277. package/dist/esm/utils/widgetDispatch.js +7 -1
  278. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  279. package/dist/esm/utils/widgetVisibility.js +4 -57
  280. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  281. package/dist/nextcloud-vue.cjs.js +19708 -9301
  282. package/dist/nextcloud-vue.cjs.js.map +2 -2
  283. package/dist/nextcloud-vue.css +2192 -222
  284. package/l10n/en.json +20 -1
  285. package/l10n/nl.json +70 -2
  286. package/package.json +2 -1
  287. package/scripts/check-docs-mdx.mjs +108 -0
  288. package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
  289. package/src/components/CnActionsBar/CnActionsBar.md +4 -0
  290. package/src/components/CnActionsBar/CnActionsBar.vue +48 -11
  291. package/src/components/CnAppRoot/CnAppRoot.md +4 -2
  292. package/src/components/CnAppRoot/CnAppRoot.vue +151 -59
  293. package/src/components/CnBannerWidget/CnBannerWidget.vue +244 -23
  294. package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
  295. package/src/components/CnCellRenderer/CnCellRenderer.vue +235 -5
  296. package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
  297. package/src/components/CnChipsFieldWidget/index.js +25 -0
  298. package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
  299. package/src/components/CnChoicePickerWidget/index.js +26 -0
  300. package/src/components/CnConversationThread/CnConversationWidget.vue +1 -1
  301. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +2 -2
  302. package/src/components/CnDashboardPage/CnDashboardPage.vue +78 -5
  303. package/src/components/CnDataTable/CnDataTable.vue +22 -12
  304. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  305. package/src/components/CnDetailPage/CnDetailPage.vue +152 -6
  306. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
  307. package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +1 -1
  308. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +7 -7
  309. package/src/components/CnFactsWidget/CnFactsWidget.vue +1190 -0
  310. package/src/components/CnFactsWidget/index.js +29 -0
  311. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +1008 -0
  312. package/src/components/CnFieldListWidget/index.js +28 -0
  313. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +588 -117
  314. package/src/components/CnFilesBrowser/filesBrowser.js +100 -0
  315. package/src/components/CnFilesBrowser/filesBrowserColumns.js +140 -0
  316. package/src/components/CnFormDialog/CnFormDialog.md +9 -3
  317. package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
  318. package/src/components/CnFormPage/CnFormPage.vue +99 -3
  319. package/src/components/CnIndexPage/CnIndexPage.vue +309 -9
  320. package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
  321. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +7 -7
  322. package/src/components/CnNextStepCard/CnNextStepWidget.vue +1 -1
  323. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
  324. package/src/components/CnObjectSidebar/CnFilesTab.vue +70 -1
  325. package/src/components/CnObjectSidebar/CnNotesTab.vue +16 -0
  326. package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
  327. package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
  328. package/src/components/CnRadioCardsWidget/index.js +27 -0
  329. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +652 -0
  330. package/src/components/CnRecordListWidget/index.js +30 -0
  331. package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
  332. package/src/components/CnSavedViewsWidget/index.js +29 -0
  333. package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
  334. package/src/components/CnSectionsWidget/index.js +34 -0
  335. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
  336. package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
  337. package/src/components/CnSettingsFormWidget/index.js +26 -0
  338. package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
  339. package/src/components/CnStatWidget/CnStatWidget.vue +88 -7
  340. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +180 -3
  341. package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
  342. package/src/components/CnSwitchRowsWidget/index.js +25 -0
  343. package/src/components/CnTabsWidget/CnTabsWidget.vue +263 -8
  344. package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
  345. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
  346. package/src/components/CnToggleTableWidget/index.js +26 -0
  347. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  348. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +7 -2
  349. package/src/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  350. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +493 -11
  351. package/src/components/index.js +19 -0
  352. package/src/composables/__tests__/useFormDraft.spec.js +69 -0
  353. package/src/composables/useFormDraft.js +139 -8
  354. package/src/composables/useListView.js +4 -4
  355. package/src/css/form-field.css +14 -0
  356. package/src/css/index-page.css +71 -0
  357. package/src/css/kpi-card.css +32 -0
  358. package/src/css/look-board-detail.css +113 -2
  359. package/src/css/look-board-index.css +90 -8
  360. package/src/css/look-board.css +109 -2
  361. package/src/css/table.css +19 -0
  362. package/src/index.js +19 -0
  363. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
  364. package/src/integrations/builtin/field-inspection.js +21 -0
  365. package/src/integrations/offline/checklistSubmission.js +137 -0
  366. package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
  367. package/src/integrations/offline/index.js +3 -0
  368. package/src/integrations/offline/offlineDb.js +6 -1
  369. package/src/integrations/offline/syncReplayService.js +8 -2
  370. package/src/schemas/app-manifest-v2.schema.json +196 -13
  371. package/src/utils/contentHeaderLink.js +48 -0
  372. package/src/utils/detailActionModel.js +59 -2
  373. package/src/utils/facets.js +74 -2
  374. package/src/utils/fetchFilterCounts.js +39 -4
  375. package/src/utils/fillTemplate.js +116 -0
  376. package/src/utils/initials.js +29 -0
  377. package/src/utils/libraryWidgetKeys.js +11 -0
  378. package/src/utils/objectWrite.js +55 -0
  379. package/src/utils/pageControls.js +78 -0
  380. package/src/utils/personalLenses.js +39 -2
  381. package/src/utils/queryPresets.js +93 -0
  382. package/src/utils/resolveFilterTokens.js +14 -1
  383. package/src/utils/resolveManifestTokens.js +2 -0
  384. package/src/utils/schema.js +21 -0
  385. package/src/utils/sentinelTokens.js +22 -4
  386. package/src/utils/userGroupsPeek.js +87 -0
  387. package/src/utils/validateManifestV2.compiled.js +3 -3
  388. package/src/utils/visibleWhen.js +56 -4
  389. package/src/utils/widgetDispatch.js +7 -1
  390. package/src/utils/widgetVisibility.js +7 -56
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="cn-index-page"
3
- :class="lookClass"
3
+ :class="[lookClass, { 'cn-index-page--with-side-panel': hasSidePanel }]"
4
4
  data-testid="cn-index-page"
5
5
  @keydown="onListKeydown">
6
6
  <!-- Header — overridable via #header slot. CnPageHeader ALWAYS renders:
@@ -76,6 +76,20 @@
76
76
  <slot name="below-header" />
77
77
  </div>
78
78
 
79
+ <!-- KPI tiles above the list (`statRow`) and cards beside it
80
+ (`sidePanel`), as DqTeamwachtrij and PqContracten
81
+ (screens-index-stat-row). -->
82
+ <CnIndexPageWidgets
83
+ v-if="statRow && statRow.length > 0"
84
+ class="cn-index-page__stat-row"
85
+ variant="stat-row"
86
+ :widgets="statRow" />
87
+ <CnIndexPageWidgets
88
+ v-if="hasSidePanel"
89
+ class="cn-index-page__side-panel"
90
+ variant="side-panel"
91
+ :widgets="sidePanel" />
92
+
79
93
  <!-- Actions bar -->
80
94
  <CnActionsBar
81
95
  :layout="isBoardLook ? 'board' : 'nextcloud'"
@@ -97,6 +111,7 @@
97
111
  :viewMode="currentViewMode"
98
112
  :showViewToggle="showViewToggle"
99
113
  :availableViewModes="effectiveToggleModes"
114
+ :disabledViewModes="viewSwitchDisabledModes"
100
115
  :cardsLabel="cardsLabel"
101
116
  :tableLabel="tableLabel"
102
117
  :listLabel="listLabel"
@@ -248,6 +263,31 @@
248
263
  @update:activeIndex="onQuickFilterChange"
249
264
  @update:selectedIndices="onQuickFilterMultiChange" />
250
265
  </template>
266
+ <!-- Board look, `filterMenu` on a page with no filter sidebar: the
267
+ board's Filter button, a menu of each enum column's values as
268
+ toggleable filters. -->
269
+ <template v-if="boardFilterMenu" #filter-menu>
270
+ <NcActions
271
+ class="cn-actions-bar__filter-menu"
272
+ variant="secondary"
273
+ :forceMenu="true"
274
+ :menuName="t('nextcloud-vue', 'Filter')"
275
+ data-testid="cn-index-filter-menu">
276
+ <template #icon>
277
+ <Tune :size="16" />
278
+ </template>
279
+ <template v-for="field in filterableFields" :key="field.key">
280
+ <NcActionCaption :name="field.label" />
281
+ <NcActionCheckbox
282
+ v-for="val in field.values"
283
+ :key="`${field.key}-${val}`"
284
+ :modelValue="isFilterActive(field.key, val)"
285
+ @update:modelValue="toggleFilter(field.key, val)">
286
+ {{ val }}
287
+ </NcActionCheckbox>
288
+ </template>
289
+ </NcActions>
290
+ </template>
251
291
  </CnActionsBar>
252
292
 
253
293
  <!-- Quick edit: a few fields of one row, over the list, with the list
@@ -610,10 +650,10 @@
610
650
  the column menu lists every governed column as a visibility
611
651
  checkbox — compact, in-table alternatives to the sidebar. -->
612
652
  <template
613
- v-if="(filterMenu && filterableFields.length) || (columnMenu && governedColumns.length)"
653
+ v-if="(showHeaderFilterMenu) || (columnMenu && governedColumns.length)"
614
654
  #actions-header>
615
655
  <NcActions
616
- v-if="filterMenu && filterableFields.length"
656
+ v-if="showHeaderFilterMenu"
617
657
  :forceMenu="true"
618
658
  :aria-label="t('nextcloud-vue', 'Filter')">
619
659
  <template #icon>
@@ -953,12 +993,14 @@ import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
953
993
  import Export from 'vue-material-design-icons/Export.vue'
954
994
  import Eye from 'vue-material-design-icons/Eye.vue'
955
995
  import FilterOutline from 'vue-material-design-icons/FilterOutline.vue'
996
+ import Tune from 'vue-material-design-icons/Tune.vue'
956
997
  import ViewColumnOutline from 'vue-material-design-icons/ViewColumnOutline.vue'
957
998
  import CnConfirmDialog from '../../dialogs/CnConfirmDialog.vue'
958
999
  import CnQuickEditDialog from '../../dialogs/CnQuickEditDialog.vue'
959
1000
  import CnBuildiqEditButton from '../CnBuildiqEditButton/CnBuildiqEditButton.vue'
960
1001
  import CnEmptyContent from '../CnEmptyContent/CnEmptyContent.vue'
961
1002
  import CnFollowToggle from '../CnFollowToggle/CnFollowToggle.vue'
1003
+ import CnIndexPageWidgets from './CnIndexPageWidgets.vue'
962
1004
  import { useContextMenu } from '../../composables/index.js'
963
1005
  import { useLook } from '../../composables/useLook.js'
964
1006
  import { copyKindsOf } from '../../composables/useObjectCopy.js'
@@ -1243,6 +1285,7 @@ export default {
1243
1285
  name: 'CnIndexPage',
1244
1286
 
1245
1287
  components: {
1288
+ CnIndexPageWidgets,
1246
1289
  CnBuildiqEditButton,
1247
1290
  CnFollowToggle,
1248
1291
  NcLoadingIcon,
@@ -1258,6 +1301,7 @@ export default {
1258
1301
  DatabaseSearch,
1259
1302
  Export,
1260
1303
  FilterOutline,
1304
+ Tune,
1261
1305
  ViewColumnOutline,
1262
1306
  NcCheckboxRadioSwitch,
1263
1307
  CnPageHeader,
@@ -1439,7 +1483,6 @@ export default {
1439
1483
  default: true,
1440
1484
  },
1441
1485
 
1442
- // eslint-disable-next-line vue/no-unused-properties
1443
1486
  /**
1444
1487
  * Draw this page in the `board` look (or `nextcloud`) whatever the app
1445
1488
  * does. Empty follows the `cnLook` CnAppRoot provides. Manifest key
@@ -1587,7 +1630,13 @@ export default {
1587
1630
  * `$route.params` just like the `filter` prop. The first tab with
1588
1631
  * `default:true` (else index 0) is active on mount; changing tabs
1589
1632
  * re-fetches at page 1. Omit (or `null`) → no tab strip, behaviour
1590
- * unchanged.
1633
+ * unchanged. Under the board look a tab with `activeLabel` ("Pipeline:
1634
+ * Sales") adds a removable chip with that text to the Active line and
1635
+ * counts on the Filter badge while it is selected; removing the chip
1636
+ * goes back to the default tab. A tab can say `empty: "field"` (or a
1637
+ * list of fields) for the rows where the field has no value, and
1638
+ * `notEmpty` for the rows where it has one: it reads as the filter
1639
+ * `{ field: { isnull: true } }`.
1591
1640
  */
1592
1641
  quickFilters: {
1593
1642
  type: Array,
@@ -1958,6 +2007,22 @@ export default {
1958
2007
  default: null,
1959
2008
  },
1960
2009
 
2010
+ /**
2011
+ * Board look: the segments the view switch draws, e.g. `['table',
2012
+ * 'cards', 'board', 'map']` as the boards do. A listed mode the page
2013
+ * can open is an ordinary segment; one it cannot (no board columns, no
2014
+ * map configured) is drawn disabled, named "<mode>: not available on
2015
+ * this list". Fed from `pages[].config.viewSwitch`. Ignored without the
2016
+ * board look, and absent the switch is as before.
2017
+ *
2018
+ * @type {Array<'table' | 'cards' | 'board' | 'map'>}
2019
+ * @spec openspec/changes/screens-view-switch-parity/specs/view-switch-board-look/spec.md#requirement-the-manifest-can-draw-segments-the-page-cannot-open
2020
+ */
2021
+ viewSwitch: {
2022
+ type: Array,
2023
+ default: null,
2024
+ },
2025
+
1961
2026
  /**
1962
2027
  * The board's configuration, mirroring the manifest `config.board`
1963
2028
  * block: `{ statusField, cardFields, swimlaneField }`. The board is
@@ -2644,6 +2709,35 @@ export default {
2644
2709
  default: null,
2645
2710
  },
2646
2711
 
2712
+ /**
2713
+ * KPI tiles above the list (manifest `config.statRow`): dashboard
2714
+ * widget definitions `{ id, type, title?, content }`, usually `stat`,
2715
+ * drawn in an auto-fit row (each at least 200px) in the listed order.
2716
+ * Types resolve like dashboard widgets: the app registry, then the
2717
+ * dashboard catalog. Empty by default.
2718
+ *
2719
+ * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-stat-row-above-the-list
2720
+ * @type {Array<object>}
2721
+ */
2722
+ statRow: {
2723
+ type: Array,
2724
+ default: () => [],
2725
+ },
2726
+
2727
+ /**
2728
+ * Cards beside the list (manifest `config.sidePanel`): dashboard
2729
+ * widget definitions `{ id, type, title?, content, headerLink? }`
2730
+ * drawn in a 300px column right of the toolbar and the list. Empty
2731
+ * by default; below 1024px the column moves above the list.
2732
+ *
2733
+ * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-side-panel-beside-the-list
2734
+ * @type {Array<object>}
2735
+ */
2736
+ sidePanel: {
2737
+ type: Array,
2738
+ default: () => [],
2739
+ },
2740
+
2647
2741
  /**
2648
2742
  * Where a row carries the actions the server says this caller may run
2649
2743
  * on it: a dotted path, read off the rows the list already fetched, so
@@ -2827,6 +2921,8 @@ export default {
2827
2921
  * Show a filter menu (funnel button) in the table header, above the
2828
2922
  * row-actions column. Its menu lists every enum/badge column's values as
2829
2923
  * toggleable facet filters — a compact alternative to the facet sidebar.
2924
+ * Under the board look, on a page with no filter sidebar, it is the
2925
+ * toolbar's labelled Filter button instead (row 1, before the view switch).
2830
2926
  * Fed from the manifest as `pages[].config.filterMenu`.
2831
2927
  */
2832
2928
  filterMenu: {
@@ -3323,6 +3419,16 @@ export default {
3323
3419
  },
3324
3420
 
3325
3421
  computed: {
3422
+ /**
3423
+ * Whether the page draws cards beside its list (`sidePanel`).
3424
+ *
3425
+ * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-side-panel-beside-the-list
3426
+ * @return {boolean}
3427
+ */
3428
+ hasSidePanel() {
3429
+ return Array.isArray(this.sidePanel) && this.sidePanel.length > 0
3430
+ },
3431
+
3326
3432
  /**
3327
3433
  * The empty-state copy run through the host translate function
3328
3434
  * (the injected `cnTranslate`, identity by default). Only this
@@ -3695,6 +3801,21 @@ export default {
3695
3801
  return Object.keys(this.mapConfig || {}).length > 0
3696
3802
  },
3697
3803
 
3804
+ /**
3805
+ * Board look: the modes `viewSwitch` lists that this page cannot open,
3806
+ * drawn as disabled segments.
3807
+ *
3808
+ * @return {Array<string>} The disabled modes.
3809
+ * @spec openspec/changes/screens-view-switch-parity/specs/view-switch-board-look/spec.md#requirement-the-manifest-can-draw-segments-the-page-cannot-open
3810
+ */
3811
+ viewSwitchDisabledModes() {
3812
+ if (!this.isBoardLook || !Array.isArray(this.viewSwitch)) {
3813
+ return []
3814
+ }
3815
+ const offered = [...this.effectiveToggleModes, ...(this.showMapSegment ? ['map'] : [])]
3816
+ return this.viewSwitch.filter((mode) => ['table', 'cards', 'board', 'map'].includes(mode) && !offered.includes(mode))
3817
+ },
3818
+
3698
3819
  /**
3699
3820
  * The base view-toggle segments (cards/table/list) passed to CnActionsBar.
3700
3821
  * Beta's explicit `viewModes` whitelist wins when set; otherwise the
@@ -5264,11 +5385,11 @@ export default {
5264
5385
  return []
5265
5386
  }
5266
5387
  const props = this.effectiveSchema?.properties || {}
5267
- const chips = []
5388
+ const chips = [...this.quickFilterActiveChips]
5268
5389
  for (const [key, raw] of Object.entries(this.effectiveActiveFilters || {})) {
5269
5390
  const values = (Array.isArray(raw) ? raw : [raw])
5270
5391
  .filter((value) => value !== null && value !== undefined && value !== '')
5271
- .map((value) => String(value))
5392
+ .map((value) => this.activeFilterValueLabel(key, value))
5272
5393
  if (values.length === 0) {
5273
5394
  continue
5274
5395
  }
@@ -5278,6 +5399,87 @@ export default {
5278
5399
  return chips
5279
5400
  },
5280
5401
 
5402
+ /**
5403
+ * The Active line's chips for the selected quick filters: one per
5404
+ * selected tab that declares an `activeLabel` ("Pipeline: Sales"), run
5405
+ * through the app's translate. A tab without one (an "All" tab) adds no
5406
+ * chip. The chip carries the tab's index so removing it can deselect it.
5407
+ *
5408
+ * @spec openspec/changes/screens-active-filter-line-parity/specs/active-filter-line-board-look/spec.md#requirement-a-quick-filter-with-an-active-label-joins-the-active-line
5409
+ * @return {Array<{key: string, label: string, quickFilterIndex: number}>}
5410
+ */
5411
+ quickFilterActiveChips() {
5412
+ const tabs = this.tabStripEntries || []
5413
+ if (tabs.length === 0) {
5414
+ return []
5415
+ }
5416
+ const indices = this.quickFilterMultiple
5417
+ ? (this.selectedQuickFilterIndices || [])
5418
+ : [this.activeQuickFilterIndex]
5419
+ return indices
5420
+ .filter((index) => typeof index === 'number' && tabs[index] && typeof tabs[index].activeLabel === 'string' && tabs[index].activeLabel !== '')
5421
+ .map((index) => ({ key: `quick-filter:${index}`, label: this.cnTranslate(tabs[index].activeLabel), quickFilterIndex: index }))
5422
+ },
5423
+
5424
+ /**
5425
+ * Filter keys over a reference property that the Active line must name,
5426
+ * and that no reference column resolves already: one spec each, with the
5427
+ * referenced register and schema off the page schema's `$ref`.
5428
+ *
5429
+ * @spec openspec/changes/screens-active-filter-line-parity/specs/active-filter-line-board-look/spec.md#requirement-an-active-chip-names-the-value-not-its-id
5430
+ * @return {Array<{key: string, labelField: string, register: string, schema: string}>}
5431
+ */
5432
+ activeFilterRefSpecs() {
5433
+ if (!this.isBoardLook || !this.effectiveSchema) {
5434
+ return []
5435
+ }
5436
+ const keys = Object.keys(this.effectiveActiveFilters || {})
5437
+ if (keys.length === 0) {
5438
+ return []
5439
+ }
5440
+ const covered = new Set(this.refLabelSpecs.map((spec) => spec.key))
5441
+ const fields = fieldsFromSchema(this.effectiveSchema, { includeReadOnly: true })
5442
+ const specs = []
5443
+ for (const key of keys) {
5444
+ if (covered.has(key)) {
5445
+ continue
5446
+ }
5447
+ const field = fields.find((f) => f.key === key)
5448
+ const ref = field && field.reference
5449
+ if (!ref || ref.schema === undefined || ref.schema === null) {
5450
+ continue
5451
+ }
5452
+ specs.push({
5453
+ key,
5454
+ labelField: '',
5455
+ register: ref.register || (typeof this.register === 'string' ? this.register : ''),
5456
+ schema: String(ref.schema),
5457
+ })
5458
+ }
5459
+ return specs
5460
+ },
5461
+
5462
+ /**
5463
+ * The ids each active reference filter holds, per filter key, for the
5464
+ * label lookup of the Active line.
5465
+ *
5466
+ * @return {{[key: string]: string[]}} Distinct ids per filter key.
5467
+ */
5468
+ activeFilterRefIds() {
5469
+ const out = {}
5470
+ const keys = new Set([...this.refLabelSpecs, ...this.activeFilterRefSpecs].map((spec) => spec.key))
5471
+ for (const [key, raw] of Object.entries(this.effectiveActiveFilters || {})) {
5472
+ if (!keys.has(key)) {
5473
+ continue
5474
+ }
5475
+ out[key] = (Array.isArray(raw) ? raw : [raw])
5476
+ .filter((id) => id !== null && id !== undefined && id !== '' && typeof id !== 'object')
5477
+ .map((id) => String(id))
5478
+ .sort()
5479
+ }
5480
+ return out
5481
+ },
5482
+
5281
5483
  /**
5282
5484
  * The plural the board bulk band names: "With the selected cases".
5283
5485
  * The schema's `titlePlural` (or `plural`), else the lower-cased
@@ -5435,6 +5637,27 @@ export default {
5435
5637
  return !!this.resolvedSidebar.enabled && this.resolvedSidebar.show !== false
5436
5638
  },
5437
5639
 
5640
+ /**
5641
+ * Whether the board toolbar draws the Filter button as a menu: the
5642
+ * board look, `filterMenu` on, something to filter by, and no filter
5643
+ * sidebar (whose toggle is that button otherwise).
5644
+ *
5645
+ * @return {boolean}
5646
+ */
5647
+ boardFilterMenu() {
5648
+ return this.isBoardLook && this.filterMenu && !this.hasSidebar && this.filterableFields.length > 0
5649
+ },
5650
+
5651
+ /**
5652
+ * Whether the funnel menu sits in the table header: `filterMenu` with
5653
+ * values to offer, unless the toolbar's Filter button is that menu.
5654
+ *
5655
+ * @return {boolean}
5656
+ */
5657
+ showHeaderFilterMenu() {
5658
+ return this.filterMenu && this.filterableFields.length > 0 && !this.boardFilterMenu
5659
+ },
5660
+
5438
5661
  /** Search props forwarded to the embedded CnIndexSidebar (defaults applied per CnIndexSidebar). */
5439
5662
  sidebarSearchProps() {
5440
5663
  return (this.sidebar && this.sidebar.search) || {}
@@ -5558,6 +5781,14 @@ export default {
5558
5781
  },
5559
5782
  },
5560
5783
 
5784
+ // The Active line names a referenced value, not its id.
5785
+ activeFilterRefIds: {
5786
+ deep: true,
5787
+ handler() {
5788
+ this.loadRefLabels()
5789
+ },
5790
+ },
5791
+
5561
5792
  countRequestKey: {
5562
5793
  immediate: true,
5563
5794
  /** @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-counts-on-filters-and-views */
@@ -5826,7 +6057,7 @@ export default {
5826
6057
  * @spec openspec/changes/index-ref-column-labels/tasks.md#task-2
5827
6058
  */
5828
6059
  async loadRefLabels() {
5829
- const specs = this.refLabelSpecs
6060
+ const specs = [...this.refLabelSpecs, ...this.activeFilterRefSpecs]
5830
6061
  if (specs.length === 0) {
5831
6062
  return
5832
6063
  }
@@ -5841,7 +6072,8 @@ export default {
5841
6072
  }
5842
6073
  await Promise.all(specs.map(async (spec) => {
5843
6074
  const known = this.refLabels[spec.key] || {}
5844
- const ids = (this.refLabelIds[spec.key] || []).filter((id) => !Object.hasOwn(known, id))
6075
+ const wanted = new Set([...(this.refLabelIds[spec.key] || []), ...(this.activeFilterRefIds[spec.key] || [])])
6076
+ const ids = [...wanted].filter((id) => !Object.hasOwn(known, id))
5845
6077
  if (ids.length === 0) {
5846
6078
  return
5847
6079
  }
@@ -6525,6 +6757,11 @@ export default {
6525
6757
  * @return {void}
6526
6758
  */
6527
6759
  onClearFilters() {
6760
+ // "Clear all" on the Active line also undoes the quick filters it
6761
+ // listed (a tab without an `activeLabel` is not a filter there).
6762
+ for (const chip of this.quickFilterActiveChips) {
6763
+ this.deselectQuickFilterChip(chip.quickFilterIndex)
6764
+ }
6528
6765
  // Clearing the view brings the person's own columns back.
6529
6766
  this.appliedViewColumns = null
6530
6767
  this.appliedSavedViewId = ''
@@ -6615,11 +6852,74 @@ export default {
6615
6852
  * @spec openspec/changes/screens-index-list-parity/specs/index-list-board-look/spec.md#requirement-the-toolbar-sits-on-the-ground-in-two-rows
6616
6853
  */
6617
6854
  onRemoveActiveFilter(chip) {
6855
+ if (chip && typeof chip.quickFilterIndex === 'number') {
6856
+ this.deselectQuickFilterChip(chip.quickFilterIndex)
6857
+ return
6858
+ }
6618
6859
  if (chip && typeof chip.key === 'string') {
6619
6860
  this.onFilterEvent({ key: chip.key, values: [] })
6620
6861
  }
6621
6862
  },
6622
6863
 
6864
+ /**
6865
+ * Undo a quick filter from the Active line. With several tabs selectable
6866
+ * the tab leaves the selection; with one, the page goes back to its
6867
+ * default tab when that tab names no active filter itself, and else to no
6868
+ * tab at all, so the chip does not come straight back.
6869
+ *
6870
+ * @param {number} index The tab index the chip stands for.
6871
+ * @return {void}
6872
+ * @spec openspec/changes/screens-active-filter-line-parity/specs/active-filter-line-board-look/spec.md#requirement-a-quick-filter-with-an-active-label-joins-the-active-line
6873
+ */
6874
+ deselectQuickFilterChip(index) {
6875
+ if (this.quickFilterMultiple) {
6876
+ this.onQuickFilterMultiChange((this.selectedQuickFilterIndices || []).filter((i) => i !== index))
6877
+ return
6878
+ }
6879
+ if (this.activeQuickFilterIndex !== index) {
6880
+ return
6881
+ }
6882
+ const tabs = this.tabStripEntries || []
6883
+ let fallback = tabs.findIndex((tab) => tab && tab.default === true)
6884
+ if (fallback < 0 && tabs.length > 0) {
6885
+ fallback = 0
6886
+ }
6887
+ const fallbackNamed = fallback >= 0 && typeof tabs[fallback].activeLabel === 'string' && tabs[fallback].activeLabel !== ''
6888
+ this.onQuickFilterChange(fallback >= 0 && fallback !== index && !fallbackNamed ? fallback : null)
6889
+ },
6890
+
6891
+ /**
6892
+ * The text an Active chip shows for one filter value: the referenced
6893
+ * object's label, the facet bucket's label, the schema's `oneOf` title,
6894
+ * else the value itself.
6895
+ *
6896
+ * @param {string} key The filter key.
6897
+ * @param {unknown} value One value of that filter.
6898
+ * @return {string} The label.
6899
+ * @spec openspec/changes/screens-active-filter-line-parity/specs/active-filter-line-board-look/spec.md#requirement-an-active-chip-names-the-value-not-its-id
6900
+ */
6901
+ activeFilterValueLabel(key, value) {
6902
+ const id = String(value)
6903
+ const refs = this.refLabels[key]
6904
+ if (refs && typeof refs[id] === 'string' && refs[id] !== '') {
6905
+ return refs[id]
6906
+ }
6907
+ const facet = this.effectiveFacetData && this.effectiveFacetData[key]
6908
+ const bucket = facet && Array.isArray(facet.values)
6909
+ ? facet.values.find((fv) => fv && typeof fv === 'object' && String(fv.value) === id)
6910
+ : null
6911
+ if (bucket && typeof bucket.label === 'string' && bucket.label !== '') {
6912
+ return this.cnTranslate(bucket.label)
6913
+ }
6914
+ const prop = this.effectiveSchema?.properties?.[key]
6915
+ const options = prop && Array.isArray(prop.oneOf) ? prop.oneOf : []
6916
+ const option = options.find((o) => o && String(o.const) === id && typeof o.title === 'string')
6917
+ if (option) {
6918
+ return this.cnTranslate(option.title)
6919
+ }
6920
+ return id
6921
+ },
6922
+
6623
6923
  /**
6624
6924
  * A header filter was applied or cleared. One column can own several
6625
6925
  * query parameters (a range is `key[gte]` and `key[lte]`), so they are
@@ -0,0 +1,169 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ SPDX-License-Identifier: EUPL-1.2
4
+
5
+ CnIndexPageWidgets — the widgets an index page draws around its list
6
+ (screens-index-stat-row): the KPI tiles above it (`statRow`, an auto-fit row)
7
+ and the cards beside it (`sidePanel`, a column). Each entry is a dashboard
8
+ widget definition `{ id, type, title?, content, headerLink? }`, resolved like
9
+ a dashboard widget: the app's registry, then the dashboard catalog, then the
10
+ built-in widgets. Internal to CnIndexPage.
11
+ -->
12
+ <template>
13
+ <component
14
+ :is="variant === 'stat-row' ? 'CnKpiGrid' : 'aside'"
15
+ v-if="entries.length > 0"
16
+ :columns="variant === 'stat-row' ? 'auto' : undefined"
17
+ class="cn-index-page-widgets"
18
+ :class="['cn-index-page-widgets--' + variant]"
19
+ :data-testid="'cn-index-page-' + variant">
20
+ <div
21
+ v-for="entry in entries"
22
+ :key="entry.id"
23
+ class="cn-index-page-widgets__cell"
24
+ :data-testid="'cn-index-page-widget-' + entry.id">
25
+ <CnWidgetWrapper
26
+ :widgetId="entry.id"
27
+ :title="entry.title"
28
+ :showTitle="variant === 'side-panel' && entry.title !== ''"
29
+ :showActions="false"
30
+ :showRefresh="false"
31
+ :headerLink="entry.headerLink"
32
+ :flush="variant === 'stat-row'">
33
+ <component
34
+ :is="entry.renderer"
35
+ :widgetId="entry.id"
36
+ :content="entry.content"
37
+ v-bind="entry.content" />
38
+ </CnWidgetWrapper>
39
+ </div>
40
+ </component>
41
+ </template>
42
+
43
+ <script>
44
+ import CnKpiGrid from '../CnKpiGrid/CnKpiGrid.vue'
45
+ import CnWidgetWrapper from '../CnWidgetWrapper/CnWidgetWrapper.vue'
46
+ import { canonicalWidgetType } from '../../utils/widgetTypeAliases.js'
47
+ import { BUILT_IN_WIDGETS } from '../CnWidgetGrid/builtInWidgets.js'
48
+ import { getWidgetTypeEntry } from '../CnWidgetGrid/dashboardWidgetRegistry.js'
49
+
50
+ // Populate the dashboard catalog (stat, table, people, …): an index page
51
+ // may be the first surface that resolves a widget type.
52
+ import '../CnWidgetGrid/registerDashboardWidgets.js'
53
+
54
+ export default {
55
+ name: 'CnIndexPageWidgets',
56
+
57
+ components: {
58
+ CnKpiGrid,
59
+ CnWidgetWrapper,
60
+ },
61
+
62
+ inject: {
63
+ /** Consumer widget registry provided by CnAppRoot (custom over built-in). */
64
+ cnRegistry: { default: () => ({}) },
65
+ /** Host translate function provided by CnAppRoot. */
66
+ cnTranslate: { default: () => (key) => key },
67
+ },
68
+
69
+ props: {
70
+ /**
71
+ * Widget definitions `{ id, type, title?, content?, headerLink? }`.
72
+ * An entry without an id or with a type no layer resolves is skipped.
73
+ */
74
+ widgets: {
75
+ type: Array,
76
+ default: () => [],
77
+ },
78
+
79
+ /** Where the widgets sit: `stat-row` above the list, `side-panel` beside it. */
80
+ variant: {
81
+ type: String,
82
+ default: 'stat-row',
83
+ validator: (v) => ['stat-row', 'side-panel'].includes(v),
84
+ },
85
+ },
86
+
87
+ computed: {
88
+ /**
89
+ * The renderable entries, in the listed order.
90
+ *
91
+ * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-stat-row-above-the-list
92
+ * @return {Array<{id: string, title: string, content: object, headerLink: (object|null), renderer: object}>}
93
+ */
94
+ entries() {
95
+ const list = Array.isArray(this.widgets) ? this.widgets : []
96
+ const out = []
97
+ for (const def of list) {
98
+ if (!def || typeof def.id !== 'string' || def.id === '' || typeof def.type !== 'string') {
99
+ continue
100
+ }
101
+ const renderer = this.resolveRenderer(def.type)
102
+ if (!renderer) {
103
+ if (process.env.NODE_ENV !== 'production') {
104
+ // eslint-disable-next-line no-console
105
+ console.warn(`[CnIndexPage] ${this.variant} widget "${def.id}" has type "${def.type}", which no widget registry resolves; skipped.`)
106
+ }
107
+ continue
108
+ }
109
+ const translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key
110
+ out.push({
111
+ id: def.id,
112
+ title: typeof def.title === 'string' && def.title !== '' ? translate(def.title) : '',
113
+ content: (def.content && typeof def.content === 'object') ? def.content : {},
114
+ headerLink: (def.headerLink && typeof def.headerLink === 'object') ? def.headerLink : null,
115
+ renderer,
116
+ })
117
+ }
118
+ return out
119
+ },
120
+ },
121
+
122
+ methods: {
123
+ /**
124
+ * Resolve a widget type: the consumer registry, then the dashboard
125
+ * catalog (the type as written, then its alias), then the built-ins.
126
+ *
127
+ * @param {string} type The widget type.
128
+ * @return {object|null} The component, or null.
129
+ */
130
+ resolveRenderer(type) {
131
+ const consumer = (this.cnRegistry || {})[type]
132
+ if (consumer) {
133
+ return consumer.component ?? consumer
134
+ }
135
+ const entry = getWidgetTypeEntry(type) || getWidgetTypeEntry(canonicalWidgetType(type))
136
+ if (entry && entry.renderer) {
137
+ return entry.renderer
138
+ }
139
+ return BUILT_IN_WIDGETS[type] || BUILT_IN_WIDGETS[canonicalWidgetType(type)] || null
140
+ },
141
+ },
142
+ }
143
+ </script>
144
+
145
+ <style scoped>
146
+ .cn-index-page-widgets--stat-row {
147
+ margin-bottom: var(--cn-board-section-gap, 20px);
148
+ }
149
+
150
+ .cn-index-page-widgets__cell {
151
+ display: flex;
152
+ min-width: 0;
153
+ }
154
+
155
+ .cn-index-page-widgets__cell > * {
156
+ flex: 1 1 auto;
157
+ min-width: 0;
158
+ }
159
+
160
+ /* The side panel column (DqTeamwachtrij: 300px, 16px between cards). Its
161
+ place beside the toolbar and the list is set by CnIndexPage
162
+ (`cn-index-page--with-side-panel`, index-page.css). */
163
+ .cn-index-page-widgets--side-panel {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 16px;
167
+ min-width: 0;
168
+ }
169
+ </style>
@@ -270,7 +270,7 @@ import Pin from 'vue-material-design-icons/Pin.vue'
270
270
  import PinOutline from 'vue-material-design-icons/PinOutline.vue'
271
271
  import ViewColumnOutline from 'vue-material-design-icons/ViewColumnOutline.vue'
272
272
  import { METADATA_COLUMNS } from '../../constants/metadata.js'
273
- import { facetOptionLabel } from '../../utils/facets.js'
273
+ import { facetOptions } from '../../utils/facets.js'
274
274
  import { labelLang } from '../../utils/manifestTranslate.js'
275
275
  import { columnsFromSchema, filtersFromSchema } from '../../utils/schema.js'
276
276
  import { CnDateRangePicker, DEFAULT_DATE_RANGE_PRESETS } from '../CnDateRangePicker/index.js'
@@ -867,12 +867,12 @@ export default {
867
867
  * @param {object} filter Filter object
868
868
  */
869
869
  getFilterOptions(filter) {
870
- const facet = this.facetData[filter.key]
871
- if (facet?.values?.length > 0) {
872
- return facet.values.map((v) => ({
873
- id: v.value,
874
- label: facetOptionLabel(v),
875
- }))
870
+ const live = facetOptions(
871
+ this.facetData[filter.key],
872
+ (count) => t('nextcloud-vue', 'No value ({count})', { count }),
873
+ )
874
+ if (live !== null) {
875
+ return live
876
876
  }
877
877
  // A reference picker's rows come from another list, and neither a
878
878
  // schema enum nor a facet bucket can carry them.
@@ -21,7 +21,7 @@ import { resolveNextStep } from '../../utils/detailActionModel.js'
21
21
  * Renders CnNextStepCard for the bound record's stage from
22
22
  * `content: { field?, stages: { <stage>: { title?, checklist, after? } } }`.
23
23
  * The checklist only: the page's own primary button stays where the page
24
- * puts it. Resolved by its registry key, not exported.
24
+ * puts it. Resolved by its registry key, and exported for an app that renders it itself.
25
25
  */
26
26
  export default {
27
27
  name: 'CnNextStepWidget',