@conduction/nextcloud-vue 2.92.0 → 2.94.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js +1 -1
  2. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +2 -1
  4. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  6. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +28 -8
  7. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +37 -2
  9. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +57 -4
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +44 -17
  13. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  14. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
  15. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +44 -2
  16. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
  17. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +140 -59
  18. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
  20. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +139 -3
  21. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
  22. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js +60 -12
  23. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
  24. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  25. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +111 -42
  26. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  27. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +117 -73
  28. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  29. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +34 -39
  30. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  31. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +7 -7
  32. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +5 -3
  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/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  37. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +6 -4
  38. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  39. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  40. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js +46 -0
  41. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js.map +1 -1
  42. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue3.js +6 -2
  43. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue3.js.map +1 -1
  44. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
  45. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +82 -9
  46. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
  47. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js +104 -90
  48. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
  49. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +9 -0
  50. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js.map +1 -0
  51. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +355 -0
  52. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -0
  53. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +462 -0
  54. package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -0
  55. package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
  56. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +21 -0
  57. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  58. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +402 -391
  59. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  60. package/dist/esm/components/CnIcon/semanticIcons.js +2 -2
  61. package/dist/esm/components/CnIcon/semanticIcons.js.map +1 -1
  62. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +141 -7
  63. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  64. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +5 -2
  65. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  66. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
  67. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +22 -1
  68. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
  69. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +20 -14
  70. package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
  71. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue.js +1 -1
  72. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue2.js +2 -0
  73. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue2.js.map +1 -1
  74. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue3.js +15 -5
  75. package/dist/esm/components/CnNotificationPreferences/CnNotificationPreferences.vue3.js.map +1 -1
  76. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue.js +8 -0
  77. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue.js.map +1 -0
  78. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js +114 -0
  79. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js.map +1 -0
  80. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue3.js +45 -0
  81. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue3.js.map +1 -0
  82. package/dist/esm/components/CnPageHeader/CnPageHeader.vue2.js +38 -2
  83. package/dist/esm/components/CnPageHeader/CnPageHeader.vue2.js.map +1 -1
  84. package/dist/esm/components/CnPageHeader/CnPageHeader.vue3.js +12 -2
  85. package/dist/esm/components/CnPageHeader/CnPageHeader.vue3.js.map +1 -1
  86. package/dist/esm/components/CnPagination/CnPagination.vue2.js.map +1 -1
  87. package/dist/esm/components/CnPagination/CnPagination.vue3.js +56 -51
  88. package/dist/esm/components/CnPagination/CnPagination.vue3.js.map +1 -1
  89. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  90. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +3 -3
  91. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  92. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  93. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue.js +1 -1
  94. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue2.js +8 -30
  95. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue2.js.map +1 -1
  96. package/dist/esm/components/CnRoadmapTab/CnRoadmapTab.vue3.js.map +1 -1
  97. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  98. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +24 -0
  99. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  100. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +3 -1
  101. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  102. package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
  103. package/dist/esm/components/CnTabs/CnTabs.vue2.js +39 -2
  104. package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
  105. package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
  106. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  107. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +85 -8
  108. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  109. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +37 -9
  110. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  111. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +9 -0
  112. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js.map +1 -0
  113. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js +164 -0
  114. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -0
  115. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js +93 -0
  116. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -0
  117. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
  118. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
  119. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -3
  120. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
  121. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  122. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +32 -0
  123. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  124. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +31 -20
  125. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  126. package/dist/esm/composables/indexSources.js +9 -0
  127. package/dist/esm/composables/indexSources.js.map +1 -1
  128. package/dist/esm/l10n/en.json.js +24 -1
  129. package/dist/esm/l10n/en.json.js.map +1 -1
  130. package/dist/esm/l10n/nl.json.js +24 -1
  131. package/dist/esm/l10n/nl.json.js.map +1 -1
  132. package/dist/esm/library-style.js +1 -1
  133. package/dist/esm/nextcloud-vue.css +1190 -410
  134. package/dist/esm/utils/dueText.js +49 -8
  135. package/dist/esm/utils/dueText.js.map +1 -1
  136. package/dist/esm/utils/featureCatalog.js +135 -0
  137. package/dist/esm/utils/featureCatalog.js.map +1 -0
  138. package/dist/esm/utils/fillTemplate.js +74 -3
  139. package/dist/esm/utils/fillTemplate.js.map +1 -1
  140. package/dist/esm/utils/headerMeta.js +62 -12
  141. package/dist/esm/utils/headerMeta.js.map +1 -1
  142. package/dist/esm/utils/roadmapIssues.js +86 -0
  143. package/dist/esm/utils/roadmapIssues.js.map +1 -0
  144. package/dist/esm/utils/userDisplayName.js +47 -0
  145. package/dist/esm/utils/userDisplayName.js.map +1 -0
  146. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  147. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  148. package/dist/nextcloud-vue.cjs.js +16229 -13423
  149. package/dist/nextcloud-vue.cjs.js.map +2 -2
  150. package/dist/nextcloud-vue.css +1190 -410
  151. package/l10n/en.json +24 -1
  152. package/l10n/nl.json +24 -1
  153. package/package.json +1 -1
  154. package/src/components/CnActionsMenu/CnActionsMenu.vue +3 -1
  155. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +39 -1
  156. package/src/components/CnAppRoot/CnAppRoot.md +2 -0
  157. package/src/components/CnAppRoot/CnAppRoot.vue +66 -5
  158. package/src/components/CnChoiceCards/CnChoiceCards.md +27 -0
  159. package/src/components/CnChoiceCards/CnChoiceCards.vue +168 -3
  160. package/src/components/CnCountdownWidget/CnCountdownWidget.vue +222 -6
  161. package/src/components/CnDashboardPage/CnDashboardPage.vue +141 -8
  162. package/src/components/CnDataTable/CnDataTable.md +1 -0
  163. package/src/components/CnDataTable/CnDataTable.vue +41 -46
  164. package/src/components/CnDetailPage/CnDetailPage.vue +5 -3
  165. package/src/components/CnFactsWidget/CnFactsWidget.vue +6 -4
  166. package/src/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue +51 -1
  167. package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +98 -13
  168. package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +1053 -0
  169. package/src/components/CnFormDialog/CnFormDialog.vue +606 -562
  170. package/src/components/CnIndexPage/CnIndexPage.vue +144 -7
  171. package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +23 -2
  172. package/src/components/CnNotificationPreferences/CnNotificationPreferences.vue +5 -0
  173. package/src/components/CnPageHeader/CnHeaderTrail.vue +140 -0
  174. package/src/components/CnPageHeader/CnPageHeader.md +11 -0
  175. package/src/components/CnPageHeader/CnPageHeader.vue +42 -0
  176. package/src/components/CnPagination/CnPagination.vue +10 -2
  177. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +3 -3
  178. package/src/components/CnRoadmapTab/CnRoadmapTab.vue +6 -28
  179. package/src/components/CnSettingsPage/CnSettingsPage.vue +26 -0
  180. package/src/components/CnTabs/CnTabs.vue +39 -2
  181. package/src/components/CnTabsWidget/CnTabsWidget.vue +106 -13
  182. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +305 -0
  183. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +4 -3
  184. package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +8 -0
  185. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +43 -2
  186. package/src/composables/indexSources.js +9 -0
  187. package/src/css/dialog.css +61 -0
  188. package/src/css/look-board-detail.css +8 -0
  189. package/src/css/look-board-index.css +27 -1
  190. package/src/css/look-board.css +60 -0
  191. package/src/css/page-header.css +16 -0
  192. package/src/schemas/app-manifest-v2.schema.json +30 -17
  193. package/src/utils/dueText.js +49 -8
  194. package/src/utils/featureCatalog.js +132 -0
  195. package/src/utils/fillTemplate.js +73 -2
  196. package/src/utils/headerMeta.js +62 -12
  197. package/src/utils/roadmapIssues.js +82 -0
  198. package/src/utils/userDisplayName.js +54 -0
  199. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -0,0 +1,93 @@
