@conduction/nextcloud-vue 2.79.0 → 2.81.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
  2. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
  3. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
  5. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  6. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +13 -11
  7. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +80 -4
  9. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +95 -91
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  12. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +179 -13
  13. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  14. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +52 -16
  15. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  16. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +96 -4
  17. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  18. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +158 -110
  19. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  20. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
  21. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
  22. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
  23. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
  24. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
  25. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
  26. package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
  27. package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
  28. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
  29. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
  30. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
  31. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
  32. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
  33. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
  34. package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
  35. package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
  36. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +1 -1
  37. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +2 -2
  40. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  41. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  42. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +65 -5
  43. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  44. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
  45. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  46. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +19 -11
  47. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  48. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
  49. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  50. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +134 -4
  51. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  52. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +21 -4
  53. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  54. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
  55. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  56. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
  57. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  58. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +1 -1
  59. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -1
  60. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -1
  61. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js +7 -7
  62. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js.map +1 -1
  63. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue3.js.map +1 -1
  64. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
  65. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
  66. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +867 -0
  67. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
  68. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
  69. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
  70. package/dist/esm/components/CnFactsWidget/index.js +30 -0
  71. package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
  72. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
  73. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
  74. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +626 -0
  75. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
  76. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +396 -0
  77. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
  78. package/dist/esm/components/CnFieldListWidget/index.js +29 -0
  79. package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
  80. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +302 -4
  81. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  82. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +417 -244
  83. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  84. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +101 -1
  85. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  86. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +141 -1
  87. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
  88. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
  89. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  90. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
  91. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  92. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +78 -3
  93. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  94. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +74 -49
  95. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  96. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +333 -73
  97. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  98. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +79 -17
  99. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  100. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
  101. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
  102. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
  103. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
  104. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
  105. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
  106. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +7 -7
  107. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  108. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  109. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +1 -1
  110. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -1
  111. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
  112. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  113. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
  114. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  115. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +63 -1
  116. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  117. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +8 -1
  118. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  119. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +14 -0
  120. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  121. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js +5 -1
  122. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  123. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
  124. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
  125. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
  126. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
  127. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
  128. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
  129. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
  130. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
  131. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
  132. package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
  133. package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
  134. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
  135. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
  136. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +411 -0
  137. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
  138. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +178 -0
  139. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
  140. package/dist/esm/components/CnRecordListWidget/index.js +31 -0
  141. package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
  142. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
  143. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
  144. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
  145. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
  146. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
  147. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
  148. package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
  149. package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
  150. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
  151. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
  152. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
  153. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
  154. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
  155. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
  156. package/dist/esm/components/CnSectionsWidget/index.js +35 -0
  157. package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
  158. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  159. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  160. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
  161. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
  162. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
  163. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
  164. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
  165. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
  166. package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
  167. package/dist/esm/components/CnSettingsFormWidget/index.js.map +1 -0
  168. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
  169. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  170. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  171. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +87 -6
  172. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  173. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
  174. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  175. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +84 -1
  176. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  177. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +85 -41
  178. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  179. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
  180. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
  181. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
  182. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
  183. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
  184. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
  185. package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
  186. package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
  187. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +168 -7
  188. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  189. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +86 -23
  190. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  191. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
  192. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  193. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
  194. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  195. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
  196. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
  197. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
  198. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
  199. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
  200. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
  201. package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
  202. package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
  203. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  204. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  205. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +7 -2
  206. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  207. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  208. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  209. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js.map +1 -1
  210. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +301 -6
  211. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  212. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +153 -55
  213. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  214. package/dist/esm/composables/useFormDraft.js +140 -9
  215. package/dist/esm/composables/useFormDraft.js.map +1 -1
  216. package/dist/esm/composables/useListView.js +4 -4
  217. package/dist/esm/composables/useListView.js.map +1 -1
  218. package/dist/esm/index.js +21 -1
  219. package/dist/esm/index.js.map +1 -1
  220. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
  221. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  222. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
  223. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  224. package/dist/esm/integrations/builtin/field-inspection.js +21 -0
  225. package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
  226. package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
  227. package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
  228. package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
  229. package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
  230. package/dist/esm/integrations/offline/index.js +2 -1
  231. package/dist/esm/integrations/offline/index.js.map +1 -1
  232. package/dist/esm/integrations/offline/offlineDb.js +6 -1
  233. package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
  234. package/dist/esm/integrations/offline/syncReplayService.js +8 -2
  235. package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
  236. package/dist/esm/l10n/en.json.js +20 -1
  237. package/dist/esm/l10n/en.json.js.map +1 -1
  238. package/dist/esm/l10n/nl.json.js +70 -2
  239. package/dist/esm/l10n/nl.json.js.map +1 -1
  240. package/dist/esm/nextcloud-vue.css +2192 -222
  241. package/dist/esm/utils/contentHeaderLink.js +51 -0
  242. package/dist/esm/utils/contentHeaderLink.js.map +1 -0
  243. package/dist/esm/utils/detailActionModel.js +60 -3
  244. package/dist/esm/utils/detailActionModel.js.map +1 -1
  245. package/dist/esm/utils/facets.js +75 -3
  246. package/dist/esm/utils/facets.js.map +1 -1
  247. package/dist/esm/utils/fetchFilterCounts.js +40 -5
  248. package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
  249. package/dist/esm/utils/fillTemplate.js +120 -0
  250. package/dist/esm/utils/fillTemplate.js.map +1 -0
  251. package/dist/esm/utils/initials.js +32 -0
  252. package/dist/esm/utils/initials.js.map +1 -0
  253. package/dist/esm/utils/libraryWidgetKeys.js +11 -0
  254. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  255. package/dist/esm/utils/objectWrite.js +59 -0
  256. package/dist/esm/utils/objectWrite.js.map +1 -0
  257. package/dist/esm/utils/pageControls.js +81 -0
  258. package/dist/esm/utils/pageControls.js.map +1 -0
  259. package/dist/esm/utils/personalLenses.js +40 -3
  260. package/dist/esm/utils/personalLenses.js.map +1 -1
  261. package/dist/esm/utils/queryPresets.js +96 -0
  262. package/dist/esm/utils/queryPresets.js.map +1 -0
  263. package/dist/esm/utils/resolveFilterTokens.js +12 -1
  264. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  265. package/dist/esm/utils/resolveManifestTokens.js +2 -0
  266. package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
  267. package/dist/esm/utils/schema.js +21 -0
  268. package/dist/esm/utils/schema.js.map +1 -1
  269. package/dist/esm/utils/sentinelTokens.js +22 -4
  270. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  271. package/dist/esm/utils/userGroupsPeek.js +91 -0
  272. package/dist/esm/utils/userGroupsPeek.js.map +1 -0
  273. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  274. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  275. package/dist/esm/utils/visibleWhen.js +57 -5
  276. package/dist/esm/utils/visibleWhen.js.map +1 -1
  277. package/dist/esm/utils/widgetDispatch.js +7 -1
  278. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  279. package/dist/esm/utils/widgetVisibility.js +4 -57
  280. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  281. package/dist/nextcloud-vue.cjs.js +19708 -9301
  282. package/dist/nextcloud-vue.cjs.js.map +2 -2
  283. package/dist/nextcloud-vue.css +2192 -222
  284. package/l10n/en.json +20 -1
  285. package/l10n/nl.json +70 -2
  286. package/package.json +2 -1
  287. package/scripts/check-docs-mdx.mjs +108 -0
  288. package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
  289. package/src/components/CnActionsBar/CnActionsBar.md +4 -0
  290. package/src/components/CnActionsBar/CnActionsBar.vue +48 -11
  291. package/src/components/CnAppRoot/CnAppRoot.md +4 -2
  292. package/src/components/CnAppRoot/CnAppRoot.vue +151 -59
  293. package/src/components/CnBannerWidget/CnBannerWidget.vue +244 -23
  294. package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
  295. package/src/components/CnCellRenderer/CnCellRenderer.vue +235 -5
  296. package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
  297. package/src/components/CnChipsFieldWidget/index.js +25 -0
  298. package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
  299. package/src/components/CnChoicePickerWidget/index.js +26 -0
  300. package/src/components/CnConversationThread/CnConversationWidget.vue +1 -1
  301. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +2 -2
  302. package/src/components/CnDashboardPage/CnDashboardPage.vue +78 -5
  303. package/src/components/CnDataTable/CnDataTable.vue +22 -12
  304. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  305. package/src/components/CnDetailPage/CnDetailPage.vue +152 -6
  306. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
  307. package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +1 -1
  308. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +7 -7
  309. package/src/components/CnFactsWidget/CnFactsWidget.vue +1190 -0
  310. package/src/components/CnFactsWidget/index.js +29 -0
  311. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +1008 -0
  312. package/src/components/CnFieldListWidget/index.js +28 -0
  313. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +588 -117
  314. package/src/components/CnFilesBrowser/filesBrowser.js +100 -0
  315. package/src/components/CnFilesBrowser/filesBrowserColumns.js +140 -0
  316. package/src/components/CnFormDialog/CnFormDialog.md +9 -3
  317. package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
  318. package/src/components/CnFormPage/CnFormPage.vue +99 -3
  319. package/src/components/CnIndexPage/CnIndexPage.vue +309 -9
  320. package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
  321. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +7 -7
  322. package/src/components/CnNextStepCard/CnNextStepWidget.vue +1 -1
  323. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
  324. package/src/components/CnObjectSidebar/CnFilesTab.vue +70 -1
  325. package/src/components/CnObjectSidebar/CnNotesTab.vue +16 -0
  326. package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
  327. package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
  328. package/src/components/CnRadioCardsWidget/index.js +27 -0
  329. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +652 -0
  330. package/src/components/CnRecordListWidget/index.js +30 -0
  331. package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
  332. package/src/components/CnSavedViewsWidget/index.js +29 -0
  333. package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
  334. package/src/components/CnSectionsWidget/index.js +34 -0
  335. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
  336. package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
  337. package/src/components/CnSettingsFormWidget/index.js +26 -0
  338. package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
  339. package/src/components/CnStatWidget/CnStatWidget.vue +88 -7
  340. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +180 -3
  341. package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
  342. package/src/components/CnSwitchRowsWidget/index.js +25 -0
  343. package/src/components/CnTabsWidget/CnTabsWidget.vue +263 -8
  344. package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
  345. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
  346. package/src/components/CnToggleTableWidget/index.js +26 -0
  347. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  348. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +7 -2
  349. package/src/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  350. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +493 -11
  351. package/src/components/index.js +19 -0
  352. package/src/composables/__tests__/useFormDraft.spec.js +69 -0
  353. package/src/composables/useFormDraft.js +139 -8
  354. package/src/composables/useListView.js +4 -4
  355. package/src/css/form-field.css +14 -0
  356. package/src/css/index-page.css +71 -0
  357. package/src/css/kpi-card.css +32 -0
  358. package/src/css/look-board-detail.css +113 -2
  359. package/src/css/look-board-index.css +90 -8
  360. package/src/css/look-board.css +109 -2
  361. package/src/css/table.css +19 -0
  362. package/src/index.js +19 -0
  363. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
  364. package/src/integrations/builtin/field-inspection.js +21 -0
  365. package/src/integrations/offline/checklistSubmission.js +137 -0
  366. package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
  367. package/src/integrations/offline/index.js +3 -0
  368. package/src/integrations/offline/offlineDb.js +6 -1
  369. package/src/integrations/offline/syncReplayService.js +8 -2
  370. package/src/schemas/app-manifest-v2.schema.json +196 -13
  371. package/src/utils/contentHeaderLink.js +48 -0
  372. package/src/utils/detailActionModel.js +59 -2
  373. package/src/utils/facets.js +74 -2
  374. package/src/utils/fetchFilterCounts.js +39 -4
  375. package/src/utils/fillTemplate.js +116 -0
  376. package/src/utils/initials.js +29 -0
  377. package/src/utils/libraryWidgetKeys.js +11 -0
  378. package/src/utils/objectWrite.js +55 -0
  379. package/src/utils/pageControls.js +78 -0
  380. package/src/utils/personalLenses.js +39 -2
  381. package/src/utils/queryPresets.js +93 -0
  382. package/src/utils/resolveFilterTokens.js +14 -1
  383. package/src/utils/resolveManifestTokens.js +2 -0
  384. package/src/utils/schema.js +21 -0
  385. package/src/utils/sentinelTokens.js +22 -4
  386. package/src/utils/userGroupsPeek.js +87 -0
  387. package/src/utils/validateManifestV2.compiled.js +3 -3
  388. package/src/utils/visibleWhen.js +56 -4
  389. package/src/utils/widgetDispatch.js +7 -1
  390. package/src/utils/widgetVisibility.js +7 -56
@@ -3,7 +3,7 @@
3
3
  - SPDX-License-Identifier: EUPL-1.2
4
4
  -->
5
5
  <template>
6
- <div class="cn-tasks-widget">
6
+ <div class="cn-tasks-widget" :class="{ 'cn-tasks-widget--list': isList }">
7
7
  <!-- One quiet line on failure, never a leaked axios status string
8
8
  (ADR-062). The real error goes to the console. -->
9
9
  <p v-if="error" class="cn-tasks-widget__error">
@@ -21,7 +21,7 @@
21
21
  <!-- The count states the server TOTAL, never the rendered length
22
22
  (ADR-062): the number a person acts on is how much work
23
23
  exists, not how much fits the cell. -->
24
- <p class="cn-tasks-widget__count">
24
+ <p v-if="!isList" class="cn-tasks-widget__count">
25
25
  {{ countLabel }}
26
26
  </p>
27
27
  <ul class="cn-tasks-widget__list">
@@ -33,23 +33,53 @@
33
33
  @click="onRowClick(task, $event)"
34
34
  @mousedown="preventMiddleClickAutoscroll"
35
35
  @auxclick="onRowAuxClick(task, $event)">
36
- <span class="cn-tasks-widget__body">
37
- <span class="cn-tasks-widget__name">{{ titleOf(task) }}</span>
38
- <span class="cn-tasks-widget__meta">{{ metaLine(task) }}</span>
39
- </span>
40
- <!-- Overdue is carried by the WORDING (taskDueLabel) and by
41
- weight; the colour only reinforces it. -->
42
- <span
43
- class="cn-tasks-widget__due"
44
- :class="{ 'cn-tasks-widget__due--overdue': task.overdue === true }">
45
- {{ dueLabel(task) }}
46
- </span>
36
+ <!-- List variant: a checkbox completes the viewer's own task
37
+ (the task with a declared outcome list keeps the menu, as
38
+ a checkbox cannot choose an outcome). Other rows get a
39
+ spacer so the titles stay aligned. -->
40
+ <template v-if="isList">
41
+ <input
42
+ v-if="canCheck(task)"
43
+ type="checkbox"
44
+ class="cn-tasks-widget__check"
45
+ :checked="completing.includes(String(task.uuid))"
46
+ :disabled="completing.includes(String(task.uuid))"
47
+ :aria-label="tr('Mark {title} as done').replace('{title}', titleOf(task))"
48
+ data-testid="cn-tasks-widget-check"
49
+ @click.stop
50
+ @change="check(task)">
51
+ <span v-else class="cn-tasks-widget__check-spacer" aria-hidden="true" />
52
+ <span class="cn-tasks-widget__body">
53
+ <span class="cn-tasks-widget__name">{{ titleOf(task) }}</span>
54
+ <span class="cn-tasks-widget__meta cn-tasks-widget__meta--split">
55
+ <span class="cn-tasks-widget__subject">{{ subjectOf(task) }}</span>
56
+ <span
57
+ class="cn-tasks-widget__due"
58
+ :class="{ 'cn-tasks-widget__due--overdue': task.overdue === true }">
59
+ {{ dueLabel(task) }}
60
+ </span>
61
+ </span>
62
+ </span>
63
+ </template>
64
+ <template v-else>
65
+ <span class="cn-tasks-widget__body">
66
+ <span class="cn-tasks-widget__name">{{ titleOf(task) }}</span>
67
+ <span class="cn-tasks-widget__meta">{{ metaLine(task) }}</span>
68
+ </span>
69
+ <!-- Overdue is carried by the WORDING (taskDueLabel) and by
70
+ weight; the colour only reinforces it. -->
71
+ <span
72
+ class="cn-tasks-widget__due"
73
+ :class="{ 'cn-tasks-widget__due--overdue': task.overdue === true }">
74
+ {{ dueLabel(task) }}
75
+ </span>
76
+ </template>
47
77
  <!-- Only verbs the contract can accept are offered; the
