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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  2. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +131 -3
  3. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +54 -18
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue.js +1 -1
  7. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js +3 -2
  8. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue2.js.map +1 -1
  9. package/dist/esm/components/CnAdvancedFormDialog/CnMetadataTab.vue3.js.map +1 -1
  10. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
  11. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +5 -4
  12. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
  13. package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
  14. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue.js +1 -1
  15. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js +2 -1
  16. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue2.js.map +1 -1
  17. package/dist/esm/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue3.js.map +1 -1
  18. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  19. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +2 -1
  20. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  21. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  22. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  23. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +376 -6
  24. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  25. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +146 -71
  26. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  27. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue.js +1 -1
  28. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js +2 -1
  29. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue2.js.map +1 -1
  30. package/dist/esm/components/CnCalendarEventPicker/CnCalendarEventPicker.vue3.js.map +1 -1
  31. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue.js +1 -1
  32. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +2 -1
  33. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
  34. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
  35. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  36. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +6 -5
  37. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue.js +1 -1
  40. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js +2 -1
  41. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue2.js.map +1 -1
  42. package/dist/esm/components/CnCollectivePagePicker/CnCollectivePagePicker.vue3.js.map +1 -1
  43. package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +1 -1
  44. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js +2 -1
  45. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -1
  46. package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -1
  47. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
  48. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +2 -1
  49. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
  50. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
  51. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  52. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +47 -1
  53. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  54. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -12
  55. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  56. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue.js +1 -1
  57. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js +3 -1
  58. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue2.js.map +1 -1
  59. package/dist/esm/components/CnDataMatrix/CnDataMatrix.vue3.js.map +1 -1
  60. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js +2 -1
  61. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue2.js.map +1 -1
  62. package/dist/esm/components/CnDetailPage/CnDetailHeaderChips.vue3.js.map +1 -1
  63. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +23 -4
  64. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  66. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  67. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +3 -1
  68. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  69. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  70. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue.js +1 -1
  71. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js +2 -1
  72. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue2.js.map +1 -1
  73. package/dist/esm/components/CnEmailPicker/CnEmailPicker.vue3.js.map +1 -1
  74. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  75. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +18 -5
  76. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  77. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  78. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue.js +1 -1
  79. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js +3 -1
  80. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue2.js.map +1 -1
  81. package/dist/esm/components/CnFederationStatus/CnFederationStatus.vue3.js.map +1 -1
  82. package/dist/esm/components/CnFileManager/CnFileManager.vue.js +1 -1
  83. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js +3 -1
  84. package/dist/esm/components/CnFileManager/CnFileManager.vue2.js.map +1 -1
  85. package/dist/esm/components/CnFileManager/CnFileManager.vue3.js.map +1 -1
  86. package/dist/esm/components/CnFilePreview/CnFilePreview.vue.js +1 -1
  87. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js +2 -1
  88. package/dist/esm/components/CnFilePreview/CnFilePreview.vue2.js.map +1 -1
  89. package/dist/esm/components/CnFilePreview/CnFilePreview.vue3.js.map +1 -1
  90. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  91. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +49 -1
  92. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  93. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +3 -3
  94. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  95. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue.js +1 -1
  96. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +2 -1
  97. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
  98. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
  99. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +571 -77
  100. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  101. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +191 -82
  102. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  103. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +11 -2
  104. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  105. package/dist/esm/components/CnNotesCard/CnNotesCard.vue.js +1 -1
  106. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js +2 -1
  107. package/dist/esm/components/CnNotesCard/CnNotesCard.vue2.js.map +1 -1
  108. package/dist/esm/components/CnNotesCard/CnNotesCard.vue3.js.map +1 -1
  109. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue.js +1 -1
  110. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js +3 -2
  111. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue2.js.map +1 -1
  112. package/dist/esm/components/CnObjectCalendar/CnObjectCalendar.vue3.js.map +1 -1
  113. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
  114. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +28 -0
  115. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  116. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +82 -75
  117. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  118. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue.js +1 -1
  119. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js +5 -4
  120. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue2.js.map +1 -1
  121. package/dist/esm/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue3.js.map +1 -1
  122. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue.js +1 -1
  123. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js +2 -1
  124. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue2.js.map +1 -1
  125. package/dist/esm/components/CnObjectSidebar/CnAuditTrailTab.vue3.js.map +1 -1
  126. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue.js +1 -1
  127. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js +2 -1
  128. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue2.js.map +1 -1
  129. package/dist/esm/components/CnObjectSidebar/CnFlowTasksPanel.vue3.js.map +1 -1
  130. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue.js +1 -1
  131. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +2 -1
  132. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  133. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  134. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue.js +1 -1
  135. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js +2 -1
  136. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue2.js.map +1 -1
  137. package/dist/esm/components/CnObjectSidebar/CnTasksTab.vue3.js.map +1 -1
  138. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue.js +1 -1
  139. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js +2 -1
  140. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue2.js.map +1 -1
  141. package/dist/esm/components/CnPropertySourceField/CnPropertySourceField.vue3.js.map +1 -1
  142. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  143. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +70 -2
  144. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  145. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  146. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
  147. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +67 -5
  148. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
  149. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +181 -124
  150. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
  151. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue.js +1 -1
  152. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js +2 -1
  153. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue2.js.map +1 -1
  154. package/dist/esm/components/CnRoadmapItem/CnRoadmapItem.vue3.js.map +1 -1
  155. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js +2 -0
  156. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue2.js.map +1 -1
  157. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js +2 -2
  158. package/dist/esm/components/CnSchemaFormDialog/CnSchemaFormDialog.vue3.js.map +1 -1
  159. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  160. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +5 -1
  161. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  162. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  163. package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
  164. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +134 -10
  165. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  166. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -2
  167. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  168. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue.js +1 -1
  169. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +2 -1
  170. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
  171. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
  172. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue.js +1 -1
  173. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js +2 -1
  174. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue2.js.map +1 -1
  175. package/dist/esm/components/CnSummaryAggregates/CnSummaryAggregates.vue3.js.map +1 -1
  176. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  177. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +6 -3
  178. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  179. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  180. package/dist/esm/components/CnTasksCard/CnTasksCard.vue.js +1 -1
  181. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js +2 -1
  182. package/dist/esm/components/CnTasksCard/CnTasksCard.vue2.js.map +1 -1
  183. package/dist/esm/components/CnTasksCard/CnTasksCard.vue3.js.map +1 -1
  184. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
  185. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +2 -1
  186. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  187. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  188. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +1 -1
  189. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +140 -7
  190. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -1
  191. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -1
  192. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue.js +1 -1
  193. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js +2 -1
  194. package/dist/esm/components/CnTranslatedBadge/CnTranslatedBadge.vue2.js.map +1 -1
  195. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue.js +1 -1
  196. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js +2 -1
  197. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue2.js.map +1 -1
  198. package/dist/esm/components/CnVersionHistory/CnVersionHistory.vue3.js.map +1 -1
  199. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
  200. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +37 -9
  201. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
  202. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +6 -5
  203. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
  204. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js +53 -1
  205. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js.map +1 -1
  206. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js +3 -2
  207. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js.map +1 -1
  208. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  209. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +135 -0
  210. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  211. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  212. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  213. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +19 -0
  214. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  215. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +37 -19
  216. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  217. package/dist/esm/composables/useListView.js +21 -0
  218. package/dist/esm/composables/useListView.js.map +1 -1
  219. package/dist/esm/dialogs/CnNoteHistoryDialog.vue.js +1 -1
  220. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js +2 -1
  221. package/dist/esm/dialogs/CnNoteHistoryDialog.vue2.js.map +1 -1
  222. package/dist/esm/dialogs/CnNoteHistoryDialog.vue3.js.map +1 -1
  223. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue.js +1 -1
  224. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js +3 -2
  225. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue2.js.map +1 -1
  226. package/dist/esm/integrations/builtin/activity/CnActivityCard.vue3.js.map +1 -1
  227. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue.js +1 -1
  228. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js +4 -3
  229. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue2.js.map +1 -1
  230. package/dist/esm/integrations/builtin/activity/CnActivityTab.vue3.js.map +1 -1
  231. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue.js +1 -1
  232. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -2
  233. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
  234. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
  235. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue.js +1 -1
  236. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js +2 -1
  237. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue2.js.map +1 -1
  238. package/dist/esm/integrations/builtin/calendar/CnCalendarCard.vue3.js.map +1 -1
  239. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue.js +1 -1
  240. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js +6 -5
  241. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue2.js.map +1 -1
  242. package/dist/esm/integrations/builtin/calendar/CnCalendarTab.vue3.js.map +1 -1
  243. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue.js +1 -1
  244. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js +2 -1
  245. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue2.js.map +1 -1
  246. package/dist/esm/integrations/builtin/contactmoment/CnContactmomentCard.vue3.js.map +1 -1
  247. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue.js +1 -1
  248. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js +2 -1
  249. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js.map +1 -1
  250. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js.map +1 -1
  251. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue.js +1 -1
  252. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +2 -1
  253. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
  254. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
  255. package/dist/esm/integrations/builtin/email/CnEmailCard.vue.js +1 -1
  256. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js +2 -1
  257. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js.map +1 -1
  258. package/dist/esm/integrations/builtin/email/CnEmailCard.vue3.js.map +1 -1
  259. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue.js +1 -1
  260. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +2 -1
  261. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  262. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  263. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue.js +1 -1
  264. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js +2 -1
  265. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue2.js.map +1 -1
  266. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionTab.vue3.js.map +1 -1
  267. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue.js +1 -1
  268. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js +2 -1
  269. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js.map +1 -1
  270. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js.map +1 -1
  271. package/dist/esm/l10n/en.json.js +57 -2
  272. package/dist/esm/l10n/en.json.js.map +1 -1
  273. package/dist/esm/l10n/nl.json.js +78 -2
  274. package/dist/esm/l10n/nl.json.js.map +1 -1
  275. package/dist/esm/library-style.js +1 -1
  276. package/dist/esm/nextcloud-vue.css +1541 -1166
  277. package/dist/esm/store/useObjectStore.js +23 -4
  278. package/dist/esm/store/useObjectStore.js.map +1 -1
  279. package/dist/esm/utils/boardColumns.js +58 -2
  280. package/dist/esm/utils/boardColumns.js.map +1 -1
  281. package/dist/esm/utils/boardReferenceColumns.js +330 -0
  282. package/dist/esm/utils/boardReferenceColumns.js.map +1 -0
  283. package/dist/esm/utils/buildManifest.js +4 -1
  284. package/dist/esm/utils/buildManifest.js.map +1 -1
  285. package/dist/esm/utils/schema.js +5 -4
  286. package/dist/esm/utils/schema.js.map +1 -1
  287. package/dist/esm/utils/userLocale.js +30 -0
  288. package/dist/esm/utils/userLocale.js.map +1 -0
  289. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  290. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  291. package/dist/esm/utils/widgetDispatch.js +8 -2
  292. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  293. package/dist/nextcloud-vue.cjs.js +30291 -27618
  294. package/dist/nextcloud-vue.cjs.js.map +2 -2
  295. package/dist/nextcloud-vue.css +1541 -1166
  296. package/l10n/en.json +57 -2
  297. package/l10n/nl.json +78 -2
  298. package/package.json +1 -1
  299. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +160 -8
  300. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +3 -2
  301. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +5 -4
  302. package/src/components/CnAnalyticsReportPicker/CnAnalyticsReportPicker.vue +2 -1
  303. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +2 -1
  304. package/src/components/CnBoardView/CnBoardView.vue +433 -12
  305. package/src/components/CnCalendarEventPicker/CnCalendarEventPicker.vue +2 -1
  306. package/src/components/CnCalendarWidget/CnCalendarWidget.vue +2 -1
  307. package/src/components/CnChartWidget/CnChartWidget.vue +6 -5
  308. package/src/components/CnCollectivePagePicker/CnCollectivePagePicker.vue +2 -1
  309. package/src/components/CnConversationThread/CnConversationThread.vue +2 -1
  310. package/src/components/CnCountdownWidget/CnCountdownWidget.vue +2 -1
  311. package/src/components/CnDashboardPage/CnDashboardPage.vue +59 -3
  312. package/src/components/CnDataMatrix/CnDataMatrix.vue +2 -1
  313. package/src/components/CnDetailPage/CnDetailHeaderChips.vue +2 -1
  314. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  315. package/src/components/CnDetailPage/CnDetailPage.vue +23 -4
  316. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +3 -1
  317. package/src/components/CnEmailPicker/CnEmailPicker.vue +2 -1
  318. package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -5
  319. package/src/components/CnFederationStatus/CnFederationStatus.vue +3 -1
  320. package/src/components/CnFileManager/CnFileManager.vue +2 -1
  321. package/src/components/CnFilePreview/CnFilePreview.vue +2 -1
  322. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +54 -6
  323. package/src/components/CnFollowToggle/CnFollowToggle.vue +2 -1
  324. package/src/components/CnIndexPage/CnIndexPage.vue +610 -25
  325. package/src/components/CnIndexPage/useSelfFetchList.js +10 -1
  326. package/src/components/CnNotesCard/CnNotesCard.vue +2 -1
  327. package/src/components/CnObjectCalendar/CnObjectCalendar.vue +3 -2
  328. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +36 -0
  329. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +5 -4
  330. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +2 -1
  331. package/src/components/CnObjectSidebar/CnFlowTasksPanel.vue +2 -1
  332. package/src/components/CnObjectSidebar/CnNotesTab.vue +2 -1
  333. package/src/components/CnObjectSidebar/CnTasksTab.vue +2 -1
  334. package/src/components/CnPropertySourceField/CnPropertySourceField.vue +2 -1
  335. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +70 -2
  336. package/src/components/CnRegisterMapping/CnRegisterMapping.md +5 -0
  337. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +231 -96
  338. package/src/components/CnRoadmapItem/CnRoadmapItem.vue +2 -1
  339. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +4 -2
  340. package/src/components/CnSettingsPage/CnSettingsPage.vue +5 -1
  341. package/src/components/CnStatWidget/CnStatWidget.vue +136 -11
  342. package/src/components/CnStatsBlock/CnStatsBlock.vue +2 -1
  343. package/src/components/CnSummaryAggregates/CnSummaryAggregates.vue +2 -1
  344. package/src/components/CnTabsWidget/CnTabsWidget.vue +6 -3
  345. package/src/components/CnTasksCard/CnTasksCard.vue +2 -1
  346. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +2 -1
  347. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +140 -7
  348. package/src/components/CnTranslatedBadge/CnTranslatedBadge.vue +2 -1
  349. package/src/components/CnVersionHistory/CnVersionHistory.vue +2 -1
  350. package/src/components/CnVersionInfoCard/CnVersionInfoCard.md +2 -1
  351. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +42 -13
  352. package/src/components/CnWidgetCardGrid/CnWidgetCardGrid.vue +55 -2
  353. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +135 -0
  354. package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +10 -0
  355. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +44 -1
  356. package/src/composables/useListView.js +21 -0
  357. package/src/css/board.css +105 -4
  358. package/src/css/dialog.css +4 -2
  359. package/src/css/index-page.css +49 -0
  360. package/src/css/look-board.css +77 -7
  361. package/src/dialogs/CnNoteHistoryDialog.vue +2 -1
  362. package/src/integrations/builtin/activity/CnActivityCard.vue +3 -2
  363. package/src/integrations/builtin/activity/CnActivityTab.vue +4 -3
  364. package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +3 -2
  365. package/src/integrations/builtin/calendar/CnCalendarCard.vue +2 -1
  366. package/src/integrations/builtin/calendar/CnCalendarTab.vue +6 -5
  367. package/src/integrations/builtin/contactmoment/CnContactmomentCard.vue +2 -1
  368. package/src/integrations/builtin/cospend/CnCospendTab.vue +2 -1
  369. package/src/integrations/builtin/deck/CnDeckTab.vue +2 -1
  370. package/src/integrations/builtin/email/CnEmailCard.vue +2 -1
  371. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +2 -1
  372. package/src/integrations/builtin/field-inspection/CnFieldInspectionTab.vue +2 -1
  373. package/src/integrations/builtin/photos/CnPhotosTab.vue +2 -1
  374. package/src/schemas/app-manifest-v2.schema.json +116 -5
  375. package/src/store/useObjectStore.js +23 -4
  376. package/src/utils/boardColumns.js +57 -1
  377. package/src/utils/boardReferenceColumns.js +326 -0
  378. package/src/utils/buildManifest.js +4 -1
  379. package/src/utils/schema.js +5 -4
  380. package/src/utils/userLocale.js +26 -0
  381. package/src/utils/validateManifestV2.compiled.js +3 -3
  382. package/src/utils/widgetDispatch.js +8 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CnToggleTableWidget.vue3.js","sources":["../../../../src/components/CnToggleTableWidget/CnToggleTableWidget.vue?vue&type=template&id=1bb40018&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-toggle-table\" data-testid=\"cn-toggle-table\">\n\t\t<p v-if=\"rows.length === 0\" class=\"cn-toggle-table__empty\" data-testid=\"cn-toggle-table-empty\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<table v-else class=\"cn-toggle-table__table\">\n\t\t\t<thead v-if=\"showHeader\">\n\t\t\t\t<tr>\n\t\t\t\t\t<th scope=\"col\" class=\"cn-toggle-table__head\">\n\t\t\t\t\t\t{{ titleHeader }}\n\t\t\t\t\t</th>\n\t\t\t\t\t<th\n\t\t\t\t\t\tv-for=\"column in columns\"\n\t\t\t\t\t\t:key=\"column.path\"\n\t\t\t\t\t\tscope=\"col\"\n\t\t\t\t\t\tclass=\"cn-toggle-table__head\">\n\t\t\t\t\t\t{{ column.header }}\n\t\t\t\t\t</th>\n\t\t\t\t\t<th scope=\"col\" class=\"cn-toggle-table__head cn-toggle-table__head--toggle\">\n\t\t\t\t\t\t{{ toggleHeader }}\n\t\t\t\t\t</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t<tr\n\t\t\t\t\tv-for=\"row in rows\"\n\t\t\t\t\t:key=\"row.key\"\n\t\t\t\t\tclass=\"cn-toggle-table__row\"\n\t\t\t\t\t:data-testid=\"`cn-toggle-table-row-${row.key}`\">\n\t\t\t\t\t<td class=\"cn-toggle-table__cell cn-toggle-table__cell--main\">\n\t\t\t\t\t\t<span class=\"cn-toggle-table__title\">{{ row.title }}</span>\n\t\t\t\t\t\t<span v-if=\"row.hint\" class=\"cn-toggle-table__hint\">{{ row.hint }}</span>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td\n\t\t\t\t\t\tv-for=\"column in columns\"\n\t\t\t\t\t\t:key=\"column.path\"\n\t\t\t\t\t\tclass=\"cn-toggle-table__cell\">\n\t\t\t\t\t\t{{ cell(row, column) }}\n\t\t\t\t\t</td>\n\t\t\t\t\t<td class=\"cn-toggle-table__cell cn-toggle-table__cell--toggle\">\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t:key=\"`${row.key}-${undone[row.key] || 0}`\"\n\t\t\t\t\t\t\t:modelValue=\"isOn(row)\"\n\t\t\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t\t\t:disabled=\"readOnly || busy === row.key\"\n\t\t\t\t\t\t\t:aria-label=\"row.title\"\n\t\t\t\t\t\t\t@update:modelValue=\"toggle(row, $event)\" />\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</tbody>\n\t\t</table>\n\t\t<NcNoteCard v-if=\"notice\" type=\"error\" data-testid=\"cn-toggle-table-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { objectUrlOf, writeFields } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n/**\n * CnToggleTableWidget — the `toggle-table` widget: rows from a configured list\n * (`rows`) or read from a source (`source`), each with a switch bound to the\n * CURRENT object, and optional extra columns read off the row. A switch is\n * stored in one of two ways:\n *\n * - `bind.mode: 'flag'` — each row names its own boolean field of the object\n * (`row.field`); the switch is that field.\n * - `bind.mode: 'list'` — ONE array field of the object (`bind.field`) holds\n * the keys of the rows that are in it; the switch is on when the row's key is\n * in the list, or NOT in it with `bind.invert` (a list of hidden items shown\n * as \"visible\" switches).\n *\n * A toggle saves at once with ONE PATCH of that field; a refused PATCH puts the\n * switch back and shows the server's words.\n *\n * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md\n */\nexport default {\n\tname: 'CnToggleTableWidget',\n\n\tcomponents: { NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `bind` — `{ mode: 'flag' }` (default) or `{ mode: 'list', field, invert? }`.\n\t\t * - `rows` — static rows `[{ key, label, hint?, field?, ...extra }]`.\n\t\t * - `source` — `{ url, path?, key, label, hint? }`: rows read from an endpoint (tokens `@objectId`, `@object.<field>`), in addition to `rows`.\n\t\t * - `columns` — extra columns `[{ header, path, map? }]` read off each row.\n\t\t * - `titleHeader`, `toggleHeader`, `emptyText`, `readOnly`.\n\t\t * - `save` — `{ url, method?, payload? }`, write through an app endpoint (tokens `{value}`, `{field}`, `{changes}`, `{object.<path>}`).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Rows read from `source`. */\n\t\t\tsourced: [],\n\t\t\t/** What the object holds, by field: the flags and the list, as last saved. */\n\t\t\tsaved: {},\n\t\t\tbusy: '',\n\t\t\tnotice: '',\n\t\t\t/** Per row, how often a refused toggle forced the switch to be drawn again from the stored value. */\n\t\t\tundone: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tbind() {\n\t\t\tconst bind = this.content.bind || {}\n\t\t\treturn bind.mode === 'list' ? { mode: 'list', field: bind.field, invert: bind.invert === true } : { mode: 'flag' }\n\t\t},\n\n\t\t/** The drawn rows: configured first, then sourced, each with a key, title and hint. */\n\t\trows() {\n\t\t\tconst configured = (Array.isArray(this.content.rows) ? this.content.rows : [])\n\t\t\t\t.filter((row) => row && row.key !== undefined)\n\t\t\t\t.map((row) => ({ ...row, key: String(row.key), title: this.tr(row.label || String(row.key)), hint: this.tr(row.hint || '') }))\n\t\t\treturn [...configured, ...this.sourced]\n\t\t},\n\n\t\tcolumns() {\n\t\t\treturn (Array.isArray(this.content.columns) ? this.content.columns : [])\n\t\t\t\t.filter((column) => column && column.path)\n\t\t\t\t.map((column) => ({ ...column, header: this.tr(column.header || '') }))\n\t\t},\n\n\t\tshowHeader() {\n\t\t\treturn this.columns.length > 0 || Boolean(this.content.titleHeader || this.content.toggleHeader)\n\t\t},\n\n\t\ttitleHeader() {\n\t\t\treturn this.tr(this.content.titleHeader || '')\n\t\t},\n\n\t\ttoggleHeader() {\n\t\t\treturn this.tr(this.content.toggleHeader || '')\n\t\t},\n\n\t\temptyLabel() {\n\t\t\treturn this.tr(this.content.emptyText || 'Nothing listed yet')\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.saved = {}\n\t\t\tthis.loadSource()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.loadSource()\n\t},\n\n\tmethods: {\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The stored value of a field: what this widget last saved, else the object's.\n\t\t *\n\t\t * @param {string} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tstored(field) {\n\t\t\treturn Object.hasOwn(this.saved, field) ? this.saved[field] : readPath(this.objectData || {}, field)\n\t\t},\n\n\t\t/**\n\t\t * Whether a row's switch is on.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {boolean}\n\t\t */\n\t\tisOn(row) {\n\t\t\tif (this.bind.mode === 'list') {\n\t\t\t\tconst list = this.stored(this.bind.field)\n\t\t\t\tconst inList = Array.isArray(list) && list.map(String).includes(row.key)\n\t\t\t\treturn this.bind.invert ? !inList : inList\n\t\t\t}\n\t\t\treturn row.field ? this.stored(row.field) === true : false\n\t\t},\n\n\t\t/**\n\t\t * The text of an extra column for a row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {object} column The column.\n\t\t * @return {string}\n\t\t */\n\t\tcell(row, column) {\n\t\t\tconst raw = readPath(row, column.path)\n\t\t\tif (raw === undefined || raw === null || raw === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (column.map && Object.hasOwn(column.map, String(raw))) {\n\t\t\t\treturn this.tr(column.map[String(raw)])\n\t\t\t}\n\t\t\treturn typeof raw === 'object' ? '' : String(raw)\n\t\t},\n\n\t\t/** Read the rows of `source`, resolving tokens in its url. */\n\t\tasync loadSource() {\n\t\t\tconst source = this.content.source\n\t\t\tif (!source || !source.url || !source.key) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst object = this.objectData || {}\n\t\t\tconst url = String(source.url)\n\t\t\t\t.replace(/@objectId/g, () => encodeURIComponent(String(this.objectId || object.id || '')))\n\t\t\t\t.replace(/@object\\.([\\w.@]+)/g, (m, path) => encodeURIComponent(String(readPath(object, path) ?? '')))\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tconst { data } = await axios.get(prefixUrl(url))\n\t\t\t\tconst list = source.path ? readPath(data, source.path) : data\n\t\t\t\tthis.sourced = (Array.isArray(list) ? list : [])\n\t\t\t\t\t.filter((item) => item && readPath(item, source.key) !== undefined)\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\t...item,\n\t\t\t\t\t\tkey: String(readPath(item, source.key)),\n\t\t\t\t\t\ttitle: String(readPath(item, source.label || source.key) ?? readPath(item, source.key)),\n\t\t\t\t\t\thint: source.hint ? String(readPath(item, source.hint) ?? '') : '',\n\t\t\t\t\t}))\n\t\t\t} catch (e) {\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Flip one switch and save that one field.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {boolean} on The new switch state.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md#requirement-a-toggle-saves-one-field\n\t\t */\n\t\tasync toggle(row, on) {\n\t\t\tconst field = this.bind.mode === 'list' ? this.bind.field : row.field\n\t\t\tif ((!this.objectUrl && !(this.content.save && this.content.save.url)) || !field) {\n\t\t\t\tthis.notice = this.tr('This switch cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet next\n\t\t\tif (this.bind.mode === 'list') {\n\t\t\t\tconst list = (Array.isArray(this.stored(field)) ? this.stored(field) : []).map(String)\n\t\t\t\tconst wantInList = this.bind.invert ? !on : on\n\t\t\t\tnext = wantInList ? (list.includes(row.key) ? list : [...list, row.key]) : list.filter((key) => key !== row.key)\n\t\t\t} else {\n\t\t\t\tnext = on\n\t\t\t}\n\t\t\tthis.notice = ''\n\t\t\tthis.busy = row.key\n\t\t\ttry {\n\t\t\t\tconst data = await writeFields(this.objectUrl, { [field]: next }, { save: this.content.save, object: this.objectData })\n\t\t\t\tconst answered = readPath(data, field)\n\t\t\t\tconst written = answered !== undefined ? answered : next\n\t\t\t\tthis.saved = { ...this.saved, [field]: written }\n\t\t\t\t/**\n\t\t\t\t * @event saved A switch was written.\n\t\t\t\t * @type {{field: string, value: unknown}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { field, value: written })\n\t\t\t} catch (e) {\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t\tthis.undone = { ...this.undone, [row.key]: (this.undone[row.key] || 0) + 1 }\n\t\t\t} finally {\n\t\t\t\tthis.busy = ''\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-toggle-table {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmin-width: 0;\n}\n\n.cn-toggle-table__table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-toggle-table__head {\n\tpadding: 8px 12px;\n\ttext-align: start;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--color-text-maxcontrast);\n\tbackground: var(--color-background-hover);\n}\n\n.cn-toggle-table__head--toggle,\n.cn-toggle-table__cell--toggle {\n\twidth: 1%;\n\twhite-space: nowrap;\n\ttext-align: end;\n}\n\n.cn-toggle-table__row {\n\tborder-top: 1px solid var(--cn-board-hairline, var(--color-border));\n}\n\n.cn-toggle-table__cell {\n\tpadding: 10px 12px;\n\tvertical-align: middle;\n\toverflow-wrap: anywhere;\n}\n\n.cn-toggle-table__title {\n\tdisplay: block;\n\tfont-weight: 600;\n}\n\n.cn-toggle-table__hint {\n\tdisplay: block;\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-toggle-table__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_createElementBlock","_toDisplayString","_createElementVNode","_Fragment","_renderList","_openBlock"],"mappings":"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"}