1
+ import { resolveComponent, openBlock, createBlock, normalizeStyle, withCtx, createElementVNode, toDisplayString, createVNode, createTextVNode, createElementBlock, Fragment, renderList, normalizeClass, withModifiers, createCommentVNode, renderSlot } from 'vue';
2
+
3
+ const _hoisted_1 = { class: "cn-user-settings-dialog__body" };
4
+ const _hoisted_2 = ["aria-label"];
5
+ const _hoisted_3 = ["href", "aria-current", "data-testid", "onClick"];
6
+ const _hoisted_4 = {
7
+ key: 0,
8
+ class: "cn-user-settings-dialog__nav-icon",
9
+ "aria-hidden": "true"
10
+ };
11
+ const _hoisted_5 = { class: "cn-user-settings-dialog__sections" };
12
+ const _hoisted_6 = {
13
+ class: "cn-user-settings-dialog__note",
14
+ "data-testid": "cn-user-settings-note"
15
+ };
16
+
17
+ function render(_ctx, _cache, $props, $setup, $data, $options) {
18
+ const _component_CnVNodes = resolveComponent("CnVNodes");
19
+ const _component_NcButton = resolveComponent("NcButton");
20
+ const _component_CnDialog = resolveComponent("CnDialog");
21
+
22
+ return (openBlock(), createBlock(_component_CnDialog, {
23
+ class: "cn-user-settings-dialog",
24
+ name: $props.title,
25
+ look: "board",
26
+ width: "wizard",
27
+ eyebrow: $props.eyebrow,
28
+ subtitle: $props.subtitle,
29
+ open: $props.open,
30
+ style: normalizeStyle($options.eyebrowStyle),
31
+ "data-testid": "cn-user-settings-dialog",
32
+ "onUpdate:open": $options.onUpdateOpen,
33
+ onClosing: $options.close
34
+ }, {
35
+ actions: withCtx(() => [
36
+ createElementVNode("p", _hoisted_6, toDisplayString($options.footerNote), 1 /* TEXT */),
37
+ createVNode(_component_NcButton, {
38
+ variant: "secondary",
39
+ "data-testid": "cn-user-settings-close",
40
+ onClick: $options.close
41
+ }, {
42
+ default: withCtx(() => [
43
+ createTextVNode(toDisplayString($options.closeLabel), 1 /* TEXT */)
44
+ ]),
45
+ _: 1 /* STABLE */
46
+ }, 8 /* PROPS */, ["onClick"])
47
+ ]),
48
+ default: withCtx(() => [
49
+ createElementVNode("div", _hoisted_1, [
50
+ ($data.sections.length > 0)
51
+ ? (openBlock(), createElementBlock("nav", {
52
+ key: 0,
53
+ class: "cn-user-settings-dialog__nav",
54
+ "aria-label": $options.navLabel,
55
+ "data-testid": "cn-user-settings-nav"
56
+ }, [
57
+ createElementVNode("ul", null, [
58
+ (openBlock(true), createElementBlock(Fragment, null, renderList($data.sections, (section) => {
59
+ return (openBlock(), createElementBlock("li", {
60
+ key: section.id
61
+ }, [
62
+ createElementVNode("a", {
63
+ href: `#settings-section_${section.id}`,
64
+ class: normalizeClass(["cn-user-settings-dialog__nav-link", { 'cn-user-settings-dialog__nav-link--active': section.id === $data.selected }]),
65
+ "aria-current": section.id === $data.selected ? 'true' : undefined,
66
+ "data-testid": `cn-user-settings-nav-${section.id}`,
67
+ onClick: withModifiers($event => ($options.selectSection(section.id)), ["prevent"])
68
+ }, [
69
+ (section.icon)
70
+ ? (openBlock(), createElementBlock("span", _hoisted_4, [
71
+ createVNode(_component_CnVNodes, {
72
+ vnodes: section.icon
73
+ }, null, 8 /* PROPS */, ["vnodes"])
74
+ ]))
75
+ : createCommentVNode("v-if", true),
76
+ createElementVNode("span", null, toDisplayString(section.name), 1 /* TEXT */)
77
+ ], 10 /* CLASS, PROPS */, _hoisted_3)
78
+ ]))
79
+ }), 128 /* KEYED_FRAGMENT */))
80
+ ])
81
+ ], 8 /* PROPS */, _hoisted_2))
82
+ : createCommentVNode("v-if", true),
83
+ createElementVNode("div", _hoisted_5, [
84
+ renderSlot(_ctx.$slots, "default")
85
+ ])
86
+ ])
87
+ ]),
88
+ _: 3 /* FORWARDED */
89
+ }, 8 /* PROPS */, ["name", "eyebrow", "subtitle", "open", "style", "onUpdate:open", "onClosing"]))
90
+ }
91
+
92
+ export { render };
93
+ //# sourceMappingURL=CnUserSettingsDialog.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnUserSettingsDialog.vue3.js","sources":["../../../../src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue?vue&type=template&id=8ebfd3c8&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\tclass=\"cn-user-settings-dialog\"\n\t\t:name=\"title\"\n\t\tlook=\"board\"\n\t\twidth=\"wizard\"\n\t\t:eyebrow=\"eyebrow\"\n\t\t:subtitle=\"subtitle\"\n\t\t:open=\"open\"\n\t\t:style=\"eyebrowStyle\"\n\t\tdata-testid=\"cn-user-settings-dialog\"\n\t\t@update:open=\"onUpdateOpen\"\n\t\t@closing=\"close\">\n\t\t<div class=\"cn-user-settings-dialog__body\">\n\t\t\t<nav\n\t\t\t\tv-if=\"sections.length > 0\"\n\t\t\t\tclass=\"cn-user-settings-dialog__nav\"\n\t\t\t\t:aria-label=\"navLabel\"\n\t\t\t\tdata-testid=\"cn-user-settings-nav\">\n\t\t\t\t<ul>\n\t\t\t\t\t<li v-for=\"section in sections\" :key=\"section.id\">\n\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t:href=\"`#settings-section_${section.id}`\"\n\t\t\t\t\t\t\tclass=\"cn-user-settings-dialog__nav-link\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-user-settings-dialog__nav-link--active': section.id === selected }\"\n\t\t\t\t\t\t\t:aria-current=\"section.id === selected ? 'true' : undefined\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-user-settings-nav-${section.id}`\"\n\t\t\t\t\t\t\t@click.prevent=\"selectSection(section.id)\">\n\t\t\t\t\t\t\t<span v-if=\"section.icon\" class=\"cn-user-settings-dialog__nav-icon\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<CnVNodes :vnodes=\"section.icon\" />\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span>{{ section.name }}</span>\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</nav>\n\t\t\t<div class=\"cn-user-settings-dialog__sections\">\n\t\t\t\t<!-- @slot default NcAppSettingsSection children; each registers itself in the navigation. -->\n\t\t\t\t<slot />\n\t\t\t</div>\n\t\t</div>\n\t\t<template #actions>\n\t\t\t<p class=\"cn-user-settings-dialog__note\" data-testid=\"cn-user-settings-note\">\n\t\t\t\t{{ footerNote }}\n\t\t\t</p>\n\t\t\t<NcButton variant=\"secondary\" data-testid=\"cn-user-settings-close\" @click=\"close\">\n\t\t\t\t{{ closeLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton } from '@nextcloud/vue'\nimport { markRaw } from 'vue'\nimport CnDialog from '../CnDialog/CnDialog.vue'\n\n/**\n * The key NcAppSettingsSection injects to register itself with its dialog\n * (`Symbol.for`, so the same symbol `@nextcloud/vue` provides).\n */\nconst REGISTRATION_KEY = Symbol.for('NcAppSettingsDialog:registration')\n\n/** Renders a section's icon vnodes as they were registered. */\nconst CnVNodes = {\n\tname: 'CnVNodes',\n\tprops: { vnodes: { type: [Array, Object], default: null } },\n\trender() {\n\t\treturn this.vnodes\n\t},\n}\n\n/**\n * CnUserSettingsDialog - the user settings dialog in the board look (board\n * PqPersoonlijk): eyebrow, title and subtitle, a left navigation listing the\n * sections with their icons, the sections themselves, and a footer with a\n * note that changes save straight away and a Close button.\n *\n * The sections stay the app's: any `NcAppSettingsSection` in the default slot\n * registers itself with this dialog exactly as it does with\n * `NcAppSettingsDialog`, with its name, order and `#icon` slot. CnAppRoot\n * renders this dialog instead of `NcAppSettingsDialog` under the board look.\n *\n * @spec openspec/changes/user-settings-board-dialog/specs/user-settings-board-dialog/spec.md#requirement-the-user-settings-dialog-takes-the-board-look\n *\n * @event update:open Emitted with `false` when the dialog closes.\n */\nexport default {\n\tname: 'CnUserSettingsDialog',\n\n\tcomponents: { CnDialog, CnVNodes, NcButton },\n\n\tprovide() {\n\t\treturn {\n\t\t\t[REGISTRATION_KEY]: {\n\t\t\t\tregisterSection: this.registerSection,\n\t\t\t\tunregisterSection: this.unregisterSection,\n\t\t\t},\n\t\t}\n\t},\n\n\tprops: {\n\t\t/** Whether the dialog is open. */\n\t\topen: { type: Boolean, default: false },\n\t\t/** Dialog title; also its accessible name. */\n\t\ttitle: { type: String, required: true },\n\t\t/** Context line above the title. */\n\t\teyebrow: { type: String, default: () => t('nextcloud-vue', 'Your account') },\n\t\t/** Sentence under the title. */\n\t\tsubtitle: { type: String, default: () => t('nextcloud-vue', 'Only for you. Colleagues keep their own settings.') },\n\t\t/** The app's name, after the footer note. */\n\t\tappName: { type: String, default: '' },\n\t},\n\n\temits: ['update:open'],\n\n\tdata() {\n\t\treturn {\n\t\t\tsections: [],\n\t\t\tselected: '',\n\t\t\tpicked: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The board's eyebrow: muted, in sentence case. */\n\t\teyebrowStyle() {\n\t\t\treturn { '--cn-dialog-eyebrow-transform': 'none', '--cn-dialog-eyebrow-color': 'var(--color-text-maxcontrast)' }\n\t\t},\n\n\t\t/** @return {string} The navigation's accessible name. */\n\t\tnavLabel() {\n\t\t\treturn t('nextcloud-vue', 'Sections of the settings')\n\t\t},\n\n\t\t/** @return {string} The footer note, with the app's name when known. */\n\t\tfooterNote() {\n\t\t\tconst note = t('nextcloud-vue', 'Changes are saved straight away')\n\t\t\treturn this.appName ? `${note} · ${this.appName}` : note\n\t\t},\n\n\t\t/** @return {string} The Close button label. */\n\t\tcloseLabel() {\n\t\t\treturn t('nextcloud-vue', 'Close')\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Add a section to the navigation, kept in `order`; a section\n\t\t * without one goes last. Until the reader picks one, the first\n\t\t * section is current.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t * @param {string} name The section name.\n\t\t * @param {number} [order] The section's place.\n\t\t * @param {Array} [icon] The section's icon vnodes.\n\t\t */\n\t\tregisterSection(id, name, order, icon) {\n\t\t\tconst rest = this.sections.filter((section) => section.id !== id)\n\t\t\tconst place = typeof order === 'number' ? order : Math.max(0, ...rest.map((section) => section.order)) + 1\n\t\t\tthis.sections = [...rest, { id, name, order: place, icon: icon ? markRaw(icon) : null }].sort((a, b) => a.order - b.order)\n\t\t\tif (!this.picked) {\n\t\t\t\tthis.selected = this.sections[0].id\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove a section from the navigation.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tunregisterSection(id) {\n\t\t\tthis.sections = this.sections.filter((section) => section.id !== id)\n\t\t\tif (this.selected === id) {\n\t\t\t\tthis.selected = this.sections.length > 0 ? this.sections[0].id : ''\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Mark a section current and scroll it into view.\n\t\t *\n\t\t * @param {string} id The section id.\n\t\t */\n\t\tselectSection(id) {\n\t\t\tthis.picked = true\n\t\t\tthis.selected = id\n\t\t\tconst target = typeof document !== 'undefined' ? document.getElementById(`settings-section_${id}`) : null\n\t\t\tif (target && typeof target.scrollIntoView === 'function') {\n\t\t\t\ttarget.scrollIntoView({ behavior: 'smooth', block: 'start' })\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Follow NcDialog's own open state.\n\t\t *\n\t\t * @param {boolean} value Whether NcDialog is open.\n\t\t */\n\t\tonUpdateOpen(value) {\n\t\t\tif (!value) {\n\t\t\t\tthis.close()\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog. */\n\t\tclose() {\n\t\t\t/**\n\t\t\t * @event update:open Emitted with `false` when the dialog closes (Close button, close icon, Escape).\n\t\t\t */\n\t\t\tthis.$emit('update:open', false)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-user-settings-dialog__body {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\tgap: 0 24px;\n}\n\n.cn-user-settings-dialog__nav {\n\tflex: 0 0 200px;\n\twidth: 200px;\n\tpadding-top: 18px;\n}\n\n.cn-user-settings-dialog__nav ul {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmargin: 0;\n\tpadding: 0;\n\tlist-style: none;\n}\n\n.cn-user-settings-dialog__nav-link {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tmin-height: 40px;\n\tpadding: 0 12px;\n\tborder-radius: var(--border-radius-element, 8px);\n\tfont-size: 15px;\n\tcolor: var(--color-main-text);\n\ttext-decoration: none;\n}\n\n.cn-user-settings-dialog__nav-link:hover {\n\tbackground: var(--color-background-hover);\n}\n\n.cn-user-settings-dialog__nav-link:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 2px;\n}\n\n.cn-user-settings-dialog__nav-link--active,\n.cn-user-settings-dialog__nav-link--active:hover {\n\tbackground: var(--color-primary-element-light);\n\tcolor: var(--color-primary-element-light-text);\n\tfont-weight: 600;\n}\n\n.cn-user-settings-dialog__nav-icon {\n\tdisplay: inline-flex;\n\tflex: none;\n\twidth: 18px;\n\theight: 18px;\n\talign-items: center;\n\tjustify-content: center;\n}\n\n.cn-user-settings-dialog__sections {\n\tdisplay: flex;\n\tflex: 1 1 380px;\n\tflex-direction: column;\n\tmin-width: 0;\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section) {\n\tmargin: 0;\n\tpadding: 18px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-user-settings-dialog__sections :deep(.app-settings-section__name) {\n\tmargin: 0 0 12px;\n\tfont-size: 17px;\n\tfont-weight: 700;\n}\n\n.cn-user-settings-dialog__note {\n\tflex: 1 1 auto;\n\tmargin: 0;\n\tfont-size: 14px;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_toDisplayString","_createVNode","_createElementVNode","_createElementBlock","_Fragment","_renderList","_withModifiers","_openBlock","_renderSlot"],"mappings":";;AAqBO,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,+BAAY,GAAA;;;;;AAehB,EAAA,KAAA,EAAA,mCAAA;AAAA,EAAA,aAAA,EAAA,MAAA;;AAQF,MAAA,UAAA,GAAA,EAAA,KAAA,EAAA,mCAAA,GAAA;;AAMF,EAAA,KAAM,EAAC,+BAAO;AAAA,EAAA,aAAA,EAAA,uBAAA;;;;;;;;;AAxCjB,IAAA,KAAK,EAAC,yBAAW;AAChB,IAAA,IAAI,EAAE,MAAK,CAAA,KAAA;AACZ,IAAA,IAAI,EAAC,OAAM;AACX,IAAA,KAAK,EAAC,QAAQ;AACb,IAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,IAAA,QAAQ,EAAE,MAAQ,CAAA,QAAA;AAClB,IAAA,IAAI,EAAE,MAAI,CAAA,IAAA;AACV,IAAA,KAAK,iBAAE,QAAY,CAAA,YAAA,CAAA;AACnB,IAAA,aAAG,EAAA,yBAAA;mBACQ,EAAE,QAAY,CAAA,YAAA;AACxB,IAAA,SAAM,EAAE,QAAK,CAAA,KAAA;;AA6BJ,IAAA,OAAO,gBAGb;wBAAA,CAAA,GAAA,YAAA,EAAAA,eAAA,CADA,QAAM,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;MAEVC;AAAQ,QAAA,OAAA,EAAA,WAAA;AAAA,QAAA,aAAA,EAAA,wBAAA;AAAA,QAAA,OAAA,EAAA,QAAA,CAAA,KAAA;;;;;;;;qBAhCP,MA2BE;AA3BF,MAAAC,kBAAA,CA2BE,OA3BF,UA2BE,EAAA;AAzBC,QAAA,CAAA,KAAA,CAAA,QAAA,CAAA,MAAA,GAAA,CAAA;0BADHC,kBAqBI,CAAA,KAAA,EAAA;;AAnBH,cAAA,KAAI,EAAC,8BAA8B;0BACjC,EAAA,QAAA,CAAA,QAAA;AACA,cAAA,aAAQ,EAAC,sBAAsB;;cAC/BD,kBAeC,CAAA,IAAA,EAAA,IAAA,EAAA;kCAdDC,kBAaG,CAAAC,QAAA,EAAA,IAAA,EAAAC,UAAA,CAbiB,KAAQ,CAAA,QAAA,EAAA,CAAlB,OAAM,KAAA;uCAAhBF,kBAaG,CAAA,IAAA,EAAA;oBAb4B,GAAG,EAAE,OAAO,CAAC,EAAE;;sCAY3C,CAAA,GAAA,EAAA;sBAVF,IAAI,EAAA,CAAA,kBAAA,EAAuB,OAAO,CAAC,EAAE,CAAA,CAAA;AACtC,sBAAA,KAAK,kBAAC,mCAAmC,EAAA,EAAA,2CAAA,EACc,OAAO,CAAC,EAAE,KAAK,KAAQ,CAAA,QAAA,EAAA,CAAA,CAAA;AAC7E,sBAAA,cAAY,EAAE,OAAO,CAAC,EAAE,KAAK,KAAA,CAAA,QAAK,YAAA,SAAA;sBAClC,aAAK,EAAA,CAAA,qBAAA,EAAA,OAAA,CAAA,EAAA,CAAA,CAAA;AACL,sBAAA,OAAK,EAAUG,aAAA,CAAA,MAAA,KAAA,QAAA,CAAA,aAAa,CAAC,OAAA,CAAA,EAAA,CAAA,CAAA,EAAA,CAAA,SAAA,CAAA,CAAA;;AAC5B,sBAAA,CAAA,OAAA,CAAA,IAAA;AAAF,2BAAAC,SAAA,EAAA,EAAAJ,kBAAA,CAEC,QAFD,UAEC,EAAA;4BADAF,WAAC,CAAA,mBAAA,EAAA;8BAAA,MAAA,EAAA,OAAA,CAAA,IAAA;;;;sBAEFC,kBAAC,CAAA,MAAA,EAAA,IAAA,EAAAF,eAAA,CAAA,OAAA,CAAA,IAAA,CAAA,EAAA,CAAA,YAAA;;;;;;;AAKL,QAAAE,kBAAA,CAGM,OAHN,UAGM,EAAA;UADLM,UAAQ,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,CAAA;;;;;;;;;;"}
@@ -2,7 +2,7 @@ import script from './CnVersionInfoCard.vue2.js';
2
2
  import { render } from './CnVersionInfoCard.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-52e4d484";