48
78
  server still authorizes, and a refusal is toasted in
49
79
  its own words. Stopped clicks: the menu must not also
50
80
  open the row. -->
51
81
  <NcActions
52
- v-if="canClaim(task) || canComplete(task)"
82
+ v-if="(canClaim(task) || canComplete(task)) && !(isList && canCheck(task))"
53
83
  class="cn-tasks-widget__actions"
54
84
  :forceMenu="true"
55
85
  :aria-label="tr('Task actions')"
@@ -90,6 +120,7 @@ import { NcActionButton, NcActions, NcLoadingIcon } from '@nextcloud/vue'
90
120
  import { inject, ref } from 'vue'
91
121
  import { taskDeepLink, taskDueLabel } from '../../composables/indexSources.js'
92
122
  import { useEndpointSource } from '../../composables/useEndpointSource.js'
123
+ import { contentHeaderLink } from '../../utils/contentHeaderLink.js'
93
124
  import { openRowTarget } from '../../utils/linkNavigation.js'
94
125
  import { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'
95
126
 
@@ -185,8 +216,14 @@ export default {
185
216
  * receiving the task uuid as `:id`. Omitted = the click opens the
186
217
  * task's openregister deep link instead.
187
218
  * - `emptyText` — override for the empty-inbox line.
219
+ * - `variant` — `list` draws a checkbox list: a checkbox that completes
220
+ * the viewer's own task, the title, the subject on a second muted
221
+ * line and the due date at its right. Default: the compact rows.
222
+ * - `viewAllRoute` / `viewAllLabel` — a "View all" text link in the
223
+ * card header: a route name or location `{ name, params?, query? }`,
224
+ * and its label (default "View all"). `headerLink` works too.
188
225
  *
189
- * @type {{scope?: string, limit?: number, pollSeconds?: number, rowRoute?: string, emptyText?: string}}
226
+ * @type {{scope?: string, limit?: number, pollSeconds?: number, rowRoute?: string, emptyText?: string, variant?: string, viewAllRoute?: (string|object), viewAllLabel?: string}}
190
227
  */
191
228
  content: {
192
229
  type: Object,
@@ -214,6 +251,8 @@ export default {
214
251
  },
215
252
  },
216
253
 
254
+ emits: ['header'],
255
+
217
256
  setup(props) {
218
257
  // The shared endpoint engine owns request dedup, the short-TTL cache
219
258
  // and the cn:page:refresh / cn:widget:refresh subscriptions — the
@@ -253,10 +292,30 @@ export default {
253
292
  data() {
254
293
  return {
255
294
  pollTimer: null,
295
+ /** Uuids of the tasks a checkbox is completing, until the next read. */
296
+ completing: [],
256
297
  }
257
298
  },
258
299
 
259
300
  computed: {
301
+ /**
302
+ * Whether the rows draw as the checkbox list (`content.variant: 'list'`).
303
+ *
304
+ * @return {boolean}
305
+ */
306
+ isList() {
307
+ return this.content.variant === 'list'
308
+ },
309
+
310
+ /**
311
+ * The header "View all" link the content declares, or null.
312
+ *
313
+ * @return {object|null}
314
+ */
315
+ headerLink() {
316
+ return contentHeaderLink(this.content)
317
+ },
318
+
260
319
  /**
261
320
  * Effective translate function: the explicit prop, then the injected
262
321
  * host one, then `@nextcloud/l10n` under the library's own app id.
@@ -357,6 +416,19 @@ export default {
357
416
  },
358
417
  },
359
418
 
419
+ watch: {
420
+ headerLink: {
421
+ immediate: true,
422
+ handler(link) {
423
+ /**
424
+ * @event header Emitted with the card header's parts: the "View all" link, if any.
425
+ * @type {{link: (object|null), note: string}}
426
+ */
427
+ this.$emit('header', { link, note: '' })
428
+ },
429
+ },
430
+ },
431
+
360
432
  mounted() {
361
433
  this.startPolling()
362
434
  document.addEventListener('visibilitychange', this.onVisibilityChange)
@@ -423,6 +495,43 @@ export default {
423
495
  return task.displayTitle || task.title || String(task.uuid || '')
424
496
  },
425
497
 
498
+ /**
499
+ * The subject (the case a task sits on), for the list variant's second line.
500
+ *
501
+ * @param {object} task The task row.
502
+ * @return {string} The subject's title, or ''.
503
+ */
504
+ subjectOf(task) {
505
+ return task.subject && task.subject.title ? String(task.subject.title) : ''
506
+ },
507
+
508
+ /**
509
+ * Whether the list variant draws a checkbox on the row: the viewer's own
510
+ * open task, with no outcome list to choose from.
511
+ *
512
+ * @param {object} task The task row.
513
+ * @return {boolean}
514
+ */
515
+ canCheck(task) {
516
+ return this.canComplete(task) && !(Array.isArray(task.outcomes) && task.outcomes.length > 0)
517
+ },
518
+
519
+ /**
520
+ * Complete a task from its checkbox, with the server's default outcome.
521
+ *
522
+ * @param {object} task The task row.
523
+ * @return {Promise<void>}
524
+ */
525
+ async check(task) {
526
+ const uuid = String(task.uuid || '')
527
+ if (uuid === '' || this.completing.includes(uuid)) {
528
+ return
529
+ }
530
+ this.completing = [...this.completing, uuid]
531
+ await this.postVerb(task, 'complete', { outcome: 'done' })
532
+ this.completing = this.completing.filter((id) => id !== uuid)
533
+ },
534
+
426
535
  /**
427
536
  * The secondary line: subject, state and priority — whichever of
428
537
  * those the row actually carries, in words.
@@ -721,6 +830,57 @@ function normaliseScope(raw) {
721
830
  font-variant-numeric: tabular-nums;
722
831
  }
723
832
 
833
+ /* List variant, after the dashboard board's My tasks card: a checkbox, the
834
+ title, the subject on a muted second line and the due date at its right. */
835
+ .cn-tasks-widget--list .cn-tasks-widget__row {
836
+ align-items: flex-start;
837
+ gap: 12px;
838
+ padding: 12px 0;
839
+ }
840
+
841
+ .cn-tasks-widget--list .cn-tasks-widget__name {
842
+ font-weight: 400;
843
+ font-size: 15px;
844
+ line-height: 1.35;
845
+ color: var(--color-main-text);
846
+ }
847
+
848
+ .cn-tasks-widget__check,
849
+ .cn-tasks-widget__check-spacer {
850
+ flex: none;
851
+ width: 20px;
852
+ height: 20px;
853
+ margin: 1px 0 0;
854
+ }
855
+
856
+ .cn-tasks-widget__check {
857
+ accent-color: var(--color-primary-element);
858
+ cursor: pointer;
859
+ }
860
+
861
+ .cn-tasks-widget__meta--split {
862
+ display: flex;
863
+ justify-content: space-between;
864
+ gap: 8px;
865
+ font-size: 13px;
866
+ overflow: visible;
867
+ }
868
+
869
+ .cn-tasks-widget__subject {
870
+ min-width: 0;
871
+ overflow: hidden;
872
+ text-overflow: ellipsis;
873
+ }
874
+
875
+ .cn-tasks-widget--list .cn-tasks-widget__due {
876
+ font-size: 13px;
877
+ font-weight: 500;
878
+ }
879
+
880
+ .cn-tasks-widget--list .cn-tasks-widget__due--overdue {
881
+ font-weight: 600;
882
+ }
883
+
724
884
  /* Overdue: weight AND colour on top of the wording, which already says
725
885
  "Overdue by N days" — the signal survives monochrome. */
726
886
  .cn-tasks-widget__due--overdue {
@@ -0,0 +1,386 @@
1
+ <!--
2
+ - SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ - SPDX-License-Identifier: EUPL-1.2
4
+ -->
5
+
6
+ <template>
7
+ <div class="cn-toggle-table" data-testid="cn-toggle-table">
8
+ <p v-if="rows.length === 0" class="cn-toggle-table__empty" data-testid="cn-toggle-table-empty">
9
+ {{ emptyLabel }}
10
+ </p>
11
+ <table v-else class="cn-toggle-table__table">
12
+ <thead v-if="showHeader">
13
+ <tr>
14
+ <th scope="col" class="cn-toggle-table__head">
15
+ {{ titleHeader }}
16
+ </th>
17
+ <th
18
+ v-for="column in columns"
19
+ :key="column.path"
20
+ scope="col"
21
+ class="cn-toggle-table__head">
22
+ {{ column.header }}
23
+ </th>
24
+ <th scope="col" class="cn-toggle-table__head cn-toggle-table__head--toggle">
25
+ {{ toggleHeader }}
26
+ </th>
27
+ </tr>
28
+ </thead>
29
+ <tbody>
30
+ <tr
31
+ v-for="row in rows"
32
+ :key="row.key"
33
+ class="cn-toggle-table__row"
34
+ :data-testid="`cn-toggle-table-row-${row.key}`">
35
+ <td class="cn-toggle-table__cell cn-toggle-table__cell--main">
36
+ <span class="cn-toggle-table__title">{{ row.title }}</span>
37
+ <span v-if="row.hint" class="cn-toggle-table__hint">{{ row.hint }}</span>
38
+ </td>
39
+ <td
40
+ v-for="column in columns"
41
+ :key="column.path"
42
+ class="cn-toggle-table__cell">
43
+ {{ cell(row, column) }}
44
+ </td>
45
+ <td class="cn-toggle-table__cell cn-toggle-table__cell--toggle">
46
+ <NcCheckboxRadioSwitch
47
+ :key="`${row.key}-${undone[row.key] || 0}`"
48
+ :modelValue="isOn(row)"
49
+ type="switch"
50
+ :disabled="readOnly || busy === row.key"
51
+ :aria-label="row.title"
52
+ @update:modelValue="toggle(row, $event)" />
53
+ </td>
54
+ </tr>
55
+ </tbody>
56
+ </table>
57
+ <NcNoteCard v-if="notice" type="error" data-testid="cn-toggle-table-notice">
58
+ {{ notice }}
59
+ </NcNoteCard>
60
+ </div>
61
+ </template>
62
+
63
+ <script>
64
+ import { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'
65
+ import { prefixUrl } from '../../utils/headers.js'
66
+ import { objectUrlOf, patchObject } from '../../utils/objectWrite.js'
67
+ import { readPath } from '../../utils/readPath.js'
68
+ import { serverErrorMessage } from '../../utils/serverErrorMessage.js'
69
+
70
+ /**
71
+ * CnToggleTableWidget — the `toggle-table` widget: rows from a configured list
72
+ * (`rows`) or read from a source (`source`), each with a switch bound to the
73
+ * CURRENT object, and optional extra columns read off the row. A switch is
74
+ * stored in one of two ways:
75
+ *
76
+ * - `bind.mode: 'flag'` — each row names its own boolean field of the object
77
+ * (`row.field`); the switch is that field.
78
+ * - `bind.mode: 'list'` — ONE array field of the object (`bind.field`) holds
79
+ * the keys of the rows that are in it; the switch is on when the row's key is
80
+ * in the list, or NOT in it with `bind.invert` (a list of hidden items shown
81
+ * as "visible" switches).
82
+ *
83
+ * A toggle saves at once with ONE PATCH of that field; a refused PATCH puts the
84
+ * switch back and shows the server's words.
85
+ *
86
+ * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md
87
+ */
88
+ export default {
89
+ name: 'CnToggleTableWidget',
90
+
91
+ components: { NcCheckboxRadioSwitch, NcNoteCard },
92
+
93
+ inject: {
94
+ cnTranslate: { default: () => (key) => key },
95
+ },
96
+
97
+ props: {
98
+ /**
99
+ * The widget configuration.
100
+ *
101
+ * - `bind` — `{ mode: 'flag' }` (default) or `{ mode: 'list', field, invert? }`.
102
+ * - `rows` — static rows `[{ key, label, hint?, field?, ...extra }]`.
103
+ * - `source` — `{ url, path?, key, label, hint? }`: rows read from an endpoint (tokens `@objectId`, `@object.<field>`), in addition to `rows`.
104
+ * - `columns` — extra columns `[{ header, path, map? }]` read off each row.
105
+ * - `titleHeader`, `toggleHeader`, `emptyText`, `readOnly`.
106
+ *
107
+ * @type {object}
108
+ */
109
+ content: {
110
+ type: Object,
111
+ default: () => ({}),
112
+ },
113
+
114
+ /** The current detail-page object. */
115
+ objectData: {
116
+ type: Object,
117
+ default: null,
118
+ },
119
+
120
+ /** The current object id. */
121
+ objectId: {
122
+ type: [String, Number],
123
+ default: '',
124
+ },
125
+
126
+ /** OpenRegister register slug of the surface. */
127
+ register: {
128
+ type: [String, Object],
129
+ default: '',
130
+ },
131
+
132
+ /** OpenRegister schema slug of the surface. */
133
+ schema: {
134
+ type: [String, Object],
135
+ default: '',
136
+ },
137
+ },
138
+
139
+ emits: ['saved'],
140
+
141
+ data() {
142
+ return {
143
+ /** Rows read from `source`. */
144
+ sourced: [],
145
+ /** What the object holds, by field: the flags and the list, as last saved. */
146
+ saved: {},
147
+ busy: '',
148
+ notice: '',
149
+ /** Per row, how often a refused toggle forced the switch to be drawn again from the stored value. */
150
+ undone: {},
151
+ }
152
+ },
153
+
154
+ computed: {
155
+ bind() {
156
+ const bind = this.content.bind || {}
157
+ return bind.mode === 'list' ? { mode: 'list', field: bind.field, invert: bind.invert === true } : { mode: 'flag' }
158
+ },
159
+
160
+ /** The drawn rows: configured first, then sourced, each with a key, title and hint. */
161
+ rows() {
162
+ const configured = (Array.isArray(this.content.rows) ? this.content.rows : [])
163
+ .filter((row) => row && row.key !== undefined)
164
+ .map((row) => ({ ...row, key: String(row.key), title: this.tr(row.label || String(row.key)), hint: this.tr(row.hint || '') }))
165
+ return [...configured, ...this.sourced]
166
+ },
167
+
168
+ columns() {
169
+ return (Array.isArray(this.content.columns) ? this.content.columns : [])
170
+ .filter((column) => column && column.path)
171
+ .map((column) => ({ ...column, header: this.tr(column.header || '') }))
172
+ },
173
+
174
+ showHeader() {
175
+ return this.columns.length > 0 || Boolean(this.content.titleHeader || this.content.toggleHeader)
176
+ },
177
+
178
+ titleHeader() {
179
+ return this.tr(this.content.titleHeader || '')
180
+ },
181
+
182
+ toggleHeader() {
183
+ return this.tr(this.content.toggleHeader || '')
184
+ },
185
+
186
+ emptyLabel() {
187
+ return this.tr(this.content.emptyText || 'Nothing listed yet')
188
+ },
189
+
190
+ readOnly() {
191
+ return this.content.readOnly === true
192
+ },
193
+
194
+ objectUrl() {
195
+ return objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))
196
+ },
197
+ },
198
+
199
+ watch: {
200
+ objectData() {
201
+ this.saved = {}
202
+ this.loadSource()
203
+ },
204
+ },
205
+
206
+ created() {
207
+ this.loadSource()
208
+ },
209
+
210
+ methods: {
211
+ tr(text) {
212
+ if (typeof text !== 'string' || text === '') {
213
+ return ''
214
+ }
215
+ return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
216
+ },
217
+
218
+ /**
219
+ * The stored value of a field: what this widget last saved, else the object's.
220
+ *
221
+ * @param {string} field The field.
222
+ * @return {unknown}
223
+ */
224
+ stored(field) {
225
+ return Object.hasOwn(this.saved, field) ? this.saved[field] : readPath(this.objectData || {}, field)
226
+ },
227
+
228
+ /**
229
+ * Whether a row's switch is on.
230
+ *
231
+ * @param {object} row The row.
232
+ * @return {boolean}
233
+ */
234
+ isOn(row) {
235
+ if (this.bind.mode === 'list') {
236
+ const list = this.stored(this.bind.field)
237
+ const inList = Array.isArray(list) && list.map(String).includes(row.key)
238
+ return this.bind.invert ? !inList : inList
239
+ }
240
+ return row.field ? this.stored(row.field) === true : false
241
+ },
242
+
243
+ /**
244
+ * The text of an extra column for a row.
245
+ *
246
+ * @param {object} row The row.
247
+ * @param {object} column The column.
248
+ * @return {string}
249
+ */
250
+ cell(row, column) {
251
+ const raw = readPath(row, column.path)
252
+ if (raw === undefined || raw === null || raw === '') {
253
+ return ''
254
+ }
255
+ if (column.map && Object.hasOwn(column.map, String(raw))) {
256
+ return this.tr(column.map[String(raw)])
257
+ }
258
+ return typeof raw === 'object' ? '' : String(raw)
259
+ },
260
+
261
+ /** Read the rows of `source`, resolving tokens in its url. */
262
+ async loadSource() {
263
+ const source = this.content.source
264
+ if (!source || !source.url || !source.key) {
265
+ return
266
+ }
267
+ const object = this.objectData || {}
268
+ const url = String(source.url)
269
+ .replace(/@objectId/g, () => encodeURIComponent(String(this.objectId || object.id || '')))
270
+ .replace(/@object\.([\w.@]+)/g, (m, path) => encodeURIComponent(String(readPath(object, path) ?? '')))
271
+ try {
272
+ const { default: axios } = await import('@nextcloud/axios')
273
+ const { data } = await axios.get(prefixUrl(url))
274
+ const list = source.path ? readPath(data, source.path) : data
275
+ this.sourced = (Array.isArray(list) ? list : [])
276
+ .filter((item) => item && readPath(item, source.key) !== undefined)
277
+ .map((item) => ({
278
+ ...item,
279
+ key: String(readPath(item, source.key)),
280
+ title: String(readPath(item, source.label || source.key) ?? readPath(item, source.key)),
281
+ hint: source.hint ? String(readPath(item, source.hint) ?? '') : '',
282
+ }))
283
+ } catch (e) {
284
+ this.notice = serverErrorMessage(e)
285
+ }
286
+ },
287
+
288
+ /**
289
+ * Flip one switch and save that one field.
290
+ *
291
+ * @param {object} row The row.
292
+ * @param {boolean} on The new switch state.
293
+ * @return {Promise<void>}
294
+ * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md#requirement-a-toggle-saves-one-field
295
+ */
296
+ async toggle(row, on) {
297
+ const field = this.bind.mode === 'list' ? this.bind.field : row.field
298
+ if (!this.objectUrl || !field) {
299
+ this.notice = this.tr('This switch cannot be saved here.')
300
+ return
301
+ }
302
+ let next
303
+ if (this.bind.mode === 'list') {
304
+ const list = (Array.isArray(this.stored(field)) ? this.stored(field) : []).map(String)
305
+ const wantInList = this.bind.invert ? !on : on
306
+ next = wantInList ? (list.includes(row.key) ? list : [...list, row.key]) : list.filter((key) => key !== row.key)
307
+ } else {
308
+ next = on
309
+ }
310
+ this.notice = ''
311
+ this.busy = row.key
312
+ try {
313
+ const data = await patchObject(this.objectUrl, { [field]: next })
314
+ const written = data[field] !== undefined ? data[field] : next
315
+ this.saved = { ...this.saved, [field]: written }
316
+ /**
317
+ * @event saved A switch was written.
318
+ * @type {{field: string, value: unknown}}
319
+ */
320
+ this.$emit('saved', { field, value: written })
321
+ } catch (e) {
322
+ this.notice = serverErrorMessage(e)
323
+ this.undone = { ...this.undone, [row.key]: (this.undone[row.key] || 0) + 1 }
324
+ } finally {
325
+ this.busy = ''
326
+ }
327
+ },
328
+ },
329
+ }
330
+ </script>
331
+
332
+ <style scoped>
333
+ .cn-toggle-table {
334
+ display: flex;
335
+ flex-direction: column;
336
+ gap: 8px;
337
+ min-width: 0;
338
+ }
339
+
340
+ .cn-toggle-table__table {
341
+ width: 100%;
342
+ border-collapse: collapse;
343
+ }
344
+
345
+ .cn-toggle-table__head {
346
+ padding: 8px 12px;
347
+ text-align: start;
348
+ font-size: 13px;
349
+ font-weight: 600;
350
+ color: var(--color-text-maxcontrast);
351
+ background: var(--color-background-hover);
352
+ }
353
+
354
+ .cn-toggle-table__head--toggle,
355
+ .cn-toggle-table__cell--toggle {
356
+ width: 1%;
357
+ white-space: nowrap;
358
+ text-align: end;
359
+ }
360
+
361
+ .cn-toggle-table__row {
362
+ border-top: 1px solid var(--cn-board-hairline, var(--color-border));
363
+ }
364
+
365
+ .cn-toggle-table__cell {
366
+ padding: 10px 12px;
367
+ vertical-align: middle;
368
+ overflow-wrap: anywhere;
369
+ }
370
+
371
+ .cn-toggle-table__title {
372
+ display: block;
373
+ font-weight: 600;
374
+ }
375
+
376
+ .cn-toggle-table__hint {
377
+ display: block;
378
+ font-size: 12px;
379
+ color: var(--color-text-maxcontrast);
380
+ }
381
+
382
+ .cn-toggle-table__empty {
383
+ margin: 0;
384
+ color: var(--color-text-maxcontrast);
385
+ }
386
+ </style>
@@ -0,0 +1,26 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ * SPDX-License-Identifier: EUPL-1.2
4
+ *
5
+ * CnToggleTableWidget — self-registers the `toggle-table` widget type (rows
6
+ * from a configured list or a source, each with a switch bound to the current
7
+ * object, and optional extra columns) into the shared dashboardWidgetRegistry.
8
+ */
9
+
10
+ import CnToggleTableWidget from './CnToggleTableWidget.vue'
11
+ import { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js'
12
+
13
+ registerDashboardWidget('toggle-table', {
14
+ renderer: CnToggleTableWidget,
15
+ form: null,
16
+ defaultContent: {
17
+ bind: { mode: 'flag' },
18
+ rows: [],
19
+ },
20
+ displayName: 'Toggle table',
21
+ icon: 'TableCheck',
22
+ surfaces: ['detail-page'],
23
+ })
24
+
25
+ export { CnToggleTableWidget }
26
+ export default CnToggleTableWidget
@@ -72,6 +72,17 @@ import '../CnDeltaWidget/index.js'
72
72
  import '../CnGaugeWidget/index.js'
73
73
  import '../CnFlowRunsWidget/index.js'
74
74
  import '../CnTasksWidget/index.js'
75
+ import '../CnSectionsWidget/index.js'
76
+ import '../CnFactsWidget/index.js'
77
+ import '../CnFieldListWidget/index.js'
78
+ import '../CnSettingsFormWidget/index.js'
79
+ import '../CnSwitchRowsWidget/index.js'
80
+ import '../CnRadioCardsWidget/index.js'
81
+ import '../CnChipsFieldWidget/index.js'
82
+ import '../CnToggleTableWidget/index.js'
83
+ import '../CnChoicePickerWidget/index.js'
84
+ import '../CnRecordListWidget/index.js'
85
+ import '../CnSavedViewsWidget/index.js'
75
86
  import '../CnNotepadWidget/index.js'
76
87
  import '../CnObjectDataWidget/dashboardRegistration.js'
77
88
  import '../CnObjectGeoWidget/dashboardRegistration.js'