@conduction/nextcloud-vue 2.56.0-beta.36 → 2.56.0-beta.38

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 (382) hide show
  1. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  2. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +131 -3
  3. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +54 -18
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue.js +1 -1
  7. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js +3 -2
  8. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js.map +1 -1
  9. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue3.js.map +1 -1
  10. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
  11. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +5 -4
  12. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
  13. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
  14. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue.js +1 -1
  15. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js +2 -1
  16. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js.map +1 -1
  17. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue3.js.map +1 -1
  18. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  19. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +2 -1
  20. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  21. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  22. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  23. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +376 -6
  24. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  25. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +146 -71
  26. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  27. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue.js +1 -1
  28. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js +2 -1
  29. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js.map +1 -1
  30. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue3.js.map +1 -1
  31. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue.js +1 -1
  32. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +2 -1
  33. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
  34. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
  35. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  36. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +6 -5
  37. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue.js +1 -1
  40. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js +2 -1
  41. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js.map +1 -1
  42. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue3.js.map +1 -1
  43. package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +1 -1
  44. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js +2 -1
  45. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -1
  46. package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -1
  47. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
  48. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +2 -1
  49. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
  50. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
  51. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  52. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +47 -1
  53. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  54. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -12
  55. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  56. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue.js +1 -1
  57. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js +3 -1
  58. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js.map +1 -1
  59. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue3.js.map +1 -1
  60. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js +2 -1
  61. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js.map +1 -1
  62. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue3.js.map +1 -1
  63. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +23 -4
  64. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  66. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  67. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +3 -1
  68. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  69. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  70. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue.js +1 -1
  71. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js +2 -1
  72. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js.map +1 -1
  73. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue3.js.map +1 -1
  74. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  75. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +18 -5
  76. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  77. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  78. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue.js +1 -1
  79. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js +3 -1
  80. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js.map +1 -1
  81. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue3.js.map +1 -1
  82. package/dist/esm/components/CnFileManager/CnFileManager.vue.js +1 -1
  83. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js +3 -1
  84. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js.map +1 -1
  85. package/dist/esm/components/CnFileManager/CnFileManager.vue3.js.map +1 -1
  86. package/dist/esm/components/CnFilePreview/CnFilePreview.vue.js +1 -1
  87. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js +2 -1
  88. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js.map +1 -1
  89. package/dist/esm/components/CnFilePreview/CnFilePreview.vue3.js.map +1 -1
  90. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  91. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +49 -1
  92. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  93. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +3 -3
  94. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  95. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue.js +1 -1
  96. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +2 -1
  97. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
  98. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
  99. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +571 -77
  100. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  101. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +191 -82
  102. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  103. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +11 -2
  104. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  105. package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
  106. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +2 -1
  107. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
  108. package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
  109. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue.js +1 -1
  110. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js +3 -2
  111. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js.map +1 -1
  112. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue3.js.map +1 -1
  113. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
  114. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +28 -0
  115. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  116. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +82 -75
  117. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  118. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue.js +1 -1
  119. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js +5 -4
  120. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js.map +1 -1
  121. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue3.js.map +1 -1
  122. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue.js +1 -1
  123. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js +2 -1
  124. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js.map +1 -1
  125. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue3.js.map +1 -1
  126. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue.js +1 -1
  127. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js +2 -1
  128. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js.map +1 -1
  129. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue3.js.map +1 -1
  130. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue.js +1 -1
  131. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +2 -1
  132. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  133. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  134. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue.js +1 -1
  135. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js +2 -1
  136. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js.map +1 -1
  137. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue3.js.map +1 -1
  138. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue.js +1 -1
  139. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js +2 -1
  140. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js.map +1 -1
  141. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue3.js.map +1 -1
  142. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  143. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +70 -2
  144. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  145. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  146. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
  147. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +67 -5
  148. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
  149. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +181 -124
  150. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
  151. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue.js +1 -1
  152. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js +2 -1
  153. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js.map +1 -1
  154. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue3.js.map +1 -1
  155. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js +2 -0
  156. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js.map +1 -1
  157. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js +2 -2
  158. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js.map +1 -1
  159. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  160. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +5 -1
  161. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  162. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  163. package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
  164. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +134 -10
  165. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  166. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -2
  167. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  168. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue.js +1 -1
  169. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +2 -1
  170. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
  171. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
  172. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue.js +1 -1
  173. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js +2 -1
  174. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js.map +1 -1
  175. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue3.js.map +1 -1
  176. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  177. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +6 -3
  178. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  179. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  180. package/dist/esm/components/CnTasksCard/CnTasksCard.vue.js +1 -1
  181. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js +2 -1
  182. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js.map +1 -1
  183. package/dist/esm/components/CnTasksCard/CnTasksCard.vue3.js.map +1 -1
  184. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
  185. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +2 -1
  186. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  187. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  188. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +1 -1
  189. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +140 -7
  190. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -1
  191. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -1
  192. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue.js +1 -1
  193. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js +2 -1
  194. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js.map +1 -1
  195. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue.js +1 -1
  196. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js +2 -1
  197. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js.map +1 -1
  198. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue3.js.map +1 -1
  199. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
  200. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +37 -9
  201. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
  202. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +6 -5
  203. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
  204. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js +53 -1
  205. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js.map +1 -1
  206. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js +3 -2
  207. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js.map +1 -1
  208. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  209. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +135 -0
  210. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  211. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  212. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  213. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +19 -0
  214. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  215. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +37 -19
  216. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  217. package/dist/esm/composables/useListView.js +21 -0
  218. package/dist/esm/composables/useListView.js.map +1 -1
  219. package/dist/esm/dialogs/CnNoteHistoryDialog.vue.js +1 -1
  220. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js +2 -1
  221. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js.map +1 -1
  222. package/dist/esm/dialogs/CnNoteHistoryDialog.vue3.js.map +1 -1
  223. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue.js +1 -1
  224. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js +3 -2
  225. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js.map +1 -1
  226. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue3.js.map +1 -1
  227. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue.js +1 -1
  228. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js +4 -3
  229. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js.map +1 -1
  230. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue3.js.map +1 -1
  231. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue.js +1 -1
  232. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -2
  233. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
  234. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
  235. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue.js +1 -1
  236. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js +2 -1
  237. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js.map +1 -1
  238. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js.map +1 -1
  239. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue.js +1 -1
  240. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js +6 -5
  241. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js.map +1 -1
  242. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue3.js.map +1 -1
  243. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue.js +1 -1
  244. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js +2 -1
  245. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js.map +1 -1
  246. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue3.js.map +1 -1
  247. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue.js +1 -1
  248. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js +2 -1
  249. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js.map +1 -1
  250. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js.map +1 -1
  251. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue.js +1 -1
  252. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +2 -1
  253. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
  254. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
  255. package/dist/esm/integrations/builtin/email/CnEmailCard.vue.js +1 -1
  256. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js +2 -1
  257. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js.map +1 -1
  258. package/dist/esm/integrations/builtin/email/CnEmailCard.vue3.js.map +1 -1
  259. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue.js +1 -1
  260. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +2 -1
  261. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  262. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  263. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue.js +1 -1
  264. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js +2 -1
  265. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js.map +1 -1
  266. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue3.js.map +1 -1
  267. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue.js +1 -1
  268. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js +2 -1
  269. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js.map +1 -1
  270. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js.map +1 -1
  271. package/dist/esm/l10n/en.json.js +57 -2
  272. package/dist/esm/l10n/en.json.js.map +1 -1
  273. package/dist/esm/l10n/nl.json.js +78 -2
  274. package/dist/esm/l10n/nl.json.js.map +1 -1
  275. package/dist/esm/library-style.js +1 -1
  276. package/dist/esm/nextcloud-vue.css +1541 -1166
  277. package/dist/esm/store/useObjectStore.js +23 -4
  278. package/dist/esm/store/useObjectStore.js.map +1 -1
  279. package/dist/esm/utils/boardColumns.js +58 -2
  280. package/dist/esm/utils/boardColumns.js.map +1 -1
  281. package/dist/esm/utils/boardReferenceColumns.js +330 -0
  282. package/dist/esm/utils/boardReferenceColumns.js.map +1 -0
  283. package/dist/esm/utils/buildManifest.js +4 -1
  284. package/dist/esm/utils/buildManifest.js.map +1 -1
  285. package/dist/esm/utils/schema.js +5 -4
  286. package/dist/esm/utils/schema.js.map +1 -1
  287. package/dist/esm/utils/userLocale.js +30 -0
  288. package/dist/esm/utils/userLocale.js.map +1 -0
  289. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  290. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  291. package/dist/esm/utils/widgetDispatch.js +8 -2
  292. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  293. package/dist/nextcloud-vue.cjs.js +30291 -27618
  294. package/dist/nextcloud-vue.cjs.js.map +2 -2
  295. package/dist/nextcloud-vue.css +1541 -1166
  296. package/l10n/en.json +57 -2
  297. package/l10n/nl.json +78 -2
  298. package/package.json +1 -1
  299. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +160 -8
  300. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +3 -2
  301. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +5 -4
  302. package/src/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue +2 -1
  303. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +2 -1
  304. package/src/components/CnBoardView/CnBoardView.vue +433 -12
  305. package/src/components/CnCalendarEventPicker/CnCalendarEventPicker.vue +2 -1
  306. package/src/components/CnCalendarWidget/CnCalendarWidget.vue +2 -1
  307. package/src/components/CnChartWidget/CnChartWidget.vue +6 -5
  308. package/src/components/CnCollectivePagePicker/CnCollectivePagePicker.vue +2 -1
  309. package/src/components/CnConversationThread/CnConversationThread.vue +2 -1
  310. package/src/components/CnCountdownWidget/CnCountdownWidget.vue +2 -1
  311. package/src/components/CnDashboardPage/CnDashboardPage.vue +59 -3
  312. package/src/components/CnDataMatrix/CnDataMatrix.vue +2 -1
  313. package/src/components/CnDetailPage/CnDetailHeaderChips.vue +2 -1
  314. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  315. package/src/components/CnDetailPage/CnDetailPage.vue +23 -4
  316. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +3 -1
  317. package/src/components/CnEmailPicker/CnEmailPicker.vue +2 -1
  318. package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -5
  319. package/src/components/CnFederationStatus/CnFederationStatus.vue +3 -1
  320. package/src/components/CnFileManager/CnFileManager.vue +2 -1
  321. package/src/components/CnFilePreview/CnFilePreview.vue +2 -1
  322. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +54 -6
  323. package/src/components/CnFollowToggle/CnFollowToggle.vue +2 -1
  324. package/src/components/CnIndexPage/CnIndexPage.vue +610 -25
  325. package/src/components/CnIndexPage/useSelfFetchList.js +10 -1
  326. package/src/components/CnNotesCard/CnNotesCard.vue +2 -1
  327. package/src/components/CnObjectCalendar/CnObjectCalendar.vue +3 -2
  328. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +36 -0
  329. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +5 -4
  330. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +2 -1
  331. package/src/components/CnObjectSidebar/CnFlowTasksPanel.vue +2 -1
  332. package/src/components/CnObjectSidebar/CnNotesTab.vue +2 -1
  333. package/src/components/CnObjectSidebar/CnTasksTab.vue +2 -1
  334. package/src/components/CnPropertySourceField/CnPropertySourceField.vue +2 -1
  335. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +70 -2
  336. package/src/components/CnRegisterMapping/CnRegisterMapping.md +5 -0
  337. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +231 -96
  338. package/src/components/CnRoadmapItem/CnRoadmapItem.vue +2 -1
  339. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +4 -2
  340. package/src/components/CnSettingsPage/CnSettingsPage.vue +5 -1
  341. package/src/components/CnStatWidget/CnStatWidget.vue +136 -11
  342. package/src/components/CnStatsBlock/CnStatsBlock.vue +2 -1
  343. package/src/components/CnSummaryAggregates/CnSummaryAggregates.vue +2 -1
  344. package/src/components/CnTabsWidget/CnTabsWidget.vue +6 -3
  345. package/src/components/CnTasksCard/CnTasksCard.vue +2 -1
  346. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +2 -1
  347. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +140 -7
  348. package/src/components/CnTranslatedBadge/CnTranslatedBadge.vue +2 -1
  349. package/src/components/CnVersionHistory/CnVersionHistory.vue +2 -1
  350. package/src/components/CnVersionInfoCard/CnVersionInfoCard.md +2 -1
  351. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +42 -13
  352. package/src/components/CnWidgetCardGrid/CnWidgetCardGrid.vue +55 -2
  353. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +135 -0
  354. package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +10 -0
  355. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +44 -1
  356. package/src/composables/useListView.js +21 -0
  357. package/src/css/board.css +105 -4
  358. package/src/css/dialog.css +4 -2
  359. package/src/css/index-page.css +49 -0
  360. package/src/css/look-board.css +77 -7
  361. package/src/dialogs/CnNoteHistoryDialog.vue +2 -1
  362. package/src/integrations/builtin/activity/CnActivityCard.vue +3 -2
  363. package/src/integrations/builtin/activity/CnActivityTab.vue +4 -3
  364. package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +3 -2
  365. package/src/integrations/builtin/calendar/CnCalendarCard.vue +2 -1
  366. package/src/integrations/builtin/calendar/CnCalendarTab.vue +6 -5
  367. package/src/integrations/builtin/contactmoment/CnContactmomentCard.vue +2 -1
  368. package/src/integrations/builtin/cospend/CnCospendTab.vue +2 -1
  369. package/src/integrations/builtin/deck/CnDeckTab.vue +2 -1
  370. package/src/integrations/builtin/email/CnEmailCard.vue +2 -1
  371. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +2 -1
  372. package/src/integrations/builtin/field-inspection/CnFieldInspectionTab.vue +2 -1
  373. package/src/integrations/builtin/photos/CnPhotosTab.vue +2 -1
  374. package/src/schemas/app-manifest-v2.schema.json +116 -5
  375. package/src/store/useObjectStore.js +23 -4
  376. package/src/utils/boardColumns.js +57 -1
  377. package/src/utils/boardReferenceColumns.js +326 -0
  378. package/src/utils/buildManifest.js +4 -1
  379. package/src/utils/schema.js +5 -4
  380. package/src/utils/userLocale.js +26 -0
  381. package/src/utils/validateManifestV2.compiled.js +3 -3
  382. package/src/utils/widgetDispatch.js +8 -2