5
+ script.__scopeId = "data-v-95a2bdce";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -1 +1 @@
1
- {"version":3,"file":"CnVersionInfoCard.vue2.js","sources":["../../../../src/components/CnVersionInfoCard/CnVersionInfoCard.vue"],"sourcesContent":["<template>\n\t<CnSettingsSection\n\t\t:name=\"title\"\n\t\t:description=\"description\"\n\t\t:docUrl=\"docUrl\"\n\t\t:loading=\"loading\"\n\t\t:wide=\"isBoard && wide\"\n\t\t:loadingMessage=\"t('nextcloud-vue', 'Loading version information…')\">\n\t\t<!-- Actions slot (top right). Under the board look the same buttons sit\n\t\t in the footer row of the card instead. -->\n\t\t<template v-if=\"!isBoard\" #actions>\n\t\t\t<!-- Update Button -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ updateButtonText }}\n\t\t\t</NcButton>\n\n\t\t\t<!-- Additional Actions (slot) -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\n\t\t<!-- Main content (only shown when not loading) -->\n\t\t<div v-if=\"!loading\" class=\"cn-version-info\" :class=\"{ 'cn-version-info--board': isBoard }\">\n\t\t\t<!-- Version card with gray background -->\n\t\t\t<div class=\"cn-version-info__card\">\n\t\t\t\t<h4>{{ cardTitle }}</h4>\n\t\t\t\t<div class=\"cn-version-info__details\">\n\t\t\t\t\t<!-- Application Name -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.appName }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appName }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Version -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.version }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Configured Version (if provided) -->\n\t\t\t\t\t<div v-if=\"configuredVersion\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.configuredVersion }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ configuredVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Additional items -->\n\t\t\t\t\t<div v-for=\"item in additionalItems\" :key=\"item.label\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ item.label }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\" :class=\"item.statusClass\">{{ item.value }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Optional additional items slot -->\n\t\t\t\t\t<slot name=\"additional-items\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- The state, then the actions (re-import), after a hairline. -->\n\t\t\t\t<div v-if=\"isBoard\" class=\"cn-version-info__footer-row\" data-testid=\"cn-version-info-footer-row\">\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ updateButtonText }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<slot name=\"actions\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Optional footer slot -->\n\t\t\t\t<slot name=\"footer\" />\n\t\t\t</div>\n\n\t\t\t<!-- Optional extra cards slot -->\n\t\t\t<slot name=\"extra-cards\" />\n\t\t</div>\n\t</CnSettingsSection>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Update from 'vue-material-design-icons/Update.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { ensureTranslations } from '../../l10n/index.js'\nimport { CnSettingsSection } from '../CnSettingsSection/index.js'\n\n/**\n * CnVersionInfoCard - App version information card for admin settings pages.\n *\n * Displays application name, version, and optional configured version with an\n * update button. Wraps CnSettingsSection for consistent admin settings layout.\n *\n * Every Conduction Nextcloud app should show this as the first section on its\n * admin settings page.\n *\n * Basic usage\n * ```vue\n * <CnVersionInfoCard app-name=\"Open Register\" app-version=\"0.2.3\" />\n * ```\n *\n * With update button\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Open Register\"\n * app-version=\"0.2.3\"\n * configured-version=\"0.2.2\"\n * :is-up-to-date=\"false\"\n * :show-update-button=\"true\"\n * :updating=\"isUpdating\"\n * @update=\"runUpdate\" />\n * ```\n *\n * With additional items and actions\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Pipelinq\"\n * app-version=\"0.1.7\"\n * :additional-items=\"[{ label: 'Database', value: 'Connected', statusClass: 'cn-version-info__status--ok' }]\">\n * <template #actions>\n * <NcButton @click=\"clearCache\">Clear App Store Cache</NcButton>\n * </template>\n * </CnVersionInfoCard>\n * ```\n */\nexport default {\n\tname: 'CnVersionInfoCard',\n\n\tcomponents: {\n\t\tCnSettingsSection,\n\t\tNcLoadingIcon,\n\t\tNcButton,\n\t\tCheck,\n\t\tUpdate,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the card is drawn in: `board` or `nextcloud`. Empty follows\n\t\t * the `cnLook` that CnAppRoot provides. Under `board` the facts are a\n\t\t * two-column list and the actions sit in a footer row.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/settings-board-look/spec.md#requirement-the-version-card-takes-the-board-facts-and-footer\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Under the board look the card spans the whole settings grid, as the\n\t\t * boards draw the version card. Set to `false` to keep it one card in\n\t\t * the grid. Without the board look it has no effect.\n\t\t *\n\t\t * @spec openspec/changes/board-version-card-full-width/specs/settings-board-look/spec.md#requirement-the-board-version-card-spans-the-settings-grid\n\t\t */\n\t\twide: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Section title */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Version information'),\n\t\t},\n\n\t\t/** Section description */\n\t\tdescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Information about the current application installation'),\n\t\t},\n\n\t\t/** Documentation URL (shows info icon next to title) */\n\t\tdocUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Card heading text */\n\t\tcardTitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Application information'),\n\t\t},\n\n\t\t/** Application name to display */\n\t\tappName: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Application version string */\n\t\tappVersion: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Configured version (optional, for apps that track configuration versions separately) */\n\t\tconfiguredVersion: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app configuration is up to date */\n\t\tisUpToDate: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Whether to show the update button */\n\t\tshowUpdateButton: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether an update is currently in progress */\n\t\tupdating: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Additional key-value items to display.\n\t\t * Format: [{ label: 'Label', value: 'Value', statusClass: 'cn-version-info__status--ok' }]\n\t\t */\n\t\tadditionalItems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether version info is loading */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Custom labels for the standard fields, `{ appName?, version?, configuredVersion? }`.\n\t\t * A label left out keeps the translated default.\n\t\t */\n\t\tlabels: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['update'],\n\n\tsetup(props) {\n\t\t// An admin page can be an entry with no other library surface: its\n\t\t// chrome reads in the user's language without the app registering.\n\t\tensureTranslations()\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The field labels: the app's, else the library's in the reader's language.\n\t\t *\n\t\t * @return {{appName: string, version: string, configuredVersion: string}}\n\t\t * @spec openspec/changes/version-card-dutch-and-header/specs/settings-board-look/spec.md#requirement-the-admin-chrome-reads-in-the-readers-language\n\t\t */\n\t\tfieldLabels() {\n\t\t\treturn {\n\t\t\t\tappName: t('nextcloud-vue', 'Application name'),\n\t\t\t\tversion: t('nextcloud-vue', 'Version'),\n\t\t\t\tconfiguredVersion: t('nextcloud-vue', 'Configured version'),\n\t\t\t\t...(this.labels || {}),\n\t\t\t}\n\t\t},\n\n\t\t/** @return {string} Button type based on update status */\n\t\tupdateButtonType() {\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn 'success'\n\t\t\t}\n\t\t\treturn 'error'\n\t\t},\n\n\t\t/** @return {boolean} Whether the update button should be disabled */\n\t\tupdateButtonDisabled() {\n\t\t\treturn this.isUpToDate || this.updating\n\t\t},\n\n\t\t/** @return {string} Update button label text */\n\t\tupdateButtonText() {\n\t\t\tif (this.updating) {\n\t\t\t\treturn t('nextcloud-vue', 'Updating…')\n\t\t\t}\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn t('nextcloud-vue', 'Up to date')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Update')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\thandleUpdateClick() {\n\t\t\tif (!this.updateButtonDisabled) {\n\t\t\t\tthis.$emit('update')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-info__card {\n\tbackground: var(--color-background-hover);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tpadding: 20px;\n\tmargin-bottom: 20px;\n}\n\n.cn-version-info__card h4 {\n\tmargin: 0 0 16px 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-info__details {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-version-info__item {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-info__item:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-info__label {\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 14px;\n}\n\n.cn-version-info__value {\n\tfont-family: 'Courier New', Courier, monospace;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n}\n\n/* Status classes for values */\n.cn-version-info__status--ok {\n\tcolor: var(--color-success);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--warning {\n\tcolor: var(--color-warning);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--error {\n\tcolor: var(--color-error);\n\tfont-weight: 600;\n}\n\n@media (max-width: 768px) {\n\t.cn-version-info__item {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 4px;\n\t}\n\n\t.cn-version-info__label {\n\t\tfont-weight: 600;\n\t}\n\n\t.cn-version-info__value {\n\t\tword-break: break-all;\n\t}\n}\n</style>\n"],"names":["CnSettingsSection","t"],"mappings":";;;;;;;;AAmGA;AACC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;AAKA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;;AAGA;AACA;;AAED,aAAe;CACd,IAAI,EAAE,mBAAmB;;CAEzB,UAAU,EAAE;AACX,qBAAAA,UAAiB;EACjB,aAAa;AACb,EAAA,QAAQ;EACR,KAAK;AACL,EAAA,MAAM;EACN;;AAED,CAAA,KAAK,EAAE;AACN;;;AAGC;AACA;AACA;;EAED,IAAI,EAAE;GACL,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;;;AAGC;AACA;AACA;;EAED,IAAI,EAAE;GACL,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,IAAI;GACb;;AAED;AACA,EAAA,KAAK,EAAE;GACN,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,MAAMC,SAAC,CAAC,eAAe,EAAE,qBAAqB,CAAC;GACxD;;;EAGD,WAAW,EAAE;GACZ,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,wDAAwD,CAAC;GAC3F;;;AAGD,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;EACA,SAAS,EAAE;GACV,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,MAAMA,SAAC,CAAC,eAAe,EAAE,yBAAyB,CAAC;GAC5D;;;AAGD,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,MAAM;GACZ,QAAQ,EAAE,IAAI;GACd;;;EAGD,UAAU,EAAE;GACX,IAAI,EAAE,MAAM;GACZ,QAAQ,EAAE,IAAI;GACd;;AAED;AACA,EAAA,iBAAiB,EAAE;GAClB,IAAI,EAAE,MAAM;GACZ,OAAO,EAAE,EAAE;GACX;;AAED;EACA,UAAU,EAAE;GACX,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,IAAI;GACb;;AAED;AACA,EAAA,gBAAgB,EAAE;GACjB,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,KAAK;GACd;;AAED;AACA,EAAA,QAAQ,EAAE;GACT,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,KAAK;GACd;;AAED;AACC;AACA;;AAED,EAAA,eAAe,EAAE;GAChB,IAAI,EAAE,KAAK;AACX,GAAA,OAAO,EAAE,MAAM,EAAE;GACjB;;AAED;AACA,EAAA,OAAO,EAAE;GACR,IAAI,EAAE,OAAO;GACb,OAAO,EAAE,KAAK;GACd;;AAED;AACC;AACA;;AAED,EAAA,MAAM,EAAE;GACP,IAAI,EAAE,MAAM;AACZ,GAAA,OAAO,EAAE,OAAO,EAAE,CAAC;GACnB;EACD;;AAED,CAAA,KAAK,EAAE,CAAC,QAAQ,CAAC;;CAEjB,KAAK,CAAC,KAAK,EAAE;;;AAGZ,EAAA,kBAAkB,GAAC;EACnB,MAAM,EAAE,OAAQ,EAAA,GAAI,OAAO,CAAC,KAAK,EAAA;AACjC,EAAA,OAAO,EAAE,OAAQ,EAAA;EACjB;;AAED,CAAA,QAAQ,EAAE;AACT;AACC;AACA;AACA;AACA;;EAED,WAAW,GAAG;AACb,GAAA,OAAO;AACN,IAAA,OAAO,EAAEA,SAAC,CAAC,eAAe,EAAE,kBAAkB,CAAC;AAC/C,IAAA,OAAO,EAAEA,SAAC,CAAC,eAAe,EAAE,SAAS,CAAC;IACtC,iBAAiB,EAAEA,SAAC,CAAC,eAAe,EAAE,oBAAoB,CAAC;AAC3D,IAAA,IAAI,IAAI,CAAC,MAAK,IAAK,EAAE,CAAC;AACvB,IAAA;GACA;;;AAGD,EAAA,gBAAgB,GAAG;AAClB,GAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACpB,IAAA,OAAO,SAAQ;AAChB,IAAA;GACA,OAAO,OAAM;GACb;;;EAGD,oBAAoB,GAAG;AACtB,GAAA,OAAO,IAAI,CAAC,UAAS,IAAK,IAAI,CAAC,QAAO;GACtC;;AAED;AACA,EAAA,gBAAgB,GAAG;AAClB,GAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;AAClB,IAAA,OAAOA,SAAC,CAAC,eAAe,EAAE,WAAW,CAAA;AACtC,IAAA;AACA,GAAA,IAAI,IAAI,CAAC,UAAU,EAAE;AACpB,IAAA,OAAOA,SAAC,CAAC,eAAe,EAAE,YAAY,CAAA;AACvC,IAAA;AACA,GAAA,OAAOA,SAAC,CAAC,eAAe,EAAE,QAAQ,CAAA;GAClC;EACD;;AAED,CAAA,OAAO,EAAE;KACRA,SAAC;;AAED,EAAA,iBAAiB,GAAG;AACnB,GAAA,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE;AAC/B,IAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAA;AACpB,IAAA;GACA;EACD;AACF;;;;"}
1
+ {"version":3,"file":"CnVersionInfoCard.vue2.js","sources":["../../../../src/components/CnVersionInfoCard/CnVersionInfoCard.vue"],"sourcesContent":["<template>\n\t<CnSettingsSection\n\t\t:name=\"title\"\n\t\t:description=\"description\"\n\t\t:docUrl=\"docUrl\"\n\t\t:loading=\"loading\"\n\t\t:wide=\"isBoard && wide\"\n\t\t:loadingMessage=\"t('nextcloud-vue', 'Loading version information…')\">\n\t\t<!-- Actions slot (top right). Under the board look the same buttons sit\n\t\t in the footer row of the card instead. -->\n\t\t<template v-if=\"!isBoard\" #actions>\n\t\t\t<!-- Update Button -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ updateButtonText }}\n\t\t\t</NcButton>\n\n\t\t\t<!-- Additional Actions (slot) -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\n\t\t<!-- Main content (only shown when not loading) -->\n\t\t<div v-if=\"!loading\" class=\"cn-version-info\" :class=\"{ 'cn-version-info--board': isBoard }\">\n\t\t\t<!-- Version card with gray background -->\n\t\t\t<div class=\"cn-version-info__card\">\n\t\t\t\t<h4>{{ cardTitle }}</h4>\n\t\t\t\t<div class=\"cn-version-info__details\">\n\t\t\t\t\t<!-- Application Name -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.appName }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appName }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Version -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.version }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Configured version: when provided, and always in the board look,\n\t\t\t\t\t which draws the row (\"Unknown\" until the app reports it). -->\n\t\t\t\t\t<div v-if=\"configuredVersion || isBoard\" class=\"cn-version-info__item\" data-testid=\"cn-version-info-configured\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.configuredVersion }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ configuredVersion || t('nextcloud-vue', 'Unknown') }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Additional items -->\n\t\t\t\t\t<div v-for=\"item in additionalItems\" :key=\"item.label\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ item.label }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\" :class=\"item.statusClass\">{{ item.value }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Optional additional items slot -->\n\t\t\t\t\t<slot name=\"additional-items\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- The state, then the actions (re-import), after a hairline. -->\n\t\t\t\t<div v-if=\"isBoard\" class=\"cn-version-info__footer-row\" data-testid=\"cn-version-info-footer-row\">\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ updateButtonText }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<slot name=\"actions\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Optional footer slot -->\n\t\t\t\t<slot name=\"footer\" />\n\t\t\t</div>\n\n\t\t\t<!-- Optional extra cards slot -->\n\t\t\t<slot name=\"extra-cards\" />\n\t\t</div>\n\t</CnSettingsSection>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Update from 'vue-material-design-icons/Update.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { ensureTranslations } from '../../l10n/index.js'\nimport { CnSettingsSection } from '../CnSettingsSection/index.js'\n\n/**\n * CnVersionInfoCard - App version information card for admin settings pages.\n *\n * Displays application name, version, and optional configured version with an\n * update button. Wraps CnSettingsSection for consistent admin settings layout.\n *\n * Every Conduction Nextcloud app should show this as the first section on its\n * admin settings page.\n *\n * Basic usage\n * ```vue\n * <CnVersionInfoCard app-name=\"Open Register\" app-version=\"0.2.3\" />\n * ```\n *\n * With update button\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Open Register\"\n * app-version=\"0.2.3\"\n * configured-version=\"0.2.2\"\n * :is-up-to-date=\"false\"\n * :show-update-button=\"true\"\n * :updating=\"isUpdating\"\n * @update=\"runUpdate\" />\n * ```\n *\n * With additional items and actions\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Pipelinq\"\n * app-version=\"0.1.7\"\n * :additional-items=\"[{ label: 'Database', value: 'Connected', statusClass: 'cn-version-info__status--ok' }]\">\n * <template #actions>\n * <NcButton @click=\"clearCache\">Clear App Store Cache</NcButton>\n * </template>\n * </CnVersionInfoCard>\n * ```\n */\nexport default {\n\tname: 'CnVersionInfoCard',\n\n\tcomponents: {\n\t\tCnSettingsSection,\n\t\tNcLoadingIcon,\n\t\tNcButton,\n\t\tCheck,\n\t\tUpdate,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the card is drawn in: `board` or `nextcloud`. Empty follows\n\t\t * the `cnLook` that CnAppRoot provides. Under `board` the facts are a\n\t\t * two-column list and the actions sit in a footer row.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/settings-board-look/spec.md#requirement-the-version-card-takes-the-board-facts-and-footer\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Under the board look the card spans the whole settings grid, as the\n\t\t * boards draw the version card. Set to `false` to keep it one card in\n\t\t * the grid. Without the board look it has no effect.\n\t\t *\n\t\t * @spec openspec/changes/board-version-card-full-width/specs/settings-board-look/spec.md#requirement-the-board-version-card-spans-the-settings-grid\n\t\t */\n\t\twide: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Section title */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Version information'),\n\t\t},\n\n\t\t/** Section description */\n\t\tdescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Information about the current application installation'),\n\t\t},\n\n\t\t/** Documentation URL (shows info icon next to title) */\n\t\tdocUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Card heading text */\n\t\tcardTitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Application information'),\n\t\t},\n\n\t\t/** Application name to display */\n\t\tappName: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Application version string */\n\t\tappVersion: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Configured version (optional, for apps that track configuration versions separately) */\n\t\tconfiguredVersion: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app configuration is up to date */\n\t\tisUpToDate: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Whether to show the update button */\n\t\tshowUpdateButton: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether an update is currently in progress */\n\t\tupdating: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Additional key-value items to display.\n\t\t * Format: [{ label: 'Label', value: 'Value', statusClass: 'cn-version-info__status--ok' }]\n\t\t */\n\t\tadditionalItems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether version info is loading */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Custom labels for the standard fields, `{ appName?, version?, configuredVersion? }`.\n\t\t * A label left out keeps the translated default.\n\t\t */\n\t\tlabels: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['update'],\n\n\tsetup(props) {\n\t\t// An admin page can be an entry with no other library surface: its\n\t\t// chrome reads in the user's language without the app registering.\n\t\tensureTranslations()\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The field labels: the app's, else the library's in the reader's language.\n\t\t *\n\t\t * @return {{appName: string, version: string, configuredVersion: string}}\n\t\t * @spec openspec/changes/version-card-dutch-and-header/specs/settings-board-look/spec.md#requirement-the-admin-chrome-reads-in-the-readers-language\n\t\t */\n\t\tfieldLabels() {\n\t\t\treturn {\n\t\t\t\tappName: t('nextcloud-vue', 'Application name'),\n\t\t\t\tversion: t('nextcloud-vue', 'Version'),\n\t\t\t\tconfiguredVersion: t('nextcloud-vue', 'Configured version'),\n\t\t\t\t...(this.labels || {}),\n\t\t\t}\n\t\t},\n\n\t\t/** @return {string} Button type based on update status */\n\t\tupdateButtonType() {\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn 'success'\n\t\t\t}\n\t\t\treturn 'error'\n\t\t},\n\n\t\t/** @return {boolean} Whether the update button should be disabled */\n\t\tupdateButtonDisabled() {\n\t\t\treturn this.isUpToDate || this.updating\n\t\t},\n\n\t\t/** @return {string} Update button label text */\n\t\tupdateButtonText() {\n\t\t\tif (this.updating) {\n\t\t\t\treturn t('nextcloud-vue', 'Updating…')\n\t\t\t}\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn t('nextcloud-vue', 'Up to date')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Update')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\thandleUpdateClick() {\n\t\t\tif (!this.updateButtonDisabled) {\n\t\t\t\tthis.$emit('update')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-info__card {\n\tbackground: var(--color-background-hover);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tpadding: 20px;\n\tmargin-bottom: 20px;\n}\n\n.cn-version-info__card h4 {\n\tmargin: 0 0 16px 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-info__details {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-version-info__item {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-info__item:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-info__label {\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 14px;\n}\n\n.cn-version-info__value {\n\tfont-family: 'Courier New', Courier, monospace;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n}\n\n/* Status classes for values */\n.cn-version-info__status--ok {\n\tcolor: var(--color-success);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--warning {\n\tcolor: var(--color-warning);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--error {\n\tcolor: var(--color-error);\n\tfont-weight: 600;\n}\n\n@media (max-width: 768px) {\n\t.cn-version-info__item {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 4px;\n\t}\n\n\t.cn-version-info__label {\n\t\tfont-weight: 600;\n\t}\n\n\t.cn-version-info__value {\n\t\tword-break: break-all;\n\t}\n}\n</style>\n"],"names":["CnSettingsSection","t"],"mappings":"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"}
@@ -10,7 +10,8 @@ const _hoisted_7 = { class: "cn-version-info__label" };
10
10
  const _hoisted_8 = { class: "cn-version-info__value" };