1
+ {"version":3,"file":"CnToggleTableWidget.vue3.js","sources":["../../../../src/components/CnToggleTableWidget/CnToggleTableWidget.vue?vue&type=template&id=24769640&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-toggle-table\" data-testid=\"cn-toggle-table\">\n\t\t<p v-if=\"rows.length === 0\" class=\"cn-toggle-table__empty\" data-testid=\"cn-toggle-table-empty\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<table v-else class=\"cn-toggle-table__table\">\n\t\t\t<thead v-if=\"showHeader\">\n\t\t\t\t<tr>\n\t\t\t\t\t<th scope=\"col\" class=\"cn-toggle-table__head\">\n\t\t\t\t\t\t{{ titleHeader }}\n\t\t\t\t\t</th>\n\t\t\t\t\t<th\n\t\t\t\t\t\tv-for=\"column in columns\"\n\t\t\t\t\t\t:key=\"column.path\"\n\t\t\t\t\t\tscope=\"col\"\n\t\t\t\t\t\tclass=\"cn-toggle-table__head\">\n\t\t\t\t\t\t{{ column.header }}\n\t\t\t\t\t</th>\n\t\t\t\t\t<th scope=\"col\" class=\"cn-toggle-table__head cn-toggle-table__head--toggle\">\n\t\t\t\t\t\t{{ toggleHeader }}\n\t\t\t\t\t</th>\n\t\t\t\t</tr>\n\t\t\t</thead>\n\t\t\t<tbody>\n\t\t\t\t<tr\n\t\t\t\t\tv-for=\"row in rows\"\n\t\t\t\t\t:key=\"row.key\"\n\t\t\t\t\tclass=\"cn-toggle-table__row\"\n\t\t\t\t\t:data-testid=\"`cn-toggle-table-row-${row.key}`\">\n\t\t\t\t\t<td class=\"cn-toggle-table__cell cn-toggle-table__cell--main\">\n\t\t\t\t\t\t<span class=\"cn-toggle-table__title\">{{ row.title }}</span>\n\t\t\t\t\t\t<span v-if=\"row.hint\" class=\"cn-toggle-table__hint\">{{ row.hint }}</span>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td\n\t\t\t\t\t\tv-for=\"column in columns\"\n\t\t\t\t\t\t:key=\"column.path\"\n\t\t\t\t\t\tclass=\"cn-toggle-table__cell\">\n\t\t\t\t\t\t{{ cell(row, column) }}\n\t\t\t\t\t</td>\n\t\t\t\t\t<td class=\"cn-toggle-table__cell cn-toggle-table__cell--toggle\">\n\t\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t\t:key=\"`${row.key}-${undone[row.key] || 0}`\"\n\t\t\t\t\t\t\t:modelValue=\"isOn(row)\"\n\t\t\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t\t\t:disabled=\"readOnly || busy === row.key\"\n\t\t\t\t\t\t\t:aria-label=\"row.title\"\n\t\t\t\t\t\t\t@update:modelValue=\"toggle(row, $event)\" />\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</tbody>\n\t\t</table>\n\t\t<NcNoteCard v-if=\"notice\" type=\"error\" data-testid=\"cn-toggle-table-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { objectUrlOf, writeFields } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n/**\n * CnToggleTableWidget — the `toggle-table` widget: rows from a configured list\n * (`rows`) or read from a source (`source`), each with a switch bound to the\n * CURRENT object, and optional extra columns read off the row. A switch is\n * stored in one of two ways:\n *\n * - `bind.mode: 'flag'` — each row names its own boolean field of the object\n * (`row.field`); the switch is that field.\n * - `bind.mode: 'list'` — ONE array field of the object (`bind.field`) holds\n * the keys of the rows that are in it; the switch is on when the row's key is\n * in the list, or NOT in it with `bind.invert` (a list of hidden items shown\n * as \"visible\" switches).\n * - `bind.mode: 'each'` — every row IS an object (read by `source`, its key the\n * object id); the switch is that object's own boolean field (`bind.field`)\n * and a toggle PATCHes that object (`bind.register` / `bind.schema`, else the\n * surface's). No current object is needed, so it serves a settings page.\n * - `bind.mode: 'map'` — a config map holds a boolean per row key: read from\n * `bind.url` (at `bind.path`) and written through `save`, or one object field\n * of the current object (`bind.field`) written by its dot-path.\n *\n * A toggle saves at once with ONE PATCH of that field; a refused PATCH puts the\n * switch back and shows the server's words.\n *\n * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md\n */\nexport default {\n\tname: 'CnToggleTableWidget',\n\n\tcomponents: { NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `bind` — `{ mode: 'flag' }` (default), `{ mode: 'list', field, invert? }`, `{ mode: 'each', field, register?, schema?, invert? }` or `{ mode: 'map', url?, path?, field?, invert? }`.\n\t\t * - `rows` — static rows `[{ key, label, hint?, field?, ...extra }]`.\n\t\t * - `source` — `{ url, path?, key, label, hint? }`: rows read from an endpoint (tokens `@objectId`, `@object.<field>`), in addition to `rows`.\n\t\t * - `columns` — extra columns `[{ header, path, map? }]` read off each row.\n\t\t * - `titleHeader`, `toggleHeader`, `emptyText`, `readOnly`.\n\t\t * - `save` — `{ url, method?, payload? }`, write through an app endpoint (tokens `{value}`, `{field}`, `{changes}`, `{object.<path>}`).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Rows read from `source`. */\n\t\t\tsourced: [],\n\t\t\t/** What the object holds, by field: the flags and the list, as last saved. */\n\t\t\tsaved: {},\n\t\t\tbusy: '',\n\t\t\tnotice: '',\n\t\t\t/** Per row, how often a refused toggle forced the switch to be drawn again from the stored value. */\n\t\t\tundone: {},\n\t\t\t/** `each` and `map`: the value written per row key. */\n\t\t\trowSaved: {},\n\t\t\t/** `map` with `bind.url`: the map as read. */\n\t\t\tmap: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * How a switch is stored.\n\t\t *\n\t\t * @return {object} The normalised `bind`.\n\t\t * @spec openspec/changes/toggle-table-objects-and-map/specs/toggle-table/spec.md#requirement-a-toggle-table-can-switch-objects-or-a-config-map\n\t\t */\n\t\tbind() {\n\t\t\tconst bind = this.content.bind || {}\n\t\t\tconst invert = bind.invert === true\n\t\t\tif (bind.mode === 'list') {\n\t\t\t\treturn { mode: 'list', field: bind.field, invert }\n\t\t\t}\n\t\t\tif (bind.mode === 'each') {\n\t\t\t\treturn { mode: 'each', field: bind.field || '', invert, register: bind.register || this.register, schema: bind.schema || this.schema }\n\t\t\t}\n\t\t\tif (bind.mode === 'map') {\n\t\t\t\treturn { mode: 'map', field: bind.field || '', url: bind.url || '', path: bind.path || '', invert }\n\t\t\t}\n\t\t\treturn { mode: 'flag' }\n\t\t},\n\n\t\t/** The drawn rows: configured first, then sourced, each with a key, title and hint. */\n\t\trows() {\n\t\t\tconst configured = (Array.isArray(this.content.rows) ? this.content.rows : [])\n\t\t\t\t.filter((row) => row && row.key !== undefined)\n\t\t\t\t.map((row) => ({ ...row, key: String(row.key), title: this.tr(row.label || String(row.key)), hint: this.tr(row.hint || '') }))\n\t\t\treturn [...configured, ...this.sourced]\n\t\t},\n\n\t\tcolumns() {\n\t\t\treturn (Array.isArray(this.content.columns) ? this.content.columns : [])\n\t\t\t\t.filter((column) => column && column.path)\n\t\t\t\t.map((column) => ({ ...column, header: this.tr(column.header || '') }))\n\t\t},\n\n\t\tshowHeader() {\n\t\t\treturn this.columns.length > 0 || Boolean(this.content.titleHeader || this.content.toggleHeader)\n\t\t},\n\n\t\ttitleHeader() {\n\t\t\treturn this.tr(this.content.titleHeader || '')\n\t\t},\n\n\t\ttoggleHeader() {\n\t\t\treturn this.tr(this.content.toggleHeader || '')\n\t\t},\n\n\t\temptyLabel() {\n\t\t\treturn this.tr(this.content.emptyText || 'Nothing listed yet')\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.saved = {}\n\t\t\tthis.rowSaved = {}\n\t\t\tthis.loadSource()\n\t\t\tthis.loadMap()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.loadSource()\n\t\tthis.loadMap()\n\t},\n\n\tmethods: {\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The stored value of a field: what this widget last saved, else the object's.\n\t\t *\n\t\t * @param {string} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tstored(field) {\n\t\t\treturn Object.hasOwn(this.saved, field) ? this.saved[field] : readPath(this.objectData || {}, field)\n\t\t},\n\n\t\t/**\n\t\t * Whether a row's switch is on.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {boolean}\n\t\t */\n\t\tisOn(row) {\n\t\t\tif (this.bind.mode === 'each' || this.bind.mode === 'map') {\n\t\t\t\tconst on = this.rowValue(row) === true\n\t\t\t\treturn this.bind.invert ? !on : on\n\t\t\t}\n\t\t\tif (this.bind.mode === 'list') {\n\t\t\t\tconst list = this.stored(this.bind.field)\n\t\t\t\tconst inList = Array.isArray(list) && list.map(String).includes(row.key)\n\t\t\t\treturn this.bind.invert ? !inList : inList\n\t\t\t}\n\t\t\treturn row.field ? this.stored(row.field) === true : false\n\t\t},\n\n\t\t/**\n\t\t * `each` and `map`: the stored value of a row's switch, as last written,\n\t\t * else read off the row's object or the map.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {unknown}\n\t\t * @spec openspec/changes/toggle-table-objects-and-map/specs/toggle-table/spec.md#requirement-a-toggle-table-can-switch-objects-or-a-config-map\n\t\t */\n\t\trowValue(row) {\n\t\t\tif (Object.hasOwn(this.rowSaved, row.key)) {\n\t\t\t\treturn this.rowSaved[row.key]\n\t\t\t}\n\t\t\tif (this.bind.mode === 'each') {\n\t\t\t\treturn this.bind.field ? readPath(row.item || row, this.bind.field) : undefined\n\t\t\t}\n\t\t\tconst map = this.bind.url ? this.map : (this.bind.field ? this.stored(this.bind.field) : null)\n\t\t\treturn map && typeof map === 'object' ? map[row.key] : undefined\n\t\t},\n\n\t\t/**\n\t\t * Resolve `@objectId` and `@object.<path>` in a url.\n\t\t *\n\t\t * @param {string} url The url.\n\t\t * @return {string}\n\t\t */\n\t\tfillUrl(url) {\n\t\t\tconst object = this.objectData || {}\n\t\t\treturn String(url)\n\t\t\t\t.replace(/@objectId/g, () => encodeURIComponent(String(this.objectId || object.id || '')))\n\t\t\t\t.replace(/@object\\.([\\w.@]+)/g, (m, path) => encodeURIComponent(String(readPath(object, path) ?? '')))\n\t\t},\n\n\t\t/**\n\t\t * `map` with `bind.url`: read the map.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/toggle-table-objects-and-map/specs/toggle-table/spec.md#requirement-a-toggle-table-can-switch-objects-or-a-config-map\n\t\t */\n\t\tasync loadMap() {\n\t\t\tif (this.bind.mode !== 'map' || !this.bind.url) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tconst { data } = await axios.get(prefixUrl(this.fillUrl(this.bind.url)))\n\t\t\t\tconst map = this.bind.path ? readPath(data, this.bind.path) : data\n\t\t\t\tthis.map = map && typeof map === 'object' ? map : {}\n\t\t\t} catch (e) {\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * `each` and `map`: write one row's switch.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {boolean} value The value to store.\n\t\t * @return {Promise<unknown>} The value the server holds now.\n\t\t * @spec openspec/changes/toggle-table-objects-and-map/specs/toggle-table/spec.md#requirement-a-toggle-table-can-switch-objects-or-a-config-map\n\t\t */\n\t\tasync writeRow(row, value) {\n\t\t\tconst save = this.content.save\n\t\t\tconst hasSave = Boolean(save && save.url)\n\t\t\tif (this.bind.mode === 'each') {\n\t\t\t\tconst url = objectUrlOf(this.bind.register, this.bind.schema, row.key)\n\t\t\t\tif ((!url && !hasSave) || !this.bind.field) {\n\t\t\t\t\tthrow new Error(this.tr('This switch cannot be saved here.'))\n\t\t\t\t}\n\t\t\t\tconst data = await writeFields(url, { [this.bind.field]: value }, { save, object: row.item || row })\n\t\t\t\tconst answered = hasSave ? undefined : readPath(data, this.bind.field)\n\t\t\t\treturn answered !== undefined ? answered : value\n\t\t\t}\n\t\t\tif (this.bind.url) {\n\t\t\t\tif (!hasSave) {\n\t\t\t\t\tthrow new Error(this.tr('This switch cannot be saved here.'))\n\t\t\t\t}\n\t\t\t\tawait writeFields('', { [row.key]: value }, { save, object: this.objectData })\n\t\t\t\treturn value\n\t\t\t}\n\t\t\tif ((!this.objectUrl && !hasSave) || !this.bind.field) {\n\t\t\t\tthrow new Error(this.tr('This switch cannot be saved here.'))\n\t\t\t}\n\t\t\tawait writeFields(this.objectUrl, { [`${this.bind.field}.${row.key}`]: value }, { save, object: this.objectData })\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * The text of an extra column for a row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {object} column The column.\n\t\t * @return {string}\n\t\t */\n\t\tcell(row, column) {\n\t\t\tconst raw = readPath(row, column.path)\n\t\t\tif (raw === undefined || raw === null || raw === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (column.map && Object.hasOwn(column.map, String(raw))) {\n\t\t\t\treturn this.tr(column.map[String(raw)])\n\t\t\t}\n\t\t\treturn typeof raw === 'object' ? '' : String(raw)\n\t\t},\n\n\t\t/** Read the rows of `source`, resolving tokens in its url. */\n\t\tasync loadSource() {\n\t\t\tconst source = this.content.source\n\t\t\tif (!source || !source.url || !source.key) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst url = this.fillUrl(source.url)\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tconst { data } = await axios.get(prefixUrl(url))\n\t\t\t\tconst list = source.path ? readPath(data, source.path) : data\n\t\t\t\tthis.sourced = (Array.isArray(list) ? list : [])\n\t\t\t\t\t.filter((item) => item && readPath(item, source.key) !== undefined)\n\t\t\t\t\t.map((item) => ({\n\t\t\t\t\t\t...item,\n\t\t\t\t\t\titem,\n\t\t\t\t\t\tkey: String(readPath(item, source.key)),\n\t\t\t\t\t\ttitle: String(readPath(item, source.label || source.key) ?? readPath(item, source.key)),\n\t\t\t\t\t\thint: source.hint ? String(readPath(item, source.hint) ?? '') : '',\n\t\t\t\t\t}))\n\t\t\t} catch (e) {\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Flip one switch and save that one field.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {boolean} on The new switch state.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-toggle-table/specs/toggle-table/spec.md#requirement-a-toggle-saves-one-field\n\t\t */\n\t\tasync toggle(row, on) {\n\t\t\tif (this.bind.mode === 'each' || this.bind.mode === 'map') {\n\t\t\t\tthis.notice = ''\n\t\t\t\tthis.busy = row.key\n\t\t\t\ttry {\n\t\t\t\t\tconst written = await this.writeRow(row, this.bind.invert ? !on : on)\n\t\t\t\t\tthis.rowSaved = { ...this.rowSaved, [row.key]: written }\n\t\t\t\t\tthis.$emit('saved', { field: this.bind.mode === 'each' ? this.bind.field : row.key, key: row.key, value: written })\n\t\t\t\t} catch (e) {\n\t\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t\t\tthis.undone = { ...this.undone, [row.key]: (this.undone[row.key] || 0) + 1 }\n\t\t\t\t} finally {\n\t\t\t\t\tthis.busy = ''\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst field = this.bind.mode === 'list' ? this.bind.field : row.field\n\t\t\tif ((!this.objectUrl && !(this.content.save && this.content.save.url)) || !field) {\n\t\t\t\tthis.notice = this.tr('This switch cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet next\n\t\t\tif (this.bind.mode === 'list') {\n\t\t\t\tconst list = (Array.isArray(this.stored(field)) ? this.stored(field) : []).map(String)\n\t\t\t\tconst wantInList = this.bind.invert ? !on : on\n\t\t\t\tnext = wantInList ? (list.includes(row.key) ? list : [...list, row.key]) : list.filter((key) => key !== row.key)\n\t\t\t} else {\n\t\t\t\tnext = on\n\t\t\t}\n\t\t\tthis.notice = ''\n\t\t\tthis.busy = row.key\n\t\t\ttry {\n\t\t\t\tconst data = await writeFields(this.objectUrl, { [field]: next }, { save: this.content.save, object: this.objectData })\n\t\t\t\tconst answered = readPath(data, field)\n\t\t\t\tconst written = answered !== undefined ? answered : next\n\t\t\t\tthis.saved = { ...this.saved, [field]: written }\n\t\t\t\t/**\n\t\t\t\t * @event saved A switch was written.\n\t\t\t\t * @type {{field: string, key?: string, value: unknown}} `key` is the row, in the `each` and `map` modes.\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { field, value: written })\n\t\t\t} catch (e) {\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t\tthis.undone = { ...this.undone, [row.key]: (this.undone[row.key] || 0) + 1 }\n\t\t\t} finally {\n\t\t\t\tthis.busy = ''\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-toggle-table {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmin-width: 0;\n}\n\n.cn-toggle-table__table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-toggle-table__head {\n\tpadding: 8px 12px;\n\ttext-align: start;\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--color-text-maxcontrast);\n\tbackground: var(--color-background-hover);\n}\n\n.cn-toggle-table__head--toggle,\n.cn-toggle-table__cell--toggle {\n\twidth: 1%;\n\twhite-space: nowrap;\n\ttext-align: end;\n}\n\n.cn-toggle-table__row {\n\tborder-top: 1px solid var(--cn-board-hairline, var(--color-border));\n}\n\n.cn-toggle-table__cell {\n\tpadding: 10px 12px;\n\tvertical-align: middle;\n\toverflow-wrap: anywhere;\n}\n\n.cn-toggle-table__title {\n\tdisplay: block;\n\tfont-weight: 600;\n}\n\n.cn-toggle-table__hint {\n\tdisplay: block;\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-toggle-table__empty {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_createElementBlock","_toDisplayString","_createElementVNode","_Fragment","_renderList","_openBlock"],"mappings":"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"}
@@ -2,7 +2,7 @@ import script from './CnTranslatedBadge.vue2.js';
2
2
  import { render } from './CnTranslatedBadge.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-355f5b08";
