@conduction/nextcloud-vue 2.56.0-beta.37 → 2.56.0-beta.39

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 (301) hide show
  1. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue.js +1 -1
  2. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js +3 -2
  3. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
  6. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +5 -4
  7. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue.js +1 -1
  10. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js +2 -1
  11. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue3.js.map +1 -1
  13. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  14. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +2 -1
  15. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  16. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  17. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  18. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +156 -14
  19. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  20. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +105 -74
  21. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  22. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue.js +1 -1
  23. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js +2 -1
  24. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js.map +1 -1
  25. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue3.js.map +1 -1
  26. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue.js +1 -1
  27. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +2 -1
  28. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
  29. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
  30. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  31. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +6 -5
  32. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  33. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  34. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue.js +1 -1
  35. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js +2 -1
  36. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js.map +1 -1
  37. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue3.js.map +1 -1
  38. package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +1 -1
  39. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js +2 -1
  40. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -1
  41. package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -1
  42. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
  43. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +2 -1
  44. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
  45. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
  46. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  47. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +2 -1
  48. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  49. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  50. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue.js +1 -1
  51. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js +3 -1
  52. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js.map +1 -1
  53. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue3.js.map +1 -1
  54. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js +2 -1
  55. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js.map +1 -1
  56. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue3.js.map +1 -1
  57. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue.js +1 -1
  58. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js +2 -1
  59. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js.map +1 -1
  60. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue3.js.map +1 -1
  61. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue.js +1 -1
  62. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js +3 -1
  63. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js.map +1 -1
  64. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue3.js.map +1 -1
  65. package/dist/esm/components/CnFileManager/CnFileManager.vue.js +1 -1
  66. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js +3 -1
  67. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js.map +1 -1
  68. package/dist/esm/components/CnFileManager/CnFileManager.vue3.js.map +1 -1
  69. package/dist/esm/components/CnFilePreview/CnFilePreview.vue.js +1 -1
  70. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js +2 -1
  71. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js.map +1 -1
  72. package/dist/esm/components/CnFilePreview/CnFilePreview.vue3.js.map +1 -1
  73. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  74. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +49 -1
  75. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  76. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +3 -3
  77. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  78. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue.js +1 -1
  79. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +2 -1
  80. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
  81. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
  82. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +30 -5
  83. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  84. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  85. package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
  86. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +2 -1
  87. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
  88. package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
  89. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue.js +1 -1
  90. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js +3 -2
  91. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js.map +1 -1
  92. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue3.js.map +1 -1
  93. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
  94. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +28 -0
  95. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  96. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +82 -75
  97. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  98. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue.js +1 -1
  99. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js +5 -4
  100. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js.map +1 -1
  101. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue3.js.map +1 -1
  102. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue.js +1 -1
  103. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js +2 -1
  104. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js.map +1 -1
  105. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue3.js.map +1 -1
  106. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue.js +1 -1
  107. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js +2 -1
  108. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js.map +1 -1
  109. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue3.js.map +1 -1
  110. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue.js +1 -1
  111. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +2 -1
  112. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  113. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  114. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue.js +1 -1
  115. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js +2 -1
  116. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js.map +1 -1
  117. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue3.js.map +1 -1
  118. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue.js +1 -1
  119. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js +2 -1
  120. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js.map +1 -1
  121. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue3.js.map +1 -1
  122. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue.js +1 -1
  123. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js +2 -1
  124. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js.map +1 -1
  125. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue3.js.map +1 -1
  126. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js +2 -0
  127. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js.map +1 -1
  128. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js +2 -2
  129. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js.map +1 -1
  130. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue.js +1 -1
  131. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +2 -1
  132. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
  133. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
  134. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue.js +1 -1
  135. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js +2 -1
  136. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js.map +1 -1
  137. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue3.js.map +1 -1
  138. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  139. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +36 -0
  140. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  141. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +55 -40
  142. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  143. package/dist/esm/components/CnTasksCard/CnTasksCard.vue.js +1 -1
  144. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js +2 -1
  145. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js.map +1 -1
  146. package/dist/esm/components/CnTasksCard/CnTasksCard.vue3.js.map +1 -1
  147. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
  148. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +2 -1
  149. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  150. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  151. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue.js +1 -1
  152. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js +2 -1
  153. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js.map +1 -1
  154. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue.js +1 -1
  155. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js +2 -1
  156. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js.map +1 -1
  157. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue3.js.map +1 -1
  158. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  159. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +3 -26
  160. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  161. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  162. package/dist/esm/dialogs/CnNoteHistoryDialog.vue.js +1 -1
  163. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js +2 -1
  164. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js.map +1 -1
  165. package/dist/esm/dialogs/CnNoteHistoryDialog.vue3.js.map +1 -1
  166. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue.js +1 -1
  167. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js +3 -2
  168. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js.map +1 -1
  169. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue3.js.map +1 -1
  170. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue.js +1 -1
  171. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js +4 -3
  172. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js.map +1 -1
  173. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue3.js.map +1 -1
  174. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue.js +1 -1
  175. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -2
  176. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
  177. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
  178. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue.js +1 -1
  179. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js +2 -1
  180. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js.map +1 -1
  181. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js.map +1 -1
  182. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue.js +1 -1
  183. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js +6 -5
  184. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js.map +1 -1
  185. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue3.js.map +1 -1
  186. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue.js +1 -1
  187. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js +2 -1
  188. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js.map +1 -1
  189. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue3.js.map +1 -1
  190. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue.js +1 -1
  191. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js +2 -1
  192. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js.map +1 -1
  193. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js.map +1 -1
  194. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue.js +1 -1
  195. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +2 -1
  196. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
  197. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
  198. package/dist/esm/integrations/builtin/email/CnEmailCard.vue.js +1 -1
  199. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js +2 -1
  200. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js.map +1 -1
  201. package/dist/esm/integrations/builtin/email/CnEmailCard.vue3.js.map +1 -1
  202. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue.js +1 -1
  203. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +2 -1
  204. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  205. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  206. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue.js +1 -1
  207. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js +2 -1
  208. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js.map +1 -1
  209. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue3.js.map +1 -1
  210. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue.js +1 -1
  211. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js +2 -1
  212. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js.map +1 -1
  213. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js.map +1 -1
  214. package/dist/esm/l10n/en.json.js +35 -2
  215. package/dist/esm/l10n/en.json.js.map +1 -1
  216. package/dist/esm/l10n/nl.json.js +38 -2
  217. package/dist/esm/l10n/nl.json.js.map +1 -1
  218. package/dist/esm/library-style.js +1 -1
  219. package/dist/esm/nextcloud-vue.css +1068 -962
  220. package/dist/esm/store/useObjectStore.js +7 -2
  221. package/dist/esm/store/useObjectStore.js.map +1 -1
  222. package/dist/esm/utils/boardColumns.js +50 -1
  223. package/dist/esm/utils/boardColumns.js.map +1 -1
  224. package/dist/esm/utils/boardReferenceColumns.js +115 -4
  225. package/dist/esm/utils/boardReferenceColumns.js.map +1 -1
  226. package/dist/esm/utils/contentHeaderLink.js +48 -1
  227. package/dist/esm/utils/contentHeaderLink.js.map +1 -1
  228. package/dist/esm/utils/schema.js +5 -4
  229. package/dist/esm/utils/schema.js.map +1 -1
  230. package/dist/esm/utils/userLocale.js +30 -0
  231. package/dist/esm/utils/userLocale.js.map +1 -0
  232. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  233. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  234. package/dist/nextcloud-vue.cjs.js +1088 -476
  235. package/dist/nextcloud-vue.cjs.js.map +2 -2
  236. package/dist/nextcloud-vue.css +1068 -962
  237. package/l10n/en.json +35 -2
  238. package/l10n/nl.json +38 -2
  239. package/package.json +1 -1
  240. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +3 -2
  241. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +5 -4
  242. package/src/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue +2 -1
  243. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +2 -1
  244. package/src/components/CnBoardView/CnBoardView.vue +189 -24
  245. package/src/components/CnCalendarEventPicker/CnCalendarEventPicker.vue +2 -1
  246. package/src/components/CnCalendarWidget/CnCalendarWidget.vue +2 -1
  247. package/src/components/CnChartWidget/CnChartWidget.vue +6 -5
  248. package/src/components/CnCollectivePagePicker/CnCollectivePagePicker.vue +2 -1
  249. package/src/components/CnConversationThread/CnConversationThread.vue +2 -1
  250. package/src/components/CnCountdownWidget/CnCountdownWidget.vue +2 -1
  251. package/src/components/CnDashboardPage/CnDashboardPage.vue +2 -1
  252. package/src/components/CnDataMatrix/CnDataMatrix.vue +2 -1
  253. package/src/components/CnDetailPage/CnDetailHeaderChips.vue +2 -1
  254. package/src/components/CnEmailPicker/CnEmailPicker.vue +2 -1
  255. package/src/components/CnFederationStatus/CnFederationStatus.vue +3 -1
  256. package/src/components/CnFileManager/CnFileManager.vue +2 -1
  257. package/src/components/CnFilePreview/CnFilePreview.vue +2 -1
  258. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +54 -6
  259. package/src/components/CnFollowToggle/CnFollowToggle.vue +2 -1
  260. package/src/components/CnIndexPage/CnIndexPage.vue +30 -4
  261. package/src/components/CnNotesCard/CnNotesCard.vue +2 -1
  262. package/src/components/CnObjectCalendar/CnObjectCalendar.vue +3 -2
  263. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +36 -0
  264. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +5 -4
  265. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +2 -1
  266. package/src/components/CnObjectSidebar/CnFlowTasksPanel.vue +2 -1
  267. package/src/components/CnObjectSidebar/CnNotesTab.vue +2 -1
  268. package/src/components/CnObjectSidebar/CnTasksTab.vue +2 -1
  269. package/src/components/CnPropertySourceField/CnPropertySourceField.vue +2 -1
  270. package/src/components/CnRoadmapItem/CnRoadmapItem.vue +2 -1
  271. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +4 -2
  272. package/src/components/CnStatsBlock/CnStatsBlock.vue +2 -1
  273. package/src/components/CnSummaryAggregates/CnSummaryAggregates.vue +2 -1
  274. package/src/components/CnTabsWidget/CnTabsWidget.vue +71 -0
  275. package/src/components/CnTasksCard/CnTasksCard.vue +2 -1
  276. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +2 -1
  277. package/src/components/CnTranslatedBadge/CnTranslatedBadge.vue +2 -1
  278. package/src/components/CnVersionHistory/CnVersionHistory.vue +2 -1
  279. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +3 -26
  280. package/src/css/board.css +40 -0
  281. package/src/dialogs/CnNoteHistoryDialog.vue +2 -1
  282. package/src/integrations/builtin/activity/CnActivityCard.vue +3 -2
  283. package/src/integrations/builtin/activity/CnActivityTab.vue +4 -3
  284. package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +3 -2
  285. package/src/integrations/builtin/calendar/CnCalendarCard.vue +2 -1
  286. package/src/integrations/builtin/calendar/CnCalendarTab.vue +6 -5
  287. package/src/integrations/builtin/contactmoment/CnContactmomentCard.vue +2 -1
  288. package/src/integrations/builtin/cospend/CnCospendTab.vue +2 -1
  289. package/src/integrations/builtin/deck/CnDeckTab.vue +2 -1
  290. package/src/integrations/builtin/email/CnEmailCard.vue +2 -1
  291. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +2 -1
  292. package/src/integrations/builtin/field-inspection/CnFieldInspectionTab.vue +2 -1
  293. package/src/integrations/builtin/photos/CnPhotosTab.vue +2 -1
  294. package/src/schemas/app-manifest-v2.schema.json +4 -1
  295. package/src/store/useObjectStore.js +7 -2
  296. package/src/utils/boardColumns.js +49 -0
  297. package/src/utils/boardReferenceColumns.js +114 -3
  298. package/src/utils/contentHeaderLink.js +47 -0
  299. package/src/utils/schema.js +5 -4
  300. package/src/utils/userLocale.js +26 -0
  301. package/src/utils/validateManifestV2.compiled.js +2 -2
package/l10n/en.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "Could not change the favourite.": "Could not change the favourite.",
74
74
  "Follow": "Follow",
75
75
  "Following": "Following",
76
- "Loading …": "Loading …",
76
+ "Loading …": "Loading …",
77
77
  "Add a colleague": "Add a colleague",
78
78
  "{count} followers": "{count} followers",
79
79
  "Follow this record to get its updates": "Follow this record to get its updates",
@@ -1440,7 +1440,40 @@
1440
1440
  "Register {id}": "Register {id}",
1441
1441
  "Schema {id}": "Schema {id}",
1442
1442
  "The registers could not be loaded: {reason}": "The registers could not be loaded: {reason}",
1443
- "no connection": "no connection"
1443
+ "no connection": "no connection",
1444
+ "Confirm action": "Confirm action",
1445
+ "Are you sure you want to continue?": "Are you sure you want to continue?",
1446
+ "Confirm": "Confirm",
1447
+ "Action failed.": "Action failed.",
1448
+ "Could not open the form.": "Could not open the form.",
1449
+ "Could not open this action.": "Could not open this action.",
1450
+ "Saved.": "Saved.",
1451
+ "Save failed.": "Save failed.",
1452
+ "Action completed.": "Action completed.",
1453
+ "Run queued": "Run queued",
1454
+ "Agent runtime unavailable": "Agent runtime unavailable",
1455
+ "Run completed.": "Run completed.",
1456
+ "Edit with Buildiq": "Edit with Buildiq",
1457
+ "Save page": "Save page",
1458
+ "Edit page": "Edit page",
1459
+ "Add widget…": "Add widget…",
1460
+ "Edit pages…": "Edit pages…",
1461
+ "Edit menu…": "Edit menu…",
1462
+ "Edit sidebar…": "Edit sidebar…",
1463
+ "Edit actions…": "Edit actions…",
1464
+ "Edit data…": "Edit data…",
1465
+ "Edit flows…": "Edit flows…",
1466
+ "This value was not accepted.": "This value was not accepted.",
1467
+ "Provide details": "Provide details",
1468
+ "This field is required.": "This field is required.",
1469
+ "This action does not accept the field \"{field}\".": "This action does not accept the field \"{field}\".",
1470
+ "Are you sure?": "Are you sure?",
1471
+ "Loading": "Loading",
1472
+ "Configure widget": "Configure widget",
1473
+ "Link related object": "Link related object",
1474
+ "{type} parts": "{type} parts",
1475
+ "Cannot save: this record has no id, so the edit would create a duplicate instead of updating it.": "Cannot save: this record has no id, so the edit would create a duplicate instead of updating it.",
1476
+ "Save failed": "Save failed"
1444
1477
  },
1445
1478
  "plurals": {
1446
1479
  "{count} selected": [
package/l10n/nl.json CHANGED
@@ -73,7 +73,7 @@
73
73
  "Could not change the favourite.": "De favoriet kon niet worden gewijzigd.",
74
74
  "Follow": "Volgen",
75
75
  "Following": "Volgend",
76
- "Loading …": "Laden …",
76
+ "Loading …": "Laden …",
77
77
  "Add a colleague": "Collega toevoegen",
78
78
  "{count} followers": "{count} volgers",
79
79
  "Follow this record to get its updates": "Volg dit dossier om de wijzigingen te ontvangen",
@@ -1600,6 +1600,9 @@
1600
1600
  "{count} on this page": "{count} op deze pagina",
1601
1601
  "{name} cannot move to {column}.": "{name} kan niet naar {column}.",
1602
1602
  "{name}, in {column}": "{name}, in {column}",
1603
+ "full": "vol",
1604
+ "{count} / {capacity}": "{count} / {capacity}",
1605
+ "{column} is full: {count} of {capacity}.": "{column} is vol: {count} van {capacity}.",
1603
1606
  "This card cannot move to that column.": "Deze kaart kan niet naar die kolom.",
1604
1607
  "Nobody": "Niemand",
1605
1608
  "{label}:": "{label}:",
@@ -1624,7 +1627,40 @@
1624
1627
  "Register {id}": "Register {id}",
1625
1628
  "Schema {id}": "Schema {id}",
1626
1629
  "The registers could not be loaded: {reason}": "De registers konden niet worden geladen: {reason}",
1627
- "no connection": "geen verbinding"
1630
+ "no connection": "geen verbinding",
1631
+ "Confirm action": "Actie bevestigen",
1632
+ "Are you sure you want to continue?": "Weet je zeker dat je wilt doorgaan?",
1633
+ "Confirm": "Bevestigen",
1634
+ "Action failed.": "De actie is mislukt.",
1635
+ "Could not open the form.": "Het formulier kon niet worden geopend.",
1636
+ "Could not open this action.": "Deze actie kon niet worden geopend.",
1637
+ "Saved.": "Opgeslagen.",
1638
+ "Save failed.": "Opslaan is mislukt.",
1639
+ "Action completed.": "Actie uitgevoerd.",
1640
+ "Run queued": "Run staat in de wachtrij",
1641
+ "Agent runtime unavailable": "De agent-runtime is niet beschikbaar",
1642
+ "Run completed.": "Run voltooid.",
1643
+ "Edit with Buildiq": "Bewerken met Buildiq",
1644
+ "Save page": "Pagina opslaan",
1645
+ "Edit page": "Pagina bewerken",
1646
+ "Add widget…": "Widget toevoegen…",
1647
+ "Edit pages…": "Pagina's bewerken…",
1648
+ "Edit menu…": "Menu bewerken…",
1649
+ "Edit sidebar…": "Zijbalk bewerken…",
1650
+ "Edit actions…": "Acties bewerken…",
1651
+ "Edit data…": "Gegevens bewerken…",
1652
+ "Edit flows…": "Flows bewerken…",
1653
+ "This value was not accepted.": "Deze waarde is niet geaccepteerd.",
1654
+ "Provide details": "Geef de details op",
1655
+ "This field is required.": "Dit veld is verplicht.",
1656
+ "This action does not accept the field \"{field}\".": "Deze actie accepteert het veld \"{field}\" niet.",
1657
+ "Are you sure?": "Weet je het zeker?",
1658
+ "Loading": "Laden",
1659
+ "Configure widget": "Widget instellen",
1660
+ "Link related object": "Gerelateerd object koppelen",
1661
+ "{type} parts": "Onderdelen van {type}",
1662
+ "Cannot save: this record has no id, so the edit would create a duplicate instead of updating it.": "Opslaan kan niet: dit record heeft geen id, dus de wijziging zou een kopie maken in plaats van het record bij te werken.",
1663
+ "Save failed": "Opslaan is mislukt"
1628
1664
  },
1629
1665
  "plurals": {
1630
1666
  "{count} selected": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/nextcloud-vue",
3
- "version": "2.56.0-beta.37",
3
+ "version": "2.56.0-beta.39",
4
4
  "description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
5
5
  "homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
6
6
  "bugs": {
@@ -30,6 +30,7 @@
30
30
 
31
31
  <script>
32
32
  import { translate as t } from '@nextcloud/l10n'
33
+ import { userLocale } from '../../utils/userLocale.js'
33
34
 
34
35
  export default {
35
36
  name: 'CnMetadataTab',
@@ -62,13 +63,13 @@ export default {
62
63
  metadataCreated() {
63
64
  const o = this.item?.['@self']
64
65
  const v = o?.created
65
- return v ? new Date(v).toLocaleString() : '—'
66
+ return v ? new Date(v).toLocaleString(userLocale()) : '—'
66
67
  },
67
68
 
68
69
  metadataUpdated() {
69
70
  const o = this.item?.['@self']
70
71
  const v = o?.updated
71
- return v ? new Date(v).toLocaleString() : '—'
72
+ return v ? new Date(v).toLocaleString(userLocale()) : '—'
72
73
  },
73
74
 
74
75
  defaultRows() {
@@ -186,6 +186,7 @@ import Plus from 'vue-material-design-icons/Plus.vue'
186
186
  import CnColorPicker from '../CnColorPicker/CnColorPicker.vue'
187
187
  import CnJsonViewer from '../CnJsonViewer/CnJsonViewer.vue'
188
188
  import { formatValue, validateValue } from '../../utils/schema.js'
189
+ import { userLocale } from '../../utils/userLocale.js'
189
190
 
190
191
  const SUPPORTED_WIDGETS = ['text', 'number', 'boolean', 'datetime', 'textarea', 'array', 'select', 'object', 'objectArray', 'color']
191
192
 
@@ -729,19 +730,19 @@ export default {
729
730
  // Same local-midnight parse as datetimeValue to avoid UTC-shift in display.
730
731
  if (fmt === 'date' && typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v)) {
731
732
  const [year, month, day] = v.split('-').map(Number)
732
- return new Date(year, month - 1, day).toLocaleDateString()
733
+ return new Date(year, month - 1, day).toLocaleDateString(userLocale())
733
734
  }
734
735
  const d = new Date(v)
735
736
  if (Number.isNaN(d.getTime())) {
736
737
  return String(v)
737
738
  }
738
739
  if (fmt === 'date') {
739
- return d.toLocaleDateString()
740
+ return d.toLocaleDateString(userLocale())
740
741
  }
741
742
  if (fmt === 'time') {
742
- return d.toLocaleTimeString()
743
+ return d.toLocaleTimeString(userLocale())
743
744
  }
744
- return d.toLocaleString()
745
+ return d.toLocaleString(userLocale())
745
746
  },
746
747
  },
747
748
 
@@ -101,6 +101,7 @@ import { translate as t } from '@nextcloud/l10n'
101
101
  import { NcButton, NcDialog, NcEmptyContent, NcLoadingIcon, NcNoteCard, NcTextField } from '@nextcloud/vue'
102
102
  import ChartBar from 'vue-material-design-icons/ChartBar.vue'
103
103
  import { buildHeaders, prefixUrl } from '../../utils/index.js'
104
+ import { userLocale } from '../../utils/userLocale.js'
104
105
 
105
106
  export default {
106
107
  name: 'CnAnalyticsReportPicker',
@@ -247,7 +248,7 @@ export default {
247
248
  if (Number.isNaN(d.getTime())) {
248
249
  return ''
249
250
  }
250
- return d.toLocaleDateString(undefined, { dateStyle: 'medium' })
251
+ return d.toLocaleDateString(userLocale(), { dateStyle: 'medium' })
251
252
  } catch {
252
253
  return ''
253
254
  }
@@ -49,6 +49,7 @@ import { markRaw } from 'vue'
49
49
  import History from 'vue-material-design-icons/History.vue'
50
50
  import CnDetailCard from '../CnDetailCard/CnDetailCard.vue'
51
51
  import { buildHeaders, prefixUrl } from '../../utils/index.js'
52
+ import { userLocale } from '../../utils/userLocale.js'
52
53
 
53
54
  /**
54
55
  * CnAuditTrailCard — compact audit-trail widget rendered by the
@@ -214,7 +215,7 @@ export default {
214
215
  if (Number.isNaN(d.getTime()) === true) {
215
216
  return String(raw)
216
217
  }
217
- return d.toLocaleString()
218
+ return d.toLocaleString(userLocale())
218
219
  },
219
220
  },
220
221
  }
@@ -36,11 +36,12 @@
36
36
  v-for="column in lane.columns"
37
37
  :key="`col-${lane.key}-${column.key}`"
38
38
  class="cn-board-view__column"
39
- :class="{ 'cn-board-view__column--unreachable': isUnreachable(column) }"
39
+ :class="{ 'cn-board-view__column--unreachable': isUnreachable(column), 'cn-board-view__column--full': isFull(column), 'cn-board-view__column--reason': dragReason(column) !== '' }"
40
40
  role="listitem"
41
41
  data-testid="cn-board-column"
42
42
  :data-column="column.key"
43
43
  :data-unreachable="isUnreachable(column) ? 'true' : null"
44
+ :data-full="isFull(column) ? 'true' : null"
44
45
  @dragover.prevent
45
46
  @drop="onDrop(column, $event)">
46
47
  <!-- Board look: a dot, the label and a white count badge, with an
@@ -53,8 +54,11 @@
53
54
  :style="{ background: dotColor(column) }"
54
55
  aria-hidden="true" />
55
56
  <span class="cn-board-view__column-title">{{ column.label }}</span>
56
- <span class="cn-board-view__badge" data-testid="cn-board-count">
57
- {{ column.count }}<span v-if="paged" class="hidden-visually"> {{ t('nextcloud-vue', 'on this page') }}</span>
57
+ <span
58
+ class="cn-board-view__badge"
59
+ :class="{ 'cn-board-view__badge--full': isFull(column) }"
60
+ data-testid="cn-board-count">
61
+ {{ capacityOf(column) === null ? column.count : capacityText(column) }}<span v-if="paged" class="hidden-visually"> {{ t('nextcloud-vue', 'on this page') }}</span><span v-if="isFull(column)" class="hidden-visually">{{ ' ' + t('nextcloud-vue', 'full') }}</span>
58
62
  </span>
59
63
  </h2>
60
64
  <span
@@ -66,11 +70,21 @@
66
70
  </div>
67
71
  <h3 v-else class="cn-board-view__column-header">
68
72
  {{ column.label }}
69
- <span class="cn-board-view__count" data-testid="cn-board-count">
70
- {{ countLabel(column) }}
73
+ <span
74
+ class="cn-board-view__count"
75
+ :class="{ 'cn-board-view__count--full': isFull(column) }"
76
+ data-testid="cn-board-count">
77
+ {{ countLabel(column) }}<span v-if="isFull(column)" class="hidden-visually">{{ ' ' + t('nextcloud-vue', 'full') }}</span>
71
78
  </span>
72
79
  </h3>
73
80
 
81
+ <p
82
+ v-if="dragReason(column) !== ''"
83
+ class="cn-board-view__column-reason"
84
+ data-testid="cn-board-column-reason">
85
+ {{ dragReason(column) }}
86
+ </p>
87
+
74
88
  <!--
75
89
  A list of its own, so a reader is told how many cards
76
90
  this column holds. The column is a listitem of the
@@ -176,14 +190,18 @@
176
190
  class="cn-board-view__menu-item"
177
191
  data-testid="cn-board-menu-move"
178
192
  :data-target="target.key"
179
- :aria-disabled="isMoveAllowed(card, target) ? null : 'true'"
180
- :class="{ 'cn-board-view__menu-item--blocked': !isMoveAllowed(card, target) }"
181
- @click="isMoveAllowed(card, target) && onMenuMove(card, column, target)">
193
+ :aria-disabled="canMoveTo(card, target) ? null : 'true'"
194
+ :class="{ 'cn-board-view__menu-item--blocked': !canMoveTo(card, target), 'cn-board-view__menu-item--reason': blockReason(card, target) !== '' }"
195
+ @click="canMoveTo(card, target) && onMenuMove(card, column, target)">
182
196
  {{ target.label }}
183
197
  <span
184
- v-if="!isMoveAllowed(card, target)"
198
+ v-if="!canMoveTo(card, target) && blockedNote(card, target) !== ''"
185
199
  class="cn-board-view__menu-note"
186
- data-testid="cn-board-menu-blocked">{{ notAllowedLabel }}</span>
200
+ data-testid="cn-board-menu-blocked">{{ blockedNote(card, target) }}</span>
201
+ <span
202
+ v-if="blockReason(card, target) !== ''"
203
+ class="cn-board-view__menu-reason"
204
+ data-testid="cn-board-menu-reason">{{ blockReason(card, target) }}</span>
187
205
  </button>
188
206
  </div>
189
207
  <button
@@ -337,13 +355,14 @@ import { translate as t } from '@nextcloud/l10n'
337
355
  import CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'
338
356
  import { normalizeLook } from '../../composables/useLook.js'
339
357
  import { isBadgeVariant } from '../../utils/badgeVariants.js'
340
- import { buildBoardColumns, resolveStageColor } from '../../utils/boardColumns.js'
358
+ import { buildBoardColumns, normalizeAllowed, resolveStageColor } from '../../utils/boardColumns.js'
341
359
  import { buildSwimlanes } from '../../utils/boardSwimlanes.js'
342
360
  import { DROP_OUTCOMES, runBoardDrop } from '../../utils/boardTransition.js'
343
361
  import { daysUntil, dueStateForRow } from '../../utils/dueRule.js'
344
362
  import { formatMetricValue } from '../../utils/formatMetric.js'
345
363
  import { readPath } from '../../utils/readPath.js'
346
364
  import { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'
365
+ import { userLocale } from '../../utils/userLocale.js'
347
366
 
348
367
  import '../../css/board.css'
349
368
 
@@ -584,7 +603,13 @@ export default {
584
603
  * it is refused without asking the host. Absent, every column is
585
604
  * offered and the host's move decides.
586
605
  *
587
- * @type {((card: object) => Promise<Array<string>|null>)|null}
606
+ * An entry may also be `{ key, allowed, reason }`. With `allowed:
607
+ * false` the column is blocked: the menu shows the reason under its
608
+ * name, the column shows it under its header during a drag, and a
609
+ * drop there is refused with it.
610
+ *
611
+ * @type {((card: object) => Promise<Array<string|{key: string, allowed?: boolean, reason?: string}>|null>)|null}
612
+ * @spec openspec/changes/board-move-block-reasons/specs/board-view/spec.md#requirement-a-move-target-can-be-blocked-with-a-reason
588
613
  * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
589
614
  */
590
615
  allowedMoves: {
@@ -609,9 +634,9 @@ export default {
609
634
  expanded: [],
610
635
  /** The card whose menu is open (board look), by card key. */
611
636
  openMenuKey: null,
612
- /** Column keys each card may move to (`allowedMoves`), by card key; absent = not asked yet. */
637
+ /** Where each card may move (`allowedMoves`), as `{ keys, reasons }` by card key; null = everywhere, absent = not asked yet. */
613
638
  allowedByCard: {},
614
- /** The column keys the dragged card may reach, or null for all. */
639
+ /** Where the dragged card may move, as `{ keys, reasons }`, or null for everywhere. */
615
640
  dragAllowed: null,
616
641
  }
617
642
  },
@@ -667,6 +692,21 @@ export default {
667
692
  return t('nextcloud-vue', 'not allowed')
668
693
  },
669
694
 
695
+ /** @return {string} The note on a menu target that is full. */
696
+ fullLabel() {
697
+ return t('nextcloud-vue', 'full')
698
+ },
699
+
700
+ /**
701
+ * Every column's total over all lanes, by key: what a limit is
702
+ * measured against, since a swimlane holds only part of a column.
703
+ *
704
+ * @return {Map<string, number>} The totals.
705
+ */
706
+ columnTotals() {
707
+ return new Map(this.board.columns.map((column) => [String(column.key), column.count]))
708
+ },
709
+
670
710
  /** @return {Array<string>} The selected row keys as strings. */
671
711
  selectedKeys() {
672
712
  return (Array.isArray(this.selectedIds) ? this.selectedIds : []).map(String)
@@ -773,7 +813,7 @@ export default {
773
813
  * Ask the host where one card may go (`allowedMoves`), once per card.
774
814
  *
775
815
  * @param {object} card The card.
776
- * @return {Promise<Array<string>|null>} The column keys, or null for all.
816
+ * @return {Promise<{keys: Array<string>, reasons: object}|null>} Where it may go, or null for everywhere.
777
817
  * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
778
818
  */
779
819
  async loadAllowed(card) {
@@ -786,8 +826,7 @@ export default {
786
826
  }
787
827
  let allowed
788
828
  try {
789
- const answer = await this.allowedMoves(card)
790
- allowed = Array.isArray(answer) ? answer.map(String) : null
829
+ allowed = normalizeAllowed(await this.allowedMoves(card))
791
830
  } catch {
792
831
  // Unknown is not "nowhere": the host's move stays the authority.
793
832
  allowed = null
@@ -805,7 +844,116 @@ export default {
805
844
  */
806
845
  isMoveAllowed(card, target) {
807
846
  const allowed = this.allowedByCard[this.cardKey(card)]
808
- return !Array.isArray(allowed) || allowed.includes(String(target.key))
847
+ return !allowed || allowed.keys.includes(String(target.key))
848
+ },
849
+
850
+ /**
851
+ * Why the host blocked a card's move to a column, when it said.
852
+ *
853
+ * @param {object} card The card.
854
+ * @param {object} target The column.
855
+ * @return {string} The reason, '' when the move is allowed or no reason was given.
856
+ * @spec openspec/changes/board-move-block-reasons/specs/board-view/spec.md#requirement-a-move-target-can-be-blocked-with-a-reason
857
+ */
858
+ blockReason(card, target) {
859
+ const allowed = this.allowedByCard[this.cardKey(card)]
860
+ if (!allowed || this.isMoveAllowed(card, target)) {
861
+ return ''
862
+ }
863
+ return allowed.reasons[String(target.key)] || ''
864
+ },
865
+
866
+ /**
867
+ * The note beside a menu target the card cannot move to.
868
+ *
869
+ * @param {object} card The card.
870
+ * @param {object} target The column.
871
+ * @return {string} "full" or "not allowed"; '' when a reason is shown instead.
872
+ */
873
+ blockedNote(card, target) {
874
+ if (this.blockReason(card, target) !== '') {
875
+ return ''
876
+ }
877
+ return this.isMoveAllowed(card, target) && this.isFull(target) ? this.fullLabel : this.notAllowedLabel
878
+ },
879
+
880
+ /**
881
+ * Why the dragged card cannot land on a column, shown under its header.
882
+ *
883
+ * @param {object} column The column.
884
+ * @return {string} The host's reason while a drag is on, else ''.
885
+ * @spec openspec/changes/board-move-block-reasons/specs/board-view/spec.md#requirement-a-move-target-can-be-blocked-with-a-reason
886
+ */
887
+ dragReason(column) {
888
+ if (this.dragging === null || !this.dragAllowed || column.key === this.dragging.fromKey) {
889
+ return ''
890
+ }
891
+ const key = String(column.key)
892
+ return this.dragAllowed.keys.includes(key) ? '' : (this.dragAllowed.reasons[key] || '')
893
+ },
894
+
895
+ /**
896
+ * A column's limit.
897
+ *
898
+ * @param {object} column The column.
899
+ * @return {number|null} The limit, or null when it has none.
900
+ * @spec openspec/changes/board-column-capacity/specs/board-view/spec.md#requirement-a-column-can-carry-a-capacity
901
+ */
902
+ capacityOf(column) {
903
+ const capacity = Number(column?.capacity)
904
+ return Number.isFinite(capacity) && capacity > 0 ? capacity : null
905
+ },
906
+
907
+ /**
908
+ * Whether a column holds as many cards as its limit, or more.
909
+ *
910
+ * @param {object} column The column.
911
+ * @return {boolean} True when full; false without a limit.
912
+ * @spec openspec/changes/board-column-capacity/specs/board-view/spec.md#requirement-a-column-can-carry-a-capacity
913
+ */
914
+ isFull(column) {
915
+ const capacity = this.capacityOf(column)
916
+ return capacity !== null && (this.columnTotals.get(String(column.key)) ?? column.count) >= capacity
917
+ },
918
+
919
+ /**
920
+ * "count / capacity" for a column with a limit.
921
+ *
922
+ * @param {object} column The column.
923
+ * @return {string} The text.
924
+ */
925
+ capacityText(column) {
926
+ return t('nextcloud-vue', '{count} / {capacity}', {
927
+ count: this.columnTotals.get(String(column.key)) ?? column.count,
928
+ capacity: this.capacityOf(column),
929
+ })
930
+ },
931
+
932
+ /**
933
+ * Whether a card may move to a column: the host allows it and the
934
+ * column is not full.
935
+ *
936
+ * @param {object} card The card.
937
+ * @param {object} target The column.
938
+ * @return {boolean} True when the move may be asked for.
939
+ * @spec openspec/changes/board-column-capacity/specs/board-view/spec.md#requirement-a-drop-into-a-full-column-is-refused
940
+ */
941
+ canMoveTo(card, target) {
942
+ return this.isMoveAllowed(card, target) && !this.isFull(target)
943
+ },
944
+
945
+ /**
946
+ * The sentence a drop into a full column is refused with.
947
+ *
948
+ * @param {object} column The column.
949
+ * @return {string} The sentence.
950
+ */
951
+ fullRefusal(column) {
952
+ return t('nextcloud-vue', '{column} is full: {count} of {capacity}.', {
953
+ column: column.label,
954
+ count: this.columnTotals.get(String(column.key)) ?? column.count,
955
+ capacity: this.capacityOf(column),
956
+ })
809
957
  },
810
958
 
811
959
  /**
@@ -815,10 +963,11 @@ export default {
815
963
  * @return {boolean} True while a drag is on and the card cannot go there.
816
964
  */
817
965
  isUnreachable(column) {
818
- return this.dragging !== null
819
- && Array.isArray(this.dragAllowed)
820
- && column.key !== this.dragging.fromKey
821
- && !this.dragAllowed.includes(String(column.key))
966
+ if (this.dragging === null || column.key === this.dragging.fromKey) {
967
+ return false
968
+ }
969
+ return this.isFull(column)
970
+ || (this.dragAllowed !== null && !this.dragAllowed.keys.includes(String(column.key)))
822
971
  },
823
972
 
824
973
  /**
@@ -942,7 +1091,7 @@ export default {
942
1091
  const date = new Date(value)
943
1092
  const shown = Number.isNaN(date.getTime())
944
1093
  ? String(value)
945
- : date.toLocaleDateString(undefined, { day: 'numeric', month: 'short' })
1094
+ : date.toLocaleDateString(userLocale(), { day: 'numeric', month: 'short' })
946
1095
  return days < 0
947
1096
  ? t('nextcloud-vue', 'Overdue {date}', { date: shown })
948
1097
  : t('nextcloud-vue', 'Due {date}', { date: shown })
@@ -1292,6 +1441,9 @@ export default {
1292
1441
  * @return {string} The count.
1293
1442
  */
1294
1443
  countLabel(column) {
1444
+ if (this.capacityOf(column) !== null) {
1445
+ return this.capacityText(column)
1446
+ }
1295
1447
  return this.paged
1296
1448
  ? t('nextcloud-vue', '{count} on this page', { count: column.count })
1297
1449
  : String(column.count)
@@ -1381,7 +1533,8 @@ export default {
1381
1533
  this.dragAllowed = null
1382
1534
  if (column.key !== fromKey && !this.isMoveAllowed(card, column)) {
1383
1535
  const name = this.roleText(card, this.roles.title) || this.cardKey(card)
1384
- this.refusal = t('nextcloud-vue', '{name} cannot move to {column}.', { name, column: column.label })
1536
+ this.refusal = this.blockReason(card, column)
1537
+ || t('nextcloud-vue', '{name} cannot move to {column}.', { name, column: column.label })
1385
1538
  this.$emit('refused', { card, message: this.refusal })
1386
1539
  return
1387
1540
  }
@@ -1411,6 +1564,13 @@ export default {
1411
1564
  async move(card, fromKey, toKey) {
1412
1565
  this.refusal = ''
1413
1566
 
1567
+ const target = this.board.columns.find((column) => String(column.key) === String(toKey))
1568
+ if (target && String(toKey) !== String(fromKey) && this.isFull(target)) {
1569
+ this.refusal = this.fullRefusal(target)
1570
+ this.$emit('refused', { card, message: this.refusal })
1571
+ return
1572
+ }
1573
+
1414
1574
  const result = await runBoardDrop({
1415
1575
  card,
1416
1576
  fromKey,
@@ -1551,4 +1711,9 @@ export default {
1551
1711
  .cn-board-view__refusal {
1552
1712
  color: var(--color-error);
1553
1713
  }
1714
+
1715
+ .cn-board-view__count--full {
1716
+ color: var(--color-error-text, var(--color-error));
1717
+ font-weight: 600;
1718
+ }
1554
1719
  </style>
@@ -120,6 +120,7 @@ import { translate as t } from '@nextcloud/l10n'
120
120
  import { NcButton, NcDialog, NcLoadingIcon, NcTextField } from '@nextcloud/vue'
121
121
  import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
122
122
  import { buildHeaders, prefixUrl } from '../../utils/index.js'
123
+ import { userLocale } from '../../utils/userLocale.js'
123
124
 
124
125
  /**
125
126
  * CnCalendarEventPicker — 2-step calendar/event picker modal for the
@@ -307,7 +308,7 @@ export default {
307
308
  if (Number.isNaN(d.getTime())) {
308
309
  return String(ev.dtstart)
309
310
  }
310
- return d.toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' })
311
+ return d.toLocaleString(userLocale(), { dateStyle: 'medium', timeStyle: 'short' })
311
312
  } catch {
312
313
  return String(ev.dtstart)
313
314
  }
@@ -130,6 +130,7 @@
130
130
 
131
131
  <script>
132
132
  import { translate as t } from '@nextcloud/l10n'
133
+ import { userLocale } from '../../utils/userLocale.js'
133
134
 
134
135
  const VIEW_MODES = ['month', 'week', 'agenda']
135
136
  const DEFAULT_DAYS_AHEAD = 14
@@ -604,7 +605,7 @@ export default {
604
605
  * @return {string} the header label.
605
606
  */
606
607
  formatDayHeader(date) {
607
- const month = date.toLocaleString(undefined, { month: 'short' })
608
+ const month = date.toLocaleString(userLocale(), { month: 'short' })
608
609
  return `${this.weekdayHeaders[date.getDay()]} ${date.getDate()} ${month}`
609
610
  },
610
611
 
@@ -78,6 +78,7 @@ import { resolveObjectOpType } from '../../utils/actionsDispatcher.js'
78
78
  import { resolveObjectTokenContext } from '../../utils/detailObjectContext.js'
79
79
  import { safeCurrencyCode } from '../../utils/formatMetric.js'
80
80
  import { resolveFilterTokens } from '../../utils/resolveFilterTokens.js'
81
+ import { userLocale } from '../../utils/userLocale.js'
81
82
 
82
83
  /**
83
84
  * Nice-ceiling ladder. Deliberately fine-grained: a coarse one (1 / 2 / 5 / 10)
@@ -1636,16 +1637,16 @@ export default {
1636
1637
  const year = d.getFullYear() === thisYear ? {} : { year: 'numeric' }
1637
1638
  switch (String(interval || '').toLowerCase()) {
1638
1639
  case 'minute':
1639
- return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
1640
+ return d.toLocaleString(userLocale(), { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
1640
1641
  case 'hour':
1641
- return d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: '2-digit' })
1642
+ return d.toLocaleString(userLocale(), { month: 'short', day: 'numeric', hour: '2-digit' })
1642
1643
  case 'day':
1643
1644
  case 'week':
1644
- return d.toLocaleDateString(undefined, { day: 'numeric', month: 'short', ...year })
1645
+ return d.toLocaleDateString(userLocale(), { day: 'numeric', month: 'short', ...year })
1645
1646
  case 'year':
1646
- return d.toLocaleDateString(undefined, { year: 'numeric' })
1647
+ return d.toLocaleDateString(userLocale(), { year: 'numeric' })
1647
1648
  default:
1648
- return d.toLocaleDateString(undefined, { month: 'short', year: '2-digit' })
1649
+ return d.toLocaleDateString(userLocale(), { month: 'short', year: '2-digit' })
1649
1650
  }
1650
1651
  },
1651
1652
 
@@ -112,6 +112,7 @@ import { translate as t } from '@nextcloud/l10n'
112
112
  import { NcButton, NcDialog, NcEmptyContent, NcLoadingIcon, NcNoteCard, NcSelect, NcTextField } from '@nextcloud/vue'
113
113
  import BookOpenPageVariant from 'vue-material-design-icons/BookOpenPageVariant.vue'
114
114
  import { buildHeaders, prefixUrl } from '../../utils/index.js'
115
+ import { userLocale } from '../../utils/userLocale.js'
115
116
 
116
117
  export default {
117
118
  name: 'CnCollectivePagePicker',
@@ -267,7 +268,7 @@ export default {
267
268
  if (Number.isNaN(d.getTime())) {
268
269
  return ''
269
270
  }
270
- return d.toLocaleDateString(undefined, { dateStyle: 'medium' })
271
+ return d.toLocaleDateString(userLocale(), { dateStyle: 'medium' })
271
272
  },
272
273
 
273
274
  confirm() {
@@ -86,6 +86,7 @@ import axios from '@nextcloud/axios'
86
86
  import { translate as t } from '@nextcloud/l10n'
87
87
  import { NcButton } from '@nextcloud/vue'
88
88
  import { prefixUrl } from '../../utils/headers.js'
89
+ import { userLocale } from '../../utils/userLocale.js'
89
90
 
90
91
  let conversationThreadUid = 0
91
92
 
@@ -299,7 +300,7 @@ export default {
299
300
  if (!looksLikeDate || Number.isNaN(date.getTime())) {
300
301
  return { label: String(value), datetime: '' }
301
302
  }
302
- const label = date.toLocaleString(undefined, { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })
303
+ const label = date.toLocaleString(userLocale(), { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })
303
304
  return { label, datetime: date.toISOString() }
304
305
  },
305
306