@conduction/nextcloud-vue 2.56.0-beta.3 → 2.56.0-beta.5

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 (314) hide show
  1. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +12 -2
  2. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +1 -2
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  5. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  6. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +0 -3
  7. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  9. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -2
  10. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +21 -1
  12. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  13. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +1 -1
  14. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  15. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +12 -5
  16. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  17. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +2 -1
  18. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +9 -1
  20. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  21. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  22. package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js +6 -1
  23. package/dist/esm/components/CnContextMenu/CnContextMenu.vue2.js.map +1 -1
  24. package/dist/esm/components/CnContextMenu/CnContextMenu.vue3.js.map +1 -1
  25. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +116 -15
  26. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  27. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +27 -14
  28. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  29. package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue2.js +13 -6
  30. package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue2.js.map +1 -1
  31. package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue3.js +2 -0
  32. package/dist/esm/components/CnDateAxisView/CnDateAxisView.vue3.js.map +1 -1
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +29 -1
  34. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  35. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  36. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
  37. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js +1 -2
  38. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
  39. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +3 -1
  40. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  41. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +17 -17
  42. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  43. package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue2.js +4 -21
  44. package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue2.js.map +1 -1
  45. package/dist/esm/components/CnFilesWidget/CnFilesWidget.vue3.js.map +1 -1
  46. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +0 -13
  47. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js +8 -8
  49. package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue2.js.map +1 -1
  51. package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue3.js +3 -2
  52. package/dist/esm/components/CnFlowsPage/CnFlowsPage.vue3.js.map +1 -1
  53. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +67 -13
  54. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  55. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +15 -8
  56. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  57. package/dist/esm/components/CnIndexPage/manifestActionDispatch.js +31 -11
  58. package/dist/esm/components/CnIndexPage/manifestActionDispatch.js.map +1 -1
  59. package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue2.js.map +1 -1
  60. package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue3.js +1 -2
  61. package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue3.js.map +1 -1
  62. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
  63. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js +0 -1
  64. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
  65. package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue2.js +2 -17
  66. package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue2.js.map +1 -1
  67. package/dist/esm/components/CnLinkButtonWidget/CnLinkButtonWidget.vue3.js.map +1 -1
  68. package/dist/esm/components/CnLogsPage/CnLogsPage.vue2.js +35 -11
  69. package/dist/esm/components/CnLogsPage/CnLogsPage.vue2.js.map +1 -1
  70. package/dist/esm/components/CnLogsPage/CnLogsPage.vue3.js +3 -2
  71. package/dist/esm/components/CnLogsPage/CnLogsPage.vue3.js.map +1 -1
  72. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +23 -5
  73. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  74. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +1 -1
  75. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  76. package/dist/esm/components/CnObjectList/CnObjectList.vue2.js +19 -3
  77. package/dist/esm/components/CnObjectList/CnObjectList.vue2.js.map +1 -1
  78. package/dist/esm/components/CnObjectList/CnObjectList.vue3.js.map +1 -1
  79. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +45 -15
  80. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  81. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +4 -2
  82. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  83. package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js +24 -6
  84. package/dist/esm/components/CnObjectRow/CnObjectRow.vue2.js.map +1 -1
  85. package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js +1 -1
  86. package/dist/esm/components/CnObjectRow/CnObjectRow.vue3.js.map +1 -1
  87. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  88. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +0 -1
  89. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  90. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
  91. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js +4 -2
  92. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
  93. package/dist/esm/components/CnRowActions/CnRowActions.vue2.js +7 -2
  94. package/dist/esm/components/CnRowActions/CnRowActions.vue2.js.map +1 -1
  95. package/dist/esm/components/CnRowActions/CnRowActions.vue3.js.map +1 -1
  96. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +49 -5
  97. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  98. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +1 -1
  99. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  100. package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue2.js +5 -3
  101. package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue2.js.map +1 -1
  102. package/dist/esm/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue3.js.map +1 -1
  103. package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
  104. package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
  105. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +3 -1
  106. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  107. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +1 -0
  108. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  109. package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue2.js +3 -1
  110. package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue2.js.map +1 -1
  111. package/dist/esm/integrations/builtin/analytics/CnAnalyticsCard.vue3.js.map +1 -1
  112. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js +3 -1
  113. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue2.js.map +1 -1
  114. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js +2 -4
  115. package/dist/esm/integrations/builtin/analytics/CnAnalyticsTab.vue3.js.map +1 -1
  116. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue2.js +6 -0
  117. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue2.js.map +1 -1
  118. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue3.js +68 -53
  119. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksCard.vue3.js.map +1 -1
  120. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue2.js +17 -0
  121. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue2.js.map +1 -1
  122. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue3.js +21 -19
  123. package/dist/esm/integrations/builtin/bookmarks/CnBookmarksTab.vue3.js.map +1 -1
  124. package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue2.js +3 -1
  125. package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue2.js.map +1 -1
  126. package/dist/esm/integrations/builtin/collectives/CnCollectivesCard.vue3.js.map +1 -1
  127. package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue2.js +3 -1
  128. package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue2.js.map +1 -1
  129. package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue3.js +2 -4
  130. package/dist/esm/integrations/builtin/collectives/CnCollectivesTab.vue3.js.map +1 -1
  131. package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue2.js +2 -1
  132. package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue2.js.map +1 -1
  133. package/dist/esm/integrations/builtin/cospend/CnCospendCard.vue3.js.map +1 -1
  134. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js +2 -1
  135. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue2.js.map +1 -1
  136. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js +1 -2
  137. package/dist/esm/integrations/builtin/cospend/CnCospendTab.vue3.js.map +1 -1
  138. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js +2 -1
  139. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js.map +1 -1
  140. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js.map +1 -1
  141. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js +2 -1
  142. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue2.js.map +1 -1
  143. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js +1 -2
  144. package/dist/esm/integrations/builtin/deck/CnDeckTab.vue3.js.map +1 -1
  145. package/dist/esm/integrations/builtin/email/CnEmailCard.vue2.js.map +1 -1
  146. package/dist/esm/integrations/builtin/email/CnEmailCard.vue3.js.map +1 -1
  147. package/dist/esm/integrations/builtin/email/CnEmailTab.vue2.js.map +1 -1
  148. package/dist/esm/integrations/builtin/email/CnEmailTab.vue3.js +1 -2
  149. package/dist/esm/integrations/builtin/email/CnEmailTab.vue3.js.map +1 -1
  150. package/dist/esm/integrations/builtin/flow/CnFlowCard.vue2.js +2 -1
  151. package/dist/esm/integrations/builtin/flow/CnFlowCard.vue2.js.map +1 -1
  152. package/dist/esm/integrations/builtin/flow/CnFlowCard.vue3.js.map +1 -1
  153. package/dist/esm/integrations/builtin/flow/CnFlowTab.vue2.js +2 -1
  154. package/dist/esm/integrations/builtin/flow/CnFlowTab.vue2.js.map +1 -1
  155. package/dist/esm/integrations/builtin/flow/CnFlowTab.vue3.js +1 -2
  156. package/dist/esm/integrations/builtin/flow/CnFlowTab.vue3.js.map +1 -1
  157. package/dist/esm/integrations/builtin/forms/CnFormsCard.vue2.js +3 -1
  158. package/dist/esm/integrations/builtin/forms/CnFormsCard.vue2.js.map +1 -1
  159. package/dist/esm/integrations/builtin/forms/CnFormsCard.vue3.js.map +1 -1
  160. package/dist/esm/integrations/builtin/forms/CnFormsTab.vue2.js +3 -1
  161. package/dist/esm/integrations/builtin/forms/CnFormsTab.vue2.js.map +1 -1
  162. package/dist/esm/integrations/builtin/forms/CnFormsTab.vue3.js +2 -4
  163. package/dist/esm/integrations/builtin/forms/CnFormsTab.vue3.js.map +1 -1
  164. package/dist/esm/integrations/builtin/maps/CnMapsCard.vue2.js +3 -1
  165. package/dist/esm/integrations/builtin/maps/CnMapsCard.vue2.js.map +1 -1
  166. package/dist/esm/integrations/builtin/maps/CnMapsCard.vue3.js.map +1 -1
  167. package/dist/esm/integrations/builtin/maps/CnMapsTab.vue2.js +3 -1
  168. package/dist/esm/integrations/builtin/maps/CnMapsTab.vue2.js.map +1 -1
  169. package/dist/esm/integrations/builtin/maps/CnMapsTab.vue3.js +2 -4
  170. package/dist/esm/integrations/builtin/maps/CnMapsTab.vue3.js.map +1 -1
  171. package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue2.js +3 -1
  172. package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue2.js.map +1 -1
  173. package/dist/esm/integrations/builtin/openproject/CnOpenprojectCard.vue3.js.map +1 -1
  174. package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue2.js +3 -1
  175. package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue2.js.map +1 -1
  176. package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue3.js +2 -4
  177. package/dist/esm/integrations/builtin/openproject/CnOpenprojectTab.vue3.js.map +1 -1
  178. package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue2.js +2 -1
  179. package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue2.js.map +1 -1
  180. package/dist/esm/integrations/builtin/photos/CnPhotosCard.vue3.js.map +1 -1
  181. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js +2 -1
  182. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue2.js.map +1 -1
  183. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js +1 -2
  184. package/dist/esm/integrations/builtin/photos/CnPhotosTab.vue3.js.map +1 -1
  185. package/dist/esm/integrations/builtin/polls/CnPollsCard.vue2.js +2 -1
  186. package/dist/esm/integrations/builtin/polls/CnPollsCard.vue2.js.map +1 -1
  187. package/dist/esm/integrations/builtin/polls/CnPollsCard.vue3.js.map +1 -1
  188. package/dist/esm/integrations/builtin/polls/CnPollsTab.vue2.js +2 -1
  189. package/dist/esm/integrations/builtin/polls/CnPollsTab.vue2.js.map +1 -1
  190. package/dist/esm/integrations/builtin/polls/CnPollsTab.vue3.js +1 -2
  191. package/dist/esm/integrations/builtin/polls/CnPollsTab.vue3.js.map +1 -1
  192. package/dist/esm/integrations/builtin/shares/CnSharesTab.vue2.js.map +1 -1
  193. package/dist/esm/integrations/builtin/shares/CnSharesTab.vue3.js +3 -6
  194. package/dist/esm/integrations/builtin/shares/CnSharesTab.vue3.js.map +1 -1
  195. package/dist/esm/integrations/builtin/talk/CnTalkCard.vue2.js +3 -1
  196. package/dist/esm/integrations/builtin/talk/CnTalkCard.vue2.js.map +1 -1
  197. package/dist/esm/integrations/builtin/talk/CnTalkCard.vue3.js.map +1 -1
  198. package/dist/esm/integrations/builtin/talk/CnTalkTab.vue2.js +3 -1
  199. package/dist/esm/integrations/builtin/talk/CnTalkTab.vue2.js.map +1 -1
  200. package/dist/esm/integrations/builtin/talk/CnTalkTab.vue3.js +2 -4
  201. package/dist/esm/integrations/builtin/talk/CnTalkTab.vue3.js.map +1 -1
  202. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue2.js +2 -1
  203. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue2.js.map +1 -1
  204. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerCard.vue3.js.map +1 -1
  205. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue2.js +2 -1
  206. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue2.js.map +1 -1
  207. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue3.js +1 -2
  208. package/dist/esm/integrations/builtin/time-tracker/CnTimeTrackerTab.vue3.js.map +1 -1
  209. package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue2.js +4 -1
  210. package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue2.js.map +1 -1
  211. package/dist/esm/integrations/builtin/xwiki/CnXwikiCard.vue3.js.map +1 -1
  212. package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue2.js +6 -3
  213. package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue2.js.map +1 -1
  214. package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue3.js +2 -4
  215. package/dist/esm/integrations/builtin/xwiki/CnXwikiTab.vue3.js.map +1 -1
  216. package/dist/esm/l10n/en.json.js +2 -0
  217. package/dist/esm/l10n/en.json.js.map +1 -1
  218. package/dist/esm/l10n/nl.json.js +2 -0
  219. package/dist/esm/l10n/nl.json.js.map +1 -1
  220. package/dist/esm/nextcloud-vue.css +78 -7
  221. package/dist/esm/utils/actionLink.js +5 -0
  222. package/dist/esm/utils/actionLink.js.map +1 -1
  223. package/dist/esm/utils/actionsDispatcher.js +16 -1
  224. package/dist/esm/utils/actionsDispatcher.js.map +1 -1
  225. package/dist/esm/utils/linkNavigation.js +6 -3
  226. package/dist/esm/utils/linkNavigation.js.map +1 -1
  227. package/dist/esm/utils/rowAuxClick.js +30 -5
  228. package/dist/esm/utils/rowAuxClick.js.map +1 -1
  229. package/dist/esm/utils/safeHref.js +18 -3
  230. package/dist/esm/utils/safeHref.js.map +1 -1
  231. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  232. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  233. package/dist/nextcloud-vue.cjs.js +885 -393
  234. package/dist/nextcloud-vue.cjs.js.map +2 -2
  235. package/dist/nextcloud-vue.css +78 -7
  236. package/l10n/en.json +2 -0
  237. package/l10n/nl.json +2 -0
  238. package/package.json +1 -1
  239. package/src/components/CnActionsBar/CnActionsBar.vue +14 -5
  240. package/src/components/CnActionsMenu/CnActionsMenu.vue +0 -3
  241. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -2
  242. package/src/components/CnAppRoot/CnAppRoot.vue +31 -2
  243. package/src/components/CnBoardView/CnBoardView.vue +13 -5
  244. package/src/components/CnCardGrid/CnCardGrid.vue +9 -1
  245. package/src/components/CnContextMenu/CnContextMenu.vue +6 -1
  246. package/src/components/CnDataTable/CnDataTable.md +1 -1
  247. package/src/components/CnDataTable/CnDataTable.vue +131 -17
  248. package/src/components/CnDateAxisView/CnDateAxisView.vue +15 -6
  249. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  250. package/src/components/CnDetailPage/CnDetailPage.vue +29 -1
  251. package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -2
  252. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +5 -3
  253. package/src/components/CnFilesWidget/CnFilesWidget.vue +4 -21
  254. package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +8 -21
  255. package/src/components/CnFlowsPage/CnFlowsPage.vue +2 -1
  256. package/src/components/CnIndexPage/CnIndexPage.vue +75 -14
  257. package/src/components/CnIndexPage/manifestActionDispatch.js +31 -11
  258. package/src/components/CnIntegrationWidget/CnIntegrationWidgetEmpty.vue +1 -2
  259. package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +0 -1
  260. package/src/components/CnLinkButtonWidget/CnLinkButtonWidget.vue +2 -17
  261. package/src/components/CnLogsPage/CnLogsPage.vue +37 -12
  262. package/src/components/CnObjectCard/CnObjectCard.vue +24 -6
  263. package/src/components/CnObjectList/CnObjectList.vue +19 -3
  264. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +47 -15
  265. package/src/components/CnObjectRow/CnObjectRow.vue +25 -7
  266. package/src/components/CnObjectSidebar/CnFilesTab.vue +0 -1
  267. package/src/components/CnPageRenderer/CnPageRenderer.vue +2 -0
  268. package/src/components/CnRowActions/CnRowActions.vue +7 -2
  269. package/src/components/CnSetupWizard/CnSetupWizard.vue +57 -6
  270. package/src/components/CnSpendAnalyticsWidget/CnSpendAnalyticsWidget.vue +5 -3
  271. package/src/components/CnTabs/CnTabs.vue +7 -3
  272. package/src/components/CnTasksWidget/CnTasksWidget.vue +4 -1
  273. package/src/css/table.css +26 -0
  274. package/src/integrations/builtin/analytics/CnAnalyticsCard.vue +3 -2
  275. package/src/integrations/builtin/analytics/CnAnalyticsTab.vue +5 -6
  276. package/src/integrations/builtin/bookmarks/CnBookmarksCard.vue +12 -1
  277. package/src/integrations/builtin/bookmarks/CnBookmarksTab.vue +23 -6
  278. package/src/integrations/builtin/bookmarks/__tests__/CnBookmarksTab.spec.js +7 -2
  279. package/src/integrations/builtin/collectives/CnCollectivesCard.vue +3 -2
  280. package/src/integrations/builtin/collectives/CnCollectivesTab.vue +5 -6
  281. package/src/integrations/builtin/cospend/CnCospendCard.vue +2 -2
  282. package/src/integrations/builtin/cospend/CnCospendTab.vue +3 -4
  283. package/src/integrations/builtin/deck/CnDeckCard.vue +2 -2
  284. package/src/integrations/builtin/deck/CnDeckTab.vue +3 -4
  285. package/src/integrations/builtin/email/CnEmailCard.vue +6 -2
  286. package/src/integrations/builtin/email/CnEmailTab.vue +7 -4
  287. package/src/integrations/builtin/flow/CnFlowCard.vue +2 -2
  288. package/src/integrations/builtin/flow/CnFlowTab.vue +3 -4
  289. package/src/integrations/builtin/forms/CnFormsCard.vue +3 -2
  290. package/src/integrations/builtin/forms/CnFormsTab.vue +5 -6
  291. package/src/integrations/builtin/maps/CnMapsCard.vue +3 -2
  292. package/src/integrations/builtin/maps/CnMapsTab.vue +5 -6
  293. package/src/integrations/builtin/maps/__tests__/CnMapsTab.spec.js +9 -0
  294. package/src/integrations/builtin/openproject/CnOpenprojectCard.vue +3 -2
  295. package/src/integrations/builtin/openproject/CnOpenprojectTab.vue +5 -6
  296. package/src/integrations/builtin/photos/CnPhotosCard.vue +2 -2
  297. package/src/integrations/builtin/photos/CnPhotosTab.vue +3 -4
  298. package/src/integrations/builtin/polls/CnPollsCard.vue +2 -2
  299. package/src/integrations/builtin/polls/CnPollsTab.vue +3 -4
  300. package/src/integrations/builtin/shares/CnSharesTab.vue +3 -6
  301. package/src/integrations/builtin/talk/CnTalkCard.vue +3 -2
  302. package/src/integrations/builtin/talk/CnTalkTab.vue +5 -6
  303. package/src/integrations/builtin/time-tracker/CnTimeTrackerCard.vue +2 -2
  304. package/src/integrations/builtin/time-tracker/CnTimeTrackerTab.vue +3 -4
  305. package/src/integrations/builtin/xwiki/CnXwikiCard.vue +4 -2
  306. package/src/integrations/builtin/xwiki/CnXwikiTab.vue +7 -7
  307. package/src/integrations/builtin/xwiki/__tests__/CnXwikiTab.spec.js +9 -0
  308. package/src/schemas/app-manifest-v2.schema.json +2 -1
  309. package/src/utils/actionLink.js +5 -0
  310. package/src/utils/actionsDispatcher.js +15 -0
  311. package/src/utils/linkNavigation.js +6 -3
  312. package/src/utils/rowAuxClick.js +29 -4
  313. package/src/utils/safeHref.js +18 -3
  314. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"CnBookmarksCard.vue2.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksCard.vue"],"sourcesContent":["<!--\n CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n integration.\n\n Replaces the generic CnIntegrationCard for the `bookmarks` leaf.\n Branches on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N bookmarks\" + the most\n recently added bookmark's favicon + title.\n - detail-page : compact list of linked bookmarks\n (favicon + title, up to COMPACT_LIMIT) with \"view all\" trail-off.\n - single-entity : chip with favicon + title for\n reference-property auto-rendering (referenceType: 'bookmarks').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnBookmarksTab; for `single-entity` the optional `value` prop addresses\n a single bookmark by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-bookmarks-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"faviconUrl(entity)\"\n\t\t\t\t\t:src=\"faviconUrl(entity)\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t@error=\"onFaviconError(entity)\">\n\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"entity.url\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(entity) }}</a>\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-bookmarks-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-bookmarks-card__headline\">\n\t\t\t\t<div class=\"cn-bookmarks-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-bookmarks-card__headline-recent\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\t:src=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t@error=\"onFaviconError(mostRecent)\">\n\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"mostRecent.url\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(mostRecent) }}</a>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"bookmarks.length > 1\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-bookmarks-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"bookmark in displayedBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__row\">\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-icon\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\t:src=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t\t@error=\"onFaviconError(bookmark)\">\n\t\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-main\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"bookmark.url\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</a>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div v-if=\"bookmarks.length > COMPACT_LIMIT\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t<a\n\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t</div>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n * integration.\n *\n * Renders Bookmarks-aware metadata across all four AD-19 surfaces. See\n * the file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnBookmarksCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, Bookmark },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\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 (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (bookmark id). */\n\t\tvalue: { type: [String, Number], default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Bookmarks') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => Bookmark },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"view all\" trail-off link label. */\n\t\tviewAllLabel: { type: String, default: () => t('nextcloud-vue', 'View all in Bookmarks') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tCOMPACT_LIMIT,\n\t\t\tbookmarks: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t\tbrokenFavicons: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedBookmarks() {\n\t\t\treturn this.bookmarks.slice(0, COMPACT_LIMIT)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.bookmarks.length\n\t\t\treturn n('nextcloud-vue', '{count} bookmark', '{count} bookmarks', total, { count: total })\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.bookmarks.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst sorted = [...this.bookmarks].sort((a, b) => {\n\t\t\t\tconst ta = Number(a.added ?? a.addedAt ?? 0)\n\t\t\t\tconst tb = Number(b.added ?? b.addedAt ?? 0)\n\t\t\t\treturn tb - ta\n\t\t\t})\n\t\t\treturn sorted[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\tchipSubtitle(bookmark) {\n\t\t\treturn bookmark.description || bookmark.url || this.bookmarkTitle(bookmark)\n\t\t},\n\n\t\tfaviconUrl(bookmark) {\n\t\t\tif (!bookmark || this.brokenFavicons[this.bookmarkKey(bookmark)]) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = new URL(bookmark.url)\n\t\t\t\treturn `${url.origin}/favicon.ico`\n\t\t\t} catch {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t},\n\n\t\tonFaviconError(bookmark) {\n\t\t\tthis.brokenFavicons[this.bookmarkKey(bookmark)] = true\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.bookmarks = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\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('[CnBookmarksCard] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (this.value === '' || this.value === undefined || this.value === null || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\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('[CnBookmarksCard] failed to fetch single bookmark', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-bookmarks-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-bookmarks-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-bookmarks-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__favicon {\n\twidth: 14px;\n\theight: 14px;\n\tobject-fit: contain;\n\tflex-shrink: 0;\n}\n\n.cn-bookmarks-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-bookmarks-card__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-bookmarks-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-bookmarks-card__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 16px;\n\theight: 16px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-bookmarks-card__row-main {\n\tflex: 1;\n\tmin-width: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-bookmarks-card__title {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-bookmarks-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__view-all {\n\tmargin-top: 6px;\n\tfont-size: 0.8em;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__view-all a {\n\tcolor: var(--color-primary-element);\n\ttext-decoration: none;\n}\n\n.cn-bookmarks-card__view-all a:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["CnDetailCard","t","n"],"mappings":"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"}