5
+ script.__scopeId = "data-v-37e3a382";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -1,4 +1,5 @@
1
1
  import { translate } from '@nextcloud/l10n';
2
+ import { userLocale } from '../../utils/userLocale.js';
2
3
 
3
4
  /**
4
5
  * CnTranslatedBadge — surfaces OR's `_translationMeta.translatedFrom`
@@ -144,7 +145,7 @@ var script = {
144
145
  try {
145
146
  const d = new Date(this.translatedAt);
146
147
  if (!Number.isNaN(d.getTime())) {
147
- return translate('nextcloud-vue', 'Translated at {when}', { when: d.toLocaleString() })
148
+ return translate('nextcloud-vue', 'Translated at {when}', { when: d.toLocaleString(userLocale()) })
148
149
  }
149
150
  } catch {
150
151
  // fall through to raw ISO
@@ -1 +1 @@
1
- {"version":3,"file":"CnTranslatedBadge.vue2.js","sources":["../../../../src/components/CnTranslatedBadge/CnTranslatedBadge.vue"],"sourcesContent":["<!--\n CnTranslatedBadge — stateless chip that surfaces OR's\n `_translationMeta` block.\n\n The badge auto-hides when the bound object has no `_translationMeta`\n block, or when `_translationMeta.translatedFrom` is null. When the\n field IS set, the badge renders \"(translated from {sourceLanguage})\"\n and exposes the `translatedAt` timestamp via the `title` attribute.\n\n Pairs with the language-negotiation getters on `createObjectStore`\n (see `i18n-language-negotiation-getters`): apps that wire\n `languageGetter` get translated bytes from OR; the badge then\n signals to the user that those bytes are a translation projection,\n not the source row.\n-->\n<template>\n\t<span\n\t\tv-if=\"visible\"\n\t\tclass=\"cn-translated-badge\"\n\t\t:title=\"hoverTitle\"\n\t\tdata-testid=\"cn-translated-badge\">\n\t\t<span class=\"cn-translated-badge__icon\" aria-hidden=\"true\">⇄</span>\n\t\t<span class=\"cn-translated-badge__label\">\n\t\t\t{{ label }}\n\t\t</span>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\n\n/**\n * CnTranslatedBadge — surfaces OR's `_translationMeta.translatedFrom`\n * as a small chip in detail surfaces.\n *\n * Basic:\n * ```vue\n * <CnTranslatedBadge :object=\"object\" />\n * ```\n *\n * With custom locale name formatter:\n * ```vue\n * <CnTranslatedBadge\n * :object=\"object\"\n * :locale-name-formatter=\"(bcp47) => myLanguageLabels[bcp47] || bcp47\" />\n * ```\n */\nexport default {\n\tname: 'CnTranslatedBadge',\n\n\tprops: {\n\t\t/**\n\t\t * The OR object whose `_translationMeta` is surfaced. The\n\t\t * badge auto-hides when `object` is null, when\n\t\t * `object._translationMeta` is missing, or when\n\t\t * `_translationMeta.translatedFrom` is null/empty.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Optional BCP-47 → display name function. Receives the\n\t\t * BCP-47 string from `_translationMeta.translatedFrom` and\n\t\t * returns a user-facing label (e.g. `'nl' → 'Nederlands'`).\n\t\t * When omitted, falls back to `Intl.DisplayNames` when\n\t\t * available, then to the raw BCP-47 string.\n\t\t *\n\t\t * @type {((locale: string) => string)|null}\n\t\t */\n\t\tlocaleNameFormatter: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The translatedFrom BCP-47 string when present, else null.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\ttranslatedFrom() {\n\t\t\tconst meta = this.object && this.object._translationMeta\n\t\t\tif (!meta) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = meta.translatedFrom\n\t\t\treturn typeof v === 'string' && v.length > 0 ? v : null\n\t\t},\n\n\t\t/**\n\t\t * The translatedAt ISO timestamp when present, else null.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\ttranslatedAt() {\n\t\t\tconst meta = this.object && this.object._translationMeta\n\t\t\tif (!meta) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = meta.translatedAt\n\t\t\treturn typeof v === 'string' && v.length > 0 ? v : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the badge should render at all.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tvisible() {\n\t\t\treturn this.translatedFrom !== null\n\t\t},\n\n\t\t/**\n\t\t * Display name for the source language. Falls back through\n\t\t * `localeNameFormatter` → `Intl.DisplayNames` → raw BCP-47.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tsourceDisplayName() {\n\t\t\tconst bcp47 = this.translatedFrom\n\t\t\tif (!bcp47) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (typeof this.localeNameFormatter === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst v = this.localeNameFormatter(bcp47)\n\t\t\t\t\tif (typeof v === 'string' && v.length > 0) {\n\t\t\t\t\t\treturn v\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// fall through to Intl\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof Intl !== 'undefined' && typeof Intl.DisplayNames === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst navLang = (typeof navigator !== 'undefined' && navigator.language) || 'en'\n\t\t\t\t\tconst dn = new Intl.DisplayNames([navLang], { type: 'language' })\n\t\t\t\t\tconst v = dn.of(bcp47)\n\t\t\t\t\tif (typeof v === 'string' && v.length > 0) {\n\t\t\t\t\t\treturn v\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// fall through to raw\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn bcp47\n\t\t},\n\n\t\t/**\n\t\t * The user-facing label, e.g. `(translated from Dutch)`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tlabel() {\n\t\t\treturn t('nextcloud-vue', '(translated from {language})', { language: this.sourceDisplayName })\n\t\t},\n\n\t\t/**\n\t\t * Hover title — exposes `translatedAt` so users can see how\n\t\t * old the projection is.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\thoverTitle() {\n\t\t\tif (!this.translatedAt) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst d = new Date(this.translatedAt)\n\t\t\t\tif (!Number.isNaN(d.getTime())) {\n\t\t\t\t\treturn t('nextcloud-vue', 'Translated at {when}', { when: d.toLocaleString() })\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// fall through to raw ISO\n\t\t\t}\n\t\t\treturn this.translatedAt\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-translated-badge {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--default-grid-baseline, 4px);\n\tpadding: calc(0.5 * var(--default-grid-baseline, 4px)) calc(2 * var(--default-grid-baseline, 4px));\n\tborder-radius: var(--border-radius-pill, 999px);\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.75em;\n\tfont-weight: 500;\n\tline-height: 1;\n}\n\n.cn-translated-badge__icon {\n\tfont-size: 0.9em;\n}\n</style>\n"],"names":["t"],"mappings":"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"}
1
+ {"version":3,"file":"CnTranslatedBadge.vue2.js","sources":["../../../../src/components/CnTranslatedBadge/CnTranslatedBadge.vue"],"sourcesContent":["<!--\n CnTranslatedBadge — stateless chip that surfaces OR's\n `_translationMeta` block.\n\n The badge auto-hides when the bound object has no `_translationMeta`\n block, or when `_translationMeta.translatedFrom` is null. When the\n field IS set, the badge renders \"(translated from {sourceLanguage})\"\n and exposes the `translatedAt` timestamp via the `title` attribute.\n\n Pairs with the language-negotiation getters on `createObjectStore`\n (see `i18n-language-negotiation-getters`): apps that wire\n `languageGetter` get translated bytes from OR; the badge then\n signals to the user that those bytes are a translation projection,\n not the source row.\n-->\n<template>\n\t<span\n\t\tv-if=\"visible\"\n\t\tclass=\"cn-translated-badge\"\n\t\t:title=\"hoverTitle\"\n\t\tdata-testid=\"cn-translated-badge\">\n\t\t<span class=\"cn-translated-badge__icon\" aria-hidden=\"true\">⇄</span>\n\t\t<span class=\"cn-translated-badge__label\">\n\t\t\t{{ label }}\n\t\t</span>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * CnTranslatedBadge — surfaces OR's `_translationMeta.translatedFrom`\n * as a small chip in detail surfaces.\n *\n * Basic:\n * ```vue\n * <CnTranslatedBadge :object=\"object\" />\n * ```\n *\n * With custom locale name formatter:\n * ```vue\n * <CnTranslatedBadge\n * :object=\"object\"\n * :locale-name-formatter=\"(bcp47) => myLanguageLabels[bcp47] || bcp47\" />\n * ```\n */\nexport default {\n\tname: 'CnTranslatedBadge',\n\n\tprops: {\n\t\t/**\n\t\t * The OR object whose `_translationMeta` is surfaced. The\n\t\t * badge auto-hides when `object` is null, when\n\t\t * `object._translationMeta` is missing, or when\n\t\t * `_translationMeta.translatedFrom` is null/empty.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Optional BCP-47 → display name function. Receives the\n\t\t * BCP-47 string from `_translationMeta.translatedFrom` and\n\t\t * returns a user-facing label (e.g. `'nl' → 'Nederlands'`).\n\t\t * When omitted, falls back to `Intl.DisplayNames` when\n\t\t * available, then to the raw BCP-47 string.\n\t\t *\n\t\t * @type {((locale: string) => string)|null}\n\t\t */\n\t\tlocaleNameFormatter: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The translatedFrom BCP-47 string when present, else null.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\ttranslatedFrom() {\n\t\t\tconst meta = this.object && this.object._translationMeta\n\t\t\tif (!meta) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = meta.translatedFrom\n\t\t\treturn typeof v === 'string' && v.length > 0 ? v : null\n\t\t},\n\n\t\t/**\n\t\t * The translatedAt ISO timestamp when present, else null.\n\t\t *\n\t\t * @return {string|null}\n\t\t */\n\t\ttranslatedAt() {\n\t\t\tconst meta = this.object && this.object._translationMeta\n\t\t\tif (!meta) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = meta.translatedAt\n\t\t\treturn typeof v === 'string' && v.length > 0 ? v : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the badge should render at all.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tvisible() {\n\t\t\treturn this.translatedFrom !== null\n\t\t},\n\n\t\t/**\n\t\t * Display name for the source language. Falls back through\n\t\t * `localeNameFormatter` → `Intl.DisplayNames` → raw BCP-47.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tsourceDisplayName() {\n\t\t\tconst bcp47 = this.translatedFrom\n\t\t\tif (!bcp47) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (typeof this.localeNameFormatter === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst v = this.localeNameFormatter(bcp47)\n\t\t\t\t\tif (typeof v === 'string' && v.length > 0) {\n\t\t\t\t\t\treturn v\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// fall through to Intl\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof Intl !== 'undefined' && typeof Intl.DisplayNames === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst navLang = (typeof navigator !== 'undefined' && navigator.language) || 'en'\n\t\t\t\t\tconst dn = new Intl.DisplayNames([navLang], { type: 'language' })\n\t\t\t\t\tconst v = dn.of(bcp47)\n\t\t\t\t\tif (typeof v === 'string' && v.length > 0) {\n\t\t\t\t\t\treturn v\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// fall through to raw\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn bcp47\n\t\t},\n\n\t\t/**\n\t\t * The user-facing label, e.g. `(translated from Dutch)`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tlabel() {\n\t\t\treturn t('nextcloud-vue', '(translated from {language})', { language: this.sourceDisplayName })\n\t\t},\n\n\t\t/**\n\t\t * Hover title — exposes `translatedAt` so users can see how\n\t\t * old the projection is.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\thoverTitle() {\n\t\t\tif (!this.translatedAt) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst d = new Date(this.translatedAt)\n\t\t\t\tif (!Number.isNaN(d.getTime())) {\n\t\t\t\t\treturn t('nextcloud-vue', 'Translated at {when}', { when: d.toLocaleString(userLocale()) })\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// fall through to raw ISO\n\t\t\t}\n\t\t\treturn this.translatedAt\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-translated-badge {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: var(--default-grid-baseline, 4px);\n\tpadding: calc(0.5 * var(--default-grid-baseline, 4px)) calc(2 * var(--default-grid-baseline, 4px));\n\tborder-radius: var(--border-radius-pill, 999px);\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.75em;\n\tfont-weight: 500;\n\tline-height: 1;\n}\n\n.cn-translated-badge__icon {\n\tfont-size: 0.9em;\n}\n</style>\n"],"names":["t"],"mappings":"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"}
@@ -2,7 +2,7 @@ import script from './CnVersionHistory.vue2.js';
2
2
  import { render } from './CnVersionHistory.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-5888d95c";
5
+ script.__scopeId = "data-v-0fca5a52";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -7,6 +7,7 @@ import FileCompare from 'vue-material-design-icons/FileCompare.vue';
7
7
  import __sfc_main from '../CnDetailCard/CnDetailCard.vue.js';
8
8
  import { foldAuditTrailEntries } from '../../utils/auditTrailDiff.js';
9
9
  import { computeObjectDiff } from '../../utils/computeObjectDiff.js';
10
+ import { userLocale } from '../../utils/userLocale.js';
10
11
  import { buildHeaders } from '../../utils/headers.js';
11
12
 
12
13
  /**
@@ -348,7 +349,7 @@ var script = {
348
349
  if (Number.isNaN(d.getTime()) === true) {
349
350
  return String(raw)
350
351
  }
351
- return d.toLocaleString()
352
+ return d.toLocaleString(userLocale())
352
353
  },
353
354
  },
354
355
  };
@@ -1 +1 @@
1
- {"version":3,"file":"CnVersionHistory.vue2.js","sources":["../../../../src/components/CnVersionHistory/CnVersionHistory.vue"],"sourcesContent":["<!--\n CnVersionHistory — object version-history + field-by-field diff\n viewer for the integration registry.\n\n Lists an OpenRegister object's audit-trail entries (timestamp, user,\n semantic version, action) newest-first, and lets the user open a\n structural diff for one entry, or \"compare\" two checked entries.\n OpenRegister only stores a per-field `changed` delta per entry (no\n full before/after snapshot), so a multi-entry compare is\n reconstructed by folding the range's deltas (`foldAuditTrailEntries`)\n before diffing (`computeObjectDiff`) — see the `version-diff-viewer`\n openspec change's design notes.\n-->\n<template>\n\t<CnDetailCard\n\t\t:title=\"resolvedTitle\"\n\t\t:icon=\"FileCompare\"\n\t\t:collapsible=\"collapsible\"\n\t\t:data-surface=\"surface\">\n\t\t<NcLoadingIcon v-if=\"loading && entries.length === 0\" />\n\t\t<div v-else-if=\"entries.length === 0\" class=\"cn-version-history__empty\">\n\t\t\t{{ noEntriesLabel }}\n\t\t</div>\n\t\t<div v-else-if=\"activeDiff === null\" class=\"cn-version-history__list\">\n\t\t\t<ul class=\"cn-version-history__rows\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"entry in entries\"\n\t\t\t\t\t:key=\"entry.id\"\n\t\t\t\t\tclass=\"cn-version-history__row\">\n\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t:modelValue=\"isSelected(entry.id)\"\n\t\t\t\t\t\t:disabled=\"isSelected(entry.id) === false && selectedIds.length >= 2\"\n\t\t\t\t\t\t:aria-label=\"selectForCompareLabel\"\n\t\t\t\t\t\t@update:modelValue=\"toggleSelected(entry.id, $event)\" />\n\t\t\t\t\t<button class=\"cn-version-history__row-main\" type=\"button\" @click=\"openSingleDiff(entry)\">\n\t\t\t\t\t\t<span class=\"cn-version-history__version\">{{ entry.version || fallbackVersionLabel }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__action\">{{ entry.action || '' }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__when\">{{ formatWhen(entry) }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__user\">{{ formatUser(entry) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div class=\"cn-version-history__toolbar\">\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"selectedIds.length !== 2\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t@click=\"openCompareDiff\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Compare :size=\"18\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ compareLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"hasMore\"\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\t\t@click=\"loadMore\">\n\t\t\t\t\t{{ loadMoreLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<div v-else class=\"cn-version-history__diff\">\n\t\t\t<div class=\"cn-version-history__diff-toolbar\">\n\t\t\t\t<NcButton variant=\"tertiary\" @click=\"closeDiff\">\n\t\t\t\t\t{{ backLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"showAllFields\" @update:modelValue=\"showAllFields = $event\">\n\t\t\t\t\t{{ showAllFieldsLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</div>\n\t\t\t<table v-if=\"visibleDiffRows.length > 0\" class=\"cn-version-history__diff-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>{{ fieldLabel }}</th>\n\t\t\t\t\t\t<th>{{ oldValueLabel }}</th>\n\t\t\t\t\t\t<th>{{ newValueLabel }}</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr v-for=\"row in visibleDiffRows\" :key=\"row.path\" :class=\"rowClass(row.type)\">\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-field\">\n\t\t\t\t\t\t\t{{ row.path }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'old')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.oldValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'new')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.newValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t\t<div v-else class=\"cn-version-history__diff-empty\">\n\t\t\t\t{{ noChangesLabel }}\n\t\t\t</div>\n\t\t</div>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport Compare from 'vue-material-design-icons/Compare.vue'\nimport FileCompare from 'vue-material-design-icons/FileCompare.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport { foldAuditTrailEntries } from '../../utils/auditTrailDiff.js'\nimport { computeObjectDiff } from '../../utils/computeObjectDiff.js'\nimport { buildHeaders } from '../../utils/index.js'\n\n/**\n * A single row rendered in the top-level diff table.\n *\n * @typedef {object} FieldDiffRow\n * @property {string} path Field name.\n * @property {'added'|'removed'|'changed'|'unchanged'} type Classification.\n * @property {unknown} oldValue Value before.\n * @property {unknown} newValue Value after.\n */\n\n/**\n * Classify one top-level field between two folded states, reusing\n * `computeObjectDiff` to decide equality (so nested objects/arrays are\n * compared structurally, not by reference).\n *\n * @param {string} key Field name.\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow} The classified row.\n */\nfunction classifyField(key, oldState, newState) {\n\tconst oldMissing = Object.hasOwn(oldState, key) === false\n\tconst newMissing = Object.hasOwn(newState, key) === false\n\tconst oldValue = oldState[key]\n\tconst newValue = newState[key]\n\n\tif (oldMissing === true && newMissing === false) {\n\t\treturn { path: key, type: 'added', oldValue: undefined, newValue }\n\t}\n\tif (oldMissing === false && newMissing === true) {\n\t\treturn { path: key, type: 'removed', oldValue, newValue: undefined }\n\t}\n\tconst nested = computeObjectDiff(oldValue, newValue)\n\tconst isChanged = nested.some((entry) => entry.type !== 'unchanged')\n\treturn { path: key, type: isChanged ? 'changed' : 'unchanged', oldValue, newValue }\n}\n\n/**\n * Build the top-level field-by-field diff table for a folded\n * before/after state pair.\n *\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow[]} One row per touched field, sorted by field name.\n */\nfunction buildFieldRows(oldState, newState) {\n\tconst keys = Array.from(new Set([...Object.keys(oldState), ...Object.keys(newState)])).sort()\n\treturn keys.map((key) => classifyField(key, oldState, newState))\n}\n\n/**\n * CnVersionHistory — object version-history list plus field-by-field\n * diff viewer, rendered by the integration registry on sidebar-tab\n * and dashboard/detail-widget surfaces alike.\n *\n * Basic usage\n * ```vue\n * <CnVersionHistory\n * :register=\"registerId\"\n * :schema=\"schemaId\"\n * :object-id=\"objectId\"\n * surface=\"detail-page\" />\n * ```\n */\nexport default {\n\tname: 'CnVersionHistory',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, NcButton, NcCheckboxRadioSwitch, Compare },\n\n\tprops: {\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface — passed for AD-19 surface fallback consumers. */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (value) => ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'].includes(value),\n\t\t},\n\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Number of history entries to fetch per page. */\n\t\tpageSize: { type: Number, default: 20 },\n\t\t/** Whether the card collapses. */\n\t\tcollapsible: { type: Boolean, default: false },\n\t\t/** Override the card title (defaults to the translated label). */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Pre-translated empty-history label. */\n\t\tnoEntriesLabel: { type: String, default: () => t('nextcloud-vue', 'No version history yet') },\n\t\t/** Pre-translated fallback shown when an entry carries no semantic version. */\n\t\tfallbackVersionLabel: { type: String, default: () => t('nextcloud-vue', 'Unversioned change') },\n\t\t/** Pre-translated \"select for compare\" checkbox label. */\n\t\tselectForCompareLabel: { type: String, default: () => t('nextcloud-vue', 'Select for compare') },\n\t\t/** Pre-translated compare-action label. */\n\t\tcompareLabel: { type: String, default: () => t('nextcloud-vue', 'Compare selected') },\n\t\t/** Pre-translated load-more label. */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/** Pre-translated back-to-list label. */\n\t\tbackLabel: { type: String, default: () => t('nextcloud-vue', 'Back to history') },\n\t\t/** Pre-translated \"show all fields\" toggle label. */\n\t\tshowAllFieldsLabel: { type: String, default: () => t('nextcloud-vue', 'Show all fields') },\n\t\t/** Pre-translated diff table field-column header. */\n\t\tfieldLabel: { type: String, default: () => t('nextcloud-vue', 'Field') },\n\t\t/** Pre-translated diff table old-value-column header. */\n\t\toldValueLabel: { type: String, default: () => t('nextcloud-vue', 'Old value') },\n\t\t/** Pre-translated diff table new-value-column header. */\n\t\tnewValueLabel: { type: String, default: () => t('nextcloud-vue', 'New value') },\n\t\t/** Pre-translated label shown when a diff has no visible rows. */\n\t\tnoChangesLabel: { type: String, default: () => t('nextcloud-vue', 'No field changes to show') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tFileCompare: markRaw(FileCompare),\n\t\t\tentries: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tselectedIds: [],\n\t\t\t/** `null` = list view; otherwise `{ oldState, newState }` for the open diff. */\n\t\t\tactiveDiff: null,\n\t\t\tshowAllFields: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tresolvedTitle() {\n\t\t\treturn this.title || t('nextcloud-vue', 'Version history')\n\t\t},\n\n\t\thasMore() {\n\t\t\treturn this.entries.length < this.total\n\t\t},\n\n\t\tdiffRows() {\n\t\t\tif (this.activeDiff === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn buildFieldRows(this.activeDiff.oldState, this.activeDiff.newState)\n\t\t},\n\n\t\tvisibleDiffRows() {\n\t\t\tif (this.showAllFields === true) {\n\t\t\t\treturn this.diffRows\n\t\t\t}\n\t\t\treturn this.diffRows.filter((row) => row.type !== 'unchanged')\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.resetAndFetch()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tresetAndFetch() {\n\t\t\tthis.page = 1\n\t\t\tthis.entries = []\n\t\t\tthis.selectedIds = []\n\t\t\tthis.activeDiff = null\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tasync fetchEntries() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = this.page === 1\n\t\t\tthis.loadingMore = this.page > 1\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams()\n\t\t\t\tparams.set('limit', String(this.pageSize))\n\t\t\t\tparams.set('_page', String(this.page))\n\t\t\t\tparams.set('_sort[created]', 'DESC')\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/audit-trails`)\n\t\t\t\tconst response = await fetch(`${url}?${params.toString()}`, { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.entries = this.page === 1 ? results : [...this.entries, ...results]\n\t\t\t\t\tthis.total = data.total || this.entries.length\n\t\t\t\t} else if (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnVersionHistory] failed to fetch version history', err)\n\t\t\t\tif (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page += 1\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tisSelected(id) {\n\t\t\treturn this.selectedIds.includes(id)\n\t\t},\n\n\t\ttoggleSelected(id, checked) {\n\t\t\tif (checked === true) {\n\t\t\t\tif (this.selectedIds.includes(id) === false && this.selectedIds.length < 2) {\n\t\t\t\t\tthis.selectedIds = [...this.selectedIds, id]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.selectedIds = this.selectedIds.filter((existing) => existing !== id)\n\t\t\t}\n\t\t},\n\n\t\topenSingleDiff(entry) {\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries([entry])\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\topenCompareDiff() {\n\t\t\tif (this.selectedIds.length !== 2) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Entries are fetched newest-first; fold oldest-first so the\n\t\t\t// \"first old\" / \"last new\" semantics land on the right side.\n\t\t\tconst selectedEntries = this.entries.filter((entry) => this.selectedIds.includes(entry.id))\n\t\t\tconst chronological = [...selectedEntries].reverse()\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries(chronological)\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\tcloseDiff() {\n\t\t\tthis.activeDiff = null\n\t\t},\n\n\t\tisNestedValue(row) {\n\t\t\tconst isObj = (v) => v !== null && typeof v === 'object'\n\t\t\treturn isObj(row.oldValue) === true || isObj(row.newValue) === true\n\t\t},\n\n\t\t/**\n\t\t * Build the per-line nested diff for one side of a table cell\n\t\t * whose value is an object/array, so each nested key can be\n\t\t * individually add/remove/change tinted.\n\t\t *\n\t\t * @param {FieldDiffRow} row The parent field row.\n\t\t * @param {'old'|'new'} side Which side is being rendered (both sides render the same nested diff so add/remove/change context matches on both columns).\n\t\t * @return {Array<{path: string, type: string, text: string}>} Rendered lines.\n\t\t */\n\t\tnestedLines(row, side) {\n\t\t\tconst base = row.oldValue !== null && typeof row.oldValue === 'object' ? row.oldValue : {}\n\t\t\tconst next = row.newValue !== null && typeof row.newValue === 'object' ? row.newValue : {}\n\t\t\tconst from = row.type === 'added' ? {} : base\n\t\t\tconst to = row.type === 'removed' ? {} : next\n\t\t\tconst nested = computeObjectDiff(from, to)\n\t\t\tconst visible = this.showAllFields === true ? nested : nested.filter((entry) => entry.type !== 'unchanged')\n\t\t\treturn visible.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\ttype: entry.type,\n\t\t\t\ttext: this.formatNestedLine(entry, side),\n\t\t\t}))\n\t\t},\n\n\t\tformatNestedLine(entry, side) {\n\t\t\tconst label = entry.path === '' ? '·' : entry.path\n\t\t\tif (entry.type === 'changed') {\n\t\t\t\tconst shown = side === 'new' ? entry.newValue : entry.oldValue\n\t\t\t\treturn `${label}: ${this.formatScalar(shown)}`\n\t\t\t}\n\t\t\tconst value = entry.type === 'removed' ? entry.oldValue : entry.newValue\n\t\t\treturn `${label}: ${this.formatScalar(value)}`\n\t\t},\n\n\t\trowClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-row': true,\n\t\t\t\t[`cn-version-history__diff-row--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tlineClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-line': true,\n\t\t\t\t[`cn-version-history__diff-line--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tvalueCellTag(row) {\n\t\t\treturn this.isNestedValue(row) === true ? 'pre' : 'span'\n\t\t},\n\n\t\tvalueCellProps(row) {\n\t\t\treturn this.isNestedValue(row) === true ? { class: 'cn-version-history__diff-json' } : {}\n\t\t},\n\n\t\tformatScalar(value) {\n\t\t\tif (value === undefined) {\n\t\t\t\treturn '—'\n\t\t\t}\n\t\t\tif (value === null) {\n\t\t\t\treturn 'null'\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(value)\n\t\t\t\t} catch {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\tformatUser(entry) {\n\t\t\treturn entry.userName || entry.user || t('nextcloud-vue', 'System')\n\t\t},\n\n\t\tformatWhen(entry) {\n\t\t\tconst raw = entry.created || entry.creationDateTime || entry.timestamp\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst d = new Date(raw)\n\t\t\tif (Number.isNaN(d.getTime()) === true) {\n\t\t\t\treturn String(raw)\n\t\t\t}\n\t\t\treturn d.toLocaleString()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-history__empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n\n.cn-version-history__rows {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-version-history__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-history__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-history__row-main {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\talign-items: baseline;\n\tflex: 1 1 auto;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\ttext-align: left;\n\tfont: inherit;\n\tcolor: inherit;\n\tpadding: 4px;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-version-history__row-main:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-version-history__version {\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-history__action {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__when {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\twhite-space: nowrap;\n}\n\n.cn-version-history__user {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-version-history__toolbar {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-top: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-toolbar {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-version-history__diff-table th,\n.cn-version-history__diff-table td {\n\tborder-bottom: 1px solid var(--color-border);\n\tpadding: 6px 8px;\n\ttext-align: left;\n\tvertical-align: top;\n}\n\n.cn-version-history__diff-field {\n\tfont-weight: 500;\n\tcolor: var(--color-main-text);\n\twhite-space: nowrap;\n}\n\n.cn-version-history__diff-json {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tfont-family: monospace;\n\tfont-size: 12px;\n}\n\n.cn-version-history__diff-row--added .cn-version-history__diff-field {\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-row--removed .cn-version-history__diff-field {\n\tcolor: var(--color-error);\n}\n\n.cn-version-history__diff-row--changed .cn-version-history__diff-field {\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--added {\n\tbackground-color: color-mix(in srgb, var(--color-success) 15%, transparent);\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-line--removed {\n\tbackground-color: color-mix(in srgb, var(--color-error) 15%, transparent);\n\tcolor: var(--color-error);\n\ttext-decoration: line-through;\n}\n\n.cn-version-history__diff-line--changed {\n\tbackground-color: color-mix(in srgb, var(--color-warning) 15%, transparent);\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--unchanged {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__diff-empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n</style>\n"],"names":["CnDetailCard","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnVersionHistory.vue2.js","sources":["../../../../src/components/CnVersionHistory/CnVersionHistory.vue"],"sourcesContent":["<!--\n CnVersionHistory — object version-history + field-by-field diff\n viewer for the integration registry.\n\n Lists an OpenRegister object's audit-trail entries (timestamp, user,\n semantic version, action) newest-first, and lets the user open a\n structural diff for one entry, or \"compare\" two checked entries.\n OpenRegister only stores a per-field `changed` delta per entry (no\n full before/after snapshot), so a multi-entry compare is\n reconstructed by folding the range's deltas (`foldAuditTrailEntries`)\n before diffing (`computeObjectDiff`) — see the `version-diff-viewer`\n openspec change's design notes.\n-->\n<template>\n\t<CnDetailCard\n\t\t:title=\"resolvedTitle\"\n\t\t:icon=\"FileCompare\"\n\t\t:collapsible=\"collapsible\"\n\t\t:data-surface=\"surface\">\n\t\t<NcLoadingIcon v-if=\"loading && entries.length === 0\" />\n\t\t<div v-else-if=\"entries.length === 0\" class=\"cn-version-history__empty\">\n\t\t\t{{ noEntriesLabel }}\n\t\t</div>\n\t\t<div v-else-if=\"activeDiff === null\" class=\"cn-version-history__list\">\n\t\t\t<ul class=\"cn-version-history__rows\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"entry in entries\"\n\t\t\t\t\t:key=\"entry.id\"\n\t\t\t\t\tclass=\"cn-version-history__row\">\n\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t:modelValue=\"isSelected(entry.id)\"\n\t\t\t\t\t\t:disabled=\"isSelected(entry.id) === false && selectedIds.length >= 2\"\n\t\t\t\t\t\t:aria-label=\"selectForCompareLabel\"\n\t\t\t\t\t\t@update:modelValue=\"toggleSelected(entry.id, $event)\" />\n\t\t\t\t\t<button class=\"cn-version-history__row-main\" type=\"button\" @click=\"openSingleDiff(entry)\">\n\t\t\t\t\t\t<span class=\"cn-version-history__version\">{{ entry.version || fallbackVersionLabel }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__action\">{{ entry.action || '' }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__when\">{{ formatWhen(entry) }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__user\">{{ formatUser(entry) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div class=\"cn-version-history__toolbar\">\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"selectedIds.length !== 2\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t@click=\"openCompareDiff\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Compare :size=\"18\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ compareLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"hasMore\"\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\t\t@click=\"loadMore\">\n\t\t\t\t\t{{ loadMoreLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<div v-else class=\"cn-version-history__diff\">\n\t\t\t<div class=\"cn-version-history__diff-toolbar\">\n\t\t\t\t<NcButton variant=\"tertiary\" @click=\"closeDiff\">\n\t\t\t\t\t{{ backLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"showAllFields\" @update:modelValue=\"showAllFields = $event\">\n\t\t\t\t\t{{ showAllFieldsLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</div>\n\t\t\t<table v-if=\"visibleDiffRows.length > 0\" class=\"cn-version-history__diff-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>{{ fieldLabel }}</th>\n\t\t\t\t\t\t<th>{{ oldValueLabel }}</th>\n\t\t\t\t\t\t<th>{{ newValueLabel }}</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr v-for=\"row in visibleDiffRows\" :key=\"row.path\" :class=\"rowClass(row.type)\">\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-field\">\n\t\t\t\t\t\t\t{{ row.path }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'old')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.oldValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'new')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.newValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t\t<div v-else class=\"cn-version-history__diff-empty\">\n\t\t\t\t{{ noChangesLabel }}\n\t\t\t</div>\n\t\t</div>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport Compare from 'vue-material-design-icons/Compare.vue'\nimport FileCompare from 'vue-material-design-icons/FileCompare.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport { foldAuditTrailEntries } from '../../utils/auditTrailDiff.js'\nimport { computeObjectDiff } from '../../utils/computeObjectDiff.js'\nimport { buildHeaders } from '../../utils/index.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * A single row rendered in the top-level diff table.\n *\n * @typedef {object} FieldDiffRow\n * @property {string} path Field name.\n * @property {'added'|'removed'|'changed'|'unchanged'} type Classification.\n * @property {unknown} oldValue Value before.\n * @property {unknown} newValue Value after.\n */\n\n/**\n * Classify one top-level field between two folded states, reusing\n * `computeObjectDiff` to decide equality (so nested objects/arrays are\n * compared structurally, not by reference).\n *\n * @param {string} key Field name.\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow} The classified row.\n */\nfunction classifyField(key, oldState, newState) {\n\tconst oldMissing = Object.hasOwn(oldState, key) === false\n\tconst newMissing = Object.hasOwn(newState, key) === false\n\tconst oldValue = oldState[key]\n\tconst newValue = newState[key]\n\n\tif (oldMissing === true && newMissing === false) {\n\t\treturn { path: key, type: 'added', oldValue: undefined, newValue }\n\t}\n\tif (oldMissing === false && newMissing === true) {\n\t\treturn { path: key, type: 'removed', oldValue, newValue: undefined }\n\t}\n\tconst nested = computeObjectDiff(oldValue, newValue)\n\tconst isChanged = nested.some((entry) => entry.type !== 'unchanged')\n\treturn { path: key, type: isChanged ? 'changed' : 'unchanged', oldValue, newValue }\n}\n\n/**\n * Build the top-level field-by-field diff table for a folded\n * before/after state pair.\n *\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow[]} One row per touched field, sorted by field name.\n */\nfunction buildFieldRows(oldState, newState) {\n\tconst keys = Array.from(new Set([...Object.keys(oldState), ...Object.keys(newState)])).sort()\n\treturn keys.map((key) => classifyField(key, oldState, newState))\n}\n\n/**\n * CnVersionHistory — object version-history list plus field-by-field\n * diff viewer, rendered by the integration registry on sidebar-tab\n * and dashboard/detail-widget surfaces alike.\n *\n * Basic usage\n * ```vue\n * <CnVersionHistory\n * :register=\"registerId\"\n * :schema=\"schemaId\"\n * :object-id=\"objectId\"\n * surface=\"detail-page\" />\n * ```\n */\nexport default {\n\tname: 'CnVersionHistory',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, NcButton, NcCheckboxRadioSwitch, Compare },\n\n\tprops: {\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface — passed for AD-19 surface fallback consumers. */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (value) => ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'].includes(value),\n\t\t},\n\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Number of history entries to fetch per page. */\n\t\tpageSize: { type: Number, default: 20 },\n\t\t/** Whether the card collapses. */\n\t\tcollapsible: { type: Boolean, default: false },\n\t\t/** Override the card title (defaults to the translated label). */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Pre-translated empty-history label. */\n\t\tnoEntriesLabel: { type: String, default: () => t('nextcloud-vue', 'No version history yet') },\n\t\t/** Pre-translated fallback shown when an entry carries no semantic version. */\n\t\tfallbackVersionLabel: { type: String, default: () => t('nextcloud-vue', 'Unversioned change') },\n\t\t/** Pre-translated \"select for compare\" checkbox label. */\n\t\tselectForCompareLabel: { type: String, default: () => t('nextcloud-vue', 'Select for compare') },\n\t\t/** Pre-translated compare-action label. */\n\t\tcompareLabel: { type: String, default: () => t('nextcloud-vue', 'Compare selected') },\n\t\t/** Pre-translated load-more label. */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/** Pre-translated back-to-list label. */\n\t\tbackLabel: { type: String, default: () => t('nextcloud-vue', 'Back to history') },\n\t\t/** Pre-translated \"show all fields\" toggle label. */\n\t\tshowAllFieldsLabel: { type: String, default: () => t('nextcloud-vue', 'Show all fields') },\n\t\t/** Pre-translated diff table field-column header. */\n\t\tfieldLabel: { type: String, default: () => t('nextcloud-vue', 'Field') },\n\t\t/** Pre-translated diff table old-value-column header. */\n\t\toldValueLabel: { type: String, default: () => t('nextcloud-vue', 'Old value') },\n\t\t/** Pre-translated diff table new-value-column header. */\n\t\tnewValueLabel: { type: String, default: () => t('nextcloud-vue', 'New value') },\n\t\t/** Pre-translated label shown when a diff has no visible rows. */\n\t\tnoChangesLabel: { type: String, default: () => t('nextcloud-vue', 'No field changes to show') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tFileCompare: markRaw(FileCompare),\n\t\t\tentries: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tselectedIds: [],\n\t\t\t/** `null` = list view; otherwise `{ oldState, newState }` for the open diff. */\n\t\t\tactiveDiff: null,\n\t\t\tshowAllFields: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tresolvedTitle() {\n\t\t\treturn this.title || t('nextcloud-vue', 'Version history')\n\t\t},\n\n\t\thasMore() {\n\t\t\treturn this.entries.length < this.total\n\t\t},\n\n\t\tdiffRows() {\n\t\t\tif (this.activeDiff === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn buildFieldRows(this.activeDiff.oldState, this.activeDiff.newState)\n\t\t},\n\n\t\tvisibleDiffRows() {\n\t\t\tif (this.showAllFields === true) {\n\t\t\t\treturn this.diffRows\n\t\t\t}\n\t\t\treturn this.diffRows.filter((row) => row.type !== 'unchanged')\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.resetAndFetch()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tresetAndFetch() {\n\t\t\tthis.page = 1\n\t\t\tthis.entries = []\n\t\t\tthis.selectedIds = []\n\t\t\tthis.activeDiff = null\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tasync fetchEntries() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = this.page === 1\n\t\t\tthis.loadingMore = this.page > 1\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams()\n\t\t\t\tparams.set('limit', String(this.pageSize))\n\t\t\t\tparams.set('_page', String(this.page))\n\t\t\t\tparams.set('_sort[created]', 'DESC')\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/audit-trails`)\n\t\t\t\tconst response = await fetch(`${url}?${params.toString()}`, { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.entries = this.page === 1 ? results : [...this.entries, ...results]\n\t\t\t\t\tthis.total = data.total || this.entries.length\n\t\t\t\t} else if (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnVersionHistory] failed to fetch version history', err)\n\t\t\t\tif (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page += 1\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tisSelected(id) {\n\t\t\treturn this.selectedIds.includes(id)\n\t\t},\n\n\t\ttoggleSelected(id, checked) {\n\t\t\tif (checked === true) {\n\t\t\t\tif (this.selectedIds.includes(id) === false && this.selectedIds.length < 2) {\n\t\t\t\t\tthis.selectedIds = [...this.selectedIds, id]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.selectedIds = this.selectedIds.filter((existing) => existing !== id)\n\t\t\t}\n\t\t},\n\n\t\topenSingleDiff(entry) {\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries([entry])\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\topenCompareDiff() {\n\t\t\tif (this.selectedIds.length !== 2) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Entries are fetched newest-first; fold oldest-first so the\n\t\t\t// \"first old\" / \"last new\" semantics land on the right side.\n\t\t\tconst selectedEntries = this.entries.filter((entry) => this.selectedIds.includes(entry.id))\n\t\t\tconst chronological = [...selectedEntries].reverse()\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries(chronological)\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\tcloseDiff() {\n\t\t\tthis.activeDiff = null\n\t\t},\n\n\t\tisNestedValue(row) {\n\t\t\tconst isObj = (v) => v !== null && typeof v === 'object'\n\t\t\treturn isObj(row.oldValue) === true || isObj(row.newValue) === true\n\t\t},\n\n\t\t/**\n\t\t * Build the per-line nested diff for one side of a table cell\n\t\t * whose value is an object/array, so each nested key can be\n\t\t * individually add/remove/change tinted.\n\t\t *\n\t\t * @param {FieldDiffRow} row The parent field row.\n\t\t * @param {'old'|'new'} side Which side is being rendered (both sides render the same nested diff so add/remove/change context matches on both columns).\n\t\t * @return {Array<{path: string, type: string, text: string}>} Rendered lines.\n\t\t */\n\t\tnestedLines(row, side) {\n\t\t\tconst base = row.oldValue !== null && typeof row.oldValue === 'object' ? row.oldValue : {}\n\t\t\tconst next = row.newValue !== null && typeof row.newValue === 'object' ? row.newValue : {}\n\t\t\tconst from = row.type === 'added' ? {} : base\n\t\t\tconst to = row.type === 'removed' ? {} : next\n\t\t\tconst nested = computeObjectDiff(from, to)\n\t\t\tconst visible = this.showAllFields === true ? nested : nested.filter((entry) => entry.type !== 'unchanged')\n\t\t\treturn visible.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\ttype: entry.type,\n\t\t\t\ttext: this.formatNestedLine(entry, side),\n\t\t\t}))\n\t\t},\n\n\t\tformatNestedLine(entry, side) {\n\t\t\tconst label = entry.path === '' ? '·' : entry.path\n\t\t\tif (entry.type === 'changed') {\n\t\t\t\tconst shown = side === 'new' ? entry.newValue : entry.oldValue\n\t\t\t\treturn `${label}: ${this.formatScalar(shown)}`\n\t\t\t}\n\t\t\tconst value = entry.type === 'removed' ? entry.oldValue : entry.newValue\n\t\t\treturn `${label}: ${this.formatScalar(value)}`\n\t\t},\n\n\t\trowClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-row': true,\n\t\t\t\t[`cn-version-history__diff-row--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tlineClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-line': true,\n\t\t\t\t[`cn-version-history__diff-line--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tvalueCellTag(row) {\n\t\t\treturn this.isNestedValue(row) === true ? 'pre' : 'span'\n\t\t},\n\n\t\tvalueCellProps(row) {\n\t\t\treturn this.isNestedValue(row) === true ? { class: 'cn-version-history__diff-json' } : {}\n\t\t},\n\n\t\tformatScalar(value) {\n\t\t\tif (value === undefined) {\n\t\t\t\treturn '—'\n\t\t\t}\n\t\t\tif (value === null) {\n\t\t\t\treturn 'null'\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(value)\n\t\t\t\t} catch {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\tformatUser(entry) {\n\t\t\treturn entry.userName || entry.user || t('nextcloud-vue', 'System')\n\t\t},\n\n\t\tformatWhen(entry) {\n\t\t\tconst raw = entry.created || entry.creationDateTime || entry.timestamp\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst d = new Date(raw)\n\t\t\tif (Number.isNaN(d.getTime()) === true) {\n\t\t\t\treturn String(raw)\n\t\t\t}\n\t\t\treturn d.toLocaleString(userLocale())\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-history__empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n\n.cn-version-history__rows {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-version-history__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-history__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-history__row-main {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\talign-items: baseline;\n\tflex: 1 1 auto;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\ttext-align: left;\n\tfont: inherit;\n\tcolor: inherit;\n\tpadding: 4px;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-version-history__row-main:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-version-history__version {\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-history__action {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__when {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\twhite-space: nowrap;\n}\n\n.cn-version-history__user {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-version-history__toolbar {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-top: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-toolbar {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-version-history__diff-table th,\n.cn-version-history__diff-table td {\n\tborder-bottom: 1px solid var(--color-border);\n\tpadding: 6px 8px;\n\ttext-align: left;\n\tvertical-align: top;\n}\n\n.cn-version-history__diff-field {\n\tfont-weight: 500;\n\tcolor: var(--color-main-text);\n\twhite-space: nowrap;\n}\n\n.cn-version-history__diff-json {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tfont-family: monospace;\n\tfont-size: 12px;\n}\n\n.cn-version-history__diff-row--added .cn-version-history__diff-field {\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-row--removed .cn-version-history__diff-field {\n\tcolor: var(--color-error);\n}\n\n.cn-version-history__diff-row--changed .cn-version-history__diff-field {\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--added {\n\tbackground-color: color-mix(in srgb, var(--color-success) 15%, transparent);\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-line--removed {\n\tbackground-color: color-mix(in srgb, var(--color-error) 15%, transparent);\n\tcolor: var(--color-error);\n\ttext-decoration: line-through;\n}\n\n.cn-version-history__diff-line--changed {\n\tbackground-color: color-mix(in srgb, var(--color-warning) 15%, transparent);\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--unchanged {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__diff-empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n</style>\n"],"names":["CnDetailCard","t"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CnVersionHistory.vue3.js","sources":["../../../../src/components/CnVersionHistory/CnVersionHistory.vue?vue&type=template&id=5888d95c&lang.js"],"sourcesContent":["<!--\n CnVersionHistory — object version-history + field-by-field diff\n viewer for the integration registry.\n\n Lists an OpenRegister object's audit-trail entries (timestamp, user,\n semantic version, action) newest-first, and lets the user open a\n structural diff for one entry, or \"compare\" two checked entries.\n OpenRegister only stores a per-field `changed` delta per entry (no\n full before/after snapshot), so a multi-entry compare is\n reconstructed by folding the range's deltas (`foldAuditTrailEntries`)\n before diffing (`computeObjectDiff`) — see the `version-diff-viewer`\n openspec change's design notes.\n-->\n<template>\n\t<CnDetailCard\n\t\t:title=\"resolvedTitle\"\n\t\t:icon=\"FileCompare\"\n\t\t:collapsible=\"collapsible\"\n\t\t:data-surface=\"surface\">\n\t\t<NcLoadingIcon v-if=\"loading && entries.length === 0\" />\n\t\t<div v-else-if=\"entries.length === 0\" class=\"cn-version-history__empty\">\n\t\t\t{{ noEntriesLabel }}\n\t\t</div>\n\t\t<div v-else-if=\"activeDiff === null\" class=\"cn-version-history__list\">\n\t\t\t<ul class=\"cn-version-history__rows\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"entry in entries\"\n\t\t\t\t\t:key=\"entry.id\"\n\t\t\t\t\tclass=\"cn-version-history__row\">\n\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t:modelValue=\"isSelected(entry.id)\"\n\t\t\t\t\t\t:disabled=\"isSelected(entry.id) === false && selectedIds.length >= 2\"\n\t\t\t\t\t\t:aria-label=\"selectForCompareLabel\"\n\t\t\t\t\t\t@update:modelValue=\"toggleSelected(entry.id, $event)\" />\n\t\t\t\t\t<button class=\"cn-version-history__row-main\" type=\"button\" @click=\"openSingleDiff(entry)\">\n\t\t\t\t\t\t<span class=\"cn-version-history__version\">{{ entry.version || fallbackVersionLabel }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__action\">{{ entry.action || '' }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__when\">{{ formatWhen(entry) }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__user\">{{ formatUser(entry) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div class=\"cn-version-history__toolbar\">\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"selectedIds.length !== 2\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t@click=\"openCompareDiff\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Compare :size=\"18\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ compareLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"hasMore\"\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\t\t@click=\"loadMore\">\n\t\t\t\t\t{{ loadMoreLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<div v-else class=\"cn-version-history__diff\">\n\t\t\t<div class=\"cn-version-history__diff-toolbar\">\n\t\t\t\t<NcButton variant=\"tertiary\" @click=\"closeDiff\">\n\t\t\t\t\t{{ backLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"showAllFields\" @update:modelValue=\"showAllFields = $event\">\n\t\t\t\t\t{{ showAllFieldsLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</div>\n\t\t\t<table v-if=\"visibleDiffRows.length > 0\" class=\"cn-version-history__diff-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>{{ fieldLabel }}</th>\n\t\t\t\t\t\t<th>{{ oldValueLabel }}</th>\n\t\t\t\t\t\t<th>{{ newValueLabel }}</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr v-for=\"row in visibleDiffRows\" :key=\"row.path\" :class=\"rowClass(row.type)\">\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-field\">\n\t\t\t\t\t\t\t{{ row.path }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'old')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.oldValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'new')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.newValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t\t<div v-else class=\"cn-version-history__diff-empty\">\n\t\t\t\t{{ noChangesLabel }}\n\t\t\t</div>\n\t\t</div>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport Compare from 'vue-material-design-icons/Compare.vue'\nimport FileCompare from 'vue-material-design-icons/FileCompare.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport { foldAuditTrailEntries } from '../../utils/auditTrailDiff.js'\nimport { computeObjectDiff } from '../../utils/computeObjectDiff.js'\nimport { buildHeaders } from '../../utils/index.js'\n\n/**\n * A single row rendered in the top-level diff table.\n *\n * @typedef {object} FieldDiffRow\n * @property {string} path Field name.\n * @property {'added'|'removed'|'changed'|'unchanged'} type Classification.\n * @property {unknown} oldValue Value before.\n * @property {unknown} newValue Value after.\n */\n\n/**\n * Classify one top-level field between two folded states, reusing\n * `computeObjectDiff` to decide equality (so nested objects/arrays are\n * compared structurally, not by reference).\n *\n * @param {string} key Field name.\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow} The classified row.\n */\nfunction classifyField(key, oldState, newState) {\n\tconst oldMissing = Object.hasOwn(oldState, key) === false\n\tconst newMissing = Object.hasOwn(newState, key) === false\n\tconst oldValue = oldState[key]\n\tconst newValue = newState[key]\n\n\tif (oldMissing === true && newMissing === false) {\n\t\treturn { path: key, type: 'added', oldValue: undefined, newValue }\n\t}\n\tif (oldMissing === false && newMissing === true) {\n\t\treturn { path: key, type: 'removed', oldValue, newValue: undefined }\n\t}\n\tconst nested = computeObjectDiff(oldValue, newValue)\n\tconst isChanged = nested.some((entry) => entry.type !== 'unchanged')\n\treturn { path: key, type: isChanged ? 'changed' : 'unchanged', oldValue, newValue }\n}\n\n/**\n * Build the top-level field-by-field diff table for a folded\n * before/after state pair.\n *\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow[]} One row per touched field, sorted by field name.\n */\nfunction buildFieldRows(oldState, newState) {\n\tconst keys = Array.from(new Set([...Object.keys(oldState), ...Object.keys(newState)])).sort()\n\treturn keys.map((key) => classifyField(key, oldState, newState))\n}\n\n/**\n * CnVersionHistory — object version-history list plus field-by-field\n * diff viewer, rendered by the integration registry on sidebar-tab\n * and dashboard/detail-widget surfaces alike.\n *\n * Basic usage\n * ```vue\n * <CnVersionHistory\n * :register=\"registerId\"\n * :schema=\"schemaId\"\n * :object-id=\"objectId\"\n * surface=\"detail-page\" />\n * ```\n */\nexport default {\n\tname: 'CnVersionHistory',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, NcButton, NcCheckboxRadioSwitch, Compare },\n\n\tprops: {\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface — passed for AD-19 surface fallback consumers. */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (value) => ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'].includes(value),\n\t\t},\n\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Number of history entries to fetch per page. */\n\t\tpageSize: { type: Number, default: 20 },\n\t\t/** Whether the card collapses. */\n\t\tcollapsible: { type: Boolean, default: false },\n\t\t/** Override the card title (defaults to the translated label). */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Pre-translated empty-history label. */\n\t\tnoEntriesLabel: { type: String, default: () => t('nextcloud-vue', 'No version history yet') },\n\t\t/** Pre-translated fallback shown when an entry carries no semantic version. */\n\t\tfallbackVersionLabel: { type: String, default: () => t('nextcloud-vue', 'Unversioned change') },\n\t\t/** Pre-translated \"select for compare\" checkbox label. */\n\t\tselectForCompareLabel: { type: String, default: () => t('nextcloud-vue', 'Select for compare') },\n\t\t/** Pre-translated compare-action label. */\n\t\tcompareLabel: { type: String, default: () => t('nextcloud-vue', 'Compare selected') },\n\t\t/** Pre-translated load-more label. */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/** Pre-translated back-to-list label. */\n\t\tbackLabel: { type: String, default: () => t('nextcloud-vue', 'Back to history') },\n\t\t/** Pre-translated \"show all fields\" toggle label. */\n\t\tshowAllFieldsLabel: { type: String, default: () => t('nextcloud-vue', 'Show all fields') },\n\t\t/** Pre-translated diff table field-column header. */\n\t\tfieldLabel: { type: String, default: () => t('nextcloud-vue', 'Field') },\n\t\t/** Pre-translated diff table old-value-column header. */\n\t\toldValueLabel: { type: String, default: () => t('nextcloud-vue', 'Old value') },\n\t\t/** Pre-translated diff table new-value-column header. */\n\t\tnewValueLabel: { type: String, default: () => t('nextcloud-vue', 'New value') },\n\t\t/** Pre-translated label shown when a diff has no visible rows. */\n\t\tnoChangesLabel: { type: String, default: () => t('nextcloud-vue', 'No field changes to show') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tFileCompare: markRaw(FileCompare),\n\t\t\tentries: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tselectedIds: [],\n\t\t\t/** `null` = list view; otherwise `{ oldState, newState }` for the open diff. */\n\t\t\tactiveDiff: null,\n\t\t\tshowAllFields: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tresolvedTitle() {\n\t\t\treturn this.title || t('nextcloud-vue', 'Version history')\n\t\t},\n\n\t\thasMore() {\n\t\t\treturn this.entries.length < this.total\n\t\t},\n\n\t\tdiffRows() {\n\t\t\tif (this.activeDiff === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn buildFieldRows(this.activeDiff.oldState, this.activeDiff.newState)\n\t\t},\n\n\t\tvisibleDiffRows() {\n\t\t\tif (this.showAllFields === true) {\n\t\t\t\treturn this.diffRows\n\t\t\t}\n\t\t\treturn this.diffRows.filter((row) => row.type !== 'unchanged')\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.resetAndFetch()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tresetAndFetch() {\n\t\t\tthis.page = 1\n\t\t\tthis.entries = []\n\t\t\tthis.selectedIds = []\n\t\t\tthis.activeDiff = null\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tasync fetchEntries() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = this.page === 1\n\t\t\tthis.loadingMore = this.page > 1\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams()\n\t\t\t\tparams.set('limit', String(this.pageSize))\n\t\t\t\tparams.set('_page', String(this.page))\n\t\t\t\tparams.set('_sort[created]', 'DESC')\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/audit-trails`)\n\t\t\t\tconst response = await fetch(`${url}?${params.toString()}`, { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.entries = this.page === 1 ? results : [...this.entries, ...results]\n\t\t\t\t\tthis.total = data.total || this.entries.length\n\t\t\t\t} else if (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnVersionHistory] failed to fetch version history', err)\n\t\t\t\tif (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page += 1\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tisSelected(id) {\n\t\t\treturn this.selectedIds.includes(id)\n\t\t},\n\n\t\ttoggleSelected(id, checked) {\n\t\t\tif (checked === true) {\n\t\t\t\tif (this.selectedIds.includes(id) === false && this.selectedIds.length < 2) {\n\t\t\t\t\tthis.selectedIds = [...this.selectedIds, id]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.selectedIds = this.selectedIds.filter((existing) => existing !== id)\n\t\t\t}\n\t\t},\n\n\t\topenSingleDiff(entry) {\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries([entry])\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\topenCompareDiff() {\n\t\t\tif (this.selectedIds.length !== 2) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Entries are fetched newest-first; fold oldest-first so the\n\t\t\t// \"first old\" / \"last new\" semantics land on the right side.\n\t\t\tconst selectedEntries = this.entries.filter((entry) => this.selectedIds.includes(entry.id))\n\t\t\tconst chronological = [...selectedEntries].reverse()\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries(chronological)\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\tcloseDiff() {\n\t\t\tthis.activeDiff = null\n\t\t},\n\n\t\tisNestedValue(row) {\n\t\t\tconst isObj = (v) => v !== null && typeof v === 'object'\n\t\t\treturn isObj(row.oldValue) === true || isObj(row.newValue) === true\n\t\t},\n\n\t\t/**\n\t\t * Build the per-line nested diff for one side of a table cell\n\t\t * whose value is an object/array, so each nested key can be\n\t\t * individually add/remove/change tinted.\n\t\t *\n\t\t * @param {FieldDiffRow} row The parent field row.\n\t\t * @param {'old'|'new'} side Which side is being rendered (both sides render the same nested diff so add/remove/change context matches on both columns).\n\t\t * @return {Array<{path: string, type: string, text: string}>} Rendered lines.\n\t\t */\n\t\tnestedLines(row, side) {\n\t\t\tconst base = row.oldValue !== null && typeof row.oldValue === 'object' ? row.oldValue : {}\n\t\t\tconst next = row.newValue !== null && typeof row.newValue === 'object' ? row.newValue : {}\n\t\t\tconst from = row.type === 'added' ? {} : base\n\t\t\tconst to = row.type === 'removed' ? {} : next\n\t\t\tconst nested = computeObjectDiff(from, to)\n\t\t\tconst visible = this.showAllFields === true ? nested : nested.filter((entry) => entry.type !== 'unchanged')\n\t\t\treturn visible.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\ttype: entry.type,\n\t\t\t\ttext: this.formatNestedLine(entry, side),\n\t\t\t}))\n\t\t},\n\n\t\tformatNestedLine(entry, side) {\n\t\t\tconst label = entry.path === '' ? '·' : entry.path\n\t\t\tif (entry.type === 'changed') {\n\t\t\t\tconst shown = side === 'new' ? entry.newValue : entry.oldValue\n\t\t\t\treturn `${label}: ${this.formatScalar(shown)}`\n\t\t\t}\n\t\t\tconst value = entry.type === 'removed' ? entry.oldValue : entry.newValue\n\t\t\treturn `${label}: ${this.formatScalar(value)}`\n\t\t},\n\n\t\trowClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-row': true,\n\t\t\t\t[`cn-version-history__diff-row--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tlineClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-line': true,\n\t\t\t\t[`cn-version-history__diff-line--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tvalueCellTag(row) {\n\t\t\treturn this.isNestedValue(row) === true ? 'pre' : 'span'\n\t\t},\n\n\t\tvalueCellProps(row) {\n\t\t\treturn this.isNestedValue(row) === true ? { class: 'cn-version-history__diff-json' } : {}\n\t\t},\n\n\t\tformatScalar(value) {\n\t\t\tif (value === undefined) {\n\t\t\t\treturn '—'\n\t\t\t}\n\t\t\tif (value === null) {\n\t\t\t\treturn 'null'\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(value)\n\t\t\t\t} catch {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\tformatUser(entry) {\n\t\t\treturn entry.userName || entry.user || t('nextcloud-vue', 'System')\n\t\t},\n\n\t\tformatWhen(entry) {\n\t\t\tconst raw = entry.created || entry.creationDateTime || entry.timestamp\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst d = new Date(raw)\n\t\t\tif (Number.isNaN(d.getTime()) === true) {\n\t\t\t\treturn String(raw)\n\t\t\t}\n\t\t\treturn d.toLocaleString()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-history__empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n\n.cn-version-history__rows {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-version-history__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-history__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-history__row-main {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\talign-items: baseline;\n\tflex: 1 1 auto;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\ttext-align: left;\n\tfont: inherit;\n\tcolor: inherit;\n\tpadding: 4px;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-version-history__row-main:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-version-history__version {\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-history__action {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__when {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\twhite-space: nowrap;\n}\n\n.cn-version-history__user {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-version-history__toolbar {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-top: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-toolbar {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-version-history__diff-table th,\n.cn-version-history__diff-table td {\n\tborder-bottom: 1px solid var(--color-border);\n\tpadding: 6px 8px;\n\ttext-align: left;\n\tvertical-align: top;\n}\n\n.cn-version-history__diff-field {\n\tfont-weight: 500;\n\tcolor: var(--color-main-text);\n\twhite-space: nowrap;\n}\n\n.cn-version-history__diff-json {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tfont-family: monospace;\n\tfont-size: 12px;\n}\n\n.cn-version-history__diff-row--added .cn-version-history__diff-field {\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-row--removed .cn-version-history__diff-field {\n\tcolor: var(--color-error);\n}\n\n.cn-version-history__diff-row--changed .cn-version-history__diff-field {\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--added {\n\tbackground-color: color-mix(in srgb, var(--color-success) 15%, transparent);\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-line--removed {\n\tbackground-color: color-mix(in srgb, var(--color-error) 15%, transparent);\n\tcolor: var(--color-error);\n\ttext-decoration: line-through;\n}\n\n.cn-version-history__diff-line--changed {\n\tbackground-color: color-mix(in srgb, var(--color-warning) 15%, transparent);\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--unchanged {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__diff-empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n</style>\n"],"names":["_createBlock","_toDisplayString","_openBlock","_createElementBlock","_createElementVNode","_Fragment","_renderList","_createVNode","_createTextVNode","_normalizeClass","_resolveDynamicComponent","_mergeProps"],"mappings":"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"}
1
+ {"version":3,"file":"CnVersionHistory.vue3.js","sources":["../../../../src/components/CnVersionHistory/CnVersionHistory.vue?vue&type=template&id=0fca5a52&lang.js"],"sourcesContent":["<!--\n CnVersionHistory — object version-history + field-by-field diff\n viewer for the integration registry.\n\n Lists an OpenRegister object's audit-trail entries (timestamp, user,\n semantic version, action) newest-first, and lets the user open a\n structural diff for one entry, or \"compare\" two checked entries.\n OpenRegister only stores a per-field `changed` delta per entry (no\n full before/after snapshot), so a multi-entry compare is\n reconstructed by folding the range's deltas (`foldAuditTrailEntries`)\n before diffing (`computeObjectDiff`) — see the `version-diff-viewer`\n openspec change's design notes.\n-->\n<template>\n\t<CnDetailCard\n\t\t:title=\"resolvedTitle\"\n\t\t:icon=\"FileCompare\"\n\t\t:collapsible=\"collapsible\"\n\t\t:data-surface=\"surface\">\n\t\t<NcLoadingIcon v-if=\"loading && entries.length === 0\" />\n\t\t<div v-else-if=\"entries.length === 0\" class=\"cn-version-history__empty\">\n\t\t\t{{ noEntriesLabel }}\n\t\t</div>\n\t\t<div v-else-if=\"activeDiff === null\" class=\"cn-version-history__list\">\n\t\t\t<ul class=\"cn-version-history__rows\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"entry in entries\"\n\t\t\t\t\t:key=\"entry.id\"\n\t\t\t\t\tclass=\"cn-version-history__row\">\n\t\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t\t:modelValue=\"isSelected(entry.id)\"\n\t\t\t\t\t\t:disabled=\"isSelected(entry.id) === false && selectedIds.length >= 2\"\n\t\t\t\t\t\t:aria-label=\"selectForCompareLabel\"\n\t\t\t\t\t\t@update:modelValue=\"toggleSelected(entry.id, $event)\" />\n\t\t\t\t\t<button class=\"cn-version-history__row-main\" type=\"button\" @click=\"openSingleDiff(entry)\">\n\t\t\t\t\t\t<span class=\"cn-version-history__version\">{{ entry.version || fallbackVersionLabel }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__action\">{{ entry.action || '' }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__when\">{{ formatWhen(entry) }}</span>\n\t\t\t\t\t\t<span class=\"cn-version-history__user\">{{ formatUser(entry) }}</span>\n\t\t\t\t\t</button>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div class=\"cn-version-history__toolbar\">\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"selectedIds.length !== 2\"\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t@click=\"openCompareDiff\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<Compare :size=\"18\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ compareLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"hasMore\"\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\t\t@click=\"loadMore\">\n\t\t\t\t\t{{ loadMoreLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t\t<div v-else class=\"cn-version-history__diff\">\n\t\t\t<div class=\"cn-version-history__diff-toolbar\">\n\t\t\t\t<NcButton variant=\"tertiary\" @click=\"closeDiff\">\n\t\t\t\t\t{{ backLabel }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"showAllFields\" @update:modelValue=\"showAllFields = $event\">\n\t\t\t\t\t{{ showAllFieldsLabel }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</div>\n\t\t\t<table v-if=\"visibleDiffRows.length > 0\" class=\"cn-version-history__diff-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th>{{ fieldLabel }}</th>\n\t\t\t\t\t\t<th>{{ oldValueLabel }}</th>\n\t\t\t\t\t\t<th>{{ newValueLabel }}</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr v-for=\"row in visibleDiffRows\" :key=\"row.path\" :class=\"rowClass(row.type)\">\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-field\">\n\t\t\t\t\t\t\t{{ row.path }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'old')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.oldValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-version-history__diff-value\">\n\t\t\t\t\t\t\t<component :is=\"valueCellTag(row)\" v-bind=\"valueCellProps(row)\">\n\t\t\t\t\t\t\t\t<template v-if=\"isNestedValue(row) === true\">\n\t\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\t\tv-for=\"line in nestedLines(row, 'new')\"\n\t\t\t\t\t\t\t\t\t\t:key=\"line.path\"\n\t\t\t\t\t\t\t\t\t\t:class=\"lineClass(line.type)\">\n\t\t\t\t\t\t\t\t\t\t{{ line.text }}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t\t\t\t{{ formatScalar(row.newValue) }}\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t</component>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t\t<div v-else class=\"cn-version-history__diff-empty\">\n\t\t\t\t{{ noChangesLabel }}\n\t\t\t</div>\n\t\t</div>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport Compare from 'vue-material-design-icons/Compare.vue'\nimport FileCompare from 'vue-material-design-icons/FileCompare.vue'\nimport CnDetailCard from '../CnDetailCard/CnDetailCard.vue'\nimport { foldAuditTrailEntries } from '../../utils/auditTrailDiff.js'\nimport { computeObjectDiff } from '../../utils/computeObjectDiff.js'\nimport { buildHeaders } from '../../utils/index.js'\nimport { userLocale } from '../../utils/userLocale.js'\n\n/**\n * A single row rendered in the top-level diff table.\n *\n * @typedef {object} FieldDiffRow\n * @property {string} path Field name.\n * @property {'added'|'removed'|'changed'|'unchanged'} type Classification.\n * @property {unknown} oldValue Value before.\n * @property {unknown} newValue Value after.\n */\n\n/**\n * Classify one top-level field between two folded states, reusing\n * `computeObjectDiff` to decide equality (so nested objects/arrays are\n * compared structurally, not by reference).\n *\n * @param {string} key Field name.\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow} The classified row.\n */\nfunction classifyField(key, oldState, newState) {\n\tconst oldMissing = Object.hasOwn(oldState, key) === false\n\tconst newMissing = Object.hasOwn(newState, key) === false\n\tconst oldValue = oldState[key]\n\tconst newValue = newState[key]\n\n\tif (oldMissing === true && newMissing === false) {\n\t\treturn { path: key, type: 'added', oldValue: undefined, newValue }\n\t}\n\tif (oldMissing === false && newMissing === true) {\n\t\treturn { path: key, type: 'removed', oldValue, newValue: undefined }\n\t}\n\tconst nested = computeObjectDiff(oldValue, newValue)\n\tconst isChanged = nested.some((entry) => entry.type !== 'unchanged')\n\treturn { path: key, type: isChanged ? 'changed' : 'unchanged', oldValue, newValue }\n}\n\n/**\n * Build the top-level field-by-field diff table for a folded\n * before/after state pair.\n *\n * @param {object} oldState Folded \"before\" state.\n * @param {object} newState Folded \"after\" state.\n * @return {FieldDiffRow[]} One row per touched field, sorted by field name.\n */\nfunction buildFieldRows(oldState, newState) {\n\tconst keys = Array.from(new Set([...Object.keys(oldState), ...Object.keys(newState)])).sort()\n\treturn keys.map((key) => classifyField(key, oldState, newState))\n}\n\n/**\n * CnVersionHistory — object version-history list plus field-by-field\n * diff viewer, rendered by the integration registry on sidebar-tab\n * and dashboard/detail-widget surfaces alike.\n *\n * Basic usage\n * ```vue\n * <CnVersionHistory\n * :register=\"registerId\"\n * :schema=\"schemaId\"\n * :object-id=\"objectId\"\n * surface=\"detail-page\" />\n * ```\n */\nexport default {\n\tname: 'CnVersionHistory',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, NcButton, NcCheckboxRadioSwitch, Compare },\n\n\tprops: {\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, required: true },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, required: true },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** Rendering surface — passed for AD-19 surface fallback consumers. */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (value) => ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'].includes(value),\n\t\t},\n\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Number of history entries to fetch per page. */\n\t\tpageSize: { type: Number, default: 20 },\n\t\t/** Whether the card collapses. */\n\t\tcollapsible: { type: Boolean, default: false },\n\t\t/** Override the card title (defaults to the translated label). */\n\t\ttitle: { type: String, default: '' },\n\t\t/** Pre-translated empty-history label. */\n\t\tnoEntriesLabel: { type: String, default: () => t('nextcloud-vue', 'No version history yet') },\n\t\t/** Pre-translated fallback shown when an entry carries no semantic version. */\n\t\tfallbackVersionLabel: { type: String, default: () => t('nextcloud-vue', 'Unversioned change') },\n\t\t/** Pre-translated \"select for compare\" checkbox label. */\n\t\tselectForCompareLabel: { type: String, default: () => t('nextcloud-vue', 'Select for compare') },\n\t\t/** Pre-translated compare-action label. */\n\t\tcompareLabel: { type: String, default: () => t('nextcloud-vue', 'Compare selected') },\n\t\t/** Pre-translated load-more label. */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/** Pre-translated back-to-list label. */\n\t\tbackLabel: { type: String, default: () => t('nextcloud-vue', 'Back to history') },\n\t\t/** Pre-translated \"show all fields\" toggle label. */\n\t\tshowAllFieldsLabel: { type: String, default: () => t('nextcloud-vue', 'Show all fields') },\n\t\t/** Pre-translated diff table field-column header. */\n\t\tfieldLabel: { type: String, default: () => t('nextcloud-vue', 'Field') },\n\t\t/** Pre-translated diff table old-value-column header. */\n\t\toldValueLabel: { type: String, default: () => t('nextcloud-vue', 'Old value') },\n\t\t/** Pre-translated diff table new-value-column header. */\n\t\tnewValueLabel: { type: String, default: () => t('nextcloud-vue', 'New value') },\n\t\t/** Pre-translated label shown when a diff has no visible rows. */\n\t\tnoChangesLabel: { type: String, default: () => t('nextcloud-vue', 'No field changes to show') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tFileCompare: markRaw(FileCompare),\n\t\t\tentries: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tselectedIds: [],\n\t\t\t/** `null` = list view; otherwise `{ oldState, newState }` for the open diff. */\n\t\t\tactiveDiff: null,\n\t\t\tshowAllFields: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tresolvedTitle() {\n\t\t\treturn this.title || t('nextcloud-vue', 'Version history')\n\t\t},\n\n\t\thasMore() {\n\t\t\treturn this.entries.length < this.total\n\t\t},\n\n\t\tdiffRows() {\n\t\t\tif (this.activeDiff === null) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn buildFieldRows(this.activeDiff.oldState, this.activeDiff.newState)\n\t\t},\n\n\t\tvisibleDiffRows() {\n\t\t\tif (this.showAllFields === true) {\n\t\t\t\treturn this.diffRows\n\t\t\t}\n\t\t\treturn this.diffRows.filter((row) => row.type !== 'unchanged')\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.resetAndFetch()\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tresetAndFetch() {\n\t\t\tthis.page = 1\n\t\t\tthis.entries = []\n\t\t\tthis.selectedIds = []\n\t\t\tthis.activeDiff = null\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tasync fetchEntries() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = this.page === 1\n\t\t\tthis.loadingMore = this.page > 1\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams()\n\t\t\t\tparams.set('limit', String(this.pageSize))\n\t\t\t\tparams.set('_page', String(this.page))\n\t\t\t\tparams.set('_sort[created]', 'DESC')\n\t\t\t\tconst url = generateUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/audit-trails`)\n\t\t\t\tconst response = await fetch(`${url}?${params.toString()}`, { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.entries = this.page === 1 ? results : [...this.entries, ...results]\n\t\t\t\t\tthis.total = data.total || this.entries.length\n\t\t\t\t} else if (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[CnVersionHistory] failed to fetch version history', err)\n\t\t\t\tif (this.page === 1) {\n\t\t\t\t\tthis.entries = []\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page += 1\n\t\t\tthis.fetchEntries()\n\t\t},\n\n\t\tisSelected(id) {\n\t\t\treturn this.selectedIds.includes(id)\n\t\t},\n\n\t\ttoggleSelected(id, checked) {\n\t\t\tif (checked === true) {\n\t\t\t\tif (this.selectedIds.includes(id) === false && this.selectedIds.length < 2) {\n\t\t\t\t\tthis.selectedIds = [...this.selectedIds, id]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.selectedIds = this.selectedIds.filter((existing) => existing !== id)\n\t\t\t}\n\t\t},\n\n\t\topenSingleDiff(entry) {\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries([entry])\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\topenCompareDiff() {\n\t\t\tif (this.selectedIds.length !== 2) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Entries are fetched newest-first; fold oldest-first so the\n\t\t\t// \"first old\" / \"last new\" semantics land on the right side.\n\t\t\tconst selectedEntries = this.entries.filter((entry) => this.selectedIds.includes(entry.id))\n\t\t\tconst chronological = [...selectedEntries].reverse()\n\t\t\tconst { oldState, newState } = foldAuditTrailEntries(chronological)\n\t\t\tthis.showAllFields = false\n\t\t\tthis.activeDiff = { oldState, newState }\n\t\t},\n\n\t\tcloseDiff() {\n\t\t\tthis.activeDiff = null\n\t\t},\n\n\t\tisNestedValue(row) {\n\t\t\tconst isObj = (v) => v !== null && typeof v === 'object'\n\t\t\treturn isObj(row.oldValue) === true || isObj(row.newValue) === true\n\t\t},\n\n\t\t/**\n\t\t * Build the per-line nested diff for one side of a table cell\n\t\t * whose value is an object/array, so each nested key can be\n\t\t * individually add/remove/change tinted.\n\t\t *\n\t\t * @param {FieldDiffRow} row The parent field row.\n\t\t * @param {'old'|'new'} side Which side is being rendered (both sides render the same nested diff so add/remove/change context matches on both columns).\n\t\t * @return {Array<{path: string, type: string, text: string}>} Rendered lines.\n\t\t */\n\t\tnestedLines(row, side) {\n\t\t\tconst base = row.oldValue !== null && typeof row.oldValue === 'object' ? row.oldValue : {}\n\t\t\tconst next = row.newValue !== null && typeof row.newValue === 'object' ? row.newValue : {}\n\t\t\tconst from = row.type === 'added' ? {} : base\n\t\t\tconst to = row.type === 'removed' ? {} : next\n\t\t\tconst nested = computeObjectDiff(from, to)\n\t\t\tconst visible = this.showAllFields === true ? nested : nested.filter((entry) => entry.type !== 'unchanged')\n\t\t\treturn visible.map((entry) => ({\n\t\t\t\tpath: entry.path,\n\t\t\t\ttype: entry.type,\n\t\t\t\ttext: this.formatNestedLine(entry, side),\n\t\t\t}))\n\t\t},\n\n\t\tformatNestedLine(entry, side) {\n\t\t\tconst label = entry.path === '' ? '·' : entry.path\n\t\t\tif (entry.type === 'changed') {\n\t\t\t\tconst shown = side === 'new' ? entry.newValue : entry.oldValue\n\t\t\t\treturn `${label}: ${this.formatScalar(shown)}`\n\t\t\t}\n\t\t\tconst value = entry.type === 'removed' ? entry.oldValue : entry.newValue\n\t\t\treturn `${label}: ${this.formatScalar(value)}`\n\t\t},\n\n\t\trowClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-row': true,\n\t\t\t\t[`cn-version-history__diff-row--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tlineClass(type) {\n\t\t\treturn {\n\t\t\t\t'cn-version-history__diff-line': true,\n\t\t\t\t[`cn-version-history__diff-line--${type}`]: true,\n\t\t\t}\n\t\t},\n\n\t\tvalueCellTag(row) {\n\t\t\treturn this.isNestedValue(row) === true ? 'pre' : 'span'\n\t\t},\n\n\t\tvalueCellProps(row) {\n\t\t\treturn this.isNestedValue(row) === true ? { class: 'cn-version-history__diff-json' } : {}\n\t\t},\n\n\t\tformatScalar(value) {\n\t\t\tif (value === undefined) {\n\t\t\t\treturn '—'\n\t\t\t}\n\t\t\tif (value === null) {\n\t\t\t\treturn 'null'\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.stringify(value)\n\t\t\t\t} catch {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\tformatUser(entry) {\n\t\t\treturn entry.userName || entry.user || t('nextcloud-vue', 'System')\n\t\t},\n\n\t\tformatWhen(entry) {\n\t\t\tconst raw = entry.created || entry.creationDateTime || entry.timestamp\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst d = new Date(raw)\n\t\t\tif (Number.isNaN(d.getTime()) === true) {\n\t\t\t\treturn String(raw)\n\t\t\t}\n\t\t\treturn d.toLocaleString(userLocale())\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-history__empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n\n.cn-version-history__rows {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-version-history__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-history__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-history__row-main {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 8px;\n\talign-items: baseline;\n\tflex: 1 1 auto;\n\tbackground: none;\n\tborder: none;\n\tcursor: pointer;\n\ttext-align: left;\n\tfont: inherit;\n\tcolor: inherit;\n\tpadding: 4px;\n\tborder-radius: var(--border-radius);\n}\n\n.cn-version-history__row-main:hover {\n\tbackground-color: var(--color-background-hover);\n}\n\n.cn-version-history__version {\n\tfont-weight: bold;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-history__action {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__when {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.85em;\n\twhite-space: nowrap;\n}\n\n.cn-version-history__user {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n}\n\n.cn-version-history__toolbar {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-top: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-toolbar {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-version-history__diff-table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n}\n\n.cn-version-history__diff-table th,\n.cn-version-history__diff-table td {\n\tborder-bottom: 1px solid var(--color-border);\n\tpadding: 6px 8px;\n\ttext-align: left;\n\tvertical-align: top;\n}\n\n.cn-version-history__diff-field {\n\tfont-weight: 500;\n\tcolor: var(--color-main-text);\n\twhite-space: nowrap;\n}\n\n.cn-version-history__diff-json {\n\tmargin: 0;\n\twhite-space: pre-wrap;\n\toverflow-wrap: anywhere;\n\tfont-family: monospace;\n\tfont-size: 12px;\n}\n\n.cn-version-history__diff-row--added .cn-version-history__diff-field {\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-row--removed .cn-version-history__diff-field {\n\tcolor: var(--color-error);\n}\n\n.cn-version-history__diff-row--changed .cn-version-history__diff-field {\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--added {\n\tbackground-color: color-mix(in srgb, var(--color-success) 15%, transparent);\n\tcolor: var(--color-success);\n}\n\n.cn-version-history__diff-line--removed {\n\tbackground-color: color-mix(in srgb, var(--color-error) 15%, transparent);\n\tcolor: var(--color-error);\n\ttext-decoration: line-through;\n}\n\n.cn-version-history__diff-line--changed {\n\tbackground-color: color-mix(in srgb, var(--color-warning) 15%, transparent);\n\tcolor: var(--color-warning);\n}\n\n.cn-version-history__diff-line--unchanged {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-version-history__diff-empty {\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n\tpadding: 12px 0;\n}\n</style>\n"],"names":["_createBlock","_toDisplayString","_openBlock","_createElementBlock","_createElementVNode","_Fragment","_renderList","_createVNode","_createTextVNode","_normalizeClass","_resolveDynamicComponent","_mergeProps"],"mappings":"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"}
@@ -2,7 +2,7 @@ import script from './CnVersionInfoCard.vue2.js';
2
2
  import { render } from './CnVersionInfoCard.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-7a828af4";
5
+ script.__scopeId = "data-v-17db98e4";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -67,6 +67,18 @@ var script = {
67
67
  default: '',
68
68
  },
69
69
 
70
+ /**
71
+ * Under the board look the card spans the whole settings grid, as the
72
+ * boards draw the version card. Set to `false` to keep it one card in
73
+ * the grid. Without the board look it has no effect.
74
+ *
75
+ * @spec openspec/changes/board-version-card-full-width/specs/settings-board-look/spec.md#requirement-the-board-version-card-spans-the-settings-grid
76
+ */
77
+ wide: {
78
+ type: Boolean,
79
+ default: true,
80
+ },
81
+
70
82
  /** Section title */
71
83
  title: {
72
84
  type: String,
@@ -142,14 +154,13 @@ var script = {
142
154
  default: false,
143
155
  },
144
156
 
145
- /** Custom labels for the standard fields */
157
+ /**
158
+ * Custom labels for the standard fields, `{ appName?, version?, configuredVersion? }`.
159
+ * A label left out keeps the translated default.
160
+ */
146
161
  labels: {
147
162
  type: Object,
148
- default: () => ({
149
- appName: 'Application Name',
150
- version: 'Version',
151
- configuredVersion: 'Configured Version',
152
- }),
163
+ default: () => ({}),
153
164
  },
154
165
  },
155
166
 
@@ -161,6 +172,21 @@ var script = {
161
172
  },
162
173
 
163
174
  computed: {
175
+ /**
176
+ * The field labels: the app's, else the library's in the reader's language.
177
+ *
178
+ * @return {{appName: string, version: string, configuredVersion: string}}
179
+ * @spec openspec/changes/version-card-dutch-and-header/specs/settings-board-look/spec.md#requirement-the-admin-chrome-reads-in-the-readers-language
180
+ */
181
+ fieldLabels() {
182
+ return {
183
+ appName: translate('nextcloud-vue', 'Application name'),
184
+ version: translate('nextcloud-vue', 'Version'),
185
+ configuredVersion: translate('nextcloud-vue', 'Configured version'),
186
+ ...(this.labels || {}),
187
+ }
188
+ },
189
+
164
190
  /** @return {string} Button type based on update status */
165
191
  updateButtonType() {
166
192
  if (this.isUpToDate) {
@@ -177,16 +203,18 @@ var script = {
177
203
  /** @return {string} Update button label text */
178
204
  updateButtonText() {
179
205
  if (this.updating) {
180
- return 'Updating...'
206
+ return translate('nextcloud-vue', 'Updating…')
181
207
  }
182
208
  if (this.isUpToDate) {
183
- return 'Up to date'
209
+ return translate('nextcloud-vue', 'Up to date')
184
210
  }
185
- return 'Update'
211
+ return translate('nextcloud-vue', 'Update')
186
212
  },
187
213
  },
188
214
 
189
215
  methods: {
216
+ t: translate,
217
+
190
218
  handleUpdateClick() {
191
219
  if (!this.updateButtonDisabled) {
192
220
  this.$emit('update');