11
11
  const _hoisted_9 = {
12
12
  key: 0,
13
- class: "cn-version-info__item"
13
+ class: "cn-version-info__item",
14
+ "data-testid": "cn-version-info-configured"
14
15
  };
15
16
  const _hoisted_10 = { class: "cn-version-info__label" };
16
17
  const _hoisted_11 = { class: "cn-version-info__value" };
@@ -53,10 +54,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
53
54
  createElementVNode("span", _hoisted_7, toDisplayString($options.fieldLabels.version) + ":", 1 /* TEXT */),
54
55
  createElementVNode("span", _hoisted_8, toDisplayString($props.appVersion), 1 /* TEXT */)
55
56
  ]),
56
- ($props.configuredVersion)
57
+ ($props.configuredVersion || $setup.isBoard)
57
58
  ? (openBlock(), createElementBlock("div", _hoisted_9, [
58
59
  createElementVNode("span", _hoisted_10, toDisplayString($options.fieldLabels.configuredVersion) + ":", 1 /* TEXT */),
59
- createElementVNode("span", _hoisted_11, toDisplayString($props.configuredVersion), 1 /* TEXT */)
60
+ createElementVNode("span", _hoisted_11, toDisplayString($props.configuredVersion || $options.t('nextcloud-vue', 'Unknown')), 1 /* TEXT */)
60
61
  ]))