@@ -207,7 +207,53 @@
207
207
  <template v-if="$slots['action-items']" #action-items>
208
208
  <slot name="action-items" />
209
209
  </template>
210
- <template v-if="$slots['after-search'] || searchInFiles" #after-search>
210
+ <template v-if="$slots['after-search'] || searchInFiles || boardControlsShown" #after-search>
211
+ <!-- Board view controls, after the search (screens-board-reference-columns):
212
+ the narrowing select ("Case type:"), the column switch ("Columns:
213
+ status | type | assignee") and the board's hint sentence. -->
214
+ <template v-if="boardControlsShown">
215
+ <label
216
+ v-if="boardNarrow"
217
+ class="cn-index-page__board-control"
218
+ data-testid="cn-board-narrow">
219
+ <span class="cn-index-page__board-control-label">{{ boardNarrowLabel }}</span>
220
+ <select
221
+ class="cn-index-page__board-select"
222
+ data-testid="cn-board-narrow-select"
223
+ :value="boardNarrowValue"
224
+ @change="onBoardNarrowChange($event.target.value)">
225
+ <option value="">{{ boardNarrowAllLabel }}</option>
226
+ <option
227
+ v-for="option in boardNarrowOptions"
228
+ :key="`narrow-${option.value}`"
229
+ :value="option.value">
230
+ {{ option.label }}
231
+ </option>
232
+ </select>
233
+ </label>
234
+ <label
235
+ v-if="boardColumnFields.length > 1"
236
+ class="cn-index-page__board-control"
237
+ data-testid="cn-board-column-switch">
238
+ <span class="cn-index-page__board-control-label">{{ boardColumnSwitchLabel }}</span>
239
+ <select
240
+ class="cn-index-page__board-select cn-index-page__board-select--strong"
241
+ data-testid="cn-board-column-switch-select"
242
+ :value="boardColumnField"
243
+ @change="onBoardColumnFieldChange($event.target.value)">
244
+ <option
245
+ v-for="entry in boardColumnFields"
246
+ :key="`colfield-${entry.field}`"
247
+ :value="entry.field">
248
+ {{ cnTranslate(entry.label) }}
249
+ </option>
250
+ </select>
251
+ </label>
252
+ <span
253
+ v-if="board.hint"
254
+ class="cn-index-page__board-hint"
255
+ data-testid="cn-board-hint">{{ cnTranslate(board.hint) }}</span>
256
+ </template>
211
257
  <NcCheckboxRadioSwitch
212
258
  v-if="searchInFiles"
213
259
  :modelValue="contentSearch"
@@ -361,6 +407,17 @@
361
407
  </button>
362
408
  </div>
363
409
 
410
+ <!-- Header actions of `type: "open-form"` or `"open-modal"`: this
411
+ instance draws nothing and owns the create dialog, as on a detail
412
+ page, so a header button or menu entry naming one opens it. -->
413
+ <CnActionButtons
414
+ v-if="dialogHeaderActions.length > 0"
415
+ :actions="dialogHeaderActions"
416
+ display="menu"
417
+ data-testid="cn-index-header-dialog-actions"
418
+ @entries="dialogHeaderRuns = $event"
419
+ @created="onHeaderActionCreated" />
420
+
364
421
  <!-- Quick edit: a few fields of one row, over the list, with the list
365
422
  keeping its place. -->
366
423
  <CnQuickEditDialog
@@ -786,8 +843,13 @@
786
843
  <CnBoardView
787
844
  v-else-if="currentViewMode === 'board'"
788
845
  :rows="displayObjects"
789
- :statusFieldSchema="boardStatusFieldSchema"
790
- :statusField="board.statusField || 'status'"
846
+ :statusFieldSchema="boardFieldSchema"
847
+ :statusField="boardColumnField"
848
+ :columnKeyOf="boardColumnKeyOf"
849
+ :wrapColumns="board.wrap === true"
850
+ :selectable="selectable"
851
+ :selectedIds="internalSelectedIds"
852
+ :allowedMoves="boardAllowedMoves"
791
853
  :cardFields="board.cardFields || []"
792
854
  :swimlaneField="board.swimlaneField || ''"
793
855
  :dueRule="board.dueRule || null"
@@ -797,8 +859,9 @@
797
859
  :sumFormat="boardSumFormat"
798
860
  :columnLimit="board.columnLimit || 0"
799
861
  :rowKey="rowKey"
800
- :runTransition="runTransition"
862
+ :runTransition="boardRunTransition"
801
863
  :paged="isPaged"
864
+ @select="onSelect"
802
865
  @loadMore="onBoardLoadMore"
803
866
  @cardClick="onRowClick"
804
867
  @cardAuxClick="onRowAuxClick"
@@ -959,9 +1022,27 @@
959
1022
  {{ t('nextcloud-vue', 'File matches are limited to the best 50.') }}
960
1023
  </p>
961
1024
 
1025
+ <!-- The board view's footer: it holds every row it loaded, so it
1026
+ counts them and offers the next batch instead of pages. -->
1027
+ <div
1028
+ v-if="boardLoadsAll && boardLoadCounts.total > 0"
1029
+ class="cn-index-page__board-load"
1030
+ data-testid="cn-index-board-load">
1031
+ <span class="cn-index-page__board-load-count" data-testid="cn-index-board-load-count">
1032
+ {{ t('nextcloud-vue', 'Showing {count} of {total}', { count: boardLoadCounts.shown, total: boardLoadCounts.total }) }}
1033
+ </span>
1034
+ <NcButton
1035
+ v-if="isPaged"
1036
+ :disabled="effectiveLoading"
1037
+ data-testid="cn-index-board-load-more"
1038
+ @click="onBoardLoadMore">
1039
+ {{ t('nextcloud-vue', 'Load more') }}
1040
+ </NcButton>
1041
+ </div>
1042
+
962
1043
  <!-- Pagination -->
963
1044
  <CnPagination
964
- v-if="effectivePagination && (effectivePagination.pages > 1 || (isBoardLook && effectivePagination.total > 0))"
1045
+ v-else-if="effectivePagination && (effectivePagination.pages > 1 || (isBoardLook && effectivePagination.total > 0))"
965
1046
  :variant="isBoardLook ? 'board' : ''"
966
1047
  :footerNote="footerNote ? cnTranslate(footerNote) : footerNote"
967
1048
  :currentPage="effectivePagination.page || 1"
@@ -1053,7 +1134,7 @@
1053
1134
 
1054
1135
  <script>
1055
1136
  import { getCurrentUser } from '@nextcloud/auth'
1056
- import { translate as t } from '@nextcloud/l10n'
1137
+ import { translatePlural as n, translate as t } from '@nextcloud/l10n'
1057
1138
  import { NcActionButton, NcActionCaption, NcActionCheckbox, NcActionLink, NcActions, NcActionSeparator, NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'
1058
1139
  import { getCurrentInstance, inject, markRaw, ref } from 'vue'
1059
1140
  import AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'
@@ -1083,6 +1164,17 @@ import { METADATA_COLUMNS } from '../../constants/metadata.js'
1083
1164
  import { useObjectStore } from '../../store/useObjectStore.js'
1084
1165
  import { followItemActionLink, resolveItemActionLink, routeHref } from '../../utils/actionLink.js'
1085
1166
  import { buildOnSuccessRoute, resolveRegisteredHandler } from '../../utils/actionsDispatcher.js'
1167
+ import {
1168
+ buildReferenceStages,
1169
+ buildValueStages,
1170
+ columnFieldsOf,
1171
+ columnKeyOfRow,
1172
+ fetchReferenceObjects,
1173
+ fullTargetOf,
1174
+ referenceTargetOf,
1175
+ refIdOf,
1176
+ resolveDropValue,
1177
+ } from '../../utils/boardReferenceColumns.js'
1086
1178
  import { reportBindingProblems } from '../../utils/diagnostics.js'
1087
1179
  import { fetchFilterCounts } from '../../utils/fetchFilterCounts.js'
1088
1180
  import { buildExportUrl } from '../../utils/indexExportHelpers.js'
@@ -1092,6 +1184,7 @@ import { resolveClaimedTeams, resolveClaimTokens, splitViewsIntoTabs, viewAsTab,
1092
1184
  import { LIST_SHORTCUTS, listPaletteCommands, shortcutFor } from '../../utils/listShortcuts.js'
1093
1185
  import { multiKeySort } from '../../utils/multiKeySort.js'
1094
1186
  import { OBJECTS_CHANGED_EVENT } from '../../utils/objectSignals.js'
1187
+ import { objectUrlOf, patchObject } from '../../utils/objectWrite.js'
1095
1188
  import { withPersonalLenses } from '../../utils/personalLenses.js'
1096
1189
  import { resolveDeepTokens, resolveFilterValue } from '../../utils/resolveFilterTokens.js'
1097
1190
  import { resolveRowActions } from '../../utils/resolveRowActions.js'
@@ -1104,6 +1197,7 @@ import { buildRouteQueryFromViewState, buildViewCreatePayload, extractViewState,
1104
1197
  import { columnsFromSchema, fieldsFromSchema } from '../../utils/schema.js'
1105
1198
  import { resolveScopeLayout } from '../../utils/scopeListLayout.js'
1106
1199
  import { dispatchObjectCreated } from '../../utils/walkthroughSignals.js'
1200
+ import { CnActionButtons } from '../CnActionButtons/index.js'
1107
1201
  import { CnActionsBar } from '../CnActionsBar/index.js'
1108
1202
  import { CnAdvancedFormDialog } from '../CnAdvancedFormDialog/index.js'
1109
1203
  import { CnBoardView } from '../CnBoardView/index.js'
@@ -1140,7 +1234,7 @@ import { orderColumns, personalColumnsKey, reconcilePersonalColumns } from './pe
1140
1234
  import { createSelfModeActions, resolveRowTarget } from './selfModeActions.js'
1141
1235
  import { applyRowPatches, normalisePaneWidth, rowIdOf, splitLayoutFor } from './splitView.js'
1142
1236
  import { useNamedSource } from './useNamedSource.js'
1143
- import { useSelfFetchList } from './useSelfFetchList.js'
1237
+ import { BOARD_PAGE_SIZE, useSelfFetchList } from './useSelfFetchList.js'
1144
1238
 
1145
1239
  /** Rows fetched for one month in calendar mode. */
1146
1240
  const CALENDAR_PAGE_SIZE = 200
@@ -1394,6 +1488,7 @@ export default {
1394
1488
  NcCheckboxRadioSwitch,
1395
1489
  CnPageHeader,
1396
1490
  CnQuickFilterBar,
1491
+ CnActionButtons,
1397
1492
  CnActionsBar,
1398
1493
  DotsHorizontal,
1399
1494
  CnIcon,
@@ -1440,6 +1535,8 @@ export default {
1440
1535
  */
1441
1536
  inject: {
1442
1537
  cnCustomComponents: { default: () => ({}) },
1538
+ /** The app id CnAppRoot provides, for the plural form of `countSubtitle`. */
1539
+ cnAppId: { default: '' },
1443
1540
  /**
1444
1541
  * The app manifest, provided by CnAppRoot. A column with `labelField`
1445
1542
  * and `link: true` finds the referenced schema's detail page here.
@@ -1526,10 +1623,17 @@ export default {
1526
1623
  * shows. Manifest key `config.countSubtitle`. Goes through the host
1527
1624
  * translate function.
1528
1625
  *
1626
+ * `{ singular, plural }` picks the form by the total ("1 invoice",
1627
+ * "12 invoices") through the app's plural translation
1628
+ * (`translatePlural` with the app id CnAppRoot provides), so a
1629
+ * language with other plural rules gets its own forms.
1630
+ *
1529
1631
  * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-an-index-page-title-is-a-manifest-key
1632
+ * @spec openspec/changes/index-count-plural/specs/index-header/spec.md#requirement-the-count-line-takes-a-singular-and-a-plural-form
1633
+ * @type {string|{singular: string, plural: string}}
1530
1634
  */
1531
1635
  countSubtitle: {
1532
- type: String,
1636
+ type: [String, Object],
1533
1637
  default: '',
1534
1638
  },
1535
1639
 
@@ -2310,10 +2414,14 @@ export default {
2310
2414
  default: () => [],
2311
2415
  },
2312
2416
 
2313
- /** Text shown when no items found */
2417
+ /**
2418
+ * Text shown when no items found. The default is the library's own
2419
+ * string, so it reads in the user's language; a page's own text goes
2420
+ * through the app's translate function.
2421
+ */
2314
2422
  emptyText: {
2315
2423
  type: String,
2316
- default: 'No items found',
2424
+ default: () => t('nextcloud-vue', 'No items found'),
2317
2425
  },
2318
2426
 
2319
2427
  /**
@@ -3335,6 +3443,7 @@ export default {
3335
3443
  'add',
3336
3444
  'apply-view',
3337
3445
  'board-move',
3446
+ 'board-column-field-change',
3338
3447
  'bulk-action',
3339
3448
  'clear-filters',
3340
3449
  'columns-change',
@@ -3446,10 +3555,21 @@ export default {
3446
3555
  data() {
3447
3556
  return {
3448
3557
  currentViewMode: this.viewMode,
3558
+ /** The column field the reader picked in the board's column switch; '' = the default. */
3559
+ boardColumnFieldChoice: '',
3560
+ /** The rows a reference column field is built from, by field. */
3561
+ boardRefs: {},
3562
+ /** The options of the board's narrowing select (`board.narrow`). */
3563
+ boardNarrowOptions: [],
3564
+ /** The menu entries CnActionButtons reports for the dialog header actions, each with its `run()`. */
3565
+ dialogHeaderRuns: [],
3449
3566
  /** The visible calendar window `{ rangeStart, rangeEnd }` (ISO dates), or null outside calendar mode. */
3450
3567
  calendarRange: null,
3451
3568
  /** The page size to restore when leaving calendar mode. */
3452
3569
  calendarPrevPageSize: null,
3570
+ // The table's page size while the board view holds the list at
3571
+ // BOARD_PAGE_SIZE; restored on leaving the board.
3572
+ boardPrevPageSize: this.viewMode === 'board' ? ((this.pagination && this.pagination.limit) || 20) : null,
3453
3573
  /** Resolved labels of reference columns: `{ [columnKey]: { [id]: label|null } }`. */
3454
3574
  refLabels: {},
3455
3575
  /** Count per tab-strip index, for the entries that asked for one; null = none. */
@@ -3670,6 +3790,24 @@ export default {
3670
3790
  *
3671
3791
  * @return {Array<object>}
3672
3792
  */
3793
+ /**
3794
+ * The header actions that open a dialog: `type: "open-form"` (the
3795
+ * schema-driven create form, as the navigation's primary action opens
3796
+ * it) or `type: "open-modal"`, without a `handler` of their own.
3797
+ * Reserved ids are left out, as in `mergedHeaderActions`.
3798
+ *
3799
+ * @spec openspec/changes/index-header-open-form/specs/index-header/spec.md#requirement-an-index-header-action-can-open-the-create-form
3800
+ * @return {Array<object>}
3801
+ */
3802
+ dialogHeaderActions() {
3803
+ const reserved = new Set(['refresh', 'import', 'export', 'copy', 'delete'])
3804
+ return (this.headerActions || []).filter((entry) => entry
3805
+ && typeof entry.id === 'string'
3806
+ && !reserved.has(entry.id)
3807
+ && (entry.handler === undefined || entry.handler === null || entry.handler === '')
3808
+ && (entry.type === 'open-form' || entry.type === 'open-modal'))
3809
+ },
3810
+
3673
3811
  mergedHeaderActions() {
3674
3812
  const reserved = new Set(['refresh', 'import', 'export', 'copy', 'delete'])
3675
3813
  const merged = []
@@ -4022,6 +4160,264 @@ export default {
4022
4160
  })
4023
4161
  },
4024
4162
 
4163
+ /**
4164
+ * The column fields the board offers (`board.columnFields`), for the
4165
+ * column switch (screens-board-reference-columns).
4166
+ *
4167
+ * @return {Array<object>} The normalised fields; empty for a board on `statusField` only.
4168
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-board-can-switch-the-field-its-columns-come-from
4169
+ */
4170
+ boardColumnFields() {
4171
+ return columnFieldsOf(this.board)
4172
+ },
4173
+
4174
+ /**
4175
+ * The column field in use: the reader's pick, else the one on
4176
+ * `statusField`, else the first. Null on a board without `columnFields`.
4177
+ *
4178
+ * @return {object|null} The normalised column field.
4179
+ */
4180
+ boardActiveColumnField() {
4181
+ const fields = this.boardColumnFields
4182
+ if (fields.length === 0) {
4183
+ return null
4184
+ }
4185
+ return fields.find((entry) => entry.field === this.boardColumnFieldChoice)
4186
+ || fields.find((entry) => entry.field === this.board?.statusField)
4187
+ || fields[0]
4188
+ },
4189
+
4190
+ /** @return {string} The row field the columns come from. */
4191
+ boardColumnField() {
4192
+ return this.boardActiveColumnField?.field || this.board?.statusField || 'status'
4193
+ },
4194
+
4195
+ /**
4196
+ * The parent the board is narrowed to: the single value of the page
4197
+ * filter on the reference's `narrowBy.rowField`, '' when none or several.
4198
+ *
4199
+ * @return {string} The parent id.
4200
+ */
4201
+ boardNarrowValue() {
4202
+ const field = this.board?.narrow?.field || this.boardActiveColumnField?.source?.narrowBy?.rowField
4203
+ if (!field) {
4204
+ return ''
4205
+ }
4206
+ const current = this.effectiveActiveFilters?.[field]
4207
+ const values = Array.isArray(current) ? current : (current === undefined || current === null || current === '' ? [] : [current])
4208
+ return values.length === 1 ? refIdOf(values[0]) : ''
4209
+ },
4210
+
4211
+ /**
4212
+ * The stages of a reference or values column field, or null for a
4213
+ * field the schema's enum or lifecycle states back.
4214
+ *
4215
+ * @return {object|null} `{ states, keyByValue, refsByKey }`.
4216
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-columns-can-be-the-rows-a-field-references
4217
+ */
4218
+ boardStages() {
4219
+ const active = this.boardActiveColumnField
4220
+ if (!active) {
4221
+ return null
4222
+ }
4223
+ if (active.kind === 'values') {
4224
+ return buildValueStages({
4225
+ rows: this.displayObjects,
4226
+ field: active.field,
4227
+ valueLabels: active.valueLabels,
4228
+ emptyLabel: active.emptyLabel ? this.cnTranslate(active.emptyLabel) : t('nextcloud-vue', 'Nobody'),
4229
+ })
4230
+ }
4231
+ if (active.kind !== 'reference') {
4232
+ return null
4233
+ }
4234
+ const source = active.source || {}
4235
+ const narrowBy = source.narrowBy && typeof source.narrowBy === 'object' ? source.narrowBy : null
4236
+ return buildReferenceStages({
4237
+ refs: this.boardRefs[active.field] || [],
4238
+ labelField: source.labelField || '',
4239
+ orderField: source.orderField || '',
4240
+ colorField: source.colorField || '',
4241
+ mergeBy: source.mergeBy || '',
4242
+ narrowBy,
4243
+ narrowValue: narrowBy ? this.boardNarrowValue : '',
4244
+ capacityField: source.capacityField || '',
4245
+ })
4246
+ },
4247
+
4248
+ /**
4249
+ * The field schema the board reads its columns from: the stages of a
4250
+ * reference or values field as lifecycle `states`, else the schema's
4251
+ * own property.
4252
+ *
4253
+ * @return {?object} The field schema, or null.
4254
+ */
4255
+ boardFieldSchema() {
4256
+ if (this.boardStages) {
4257
+ return { states: this.boardStages.states }
4258
+ }
4259
+ const field = this.boardColumnField
4260
+ return this.effectiveSchema?.properties?.[field] || null
4261
+ },
4262
+
4263
+ /**
4264
+ * The column a card sits in, for a reference or values field.
4265
+ *
4266
+ * @return {((row: object) => string)|null} The mapper, or null.
4267
+ */
4268
+ boardColumnKeyOf() {
4269
+ const stages = this.boardStages
4270
+ if (!stages) {
4271
+ return null
4272
+ }
4273
+ const field = this.boardColumnField
4274
+ return (row) => columnKeyOfRow(row, field, stages.keyByValue)
4275
+ },
4276
+
4277
+ /**
4278
+ * The move the board runs on a drop or a menu pick.
4279
+ *
4280
+ * A named handler (`moveHandler`, from the app's registry) gets
4281
+ * `{ card, toKey, field, value, target }` and owns the write; the
4282
+ * status of a case goes through the app's transition this way. A
4283
+ * reference or values field without one has its value written on the
4284
+ * row (PATCH). `readOnly` gives no move. A board on `statusField` with
4285
+ * neither keeps the `runTransition` prop.
4286
+ *
4287
+ * With `source.capacityField`, a drop that would fill the referenced
4288
+ * row past its limit is refused before the handler or the PATCH runs.
4289
+ * The server still guards; this only spares the round trip.
4290
+ *
4291
+ * @return {((move: {card: object, toKey: string}) => Promise<object>)|null} The move, or null for a read-only board.
4292
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-drop-writes-the-reference
4293
+ */
4294
+ boardRunTransition() {
4295
+ const active = this.boardActiveColumnField
4296
+ if (active?.readOnly) {
4297
+ return null
4298
+ }
4299
+ const onStatusField = !active || active.field === this.board?.statusField
4300
+ const name = active?.moveHandler || (onStatusField ? (this.board?.moveHandler || '') : '')
4301
+ const handler = name ? resolveRegisteredHandler(name, this.effectiveRegistry, this.resolvedCustomComponents) : null
4302
+ if (name && typeof handler !== 'function') {
4303
+ return null
4304
+ }
4305
+ const stages = this.boardStages
4306
+ if (!handler && !stages) {
4307
+ return this.runTransition
4308
+ }
4309
+ const field = this.boardColumnField
4310
+ const kind = active?.kind || 'schema'
4311
+ const narrowBy = active?.source?.narrowBy || null
4312
+ const capacityField = active?.source?.capacityField || ''
4313
+ return async ({ card, toKey }) => {
4314
+ const drop = stages
4315
+ ? resolveDropValue({ card, toKey, kind, refsByKey: stages.refsByKey, narrowBy })
4316
+ : { value: toKey, target: null }
4317
+ if (drop === null) {
4318
+ throw new Error(t('nextcloud-vue', 'This card cannot move to that column.'))
4319
+ }
4320
+ const full = capacityField && drop.target
4321
+ ? fullTargetOf({ target: drop.target, card, rows: this.displayObjects, field, capacityField, rowKey: this.rowKey })
4322
+ : null
4323
+ if (full) {
4324
+ const column = stages.states.find((state) => state.key === String(toKey))?.label || String(toKey)
4325
+ throw new Error(t('nextcloud-vue', '{column} is full: {count} of {capacity}.', { column, count: full.count, capacity: full.capacity }))
4326
+ }
4327
+ if (handler) {
4328
+ return handler({ card, toKey, field, value: drop.value, target: drop.target })
4329
+ }
4330
+ const id = card?.id ?? card?.['@self']?.id ?? card?.[this.rowKey]
4331
+ const url = objectUrlOf(this.register, this.exportSchemaSlug, id)
4332
+ if (url === '') {
4333
+ throw new Error(t('nextcloud-vue', 'This card cannot move to that column.'))
4334
+ }
4335
+ return patchObject(url, { [field]: drop.value })
4336
+ }
4337
+ },
4338
+
4339
+ /**
4340
+ * Where a card may go, from the app's `moveTargetsHandler`: it gets
4341
+ * `{ card, field }` and answers the values (referenced ids) the card
4342
+ * can reach; the board maps them to its columns. An entry may also be
4343
+ * `{ key, allowed, reason }`: a target that is offered but blocked,
4344
+ * with the sentence that says why.
4345
+ *
4346
+ * @return {((card: object) => Promise<Array<string|{key: string, allowed: boolean, reason: string}>|null>)|null} The question, or null.
4347
+ * @spec openspec/changes/board-move-block-reasons/specs/board-view/spec.md#requirement-a-move-target-can-be-blocked-with-a-reason
4348
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
4349
+ */
4350
+ boardAllowedMoves() {
4351
+ const active = this.boardActiveColumnField
4352
+ const onStatusField = !active || active.field === this.board?.statusField
4353
+ const name = active?.moveTargetsHandler || (onStatusField ? (this.board?.moveTargetsHandler || '') : '')
4354
+ const handler = name ? resolveRegisteredHandler(name, this.effectiveRegistry, this.resolvedCustomComponents) : null
4355
+ if (typeof handler !== 'function' || this.boardRunTransition === null) {
4356
+ return null
4357
+ }
4358
+ const field = this.boardColumnField
4359
+ const stages = this.boardStages
4360
+ return async (card) => {
4361
+ const values = await handler({ card, field })
4362
+ if (!Array.isArray(values)) {
4363
+ return null
4364
+ }
4365
+ const columnOf = (id) => (stages && stages.keyByValue.has(id) ? stages.keyByValue.get(id) : id)
4366
+ return values.map((value) => {
4367
+ if (value && typeof value === 'object' && Object.hasOwn(value, 'key')) {
4368
+ return {
4369
+ key: columnOf(refIdOf(value.key)),
4370
+ allowed: value.allowed !== false,
4371
+ reason: typeof value.reason === 'string' ? value.reason : '',
4372
+ }
4373
+ }
4374
+ return columnOf(refIdOf(value))
4375
+ })
4376
+ }
4377
+ },
4378
+
4379
+ /** @return {object|null} The board's narrowing select (`board.narrow`). */
4380
+ boardNarrow() {
4381
+ const narrow = this.board?.narrow
4382
+ return narrow && typeof narrow === 'object' && typeof narrow.field === 'string' && narrow.field !== '' ? narrow : null
4383
+ },
4384
+
4385
+ /** @return {string} The narrowing select's label, with its colon. */
4386
+ boardNarrowLabel() {
4387
+ const narrow = this.boardNarrow || {}
4388
+ const prop = (this.effectiveSchema?.properties || {})[narrow.field] || {}
4389
+ return t('nextcloud-vue', '{label}:', { label: this.cnTranslate(narrow.label || prop.title || narrow.field || '') })
4390
+ },
4391
+
4392
+ /** @return {string} The narrowing select's "all" option. */
4393
+ boardNarrowAllLabel() {
4394
+ return this.boardNarrow?.allLabel ? this.cnTranslate(this.boardNarrow.allLabel) : t('nextcloud-vue', 'All')
4395
+ },
4396
+
4397
+ /** @return {string} The column switch's label, with its colon. */
4398
+ boardColumnSwitchLabel() {
4399
+ const label = this.board?.columnSwitchLabel ? this.cnTranslate(this.board.columnSwitchLabel) : t('nextcloud-vue', 'Columns')
4400
+ return t('nextcloud-vue', '{label}:', { label })
4401
+ },
4402
+
4403
+ /** @return {boolean} Whether the board view draws its controls row. */
4404
+ boardControlsShown() {
4405
+ return this.currentViewMode === 'board'
4406
+ && (this.boardColumnFields.length > 1 || this.boardNarrow !== null || Boolean(this.board?.hint))
4407
+ },
4408
+
4409
+ /**
4410
+ * What the board needs fetched, as one key the watcher reacts to.
4411
+ *
4412
+ * @return {string} The key, '' outside the board view.
4413
+ */
4414
+ boardFetchKey() {
4415
+ if (this.currentViewMode !== 'board') {
4416
+ return ''
4417
+ }
4418
+ return [this.boardColumnField, this.boardActiveColumnField?.kind || '', this.effectiveSchema ? 1 : 0, this.boardNarrow ? this.boardNarrow.field : ''].join('|')
4419
+ },
4420
+
4025
4421
  /**
4026
4422
  * The status field's schema, for the board's columns.
4027
4423
  *
@@ -4068,9 +4464,36 @@ export default {
4068
4464
  * @return {boolean} True when there is more than this page.
4069
4465
  */
4070
4466
  isPaged() {
4467
+ if (this.boardLoadsAll) {
4468
+ const loaded = this.effectivePagination || {}
4469
+ return Number(loaded.page || 1) < Number(loaded.pages || 1)
4470
+ }
4071
4471
  return Number(this.pagination?.pages || 1) > 1
4072
4472
  },
4073
4473
 
4474
+ /**
4475
+ * Whether the board view gathers every row itself: in self-fetch mode
4476
+ * it adds page after page (`list.loadMore`) instead of paging, and
4477
+ * draws its own footer in place of the pagination.
4478
+ *
4479
+ * @return {boolean} True for a self-fetching page in board view.
4480
+ * @spec openspec/changes/board-loads-every-row/specs/board-view/spec.md#requirement-the-index-board-shows-every-matching-row
4481
+ */
4482
+ boardLoadsAll() {
4483
+ return this.currentViewMode === 'board' && this.isSelfFetchMode && !this.isNamedSource && typeof this.list.loadMore === 'function'
4484
+ },
4485
+
4486
+ /**
4487
+ * The rows the board holds against the rows that match, for the
4488
+ * board's footer.
4489
+ *
4490
+ * @return {{shown: number, total: number}} The counts.
4491
+ */
4492
+ boardLoadCounts() {
4493
+ const shown = this.effectiveObjects.length
4494
+ return { shown, total: Math.max(shown, Number(this.effectivePagination?.total || 0)) }
4495
+ },
4496
+
4074
4497
  /**
4075
4498
  * The CnFolderSidebar source. A `register` source is fetched by this
4076
4499
  * component and handed to CnFolderSidebar as a `custom` folder list.
@@ -5873,13 +6296,15 @@ export default {
5873
6296
  if (!this.countText && !this.countSubtitle) {
5874
6297
  return t('nextcloud-vue', '{shown} of {total}', { shown, total })
5875
6298
  }
5876
- const template = this.countText || this.countSubtitle
5877
- return this.cnTranslate(template)
5878
- .replace('{shown}', String(shown))
5879
- .replace('{total}', String(total))
6299
+ if (this.countText) {
6300
+ return this.cnTranslate(this.countText)
6301
+ .replace('{shown}', String(shown))
6302
+ .replace('{total}', String(total))
6303
+ }
6304
+ return this.countLine(this.countSubtitle, total, shown)
5880
6305
  }
5881
6306
  if (this.countSubtitle && typeof total === 'number' && total >= 0) {
5882
- return this.cnTranslate(this.countSubtitle).replace('{total}', String(total))
6307
+ return this.countLine(this.countSubtitle, total, null)
5883
6308
  }
5884
6309
  return this.description
5885
6310
  },
@@ -6045,6 +6470,19 @@ export default {
6045
6470
  },
6046
6471
 
6047
6472
  watch: {
6473
+ '$route.query._view': function() {
6474
+ this.applyViewModeFromRoute()
6475
+ },
6476
+
6477
+ boardFetchKey: {
6478
+ immediate: true,
6479
+ handler(key) {
6480
+ if (key !== '') {
6481
+ this.loadBoardSources()
6482
+ }
6483
+ },
6484
+ },
6485
+
6048
6486
  effectiveObjects: {
6049
6487
  immediate: true,
6050
6488
  handler(rows) {
@@ -6118,22 +6556,33 @@ export default {
6118
6556
  // Entering calendar mode fetches one page sized to the month; leaving
6119
6557
  // removes the month range and restores the page size, so the table is
6120
6558
  // never left narrowed.
6559
+ // The board does the same at BOARD_PAGE_SIZE, so it shows every row
6560
+ // rather than the table's first page.
6121
6561
  currentViewMode(mode, previous) {
6122
6562
  if (!this.isSelfFetchMode) {
6123
6563
  return
6124
6564
  }
6125
- if (mode === 'calendar') {
6126
- this.calendarPrevPageSize = this.list.pageSize.value
6127
- if (typeof this.list.onPageSizeChange === 'function') {
6128
- this.list.onPageSizeChange(CALENDAR_PAGE_SIZE)
6129
- }
6130
- } else if (previous === 'calendar') {
6565
+ let listSize = this.list.pageSize.value
6566
+ if (previous === 'calendar') {
6131
6567
  this.calendarRange = null
6132
- const restore = this.calendarPrevPageSize || 20
6568
+ listSize = this.calendarPrevPageSize || 20
6133
6569
  this.calendarPrevPageSize = null
6134
- if (typeof this.list.onPageSizeChange === 'function') {
6135
- this.list.onPageSizeChange(restore)
6136
- }
6570
+ } else if (previous === 'board') {
6571
+ listSize = this.boardPrevPageSize || 20
6572
+ this.boardPrevPageSize = null
6573
+ }
6574
+ let size = null
6575
+ if (mode === 'calendar') {
6576
+ this.calendarPrevPageSize = listSize
6577
+ size = CALENDAR_PAGE_SIZE
6578
+ } else if (mode === 'board') {
6579
+ this.boardPrevPageSize = listSize
6580
+ size = BOARD_PAGE_SIZE
6581
+ } else if (previous === 'calendar' || previous === 'board') {
6582
+ size = listSize
6583
+ }
6584
+ if (size !== null && typeof this.list.onPageSizeChange === 'function') {
6585
+ this.list.onPageSizeChange(size)
6137
6586
  }
6138
6587
  },
6139
6588
 
@@ -6288,6 +6737,7 @@ export default {
6288
6737
  },
6289
6738
 
6290
6739
  created() {
6740
+ this.applyViewModeFromRoute()
6291
6741
  this.pushAiContext()
6292
6742
  if (this.allowSavedViews) {
6293
6743
  this.fetchSavedViews()
@@ -7070,6 +7520,11 @@ export default {
7070
7520
  const entry = this.mergedHeaderActions.find((e) => e.id === id)
7071
7521
  if (entry && typeof entry.handler === 'function') {
7072
7522
  entry.handler()
7523
+ } else {
7524
+ const dialogRun = this.dialogHeaderRuns.find((e) => e.id === id)
7525
+ if (dialogRun && typeof dialogRun.run === 'function') {
7526
+ dialogRun.run()
7527
+ }
7073
7528
  }
7074
7529
  if (entry && entry._dispatchSuppress) {
7075
7530
  return
@@ -7077,6 +7532,49 @@ export default {
7077
7532
  this.$emit('header-action', { action: id, id })
7078
7533
  },
7079
7534
 
7535
+ /**
7536
+ * The `countSubtitle` line for a total. A string goes through the host
7537
+ * translate; `{ singular, plural }` takes the form for the total
7538
+ * through the app's plural translation, or by `total === 1` when no app
7539
+ * id is provided. `{total}` (and `{shown}` when given) are filled in.
7540
+ *
7541
+ * @spec openspec/changes/index-count-plural/specs/index-header/spec.md#requirement-the-count-line-takes-a-singular-and-a-plural-form
7542
+ * @param {string|{singular: string, plural: string}} subtitle The declared line.
7543
+ * @param {number} total The collection's total.
7544
+ * @param {number|null} shown The rows on this page, or null to leave `{shown}` alone.
7545
+ * @return {string} The line, '' for a declaration without both forms.
7546
+ */
7547
+ countLine(subtitle, total, shown) {
7548
+ const fill = (text) => {
7549
+ const out = String(text).replace('{total}', String(total))
7550
+ return shown === null ? out : out.replace('{shown}', String(shown))
7551
+ }
7552
+ if (typeof subtitle === 'string') {
7553
+ return fill(this.cnTranslate(subtitle))
7554
+ }
7555
+ const singular = subtitle && typeof subtitle.singular === 'string' ? subtitle.singular : ''
7556
+ const plural = subtitle && typeof subtitle.plural === 'string' ? subtitle.plural : ''
7557
+ if (singular === '' || plural === '') {
7558
+ return ''
7559
+ }
7560
+ if (typeof this.cnAppId === 'string' && this.cnAppId !== '') {
7561
+ const vars = shown === null ? { total } : { total, shown }
7562
+ return n(this.cnAppId, singular, plural, total, vars)
7563
+ }
7564
+ return fill(this.cnTranslate(total === 1 ? singular : plural))
7565
+ },
7566
+
7567
+ /**
7568
+ * An `open-form` header action saved a record: the list reloads so the
7569
+ * new row shows.
7570
+ *
7571
+ * @spec openspec/changes/index-header-open-form/specs/index-header/spec.md#requirement-an-index-header-action-can-open-the-create-form
7572
+ * @return {void}
7573
+ */
7574
+ onHeaderActionCreated() {
7575
+ this.onRefreshEvent()
7576
+ },
7577
+
7080
7578
  pushAiContext() {
7081
7579
  applyAiContext(this.cnAiContext, 'index', {
7082
7580
  register: this.register,
@@ -7292,6 +7790,72 @@ export default {
7292
7790
  this.$emit('clear-filters')
7293
7791
  },
7294
7792
 
7793
+ /**
7794
+ * Fetch what the board view needs: the rows of a reference column
7795
+ * field (once per field) and the narrowing select's options.
7796
+ *
7797
+ * @return {Promise<void>}
7798
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-columns-can-be-the-rows-a-field-references
7799
+ */
7800
+ async loadBoardSources() {
7801
+ const active = this.boardActiveColumnField
7802
+ if (active && active.kind === 'reference' && !Object.hasOwn(this.boardRefs, active.field)) {
7803
+ const property = this.effectiveSchema?.properties?.[active.field] || null
7804
+ const target = referenceTargetOf(active.source, { register: this.register, property })
7805
+ if (target.register && target.schema) {
7806
+ let rows
7807
+ try {
7808
+ rows = await fetchReferenceObjects({ ...target, filter: active.source?.filter || {} })
7809
+ } catch {
7810
+ rows = []
7811
+ }
7812
+ this.boardRefs = { ...this.boardRefs, [active.field]: rows }
7813
+ }
7814
+ }
7815
+ const narrow = this.boardNarrow
7816
+ if (narrow && this.boardNarrowOptions.length === 0) {
7817
+ const property = this.effectiveSchema?.properties?.[narrow.field] || null
7818
+ const target = referenceTargetOf(narrow.source || {}, { register: this.register, property })
7819
+ let rows
7820
+ try {
7821
+ rows = await fetchReferenceObjects({ ...target, filter: narrow.source?.filter || {} })
7822
+ } catch {
7823
+ rows = []
7824
+ }
7825
+ const labelField = narrow.source?.labelField || 'title'
7826
+ this.boardNarrowOptions = rows
7827
+ .map((row) => ({ value: refIdOf(row), label: String(row?.[labelField] ?? row?.name ?? row?.title ?? refIdOf(row)) }))
7828
+ .filter((option) => option.value !== '')
7829
+ .sort((a, b) => a.label.localeCompare(b.label))
7830
+ }
7831
+ },
7832
+
7833
+ /**
7834
+ * The column switch changed.
7835
+ *
7836
+ * @param {string} field The column field picked.
7837
+ * @return {void}
7838
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-board-can-switch-the-field-its-columns-come-from
7839
+ */
7840
+ onBoardColumnFieldChange(field) {
7841
+ this.boardColumnFieldChoice = field
7842
+ /**
7843
+ * @event board-column-field-change The board's column switch picked another field. Payload: the field name.
7844
+ */
7845
+ this.$emit('board-column-field-change', field)
7846
+ },
7847
+
7848
+ /**
7849
+ * The narrowing select changed: it sets the page filter on its field,
7850
+ * so the cards narrow with the columns and the active filter shows.
7851
+ *
7852
+ * @param {string} value The parent id, '' for all.
7853
+ * @return {void}
7854
+ */
7855
+ onBoardNarrowChange(value) {
7856
+ this.onFilterEvent({ key: this.boardNarrow.field, values: value === '' ? [] : [value] })
7857
+ },
7858
+
7295
7859
  /**
7296
7860
  * A paged board's "Show N more": ask for the next page.
7297
7861
  *
@@ -7299,6 +7863,10 @@ export default {
7299
7863
  * @spec openspec/changes/screens-kanban-parity/specs/board-view/spec.md#requirement-a-long-column-is-cut-with-a-show-more-button
7300
7864
  */
7301
7865
  onBoardLoadMore() {
7866
+ if (this.boardLoadsAll) {
7867
+ this.list.loadMore()
7868
+ return
7869
+ }
7302
7870
  const page = Number(this.pagination?.page || 1)
7303
7871
  if (page < Number(this.pagination?.pages || 1)) {
7304
7872
  this.onPageEvent(page + 1)
@@ -8637,6 +9205,23 @@ export default {
8637
9205
  this.$emit('view-mode-change', mode)
8638
9206
  },
8639
9207
 
9208
+ /**
9209
+ * Open in the mode the address names (`?_view=board`), when the page
9210
+ * offers it. The key starts with `_`, like `_search` and `_page`, so it
9211
+ * is never read as a list filter. A menu entry's `query` can so open a
9212
+ * list as its board, on the one page that lists the schema
9213
+ * (screens-board-reference-columns).
9214
+ *
9215
+ * @return {void}
9216
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-address-can-open-a-list-in-a-view-mode
9217
+ */
9218
+ applyViewModeFromRoute() {
9219
+ const wanted = this.$route?.query?._view
9220
+ if (typeof wanted === 'string' && wanted !== this.currentViewMode && this.effectiveToggleModes.includes(wanted)) {
9221
+ this.currentViewMode = wanted
9222
+ }
9223
+ },
9224
+
8640
9225
  /**
8641
9226
  * Handle selection changes from CnDataTable/CnCardGrid.
8642
9227
  * Updates internal state and re-emits for parent.