1
+ {"version":3,"file":"CnBookmarksCard.vue2.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksCard.vue"],"sourcesContent":["<!--\n CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n integration.\n\n Replaces the generic CnIntegrationCard for the `bookmarks` leaf.\n Branches on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N bookmarks\" + the most\n recently added bookmark's favicon + title.\n - detail-page : compact list of linked bookmarks\n (favicon + title, up to COMPACT_LIMIT) with \"view all\" trail-off.\n - single-entity : chip with favicon + title for\n reference-property auto-rendering (referenceType: 'bookmarks').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnBookmarksTab; for `single-entity` the optional `value` prop addresses\n a single bookmark by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-bookmarks-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"faviconUrl(entity)\"\n\t\t\t\t\t:src=\"faviconUrl(entity)\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t@error=\"onFaviconError(entity)\">\n\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"hasSafeUrl(entity)\"\n\t\t\t\t\t:href=\"entity.url\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(entity) }}</a>\n\t\t\t\t<span v-else>{{ bookmarkTitle(entity) }}</span>\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-bookmarks-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-bookmarks-card__headline\">\n\t\t\t\t<div class=\"cn-bookmarks-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-bookmarks-card__headline-recent\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\t:src=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t@error=\"onFaviconError(mostRecent)\">\n\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\tv-if=\"hasSafeUrl(mostRecent)\"\n\t\t\t\t\t\t:href=\"mostRecent.url\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(mostRecent) }}</a>\n\t\t\t\t\t<span v-else>{{ bookmarkTitle(mostRecent) }}</span>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"bookmarks.length > 1\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-bookmarks-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"bookmark in displayedBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__row\">\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-icon\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\t:src=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t\t@error=\"onFaviconError(bookmark)\">\n\t\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-main\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tv-if=\"hasSafeUrl(bookmark)\"\n\t\t\t\t\t\t\t:href=\"bookmark.url\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</a>\n\t\t\t\t\t\t<span v-else class=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div v-if=\"bookmarks.length > COMPACT_LIMIT\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t<a\n\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t</div>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n * integration.\n *\n * Renders Bookmarks-aware metadata across all four AD-19 surfaces. See\n * the file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnBookmarksCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, Bookmark },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\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 (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (bookmark id). */\n\t\tvalue: { type: [String, Number], default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Bookmarks') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => Bookmark },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"view all\" trail-off link label. */\n\t\tviewAllLabel: { type: String, default: () => t('nextcloud-vue', 'View all in Bookmarks') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tCOMPACT_LIMIT,\n\t\t\tbookmarks: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t\tbrokenFavicons: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedBookmarks() {\n\t\t\treturn this.bookmarks.slice(0, COMPACT_LIMIT)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.bookmarks.length\n\t\t\treturn n('nextcloud-vue', '{count} bookmark', '{count} bookmarks', total, { count: total })\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.bookmarks.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst sorted = [...this.bookmarks].sort((a, b) => {\n\t\t\t\tconst ta = Number(a.added ?? a.addedAt ?? 0)\n\t\t\t\tconst tb = Number(b.added ?? b.addedAt ?? 0)\n\t\t\t\treturn tb - ta\n\t\t\t})\n\t\t\treturn sorted[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\t// Bookmark URLs are user-entered (bookmarklets are `javascript:`), so only a safe one is a link.\n\t\thasSafeUrl(bookmark) {\n\t\t\treturn safeHref(bookmark.url) !== '#'\n\t\t},\n\n\t\tchipSubtitle(bookmark) {\n\t\t\treturn bookmark.description || bookmark.url || this.bookmarkTitle(bookmark)\n\t\t},\n\n\t\tfaviconUrl(bookmark) {\n\t\t\tif (!bookmark || this.brokenFavicons[this.bookmarkKey(bookmark)]) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = new URL(bookmark.url)\n\t\t\t\treturn `${url.origin}/favicon.ico`\n\t\t\t} catch {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t},\n\n\t\tonFaviconError(bookmark) {\n\t\t\tthis.brokenFavicons[this.bookmarkKey(bookmark)] = true\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.bookmarks = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\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('[CnBookmarksCard] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (this.value === '' || this.value === undefined || this.value === null || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\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('[CnBookmarksCard] failed to fetch single bookmark', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-bookmarks-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-bookmarks-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-bookmarks-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__favicon {\n\twidth: 14px;\n\theight: 14px;\n\tobject-fit: contain;\n\tflex-shrink: 0;\n}\n\n.cn-bookmarks-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-bookmarks-card__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-bookmarks-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-bookmarks-card__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 16px;\n\theight: 16px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-bookmarks-card__row-main {\n\tflex: 1;\n\tmin-width: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-bookmarks-card__title {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-bookmarks-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__view-all {\n\tmargin-top: 6px;\n\tfont-size: 0.8em;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__view-all a {\n\tcolor: var(--color-primary-element);\n\ttext-decoration: none;\n}\n\n.cn-bookmarks-card__view-all a:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["CnDetailCard","t","n"],"mappings":"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"}
@@ -1,57 +1,63 @@
1
- import { resolveComponent, openBlock, createBlock, withCtx, createElementBlock, Fragment, createElementVNode, toDisplayString, createCommentVNode, renderList } from 'vue';
1
+ import { resolveComponent, openBlock, createBlock, withCtx, createElementBlock, Fragment, toDisplayString, createElementVNode, createCommentVNode, renderList } from 'vue';
2
2
 
3
3
  const _hoisted_1 = ["title"];
4
4
  const _hoisted_2 = ["src"];
5
5
  const _hoisted_3 = ["href"];
6
- const _hoisted_4 = {
6
+ const _hoisted_4 = { key: 3 };
7
+ const _hoisted_5 = {
7
8
  key: 1,
8
9
  class: "cn-bookmarks-card__empty"
9
10
  };
10
- const _hoisted_5 = {
11
+ const _hoisted_6 = {
11
12
  key: 0,
12
13
  class: "cn-bookmarks-card__empty"
13
14
  };
14
- const _hoisted_6 = {
15
+ const _hoisted_7 = {
15
16
  key: 1,
16
17
  class: "cn-bookmarks-card__empty"
17
18
  };
18
- const _hoisted_7 = {
19
+ const _hoisted_8 = {
19
20
  key: 2,
20
21
  class: "cn-bookmarks-card__headline"
21
22
  };
22
- const _hoisted_8 = { class: "cn-bookmarks-card__headline-line" };
23
- const _hoisted_9 = {
23
+ const _hoisted_9 = { class: "cn-bookmarks-card__headline-line" };
24
+ const _hoisted_10 = {
24
25
  key: 0,
25
26
  class: "cn-bookmarks-card__headline-recent"
26
27
  };
27
- const _hoisted_10 = ["src"];
28
- const _hoisted_11 = ["href"];
29
- const _hoisted_12 = {
28
+ const _hoisted_11 = ["src"];
29
+ const _hoisted_12 = ["href"];
30
+ const _hoisted_13 = { key: 3 };
31
+ const _hoisted_14 = {
30
32
  key: 1,
31
33
  class: "cn-bookmarks-card__view-all"
32
34
  };
33
- const _hoisted_13 = ["href"];
34
- const _hoisted_14 = {
35
+ const _hoisted_15 = ["href"];
36
+ const _hoisted_16 = {
35
37
  key: 0,
36
38
  class: "cn-bookmarks-card__empty"
37
39
  };
38
- const _hoisted_15 = {
40
+ const _hoisted_17 = {
39
41
  key: 1,
40
42
  class: "cn-bookmarks-card__empty"
41
43
  };
42
- const _hoisted_16 = {
44
+ const _hoisted_18 = {
43
45
  key: 2,
44
46
  class: "cn-bookmarks-card__list"
45
47
  };
46
- const _hoisted_17 = { class: "cn-bookmarks-card__row-icon" };
47
- const _hoisted_18 = ["src", "onError"];
48
- const _hoisted_19 = { class: "cn-bookmarks-card__row-main" };
49
- const _hoisted_20 = ["href"];
50
- const _hoisted_21 = {
48
+ const _hoisted_19 = { class: "cn-bookmarks-card__row-icon" };
49
+ const _hoisted_20 = ["src", "onError"];
50
+ const _hoisted_21 = { class: "cn-bookmarks-card__row-main" };
51
+ const _hoisted_22 = ["href"];
52
+ const _hoisted_23 = {
53
+ key: 1,
54
+ class: "cn-bookmarks-card__title"
55
+ };
56
+ const _hoisted_24 = {
51
57
  key: 3,
52
58
  class: "cn-bookmarks-card__view-all"
53
59
  };
54
- const _hoisted_22 = ["href"];
60
+ const _hoisted_25 = ["href"];
55
61
 
56
62
  function render(_ctx, _cache, $props, $setup, $data, $options) {
57
63
  const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
@@ -86,26 +92,29 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
86
92
  key: 1,
87
93
  size: 14
88
94
  })),
89
- createElementVNode("a", {
90
- href: $data.entity.url,
91
- target: "_blank",
92
- rel: "noopener noreferrer"
93
- }, toDisplayString($options.bookmarkTitle($data.entity)), 9 /* TEXT, PROPS */, _hoisted_3)
95
+ ($options.hasSafeUrl($data.entity))
96
+ ? (openBlock(), createElementBlock("a", {
97
+ key: 2,
98
+ href: $data.entity.url,
99
+ target: "_blank",
100
+ rel: "noopener noreferrer"
101
+ }, toDisplayString($options.bookmarkTitle($data.entity)), 9 /* TEXT, PROPS */, _hoisted_3))
102
+ : (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString($options.bookmarkTitle($data.entity)), 1 /* TEXT */))
94
103
  ], 8 /* PROPS */, _hoisted_1))
95
- : (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString($props.emptyLabel), 1 /* TEXT */))
104
+ : (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString($props.emptyLabel), 1 /* TEXT */))
96
105
  ], 64 /* STABLE_FRAGMENT */))
97
106
  : ($props.surface === 'user-dashboard' || $props.surface === 'app-dashboard')
98
107
  ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [
99
108
  ($data.degraded)
100
- ? (openBlock(), createElementBlock("div", _hoisted_5, toDisplayString($data.degraded), 1 /* TEXT */))
109
+ ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString($data.degraded), 1 /* TEXT */))
101
110
  : ($data.bookmarks.length === 0)
102
- ? (openBlock(), createElementBlock("div", _hoisted_6, toDisplayString($props.emptyLabel), 1 /* TEXT */))
103
- : (openBlock(), createElementBlock("div", _hoisted_7, [
104
- createElementVNode("div", _hoisted_8, [
111
+ ? (openBlock(), createElementBlock("div", _hoisted_7, toDisplayString($props.emptyLabel), 1 /* TEXT */))
112
+ : (openBlock(), createElementBlock("div", _hoisted_8, [
113
+ createElementVNode("div", _hoisted_9, [
105
114
  createElementVNode("strong", null, toDisplayString($options.countHeadline), 1 /* TEXT */)
106
115
  ]),
107
116
  ($options.mostRecent)
108
- ? (openBlock(), createElementBlock("div", _hoisted_9, [
117
+ ? (openBlock(), createElementBlock("div", _hoisted_10, [
109
118
  ($options.faviconUrl($options.mostRecent))
110
119
  ? (openBlock(), createElementBlock("img", {
111
120
  key: 0,
@@ -113,41 +122,44 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
113
122
  alt: "",
114
123
  class: "cn-bookmarks-card__favicon",
115
124
  onError: _cache[1] || (_cache[1] = $event => ($options.onFaviconError($options.mostRecent)))
116
- }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_10))
125
+ }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_11))
117
126
  : (openBlock(), createBlock(_component_Bookmark, {
118
127
  key: 1,
119
128
  size: 14
120
129
  })),
121
- createElementVNode("a", {
122
- href: $options.mostRecent.url,
123
- target: "_blank",
124
- rel: "noopener noreferrer"
125
- }, toDisplayString($options.bookmarkTitle($options.mostRecent)), 9 /* TEXT, PROPS */, _hoisted_11)
130
+ ($options.hasSafeUrl($options.mostRecent))
131
+ ? (openBlock(), createElementBlock("a", {
132
+ key: 2,
133
+ href: $options.mostRecent.url,
134
+ target: "_blank",
135
+ rel: "noopener noreferrer"
136
+ }, toDisplayString($options.bookmarkTitle($options.mostRecent)), 9 /* TEXT, PROPS */, _hoisted_12))
137
+ : (openBlock(), createElementBlock("span", _hoisted_13, toDisplayString($options.bookmarkTitle($options.mostRecent)), 1 /* TEXT */))
126
138
  ]))
127
139
  : createCommentVNode("v-if", true),
128
140
  ($data.bookmarks.length > 1)
129
- ? (openBlock(), createElementBlock("div", _hoisted_12, [
141
+ ? (openBlock(), createElementBlock("div", _hoisted_14, [
130
142
  createElementVNode("a", {
131
143
  href: $props.bookmarksAppUrl,
132
144
  target: "_blank",
133
145
  rel: "noopener noreferrer"
134
- }, toDisplayString($props.viewAllLabel), 9 /* TEXT, PROPS */, _hoisted_13)
146
+ }, toDisplayString($props.viewAllLabel), 9 /* TEXT, PROPS */, _hoisted_15)
135
147
  ]))
136
148
  : createCommentVNode("v-if", true)
137
149
  ]))
138
150
  ], 64 /* STABLE_FRAGMENT */))
139
151
  : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
140
152
  ($data.degraded)
141
- ? (openBlock(), createElementBlock("div", _hoisted_14, toDisplayString($data.degraded), 1 /* TEXT */))
153
+ ? (openBlock(), createElementBlock("div", _hoisted_16, toDisplayString($data.degraded), 1 /* TEXT */))
142
154
  : ($data.bookmarks.length === 0)
143
- ? (openBlock(), createElementBlock("div", _hoisted_15, toDisplayString($props.emptyLabel), 1 /* TEXT */))
144
- : (openBlock(), createElementBlock("ul", _hoisted_16, [
155
+ ? (openBlock(), createElementBlock("div", _hoisted_17, toDisplayString($props.emptyLabel), 1 /* TEXT */))
156
+ : (openBlock(), createElementBlock("ul", _hoisted_18, [
145
157
  (openBlock(true), createElementBlock(Fragment, null, renderList($options.displayedBookmarks, (bookmark) => {
146
158
  return (openBlock(), createElementBlock("li", {
147
159
  key: $options.bookmarkKey(bookmark),
148
160
  class: "cn-bookmarks-card__row"
149
161
  }, [
150
- createElementVNode("div", _hoisted_17, [
162
+ createElementVNode("div", _hoisted_19, [
151
163
  ($options.faviconUrl(bookmark))
152
164
  ? (openBlock(), createElementBlock("img", {
153
165
  key: 0,
@@ -155,30 +167,33 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
155
167
  alt: "",
156
168
  class: "cn-bookmarks-card__favicon",
157
169
  onError: $event => ($options.onFaviconError(bookmark))
158
- }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_18))
170
+ }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_20))
159
171
  : (openBlock(), createBlock(_component_Bookmark, {
160
172
  key: 1,
161
173
  size: 14
162
174
  }))
163
175
  ]),
164
- createElementVNode("div", _hoisted_19, [
165
- createElementVNode("a", {
166
- href: bookmark.url,
167
- target: "_blank",
168
- rel: "noopener noreferrer",
169
- class: "cn-bookmarks-card__title"
170
- }, toDisplayString($options.bookmarkTitle(bookmark)), 9 /* TEXT, PROPS */, _hoisted_20)
176
+ createElementVNode("div", _hoisted_21, [
177
+ ($options.hasSafeUrl(bookmark))
178
+ ? (openBlock(), createElementBlock("a", {
179
+ key: 0,
180
+ href: bookmark.url,
181
+ target: "_blank",
182
+ rel: "noopener noreferrer",
183
+ class: "cn-bookmarks-card__title"
184
+ }, toDisplayString($options.bookmarkTitle(bookmark)), 9 /* TEXT, PROPS */, _hoisted_22))
185
+ : (openBlock(), createElementBlock("span", _hoisted_23, toDisplayString($options.bookmarkTitle(bookmark)), 1 /* TEXT */))
171
186
  ])
172
187
  ]))
173
188
  }), 128 /* KEYED_FRAGMENT */))
174
189
  ])),
175
190
  ($data.bookmarks.length > $data.COMPACT_LIMIT)
176
- ? (openBlock(), createElementBlock("div", _hoisted_21, [
191
+ ? (openBlock(), createElementBlock("div", _hoisted_24, [
177
192
  createElementVNode("a", {
178
193
  href: $props.bookmarksAppUrl,
179
194
  target: "_blank",
180
195
  rel: "noopener noreferrer"
181
- }, toDisplayString($props.viewAllLabel), 9 /* TEXT, PROPS */, _hoisted_22)
196
+ }, toDisplayString($props.viewAllLabel), 9 /* TEXT, PROPS */, _hoisted_25)
182
197
  ]))
183
198
  : createCommentVNode("v-if", true)
184
199
  ], 64 /* STABLE_FRAGMENT */))
@@ -1 +1 @@
1
- {"version":3,"file":"CnBookmarksCard.vue3.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksCard.vue?vue&type=template&id=86bb63e6&lang.js"],"sourcesContent":["<!--\n CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n integration.\n\n Replaces the generic CnIntegrationCard for the `bookmarks` leaf.\n Branches on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N bookmarks\" + the most\n recently added bookmark's favicon + title.\n - detail-page : compact list of linked bookmarks\n (favicon + title, up to COMPACT_LIMIT) with \"view all\" trail-off.\n - single-entity : chip with favicon + title for\n reference-property auto-rendering (referenceType: 'bookmarks').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnBookmarksTab; for `single-entity` the optional `value` prop addresses\n a single bookmark by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-bookmarks-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"faviconUrl(entity)\"\n\t\t\t\t\t:src=\"faviconUrl(entity)\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t@error=\"onFaviconError(entity)\">\n\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\t:href=\"entity.url\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(entity) }}</a>\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-bookmarks-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-bookmarks-card__headline\">\n\t\t\t\t<div class=\"cn-bookmarks-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-bookmarks-card__headline-recent\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\t:src=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t@error=\"onFaviconError(mostRecent)\">\n\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"mostRecent.url\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(mostRecent) }}</a>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"bookmarks.length > 1\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-bookmarks-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"bookmark in displayedBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__row\">\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-icon\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\t:src=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t\t@error=\"onFaviconError(bookmark)\">\n\t\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-main\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"bookmark.url\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</a>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div v-if=\"bookmarks.length > COMPACT_LIMIT\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t<a\n\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t</div>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n * integration.\n *\n * Renders Bookmarks-aware metadata across all four AD-19 surfaces. See\n * the file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnBookmarksCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, Bookmark },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\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 (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (bookmark id). */\n\t\tvalue: { type: [String, Number], default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Bookmarks') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => Bookmark },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"view all\" trail-off link label. */\n\t\tviewAllLabel: { type: String, default: () => t('nextcloud-vue', 'View all in Bookmarks') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tCOMPACT_LIMIT,\n\t\t\tbookmarks: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t\tbrokenFavicons: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedBookmarks() {\n\t\t\treturn this.bookmarks.slice(0, COMPACT_LIMIT)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.bookmarks.length\n\t\t\treturn n('nextcloud-vue', '{count} bookmark', '{count} bookmarks', total, { count: total })\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.bookmarks.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst sorted = [...this.bookmarks].sort((a, b) => {\n\t\t\t\tconst ta = Number(a.added ?? a.addedAt ?? 0)\n\t\t\t\tconst tb = Number(b.added ?? b.addedAt ?? 0)\n\t\t\t\treturn tb - ta\n\t\t\t})\n\t\t\treturn sorted[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\tchipSubtitle(bookmark) {\n\t\t\treturn bookmark.description || bookmark.url || this.bookmarkTitle(bookmark)\n\t\t},\n\n\t\tfaviconUrl(bookmark) {\n\t\t\tif (!bookmark || this.brokenFavicons[this.bookmarkKey(bookmark)]) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = new URL(bookmark.url)\n\t\t\t\treturn `${url.origin}/favicon.ico`\n\t\t\t} catch {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t},\n\n\t\tonFaviconError(bookmark) {\n\t\t\tthis.brokenFavicons[this.bookmarkKey(bookmark)] = true\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.bookmarks = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\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('[CnBookmarksCard] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (this.value === '' || this.value === undefined || this.value === null || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\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('[CnBookmarksCard] failed to fetch single bookmark', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-bookmarks-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-bookmarks-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-bookmarks-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__favicon {\n\twidth: 14px;\n\theight: 14px;\n\tobject-fit: contain;\n\tflex-shrink: 0;\n}\n\n.cn-bookmarks-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-bookmarks-card__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-bookmarks-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-bookmarks-card__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 16px;\n\theight: 16px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-bookmarks-card__row-main {\n\tflex: 1;\n\tmin-width: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-bookmarks-card__title {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-bookmarks-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__view-all {\n\tmargin-top: 6px;\n\tfont-size: 0.8em;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__view-all a {\n\tcolor: var(--color-primary-element);\n\ttext-decoration: none;\n}\n\n.cn-bookmarks-card__view-all a:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["_createBlock","_Fragment","_createElementBlock","_createElementVNode","_toDisplayString","_openBlock"],"mappings":";;;;;;;AA6DgB,EAAA,KAAK,EAAC,0BAAmB;;;;AAKjB,EAAA,KAAK,EAAC,0BAA0B;;;;AAGlD,EAAA,KAAA,EAAA,0BAAA;;;;AAGS,EAAA,KAAK,EAAC,6BAA6B;;AACzC,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,kCAAA,GAAA;;;;;;;;;AAgB0B,EAAA,KAAA,EAAA,6BAAA;;;;;AAW5B,EAAA,KAAA,EAAA,0BAAA;;;;AAGwB,EAAA,KAAA,EAAA,0BAAA;;;;AAGvB,EAAA,KAAA,EAAA,yBAAA;;AAKE,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,6BAAG,GAAA;;;;;;;;;;;;;;;uBApEjBA;AAAa,IAAA,KAAM,EAAE,QAAS,CAAA,SAAA;AAAE,IAAA,IAAK,EAAE,QAAO,CAAA,QAAA;AAAI,IAAA,WAAA,EAAA,MAAA,CAAA,WAAA;;qBAClD;OAAqB,KAAM,CAAA,OAAA;wBAA3BA;WAGM,MAAA,CAAA,OAAA,KAAA,eAAA;4CAeK,CAAAC,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;eAdE,KAAM,CAAA,MAAA;gCAAlBC,kBAYO,CAAA,MAAA,EAAA;;AAZa,oBAAA,KAAK,EAAC,yBAAyB;oBAAE,KAAK,EAAE,QAAY,CAAA,YAAA,CAAA,KAAA,CAAA,MAAA,CAAA;;AAEnE,oBAAA,CAAA,QAAA,CAAA,UAAA,CAAA,KAAA,CAAA,MAAA,CAAA;sCADJA,kBAKK,CAAA,KAAA,EAAA;;0BAHH,GAAG,EAAE,QAAU,CAAA,UAAA,CAAC,KAAM,CAAA,MAAA,CAAA;AACvB,0BAAA,GAAE,EAAE,EAAE;AACN,0BAAA,KAAK,EAAC,4BAA4B;0BACjC,OAAG,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,MAAA,KAAA,QAAA,CAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;sCACLF,WAA8B,CAAA,mBAAA,EAAA;;AAAZ,0BAAA,IAAG,EAAG,EAAE;;oBACzBG,kBAGM,CAAA,GAAA,EAAA;sBAFL,IAAI,EAAE,KAAM,CAAA,MAAA,CAAC,GAAG;4BACX,EAAC,QAAQ;yBACZ,EAAC,qBAAE;AAAA,qBAAA,EAAAC,eAAA,CAAA,QAAA,CAAA,aAAA,CAAA,KAAA,CAAA,MAAA,CAAA,CAAA,EAAA,CAAA,oBAAA,UAAA,CAAA;;gCAELF,kBAAmC,CAAA,MAAA,EAAnC,UAAmC,EAAAE,eAAA,CAAA,MAAA,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA,CAAA;;AAIrB,YAAA,CAAA,MAAA,CAAA,OAAA,yBAAA,MAAA,CAAA,OAAA,KAAA,eAAA;4BAAdF,kBA+BO,CAAAD,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;iBA9BC,KAAQ,CAAA,QAAA;oDAEb,CAAA,KAAA,YAAA,EAAAG,eAAA,CADF,KAAE,CAAA,QAAA,CAAA,EAAA,CAAA,YAAA;AAEH,oBAAA,CAAA,KAAA,CAAA,SAAA,CAAA,MAAA,KAAA,CAAA;sDAEG,CAAA,KAAA,YAAA,EAAAA,eAAA,CADF,MAAU,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;AAEX,uBAAAC,SAAA,EAAA,EAAAH,kBAAA,CAuBG,OAvBH,UAuBG,EAAA;AAtBL,wBAAAC,kBAAA,CAEM,OAFN,UAEM,EAAA;AADL,0BAAAA,kBAAA,CAAG,gCAAA,QAAA,CAAA,aAAA,CAAA,EAAA,CAAA,YAAA;;;6DAcE,iBAAA,EAAA;AAVE,8BAAA,CAAA,QAAA,CAAA,UAAM,CAAA,QAAA,CAAA,UAAA,CAAA;gDADbD,kBAKoC,CAAA,KAAA,EAAA;;oCAHjC,GAAE,EAAE,QAAU,CAAA,UAAA,SAAW,CAAA,UAAA,CAAA;AAC5B,oCAAA,GAAI,EAAC,EAAE;AACN,oCAAA,KAAE,EAAA,4BAAA;oCACA,OAAI,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,MAAA,KAAE,QAAc,CAAA,cAAA,CAAC,QAAS,CAAA,UAAA,CAAA,CAAA,CAAA;;gDACjCF,WAAc,CAAA,mBAAA,EAAA;;AAAA,oCAAA,IAAA,EAAA,EAAA;;8BACdG,kBAGqC,CAAA,GAAA,EAAA;gCAFnC,IAAI,EAAC,QAAW,CAAA,UAAA,CAAC,GAAG;AACrB,gCAAA,MAAA,EAAA,QAAA;AACA,gCAAA,GAAG,EAAC,qBAAqB;AAAI,+BAAA,EAAAC,eAAA,CAAA,QAAA,CAAA,aAAO,CAAA,QAAA,CAAA,UAAA,CAAA,CAAA,EAAA,CAAA,oBAAA,WAAA,CAAA;;;AAE3B,wBAAA,CAAA,KAAA,CAAA,SAAS,CAAC,MAAM,GAAA,CAAA;AAA1B,6BAAAC,SAAA,EAAA,EAAAH,kBAAA,CAKK,OALL,WAKK,EAAA;8BAJLC,kBAG4B,CAAA,GAAA,EAAA;AAF1B,gCAAA,IAAE,EAAA,MAAA,CAAA,eAAA;sCACG,EAAC,QAAQ;mCACZ,EAAC,qBAAqB;iDAAE,MAAA,CAAA,YAAA,CAAA,EAAA,CAAA,oBAAA,WAAA,CAAA;;;;;4BAM5BD;iBACE,KAAA,CAAA,QAAA;oDAEE,CAAA,KAAA,aAAA,EAAAE,eAAA,CADF,KAAQ,CAAA,QAAA,CAAA,EAAA,CAAA,YAAA;AAEI,oBAAA,CAAA,KAAA,CAAA,SAAS,CAAC,MAAE,KAAA,CAAA;sDAEtB,CAAA,KAAA,aAAA,EAAAA,eAAA,CADF,MAAU,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;;0CAGbF,8CACoB,QAAkB,CAAA,kBAAA,EAAA,CAA9B,QAAQ,KAAA;+CADhBA;4BAEC,GAAA,EAAA,QAAA,CAAA,WAAA,CAAA,QAAA,CAAA;AACA,4BAAA,KAAK,EAAC,wBAAgB;;AACtB,4BAAAC,kBAAA,QAAA;AAEG,8BAAA,CAAA,QAAA,CAAA,UAAA,CAAA,QAAA,CAAA;gDADFD;;oCAEE,GAAG,EAAC,QAAA,CAAA,UAAA,CAAA,QAAA,CAAA;AACL,oCAAA,GAAG,EAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CnBookmarksCard.vue3.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksCard.vue?vue&type=template&id=86bb63e6&lang.js"],"sourcesContent":["<!--\n CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n integration.\n\n Replaces the generic CnIntegrationCard for the `bookmarks` leaf.\n Branches on `surface` per AD-19:\n - user-dashboard / app-dashboard : headline \"N bookmarks\" + the most\n recently added bookmark's favicon + title.\n - detail-page : compact list of linked bookmarks\n (favicon + title, up to COMPACT_LIMIT) with \"view all\" trail-off.\n - single-entity : chip with favicon + title for\n reference-property auto-rendering (referenceType: 'bookmarks').\n\n Pulls rows from the same OR pluggable-integration sub-resource as\n CnBookmarksTab; for `single-entity` the optional `value` prop addresses\n a single bookmark by id (matching CnIntegrationCard's fetchSingle\n contract).\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), AD-19 (surface fallback).\n-->\n<template>\n\t<CnDetailCard :title=\"cardTitle\" :icon=\"cardIcon\" :collapsible=\"collapsible\">\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\n\t\t<!-- single-entity surface: chip -->\n\t\t<template v-else-if=\"surface === 'single-entity'\">\n\t\t\t<span v-if=\"entity\" class=\"cn-bookmarks-card__chip\" :title=\"chipSubtitle(entity)\">\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"faviconUrl(entity)\"\n\t\t\t\t\t:src=\"faviconUrl(entity)\"\n\t\t\t\t\talt=\"\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t@error=\"onFaviconError(entity)\">\n\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t<a\n\t\t\t\t\tv-if=\"hasSafeUrl(entity)\"\n\t\t\t\t\t:href=\"entity.url\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(entity) }}</a>\n\t\t\t\t<span v-else>{{ bookmarkTitle(entity) }}</span>\n\t\t\t</span>\n\t\t\t<span v-else class=\"cn-bookmarks-card__empty\">{{ emptyLabel }}</span>\n\t\t</template>\n\n\t\t<!-- dashboard surfaces: headline + most-recent -->\n\t\t<template v-else-if=\"surface === 'user-dashboard' || surface === 'app-dashboard'\">\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<div v-else class=\"cn-bookmarks-card__headline\">\n\t\t\t\t<div class=\"cn-bookmarks-card__headline-line\">\n\t\t\t\t\t<strong>{{ countHeadline }}</strong>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"mostRecent\" class=\"cn-bookmarks-card__headline-recent\">\n\t\t\t\t\t<img\n\t\t\t\t\t\tv-if=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\t:src=\"faviconUrl(mostRecent)\"\n\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t@error=\"onFaviconError(mostRecent)\">\n\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t<a\n\t\t\t\t\t\tv-if=\"hasSafeUrl(mostRecent)\"\n\t\t\t\t\t\t:href=\"mostRecent.url\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ bookmarkTitle(mostRecent) }}</a>\n\t\t\t\t\t<span v-else>{{ bookmarkTitle(mostRecent) }}</span>\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"bookmarks.length > 1\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t\t<a\n\t\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</template>\n\n\t\t<!-- detail-page surface: compact list -->\n\t\t<template v-else>\n\t\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ degraded }}\n\t\t\t</div>\n\t\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-bookmarks-card__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</div>\n\t\t\t<ul v-else class=\"cn-bookmarks-card__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"bookmark in displayedBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-card__row\">\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-icon\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\t:src=\"faviconUrl(bookmark)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__favicon\"\n\t\t\t\t\t\t\t@error=\"onFaviconError(bookmark)\">\n\t\t\t\t\t\t<Bookmark v-else :size=\"14\" />\n\t\t\t\t\t</div>\n\t\t\t\t\t<div class=\"cn-bookmarks-card__row-main\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\tv-if=\"hasSafeUrl(bookmark)\"\n\t\t\t\t\t\t\t:href=\"bookmark.url\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\tclass=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</a>\n\t\t\t\t\t\t<span v-else class=\"cn-bookmarks-card__title\">{{ bookmarkTitle(bookmark) }}</span>\n\t\t\t\t\t</div>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<div v-if=\"bookmarks.length > COMPACT_LIMIT\" class=\"cn-bookmarks-card__view-all\">\n\t\t\t\t<a\n\t\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noopener noreferrer\">{{ viewAllLabel }}</a>\n\t\t\t</div>\n\t\t</template>\n\t</CnDetailCard>\n</template>\n\n<script>\nimport { translatePlural as n, translate as t } from '@nextcloud/l10n'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport CnDetailCard from '../../../components/CnDetailCard/CnDetailCard.vue'\nimport { buildHeaders, prefixUrl, safeHref } from '../../../utils/index.js'\n\nconst VALID_SURFACES = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity']\nconst COMPACT_LIMIT = 5\n\n/**\n * CnBookmarksCard — bespoke surface-aware widget for the `bookmarks`\n * integration.\n *\n * Renders Bookmarks-aware metadata across all four AD-19 surfaces. See\n * the file-level docblock for surface-by-surface behaviour.\n */\nexport default {\n\tname: 'CnBookmarksCard',\n\n\tcomponents: { CnDetailCard, NcLoadingIcon, Bookmark },\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\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 (AD-19). */\n\t\tsurface: {\n\t\t\ttype: String,\n\t\t\tdefault: 'detail-page',\n\t\t\tvalidator: (s) => VALID_SURFACES.includes(s),\n\t\t},\n\n\t\t/** Optional single-entity reference (bookmark id). */\n\t\tvalue: { type: [String, Number], default: '' },\n\t\t/** Pre-translated card title. */\n\t\ttitle: { type: String, default: () => t('nextcloud-vue', 'Bookmarks') },\n\t\t/** Optional Material Design Icon component. */\n\t\ticon: { type: Object, default: () => Bookmark },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Whether the card body is collapsible. */\n\t\tcollapsible: { type: Boolean, default: true },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated unavailable label. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"view all\" trail-off link label. */\n\t\tviewAllLabel: { type: String, default: () => t('nextcloud-vue', 'View all in Bookmarks') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tCOMPACT_LIMIT,\n\t\t\tbookmarks: [],\n\t\t\tentity: null,\n\t\t\tloading: false,\n\t\t\tdegraded: '',\n\t\t\tbrokenFavicons: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tcardTitle() {\n\t\t\treturn this.title || this.integrationId\n\t\t},\n\n\t\tcardIcon() {\n\t\t\treturn this.icon\n\t\t},\n\n\t\tdisplayedBookmarks() {\n\t\t\treturn this.bookmarks.slice(0, COMPACT_LIMIT)\n\t\t},\n\n\t\tcountHeadline() {\n\t\t\tconst total = this.bookmarks.length\n\t\t\treturn n('nextcloud-vue', '{count} bookmark', '{count} bookmarks', total, { count: total })\n\t\t},\n\n\t\tmostRecent() {\n\t\t\tif (this.bookmarks.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst sorted = [...this.bookmarks].sort((a, b) => {\n\t\t\t\tconst ta = Number(a.added ?? a.addedAt ?? 0)\n\t\t\t\tconst tb = Number(b.added ?? b.addedAt ?? 0)\n\t\t\t\treturn tb - ta\n\t\t\t})\n\t\t\treturn sorted[0]\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler() {\n\t\t\tthis.fetch()\n\t\t} },\n\n\t\tsurface() {\n\t\t\tthis.fetch()\n\t\t},\n\n\t\tvalue() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\t// Bookmark URLs are user-entered (bookmarklets are `javascript:`), so only a safe one is a link.\n\t\thasSafeUrl(bookmark) {\n\t\t\treturn safeHref(bookmark.url) !== '#'\n\t\t},\n\n\t\tchipSubtitle(bookmark) {\n\t\t\treturn bookmark.description || bookmark.url || this.bookmarkTitle(bookmark)\n\t\t},\n\n\t\tfaviconUrl(bookmark) {\n\t\t\tif (!bookmark || this.brokenFavicons[this.bookmarkKey(bookmark)]) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = new URL(bookmark.url)\n\t\t\t\treturn `${url.origin}/favicon.ico`\n\t\t\t} catch {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t},\n\n\t\tonFaviconError(bookmark) {\n\t\t\tthis.brokenFavicons[this.bookmarkKey(bookmark)] = true\n\t\t},\n\n\t\tfetch() {\n\t\t\tif (this.surface === 'single-entity') {\n\t\t\t\tthis.fetchSingle()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.fetchList()\n\t\t},\n\n\t\tasync fetchList() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tthis.bookmarks = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\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('[CnBookmarksCard] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\tasync fetchSingle() {\n\t\t\tif (this.value === '' || this.value === undefined || this.value === null || !this.register || !this.schema || !this.objectId) {\n\t\t\t\tthis.entity = null\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() })\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tthis.entity = await response.json()\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.entity = null\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.entity = null\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('[CnBookmarksCard] failed to fetch single bookmark', err)\n\t\t\t\tthis.entity = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-card__empty {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 0.9em;\n\tpadding: 8px 0;\n}\n\n.cn-bookmarks-card__headline {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n}\n\n.cn-bookmarks-card__headline-line {\n\tfont-size: 1.1em;\n\tcolor: var(--color-main-text);\n}\n\n.cn-bookmarks-card__headline-recent {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 6px;\n\tfont-size: 0.9em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__headline-recent a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 6px;\n\tpadding: 4px 8px;\n\tborder-radius: 12px;\n\tbackground: var(--color-background-hover);\n\tfont-size: 0.9em;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__chip a {\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-card__chip a:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__favicon {\n\twidth: 14px;\n\theight: 14px;\n\tobject-fit: contain;\n\tflex-shrink: 0;\n}\n\n.cn-bookmarks-card__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.cn-bookmarks-card__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-bookmarks-card__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-bookmarks-card__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 16px;\n\theight: 16px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-bookmarks-card__row-main {\n\tflex: 1;\n\tmin-width: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-bookmarks-card__title {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\na.cn-bookmarks-card__title:hover {\n\ttext-decoration: underline;\n}\n\n.cn-bookmarks-card__view-all {\n\tmargin-top: 6px;\n\tfont-size: 0.8em;\n}\n\n/* stylelint-disable-next-line no-descending-specificity */\n.cn-bookmarks-card__view-all a {\n\tcolor: var(--color-primary-element);\n\ttext-decoration: none;\n}\n\n.cn-bookmarks-card__view-all a:hover {\n\ttext-decoration: underline;\n}\n</style>\n"],"names":["_Fragment","_createElementBlock","_createBlock","_toDisplayString","_createElementVNode","_openBlock"],"mappings":"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"}
@@ -236,6 +236,23 @@ var script = {
236
236
  return safeHref(bookmark.url)
237
237
  },
238
238
 
239
+ /**
240
+ * Whether the bookmark's URL passed `safeHref`, so its row is a link.
241
+ *
242
+ * @param {object} bookmark The bookmark row.
243
+ * @return {boolean}
244
+ */
245
+ hasSafeUrl(bookmark) {
246
+ return this.bookmarkHref(bookmark) !== '#'
247
+ },
248
+
249
+ // NcListItem always renders an anchor; one without a safe URL must not follow `#`.
250
+ onBookmarkClick(bookmark, event) {
251
+ if (!this.hasSafeUrl(bookmark)) {
252
+ event?.preventDefault?.();
253
+ }
254
+ },
255
+
239
256
  bookmarkTags(bookmark) {
240
257
  const tags = bookmark.tags;
241
258
  if (!Array.isArray(tags)) {
@@ -1 +1 @@
1
- {"version":3,"file":"CnBookmarksTab.vue2.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksTab.vue"],"sourcesContent":["<!--\n CnBookmarksTab — bespoke sidebar tab for the `bookmarks` integration.\n\n Replaces the generic CnIntegrationTab for the `bookmarks` leaf: renders\n URL preview cards (favicon, title, URL, description snippet, tag chips)\n one per linked bookmark. Talks to the same OpenRegister\n pluggable-integration sub-resource\n `/api/objects/{register}/{schema}/{objectId}/integrations/bookmarks`\n served by `OCA\\OpenRegister\\Service\\Integration\\Providers\\BookmarksProvider`\n (which uses NC Bookmarks' own BookmarkMapper filtered by an `or:{uuid}`\n tag). Payload shape: `{ id, title, url, description, tags, added }`.\n\n Surface behaviour:\n - Empty state with \"Open Bookmarks\" CTA when no linked URLs.\n - Loading + 503 \"currently unavailable\" + generic error states match\n CnIntegrationTab's behaviour for AD-23 graceful degradation.\n - Tag chips above the list filter the displayed rows client-side per\n the integration-bookmarks spec (Tag-Aware Display).\n\n Bespoke-vs-generic rationale: the generic tab renders a flat link list\n which loses the favicon, the description snippet, and the Bookmarks-side\n tags — three signals case-workers rely on to triage which reference is\n relevant. The bespoke tab surfaces them per row.\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), ADR-022 (consumption principle).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-bookmarks-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div class=\"cn-bookmarks-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<LinkVariant :size=\"18\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing bookmark') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton variant=\"primary\" @click=\"openCreate\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"18\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Create new bookmark') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-bookmarks-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-sidebar-tab__empty cn-bookmarks-tab__empty\">\n\t\t\t<Bookmark :size=\"32\" class=\"cn-bookmarks-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\ttarget=\"_blank\"\n\t\t\t\trel=\"noopener noreferrer\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Bookmark :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openBookmarksLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<div v-else>\n\t\t\t<div v-if=\"allTags.length > 0\" class=\"cn-bookmarks-tab__filters\">\n\t\t\t\t<button\n\t\t\t\t\tv-for=\"tag in allTags\"\n\t\t\t\t\t:key=\"tag\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__chip\"\n\t\t\t\t\t:class=\"{ 'cn-bookmarks-tab__chip--active': activeTag === tag }\"\n\t\t\t\t\t@click=\"toggleTagFilter(tag)\">\n\t\t\t\t\t{{ tag }}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\tv-if=\"activeTag\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__chip cn-bookmarks-tab__chip--clear\"\n\t\t\t\t\t@click=\"activeTag = ''\">\n\t\t\t\t\t{{ clearFilterLabel }}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<ul class=\"cn-bookmarks-tab__list\">\n\t\t\t\t<NcListItem\n\t\t\t\t\tv-for=\"bookmark in filteredBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__row\"\n\t\t\t\t\t:name=\"bookmarkTitle(bookmark)\"\n\t\t\t\t\t:bold=\"true\"\n\t\t\t\t\t:href=\"bookmarkHref(bookmark)\"\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t:forceDisplayActions=\"true\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__row-icon\">\n\t\t\t\t\t\t\t<Bookmark :size=\"20\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #subname>\n\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__url\" :title=\"bookmark.url\">\n\t\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__url-text\">{{ displayUrl(bookmark) }}</span>\n\t\t\t\t\t\t\t<OpenInNew :size=\"12\" class=\"cn-bookmarks-tab__url-ext\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #extra>\n\t\t\t\t\t\t<span v-if=\"bookmark.description\" class=\"cn-bookmarks-tab__description\">\n\t\t\t\t\t\t\t{{ bookmark.description }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"bookmarkTags(bookmark).length > 0\" class=\"cn-bookmarks-tab__tags\">\n\t\t\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\t\t\tv-for=\"tag in bookmarkTags(bookmark)\"\n\t\t\t\t\t\t\t\t:key=\"tag\"\n\t\t\t\t\t\t\t\tclass=\"cn-bookmarks-tab__tag\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tvariant=\"info\"\n\t\t\t\t\t\t\t\t:label=\"tag\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #actions>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t:href=\"bookmarkHref(bookmark)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\trel=\"noopener noreferrer\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<OpenInNew :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Open bookmark') }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"unlinkBookmark(bookmark)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<LinkOff :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink bookmark') }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</template>\n\t\t\t\t</NcListItem>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<CnBookmarkPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLinkPick\" />\n\n\t\t<CnBookmarkCreate\n\t\t\tv-if=\"createOpen\"\n\t\t\t@close=\"createOpen = false\"\n\t\t\t@create=\"onCreatePick\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcActionLink, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport LinkOff from 'vue-material-design-icons/LinkOff.vue'\nimport LinkVariant from 'vue-material-design-icons/LinkVariant.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport CnBookmarkCreate from '../../../components/CnBookmarkCreate/CnBookmarkCreate.vue'\nimport CnBookmarkPicker from '../../../components/CnBookmarkPicker/CnBookmarkPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\nimport { safeHref } from '../../../utils/safeHref.js'\n\n/**\n * CnBookmarksTab — bespoke URL preview list for the `bookmarks`\n * integration.\n *\n * Renders rows pulled from the OR pluggable-integration endpoint with\n * favicon, title, URL, description, and Bookmarks-side tag chips. Tag\n * chips at the top filter the visible rows client-side. Tier-2: adds\n * link/create modals and per-row unlink.\n */\nexport default {\n\tname: 'CnBookmarksTab',\n\n\tcomponents: {\n\t\tNcActionButton,\n\t\tNcActionLink,\n\t\tNcButton,\n\t\tNcListItem,\n\t\tNcLoadingIcon,\n\t\tAlertCircleOutline,\n\t\tBookmark,\n\t\tLinkOff,\n\t\tLinkVariant,\n\t\tOpenInNew,\n\t\tPlus,\n\t\tCnBookmarkPicker,\n\t\tCnBookmarkCreate,\n\t\tCnStatusBadge,\n\t},\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated \"Open Bookmarks\" CTA label. */\n\t\topenBookmarksLabel: { type: String, default: () => t('nextcloud-vue', 'Open Bookmarks') },\n\t\t/** Pre-translated banner when Bookmarks is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"Clear filter\" chip label. */\n\t\tclearFilterLabel: { type: String, default: () => t('nextcloud-vue', 'Clear filter') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tbookmarks: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tactiveTag: '',\n\t\t\tpickerOpen: false,\n\t\t\tcreateOpen: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tallTags() {\n\t\t\tconst set = new Set()\n\t\t\tfor (const b of this.bookmarks) {\n\t\t\t\tfor (const tag of this.bookmarkTags(b)) {\n\t\t\t\t\tset.add(tag)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Array.from(set).sort()\n\t\t},\n\n\t\tfilteredBookmarks() {\n\t\t\tif (!this.activeTag) {\n\t\t\t\treturn this.bookmarks\n\t\t\t}\n\t\t\treturn this.bookmarks.filter((b) => this.bookmarkTags(b).includes(this.activeTag))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchBookmarks()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchBookmarks()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchBookmarks()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\t/**\n\t\t * Base for the Tier-2 bookmark endpoints (link/new/destroy).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tbookmarksEndpoint() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/bookmarks`\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\topenCreate() {\n\t\t\tthis.createOpen = true\n\t\t},\n\n\t\tbookmarkId(bookmark) {\n\t\t\treturn bookmark.bookmarkId ?? bookmark.id ?? ''\n\t\t},\n\n\t\tasync onLinkPick(payload) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.bookmarksEndpoint()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'This bookmark is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link bookmark.')\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('[CnBookmarksTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tasync onCreatePick(payload) {\n\t\t\tthis.createOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.bookmarksEndpoint()}/new`), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not create bookmark.')\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('[CnBookmarksTab] create failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not create bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tasync unlinkBookmark(bookmark) {\n\t\t\tconst id = this.bookmarkId(bookmark)\n\t\t\tif (!id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.bookmarksEndpoint()}/${id}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink bookmark.')\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('[CnBookmarksTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\t/**\n\t\t * Host (+ path) of the bookmark URL for the subline — drops the\n\t\t * scheme and trailing slash so the row reads like NC Bookmarks\n\t\t * (\"example.com/spec\" rather than \"https://example.com/spec/\").\n\t\t * Falls back to the raw URL when it cannot be parsed.\n\t\t *\n\t\t * @param {object} bookmark Bookmark row.\n\t\t * @return {string} Display URL.\n\t\t */\n\t\tdisplayUrl(bookmark) {\n\t\t\tconst raw = bookmark.url || ''\n\t\t\ttry {\n\t\t\t\tconst url = new URL(raw)\n\t\t\t\tconst path = url.pathname === '/' ? '' : url.pathname.replace(/\\/$/, '')\n\t\t\t\treturn `${url.host}${path}${url.search}`\n\t\t\t} catch {\n\t\t\t\treturn raw\n\t\t\t}\n\t\t},\n\n\t\t// Bookmark URLs are user data; block javascript:/data: schemes.\n\t\tbookmarkHref(bookmark) {\n\t\t\treturn safeHref(bookmark.url)\n\t\t},\n\n\t\tbookmarkTags(bookmark) {\n\t\t\tconst tags = bookmark.tags\n\t\t\tif (!Array.isArray(tags)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn tags.filter((tag) => typeof tag === 'string' && tag !== '' && !tag.startsWith('or:'))\n\t\t},\n\n\t\ttoggleTagFilter(tag) {\n\t\t\tthis.activeTag = this.activeTag === tag ? '' : tag\n\t\t},\n\n\t\tasync fetchBookmarks() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { 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 rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.bookmarks = rows\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load bookmarks.')\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('[CnBookmarksTab] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load bookmarks.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-tab__actions {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-bookmarks-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-bookmarks-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-bookmarks-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-bookmarks-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__filters {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n\tmargin-bottom: 10px;\n}\n\n.cn-bookmarks-tab__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tpadding: 3px 10px;\n\tborder-radius: 12px;\n\tborder: 1px solid var(--color-border);\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.8em;\n\tcursor: pointer;\n}\n\n.cn-bookmarks-tab__chip:hover {\n\tbackground: var(--color-background-darker, var(--color-background-hover));\n}\n\n.cn-bookmarks-tab__chip--active {\n\tbackground: var(--color-primary-element);\n\tcolor: var(--color-primary-element-text);\n\tborder-color: var(--color-primary-element);\n}\n\n.cn-bookmarks-tab__chip--clear {\n\tfont-style: italic;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n/* Favicon / fallback glyph rendered inside NcListItem's #icon slot,\n sized like a real NC Bookmarks site icon. */\n.cn-bookmarks-tab__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 32px;\n\theight: 32px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-background-hover);\n}\n\n/* Truncated URL subline with a trailing external-link affordance. */\n.cn-bookmarks-tab__url {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 3px;\n\tmax-width: 100%;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__url-text {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-tab__url-ext {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__description {\n\tdisplay: -webkit-box;\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\t-webkit-line-clamp: 1;\n\t-webkit-box-orient: vertical;\n}\n\n.cn-bookmarks-tab__tags {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n\tmargin-top: 2px;\n}\n</style>\n"],"names":["CnBookmarkPicker","CnBookmarkCreate","CnStatusBadge","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnBookmarksTab.vue2.js","sources":["../../../../../src/integrations/builtin/bookmarks/CnBookmarksTab.vue"],"sourcesContent":["<!--\n CnBookmarksTab — bespoke sidebar tab for the `bookmarks` integration.\n\n Replaces the generic CnIntegrationTab for the `bookmarks` leaf: renders\n URL preview cards (favicon, title, URL, description snippet, tag chips)\n one per linked bookmark. Talks to the same OpenRegister\n pluggable-integration sub-resource\n `/api/objects/{register}/{schema}/{objectId}/integrations/bookmarks`\n served by `OCA\\OpenRegister\\Service\\Integration\\Providers\\BookmarksProvider`\n (which uses NC Bookmarks' own BookmarkMapper filtered by an `or:{uuid}`\n tag). Payload shape: `{ id, title, url, description, tags, added }`.\n\n Surface behaviour:\n - Empty state with \"Open Bookmarks\" CTA when no linked URLs.\n - Loading + 503 \"currently unavailable\" + generic error states match\n CnIntegrationTab's behaviour for AD-23 graceful degradation.\n - Tag chips above the list filter the displayed rows client-side per\n the integration-bookmarks spec (Tag-Aware Display).\n\n Bespoke-vs-generic rationale: the generic tab renders a flat link list\n which loses the favicon, the description snippet, and the Bookmarks-side\n tags — three signals case-workers rely on to triage which reference is\n relevant. The bespoke tab surfaces them per row.\n\n See `openregister/openspec/changes/integration-bookmarks/` for the spec\n delta and ADR-019 (registry mechanism), ADR-022 (consumption principle).\n-->\n<template>\n\t<div class=\"cn-sidebar-tab cn-bookmarks-tab\">\n\t\t<div v-if=\"degraded\" class=\"cn-bookmarks-tab__banner\" role=\"alert\">\n\t\t\t<AlertCircleOutline :size=\"18\" />\n\t\t\t<span>{{ degraded }}</span>\n\t\t</div>\n\n\t\t<div class=\"cn-bookmarks-tab__actions\">\n\t\t\t<NcButton variant=\"secondary\" @click=\"openPicker\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<LinkVariant :size=\"18\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Link existing bookmark') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton variant=\"primary\" @click=\"openCreate\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Plus :size=\"18\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Create new bookmark') }}\n\t\t\t</NcButton>\n\t\t</div>\n\n\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t<div v-else-if=\"error\" class=\"cn-bookmarks-tab__error\" role=\"alert\">\n\t\t\t{{ error }}\n\t\t</div>\n\t\t<div v-else-if=\"bookmarks.length === 0\" class=\"cn-sidebar-tab__empty cn-bookmarks-tab__empty\">\n\t\t\t<Bookmark :size=\"32\" class=\"cn-bookmarks-tab__empty-icon\" />\n\t\t\t<p>{{ emptyLabel }}</p>\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:href=\"bookmarksAppUrl\"\n\t\t\t\ttarget=\"_blank\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Bookmark :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ openBookmarksLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t\t<div v-else>\n\t\t\t<div v-if=\"allTags.length > 0\" class=\"cn-bookmarks-tab__filters\">\n\t\t\t\t<button\n\t\t\t\t\tv-for=\"tag in allTags\"\n\t\t\t\t\t:key=\"tag\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__chip\"\n\t\t\t\t\t:class=\"{ 'cn-bookmarks-tab__chip--active': activeTag === tag }\"\n\t\t\t\t\t@click=\"toggleTagFilter(tag)\">\n\t\t\t\t\t{{ tag }}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\tv-if=\"activeTag\"\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__chip cn-bookmarks-tab__chip--clear\"\n\t\t\t\t\t@click=\"activeTag = ''\">\n\t\t\t\t\t{{ clearFilterLabel }}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<ul class=\"cn-bookmarks-tab__list\">\n\t\t\t\t<NcListItem\n\t\t\t\t\tv-for=\"bookmark in filteredBookmarks\"\n\t\t\t\t\t:key=\"bookmarkKey(bookmark)\"\n\t\t\t\t\tclass=\"cn-bookmarks-tab__row\"\n\t\t\t\t\t:name=\"bookmarkTitle(bookmark)\"\n\t\t\t\t\t:bold=\"true\"\n\t\t\t\t\t:href=\"bookmarkHref(bookmark)\"\n\t\t\t\t\t:target=\"hasSafeUrl(bookmark) ? '_blank' : undefined\"\n\t\t\t\t\t:forceDisplayActions=\"true\"\n\t\t\t\t\t@click=\"onBookmarkClick(bookmark, $event)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__row-icon\">\n\t\t\t\t\t\t\t<Bookmark :size=\"20\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #subname>\n\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__url\" :title=\"bookmark.url\">\n\t\t\t\t\t\t\t<span class=\"cn-bookmarks-tab__url-text\">{{ displayUrl(bookmark) }}</span>\n\t\t\t\t\t\t\t<OpenInNew :size=\"12\" class=\"cn-bookmarks-tab__url-ext\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #extra>\n\t\t\t\t\t\t<span v-if=\"bookmark.description\" class=\"cn-bookmarks-tab__description\">\n\t\t\t\t\t\t\t{{ bookmark.description }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<span v-if=\"bookmarkTags(bookmark).length > 0\" class=\"cn-bookmarks-tab__tags\">\n\t\t\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\t\t\tv-for=\"tag in bookmarkTags(bookmark)\"\n\t\t\t\t\t\t\t\t:key=\"tag\"\n\t\t\t\t\t\t\t\tclass=\"cn-bookmarks-tab__tag\"\n\t\t\t\t\t\t\t\tsize=\"small\"\n\t\t\t\t\t\t\t\tvariant=\"info\"\n\t\t\t\t\t\t\t\t:label=\"tag\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #actions>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"hasSafeUrl(bookmark)\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t:href=\"bookmarkHref(bookmark)\"\n\t\t\t\t\t\t\ttarget=\"_blank\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<OpenInNew :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Open bookmark') }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"unlinkBookmark(bookmark)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<LinkOff :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'Unlink bookmark') }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</template>\n\t\t\t\t</NcListItem>\n\t\t\t</ul>\n\t\t</div>\n\n\t\t<CnBookmarkPicker\n\t\t\tv-if=\"pickerOpen\"\n\t\t\t:apiBase=\"apiBase\"\n\t\t\t@close=\"pickerOpen = false\"\n\t\t\t@link=\"onLinkPick\" />\n\n\t\t<CnBookmarkCreate\n\t\t\tv-if=\"createOpen\"\n\t\t\t@close=\"createOpen = false\"\n\t\t\t@create=\"onCreatePick\" />\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcActionButton, NcActionLink, NcButton, NcListItem, NcLoadingIcon } from '@nextcloud/vue'\nimport AlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'\nimport Bookmark from 'vue-material-design-icons/Bookmark.vue'\nimport LinkOff from 'vue-material-design-icons/LinkOff.vue'\nimport LinkVariant from 'vue-material-design-icons/LinkVariant.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Plus from 'vue-material-design-icons/Plus.vue'\nimport CnBookmarkCreate from '../../../components/CnBookmarkCreate/CnBookmarkCreate.vue'\nimport CnBookmarkPicker from '../../../components/CnBookmarkPicker/CnBookmarkPicker.vue'\nimport CnStatusBadge from '../../../components/CnStatusBadge/CnStatusBadge.vue'\nimport { buildHeaders, prefixUrl } from '../../../utils/index.js'\nimport { safeHref } from '../../../utils/safeHref.js'\n\n/**\n * CnBookmarksTab — bespoke URL preview list for the `bookmarks`\n * integration.\n *\n * Renders rows pulled from the OR pluggable-integration endpoint with\n * favicon, title, URL, description, and Bookmarks-side tag chips. Tag\n * chips at the top filter the visible rows client-side. Tier-2: adds\n * link/create modals and per-row unlink.\n */\nexport default {\n\tname: 'CnBookmarksTab',\n\n\tcomponents: {\n\t\tNcActionButton,\n\t\tNcActionLink,\n\t\tNcButton,\n\t\tNcListItem,\n\t\tNcLoadingIcon,\n\t\tAlertCircleOutline,\n\t\tBookmark,\n\t\tLinkOff,\n\t\tLinkVariant,\n\t\tOpenInNew,\n\t\tPlus,\n\t\tCnBookmarkPicker,\n\t\tCnBookmarkCreate,\n\t\tCnStatusBadge,\n\t},\n\n\tprops: {\n\t\t/** Stable integration id (forwarded from the registry — always `'bookmarks'`). */\n\t\tintegrationId: { type: String, default: 'bookmarks' },\n\t\t/** Parent object id. */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register id (slug or uuid). */\n\t\tregister: { type: String, default: '' },\n\t\t/** OpenRegister schema id (slug or uuid). */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base API URL. */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Pre-translated empty-state label. */\n\t\temptyLabel: { type: String, default: () => t('nextcloud-vue', 'No bookmarks linked yet') },\n\t\t/** Pre-translated \"Open Bookmarks\" CTA label. */\n\t\topenBookmarksLabel: { type: String, default: () => t('nextcloud-vue', 'Open Bookmarks') },\n\t\t/** Pre-translated banner when Bookmarks is unavailable. */\n\t\tunavailableLabel: { type: String, default: () => t('nextcloud-vue', 'NC Bookmarks is currently unavailable.') },\n\t\t/** Pre-translated \"Clear filter\" chip label. */\n\t\tclearFilterLabel: { type: String, default: () => t('nextcloud-vue', 'Clear filter') },\n\t\t/** URL of the NC Bookmarks app entry. */\n\t\tbookmarksAppUrl: { type: String, default: '/index.php/apps/bookmarks' },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tbookmarks: [],\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t\tdegraded: '',\n\t\t\tactiveTag: '',\n\t\t\tpickerOpen: false,\n\t\t\tcreateOpen: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tallTags() {\n\t\t\tconst set = new Set()\n\t\t\tfor (const b of this.bookmarks) {\n\t\t\t\tfor (const tag of this.bookmarkTags(b)) {\n\t\t\t\t\tset.add(tag)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Array.from(set).sort()\n\t\t},\n\n\t\tfilteredBookmarks() {\n\t\t\tif (!this.activeTag) {\n\t\t\t\treturn this.bookmarks\n\t\t\t}\n\t\t\treturn this.bookmarks.filter((b) => this.bookmarkTags(b).includes(this.activeTag))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectId: { immediate: true, handler(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.fetchBookmarks()\n\t\t\t}\n\t\t} },\n\n\t\tregister() {\n\t\t\tthis.fetchBookmarks()\n\t\t},\n\n\t\tschema() {\n\t\t\tthis.fetchBookmarks()\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\tbaseUrl() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`\n\t\t},\n\n\t\t/**\n\t\t * Base for the Tier-2 bookmark endpoints (link/new/destroy).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tbookmarksEndpoint() {\n\t\t\treturn `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/bookmarks`\n\t\t},\n\n\t\topenPicker() {\n\t\t\tthis.pickerOpen = true\n\t\t},\n\n\t\topenCreate() {\n\t\t\tthis.createOpen = true\n\t\t},\n\n\t\tbookmarkId(bookmark) {\n\t\t\treturn bookmark.bookmarkId ?? bookmark.id ?? ''\n\t\t},\n\n\t\tasync onLinkPick(payload) {\n\t\t\tthis.pickerOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.bookmarksEndpoint()), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else if (response.status === 409) {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'This bookmark is already linked.')\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link bookmark.')\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('[CnBookmarksTab] link failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not link bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tasync onCreatePick(payload) {\n\t\t\tthis.createOpen = false\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.bookmarksEndpoint()}/new`), {\n\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\theaders: { ...buildHeaders(), 'Content-Type': 'application/json' },\n\t\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not create bookmark.')\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('[CnBookmarksTab] create failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not create bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tasync unlinkBookmark(bookmark) {\n\t\t\tconst id = this.bookmarkId(bookmark)\n\t\t\tif (!id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(`${this.bookmarksEndpoint()}/${id}`), {\n\t\t\t\t\tmethod: 'DELETE',\n\t\t\t\t\theaders: buildHeaders(),\n\t\t\t\t})\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tawait this.fetchBookmarks()\n\t\t\t\t} else {\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink bookmark.')\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('[CnBookmarksTab] unlink failed', err)\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not unlink bookmark.')\n\t\t\t}\n\t\t},\n\n\t\tbookmarkKey(bookmark) {\n\t\t\treturn bookmark.id ?? bookmark.url ?? ''\n\t\t},\n\n\t\tbookmarkTitle(bookmark) {\n\t\t\treturn bookmark.title || bookmark.url || ''\n\t\t},\n\n\t\t/**\n\t\t * Host (+ path) of the bookmark URL for the subline — drops the\n\t\t * scheme and trailing slash so the row reads like NC Bookmarks\n\t\t * (\"example.com/spec\" rather than \"https://example.com/spec/\").\n\t\t * Falls back to the raw URL when it cannot be parsed.\n\t\t *\n\t\t * @param {object} bookmark Bookmark row.\n\t\t * @return {string} Display URL.\n\t\t */\n\t\tdisplayUrl(bookmark) {\n\t\t\tconst raw = bookmark.url || ''\n\t\t\ttry {\n\t\t\t\tconst url = new URL(raw)\n\t\t\t\tconst path = url.pathname === '/' ? '' : url.pathname.replace(/\\/$/, '')\n\t\t\t\treturn `${url.host}${path}${url.search}`\n\t\t\t} catch {\n\t\t\t\treturn raw\n\t\t\t}\n\t\t},\n\n\t\t// Bookmark URLs are user data; block javascript:/data: schemes.\n\t\tbookmarkHref(bookmark) {\n\t\t\treturn safeHref(bookmark.url)\n\t\t},\n\n\t\t/**\n\t\t * Whether the bookmark's URL passed `safeHref`, so its row is a link.\n\t\t *\n\t\t * @param {object} bookmark The bookmark row.\n\t\t * @return {boolean}\n\t\t */\n\t\thasSafeUrl(bookmark) {\n\t\t\treturn this.bookmarkHref(bookmark) !== '#'\n\t\t},\n\n\t\t// NcListItem always renders an anchor; one without a safe URL must not follow `#`.\n\t\tonBookmarkClick(bookmark, event) {\n\t\t\tif (!this.hasSafeUrl(bookmark)) {\n\t\t\t\tevent?.preventDefault?.()\n\t\t\t}\n\t\t},\n\n\t\tbookmarkTags(bookmark) {\n\t\t\tconst tags = bookmark.tags\n\t\t\tif (!Array.isArray(tags)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn tags.filter((tag) => typeof tag === 'string' && tag !== '' && !tag.startsWith('or:'))\n\t\t},\n\n\t\ttoggleTagFilter(tag) {\n\t\t\tthis.activeTag = this.activeTag === tag ? '' : tag\n\t\t},\n\n\t\tasync fetchBookmarks() {\n\t\t\tif (!this.register || !this.schema || !this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\tthis.degraded = ''\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(prefixUrl(this.baseUrl()), { 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 rows = data.results || data.items || (Array.isArray(data) ? data : []) || []\n\t\t\t\t\tthis.bookmarks = rows\n\t\t\t\t} else if (response.status === 503) {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.degraded = this.unavailableLabel\n\t\t\t\t} else {\n\t\t\t\t\tthis.bookmarks = []\n\t\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load bookmarks.')\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('[CnBookmarksTab] failed to fetch bookmarks', err)\n\t\t\t\tthis.bookmarks = []\n\t\t\t\tthis.error = t('nextcloud-vue', 'Could not load bookmarks.')\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-bookmarks-tab__actions {\n\tdisplay: flex;\n\tgap: 8px;\n\tmargin-bottom: 8px;\n\tflex-wrap: wrap;\n}\n\n.cn-bookmarks-tab__banner {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 8px 10px;\n\tmargin-bottom: 10px;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-warning, #e9a40f);\n\tcolor: var(--color-main-background);\n\tfont-size: 0.9em;\n}\n\n.cn-bookmarks-tab__error {\n\tcolor: var(--color-error);\n\tfont-size: 0.9em;\n\tmargin: 4px 0 8px;\n}\n\n.cn-bookmarks-tab__empty {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 16px 8px;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-align: center;\n}\n\n.cn-bookmarks-tab__empty-icon {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__filters {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 6px;\n\tmargin-bottom: 10px;\n}\n\n.cn-bookmarks-tab__chip {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tpadding: 3px 10px;\n\tborder-radius: 12px;\n\tborder: 1px solid var(--color-border);\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n\tfont-size: 0.8em;\n\tcursor: pointer;\n}\n\n.cn-bookmarks-tab__chip:hover {\n\tbackground: var(--color-background-darker, var(--color-background-hover));\n}\n\n.cn-bookmarks-tab__chip--active {\n\tbackground: var(--color-primary-element);\n\tcolor: var(--color-primary-element-text);\n\tborder-color: var(--color-primary-element);\n}\n\n.cn-bookmarks-tab__chip--clear {\n\tfont-style: italic;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n/* Favicon / fallback glyph rendered inside NcListItem's #icon slot,\n sized like a real NC Bookmarks site icon. */\n.cn-bookmarks-tab__row-icon {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n\twidth: 32px;\n\theight: 32px;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tborder-radius: var(--border-radius);\n\tbackground: var(--color-background-hover);\n}\n\n/* Truncated URL subline with a trailing external-link affordance. */\n.cn-bookmarks-tab__url {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 3px;\n\tmax-width: 100%;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__url-text {\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-bookmarks-tab__url-ext {\n\tflex-shrink: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-bookmarks-tab__description {\n\tdisplay: -webkit-box;\n\tfont-size: 0.85em;\n\tcolor: var(--color-text-maxcontrast);\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\t-webkit-line-clamp: 1;\n\t-webkit-box-orient: vertical;\n}\n\n.cn-bookmarks-tab__tags {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 4px;\n\tmargin-top: 2px;\n}\n</style>\n"],"names":["CnBookmarkPicker","CnBookmarkCreate","CnStatusBadge","t"],"mappings":"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"}