61
62
  : createCommentVNode("v-if", true),
62
63
  (openBlock(true), createElementBlock(Fragment, null, renderList($props.additionalItems, (item) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CnVersionInfoCard.vue3.js","sources":["../../../../src/components/CnVersionInfoCard/CnVersionInfoCard.vue?vue&type=template&id=52e4d484&lang.js"],"sourcesContent":["<template>\n\t<CnSettingsSection\n\t\t:name=\"title\"\n\t\t:description=\"description\"\n\t\t:docUrl=\"docUrl\"\n\t\t:loading=\"loading\"\n\t\t:wide=\"isBoard && wide\"\n\t\t:loadingMessage=\"t('nextcloud-vue', 'Loading version information…')\">\n\t\t<!-- Actions slot (top right). Under the board look the same buttons sit\n\t\t in the footer row of the card instead. -->\n\t\t<template v-if=\"!isBoard\" #actions>\n\t\t\t<!-- Update Button -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ updateButtonText }}\n\t\t\t</NcButton>\n\n\t\t\t<!-- Additional Actions (slot) -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\n\t\t<!-- Main content (only shown when not loading) -->\n\t\t<div v-if=\"!loading\" class=\"cn-version-info\" :class=\"{ 'cn-version-info--board': isBoard }\">\n\t\t\t<!-- Version card with gray background -->\n\t\t\t<div class=\"cn-version-info__card\">\n\t\t\t\t<h4>{{ cardTitle }}</h4>\n\t\t\t\t<div class=\"cn-version-info__details\">\n\t\t\t\t\t<!-- Application Name -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.appName }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appName }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Version -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.version }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Configured Version (if provided) -->\n\t\t\t\t\t<div v-if=\"configuredVersion\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.configuredVersion }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ configuredVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Additional items -->\n\t\t\t\t\t<div v-for=\"item in additionalItems\" :key=\"item.label\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ item.label }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\" :class=\"item.statusClass\">{{ item.value }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Optional additional items slot -->\n\t\t\t\t\t<slot name=\"additional-items\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- The state, then the actions (re-import), after a hairline. -->\n\t\t\t\t<div v-if=\"isBoard\" class=\"cn-version-info__footer-row\" data-testid=\"cn-version-info-footer-row\">\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ updateButtonText }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<slot name=\"actions\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Optional footer slot -->\n\t\t\t\t<slot name=\"footer\" />\n\t\t\t</div>\n\n\t\t\t<!-- Optional extra cards slot -->\n\t\t\t<slot name=\"extra-cards\" />\n\t\t</div>\n\t</CnSettingsSection>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Update from 'vue-material-design-icons/Update.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { ensureTranslations } from '../../l10n/index.js'\nimport { CnSettingsSection } from '../CnSettingsSection/index.js'\n\n/**\n * CnVersionInfoCard - App version information card for admin settings pages.\n *\n * Displays application name, version, and optional configured version with an\n * update button. Wraps CnSettingsSection for consistent admin settings layout.\n *\n * Every Conduction Nextcloud app should show this as the first section on its\n * admin settings page.\n *\n * Basic usage\n * ```vue\n * <CnVersionInfoCard app-name=\"Open Register\" app-version=\"0.2.3\" />\n * ```\n *\n * With update button\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Open Register\"\n * app-version=\"0.2.3\"\n * configured-version=\"0.2.2\"\n * :is-up-to-date=\"false\"\n * :show-update-button=\"true\"\n * :updating=\"isUpdating\"\n * @update=\"runUpdate\" />\n * ```\n *\n * With additional items and actions\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Pipelinq\"\n * app-version=\"0.1.7\"\n * :additional-items=\"[{ label: 'Database', value: 'Connected', statusClass: 'cn-version-info__status--ok' }]\">\n * <template #actions>\n * <NcButton @click=\"clearCache\">Clear App Store Cache</NcButton>\n * </template>\n * </CnVersionInfoCard>\n * ```\n */\nexport default {\n\tname: 'CnVersionInfoCard',\n\n\tcomponents: {\n\t\tCnSettingsSection,\n\t\tNcLoadingIcon,\n\t\tNcButton,\n\t\tCheck,\n\t\tUpdate,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the card is drawn in: `board` or `nextcloud`. Empty follows\n\t\t * the `cnLook` that CnAppRoot provides. Under `board` the facts are a\n\t\t * two-column list and the actions sit in a footer row.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/settings-board-look/spec.md#requirement-the-version-card-takes-the-board-facts-and-footer\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Under the board look the card spans the whole settings grid, as the\n\t\t * boards draw the version card. Set to `false` to keep it one card in\n\t\t * the grid. Without the board look it has no effect.\n\t\t *\n\t\t * @spec openspec/changes/board-version-card-full-width/specs/settings-board-look/spec.md#requirement-the-board-version-card-spans-the-settings-grid\n\t\t */\n\t\twide: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Section title */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Version information'),\n\t\t},\n\n\t\t/** Section description */\n\t\tdescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Information about the current application installation'),\n\t\t},\n\n\t\t/** Documentation URL (shows info icon next to title) */\n\t\tdocUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Card heading text */\n\t\tcardTitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Application information'),\n\t\t},\n\n\t\t/** Application name to display */\n\t\tappName: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Application version string */\n\t\tappVersion: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Configured version (optional, for apps that track configuration versions separately) */\n\t\tconfiguredVersion: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app configuration is up to date */\n\t\tisUpToDate: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Whether to show the update button */\n\t\tshowUpdateButton: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether an update is currently in progress */\n\t\tupdating: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Additional key-value items to display.\n\t\t * Format: [{ label: 'Label', value: 'Value', statusClass: 'cn-version-info__status--ok' }]\n\t\t */\n\t\tadditionalItems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether version info is loading */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Custom labels for the standard fields, `{ appName?, version?, configuredVersion? }`.\n\t\t * A label left out keeps the translated default.\n\t\t */\n\t\tlabels: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['update'],\n\n\tsetup(props) {\n\t\t// An admin page can be an entry with no other library surface: its\n\t\t// chrome reads in the user's language without the app registering.\n\t\tensureTranslations()\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The field labels: the app's, else the library's in the reader's language.\n\t\t *\n\t\t * @return {{appName: string, version: string, configuredVersion: string}}\n\t\t * @spec openspec/changes/version-card-dutch-and-header/specs/settings-board-look/spec.md#requirement-the-admin-chrome-reads-in-the-readers-language\n\t\t */\n\t\tfieldLabels() {\n\t\t\treturn {\n\t\t\t\tappName: t('nextcloud-vue', 'Application name'),\n\t\t\t\tversion: t('nextcloud-vue', 'Version'),\n\t\t\t\tconfiguredVersion: t('nextcloud-vue', 'Configured version'),\n\t\t\t\t...(this.labels || {}),\n\t\t\t}\n\t\t},\n\n\t\t/** @return {string} Button type based on update status */\n\t\tupdateButtonType() {\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn 'success'\n\t\t\t}\n\t\t\treturn 'error'\n\t\t},\n\n\t\t/** @return {boolean} Whether the update button should be disabled */\n\t\tupdateButtonDisabled() {\n\t\t\treturn this.isUpToDate || this.updating\n\t\t},\n\n\t\t/** @return {string} Update button label text */\n\t\tupdateButtonText() {\n\t\t\tif (this.updating) {\n\t\t\t\treturn t('nextcloud-vue', 'Updating…')\n\t\t\t}\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn t('nextcloud-vue', 'Up to date')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Update')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\thandleUpdateClick() {\n\t\t\tif (!this.updateButtonDisabled) {\n\t\t\t\tthis.$emit('update')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-info__card {\n\tbackground: var(--color-background-hover);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tpadding: 20px;\n\tmargin-bottom: 20px;\n}\n\n.cn-version-info__card h4 {\n\tmargin: 0 0 16px 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-info__details {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-version-info__item {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-info__item:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-info__label {\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 14px;\n}\n\n.cn-version-info__value {\n\tfont-family: 'Courier New', Courier, monospace;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n}\n\n/* Status classes for values */\n.cn-version-info__status--ok {\n\tcolor: var(--color-success);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--warning {\n\tcolor: var(--color-warning);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--error {\n\tcolor: var(--color-error);\n\tfont-weight: 600;\n}\n\n@media (max-width: 768px) {\n\t.cn-version-info__item {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 4px;\n\t}\n\n\t.cn-version-info__label {\n\t\tfont-weight: 600;\n\t}\n\n\t.cn-version-info__value {\n\t\tword-break: break-all;\n\t}\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_openBlock","_Fragment","_renderList","_renderSlot","_createTextVNode"],"mappings":"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"}
1
+ {"version":3,"file":"CnVersionInfoCard.vue3.js","sources":["../../../../src/components/CnVersionInfoCard/CnVersionInfoCard.vue?vue&type=template&id=95a2bdce&lang.js"],"sourcesContent":["<template>\n\t<CnSettingsSection\n\t\t:name=\"title\"\n\t\t:description=\"description\"\n\t\t:docUrl=\"docUrl\"\n\t\t:loading=\"loading\"\n\t\t:wide=\"isBoard && wide\"\n\t\t:loadingMessage=\"t('nextcloud-vue', 'Loading version information…')\">\n\t\t<!-- Actions slot (top right). Under the board look the same buttons sit\n\t\t in the footer row of the card instead. -->\n\t\t<template v-if=\"!isBoard\" #actions>\n\t\t\t<!-- Update Button -->\n\t\t\t<NcButton\n\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ updateButtonText }}\n\t\t\t</NcButton>\n\n\t\t\t<!-- Additional Actions (slot) -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\n\t\t<!-- Main content (only shown when not loading) -->\n\t\t<div v-if=\"!loading\" class=\"cn-version-info\" :class=\"{ 'cn-version-info--board': isBoard }\">\n\t\t\t<!-- Version card with gray background -->\n\t\t\t<div class=\"cn-version-info__card\">\n\t\t\t\t<h4>{{ cardTitle }}</h4>\n\t\t\t\t<div class=\"cn-version-info__details\">\n\t\t\t\t\t<!-- Application Name -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.appName }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appName }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Version -->\n\t\t\t\t\t<div class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.version }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ appVersion }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Configured version: when provided, and always in the board look,\n\t\t\t\t\t which draws the row (\"Unknown\" until the app reports it). -->\n\t\t\t\t\t<div v-if=\"configuredVersion || isBoard\" class=\"cn-version-info__item\" data-testid=\"cn-version-info-configured\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ fieldLabels.configuredVersion }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\">{{ configuredVersion || t('nextcloud-vue', 'Unknown') }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Additional items -->\n\t\t\t\t\t<div v-for=\"item in additionalItems\" :key=\"item.label\" class=\"cn-version-info__item\">\n\t\t\t\t\t\t<span class=\"cn-version-info__label\">{{ item.label }}:</span>\n\t\t\t\t\t\t<span class=\"cn-version-info__value\" :class=\"item.statusClass\">{{ item.value }}</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<!-- Optional additional items slot -->\n\t\t\t\t\t<slot name=\"additional-items\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- The state, then the actions (re-import), after a hairline. -->\n\t\t\t\t<div v-if=\"isBoard\" class=\"cn-version-info__footer-row\" data-testid=\"cn-version-info-footer-row\">\n\t\t\t\t\t<NcButton\n\t\t\t\t\t\tv-if=\"showUpdateButton\"\n\t\t\t\t\t\t:type=\"updateButtonType\"\n\t\t\t\t\t\t:disabled=\"updateButtonDisabled\"\n\t\t\t\t\t\t@click=\"handleUpdateClick\">\n\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t<NcLoadingIcon v-if=\"updating\" :size=\"20\" />\n\t\t\t\t\t\t\t<Check v-else-if=\"isUpToDate\" :size=\"20\" />\n\t\t\t\t\t\t\t<Update v-else :size=\"20\" />\n\t\t\t\t\t\t</template>\n\t\t\t\t\t\t{{ updateButtonText }}\n\t\t\t\t\t</NcButton>\n\t\t\t\t\t<slot name=\"actions\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Optional footer slot -->\n\t\t\t\t<slot name=\"footer\" />\n\t\t\t</div>\n\n\t\t\t<!-- Optional extra cards slot -->\n\t\t\t<slot name=\"extra-cards\" />\n\t\t</div>\n\t</CnSettingsSection>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport Check from 'vue-material-design-icons/Check.vue'\nimport Update from 'vue-material-design-icons/Update.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { ensureTranslations } from '../../l10n/index.js'\nimport { CnSettingsSection } from '../CnSettingsSection/index.js'\n\n/**\n * CnVersionInfoCard - App version information card for admin settings pages.\n *\n * Displays application name, version, and optional configured version with an\n * update button. Wraps CnSettingsSection for consistent admin settings layout.\n *\n * Every Conduction Nextcloud app should show this as the first section on its\n * admin settings page.\n *\n * Basic usage\n * ```vue\n * <CnVersionInfoCard app-name=\"Open Register\" app-version=\"0.2.3\" />\n * ```\n *\n * With update button\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Open Register\"\n * app-version=\"0.2.3\"\n * configured-version=\"0.2.2\"\n * :is-up-to-date=\"false\"\n * :show-update-button=\"true\"\n * :updating=\"isUpdating\"\n * @update=\"runUpdate\" />\n * ```\n *\n * With additional items and actions\n * ```vue\n * <CnVersionInfoCard\n * app-name=\"Pipelinq\"\n * app-version=\"0.1.7\"\n * :additional-items=\"[{ label: 'Database', value: 'Connected', statusClass: 'cn-version-info__status--ok' }]\">\n * <template #actions>\n * <NcButton @click=\"clearCache\">Clear App Store Cache</NcButton>\n * </template>\n * </CnVersionInfoCard>\n * ```\n */\nexport default {\n\tname: 'CnVersionInfoCard',\n\n\tcomponents: {\n\t\tCnSettingsSection,\n\t\tNcLoadingIcon,\n\t\tNcButton,\n\t\tCheck,\n\t\tUpdate,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The look the card is drawn in: `board` or `nextcloud`. Empty follows\n\t\t * the `cnLook` that CnAppRoot provides. Under `board` the facts are a\n\t\t * two-column list and the actions sit in a footer row.\n\t\t *\n\t\t * @spec openspec/changes/screens-chrome-parity/specs/settings-board-look/spec.md#requirement-the-version-card-takes-the-board-facts-and-footer\n\t\t */\n\t\tlook: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Under the board look the card spans the whole settings grid, as the\n\t\t * boards draw the version card. Set to `false` to keep it one card in\n\t\t * the grid. Without the board look it has no effect.\n\t\t *\n\t\t * @spec openspec/changes/board-version-card-full-width/specs/settings-board-look/spec.md#requirement-the-board-version-card-spans-the-settings-grid\n\t\t */\n\t\twide: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Section title */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Version information'),\n\t\t},\n\n\t\t/** Section description */\n\t\tdescription: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Information about the current application installation'),\n\t\t},\n\n\t\t/** Documentation URL (shows info icon next to title) */\n\t\tdocUrl: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Card heading text */\n\t\tcardTitle: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Application information'),\n\t\t},\n\n\t\t/** Application name to display */\n\t\tappName: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Application version string */\n\t\tappVersion: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Configured version (optional, for apps that track configuration versions separately) */\n\t\tconfiguredVersion: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Whether the app configuration is up to date */\n\t\tisUpToDate: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Whether to show the update button */\n\t\tshowUpdateButton: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether an update is currently in progress */\n\t\tupdating: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Additional key-value items to display.\n\t\t * Format: [{ label: 'Label', value: 'Value', statusClass: 'cn-version-info__status--ok' }]\n\t\t */\n\t\tadditionalItems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether version info is loading */\n\t\tloading: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Custom labels for the standard fields, `{ appName?, version?, configuredVersion? }`.\n\t\t * A label left out keeps the translated default.\n\t\t */\n\t\tlabels: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\t},\n\n\temits: ['update'],\n\n\tsetup(props) {\n\t\t// An admin page can be an entry with no other library surface: its\n\t\t// chrome reads in the user's language without the app registering.\n\t\tensureTranslations()\n\t\tconst { isBoard } = useLook(props)\n\t\treturn { isBoard }\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The field labels: the app's, else the library's in the reader's language.\n\t\t *\n\t\t * @return {{appName: string, version: string, configuredVersion: string}}\n\t\t * @spec openspec/changes/version-card-dutch-and-header/specs/settings-board-look/spec.md#requirement-the-admin-chrome-reads-in-the-readers-language\n\t\t */\n\t\tfieldLabels() {\n\t\t\treturn {\n\t\t\t\tappName: t('nextcloud-vue', 'Application name'),\n\t\t\t\tversion: t('nextcloud-vue', 'Version'),\n\t\t\t\tconfiguredVersion: t('nextcloud-vue', 'Configured version'),\n\t\t\t\t...(this.labels || {}),\n\t\t\t}\n\t\t},\n\n\t\t/** @return {string} Button type based on update status */\n\t\tupdateButtonType() {\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn 'success'\n\t\t\t}\n\t\t\treturn 'error'\n\t\t},\n\n\t\t/** @return {boolean} Whether the update button should be disabled */\n\t\tupdateButtonDisabled() {\n\t\t\treturn this.isUpToDate || this.updating\n\t\t},\n\n\t\t/** @return {string} Update button label text */\n\t\tupdateButtonText() {\n\t\t\tif (this.updating) {\n\t\t\t\treturn t('nextcloud-vue', 'Updating…')\n\t\t\t}\n\t\t\tif (this.isUpToDate) {\n\t\t\t\treturn t('nextcloud-vue', 'Up to date')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Update')\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\thandleUpdateClick() {\n\t\t\tif (!this.updateButtonDisabled) {\n\t\t\t\tthis.$emit('update')\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-version-info__card {\n\tbackground: var(--color-background-hover);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large);\n\tpadding: 20px;\n\tmargin-bottom: 20px;\n}\n\n.cn-version-info__card h4 {\n\tmargin: 0 0 16px 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-version-info__details {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-version-info__item {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: center;\n\tpadding: 8px 0;\n\tborder-bottom: 1px solid var(--color-border);\n}\n\n.cn-version-info__item:last-child {\n\tborder-bottom: none;\n}\n\n.cn-version-info__label {\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 14px;\n}\n\n.cn-version-info__value {\n\tfont-family: 'Courier New', Courier, monospace;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n}\n\n/* Status classes for values */\n.cn-version-info__status--ok {\n\tcolor: var(--color-success);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--warning {\n\tcolor: var(--color-warning);\n\tfont-weight: 600;\n}\n\n.cn-version-info__status--error {\n\tcolor: var(--color-error);\n\tfont-weight: 600;\n}\n\n@media (max-width: 768px) {\n\t.cn-version-info__item {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 4px;\n\t}\n\n\t.cn-version-info__label {\n\t\tfont-weight: 600;\n\t}\n\n\t.cn-version-info__value {\n\t\tword-break: break-all;\n\t}\n}\n</style>\n"],"names":["_createBlock","_createElementBlock","_normalizeClass","_createElementVNode","_toDisplayString","_openBlock","_Fragment","_renderList","_renderSlot","_createTextVNode"],"mappings":"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"}
@@ -2,7 +2,7 @@ import script from './CnWidgetWrapper.vue2.js';
2
2
  import { render } from './CnWidgetWrapper.vue3.js';
3
3
 
4
4
  script.render = render;
5
- script.__scopeId = "data-v-4f6c55f6";
5
+ script.__scopeId = "data-v-cc60e4c8";
6
6
  const __sfc_main = script;
7
7
 
8
8
  export { __sfc_main as default };
@@ -48,6 +48,18 @@ var script = {
48
48
  CnActionsMenu: __sfc_main,
49
49
  },
50
50
 
51
+ provide() {
52
+ return {
53
+ /**
54
+ * Whether this card draws a title row, so a widget inside it can
55
+ * leave out a heading of its own (nc-widget-header).
56
+ *
57
+ * @return {boolean}
58
+ */
59
+ cnWidgetTitled: () => this.titleVisible && Boolean(this.displayTitle),
60
+ }
61
+ },
62
+
51
63
  inject: {
52
64
  /**
53
65
  * Host translate function provided by CnAppRoot as
@@ -75,6 +87,17 @@ var script = {
75
87
  default: '',
76
88
  },
77
89
 
90
+ /**
91
+ * A muted line under the title, such as the period a chart covers.
92
+ * Run through the host translate function. Empty draws none.
93
+ *
94
+ * @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-dashboard-widget-card-can-carry-a-line-under-its-title
95
+ */
96
+ subtitle: {
97
+ type: String,
98
+ default: '',
99
+ },
100
+
78
101
  /** Whether to show the header with title */
79
102
  showTitle: {
80
103
  type: Boolean,
@@ -544,6 +567,15 @@ var script = {
544
567
  return this.eyebrow ? this.effectiveTranslate(this.eyebrow) : ''
545
568
  },
546
569
 
570
+ /**
571
+ * The subtitle run through the host translate function.
572
+ *
573
+ * @return {string}
574
+ */
575
+ resolvedSubtitle() {
576
+ return this.subtitle ? this.effectiveTranslate(this.subtitle) : ''
577
+ },
578
+
547
579
  /**
548
580
  * The RENDERED widget title — `displayTitle` run through the host
549
581
  * translate function. Kept separate from `displayTitle` on purpose: