@conduction/nextcloud-vue 0.1.0-beta.1 → 0.1.0-beta.11

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 (208) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs.js +79416 -7715
  4. package/dist/nextcloud-vue.cjs.js.map +1 -1
  5. package/dist/nextcloud-vue.css +3583 -504
  6. package/dist/nextcloud-vue.esm.js +79343 -7692
  7. package/dist/nextcloud-vue.esm.js.map +1 -1
  8. package/l10n/en.json +164 -0
  9. package/l10n/nl.json +164 -0
  10. package/package.json +104 -63
  11. package/src/components/CnActionsBar/CnActionsBar.vue +254 -0
  12. package/src/components/CnActionsBar/index.js +1 -0
  13. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +570 -0
  14. package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
  15. package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
  16. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +422 -0
  17. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
  18. package/src/components/CnAdvancedFormDialog/index.js +1 -0
  19. package/src/components/CnCard/CnCard.vue +415 -0
  20. package/src/components/CnCard/index.js +1 -0
  21. package/src/components/CnCardGrid/CnCardGrid.vue +156 -152
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/CnCellRenderer.vue +132 -132
  24. package/src/components/CnCellRenderer/index.js +1 -1
  25. package/src/components/CnChartWidget/CnChartWidget.vue +346 -0
  26. package/src/components/CnChartWidget/index.js +1 -0
  27. package/src/components/CnConfigurationCard/CnConfigurationCard.vue +77 -77
  28. package/src/components/CnConfigurationCard/index.js +1 -1
  29. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  30. package/src/components/CnContextMenu/index.js +1 -0
  31. package/src/components/CnCopyDialog/CnCopyDialog.vue +266 -0
  32. package/src/components/CnCopyDialog/index.js +1 -0
  33. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  34. package/src/components/CnDashboardGrid/index.js +1 -0
  35. package/src/components/CnDashboardPage/CnDashboardPage.vue +397 -0
  36. package/src/components/CnDashboardPage/index.js +1 -0
  37. package/src/components/CnDataTable/CnDataTable.vue +362 -354
  38. package/src/components/CnDataTable/index.js +1 -1
  39. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  40. package/src/components/CnDeleteDialog/index.js +1 -0
  41. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  42. package/src/components/CnDetailCard/index.js +1 -0
  43. package/src/components/CnDetailGrid/CnDetailGrid.vue +256 -0
  44. package/src/components/CnDetailGrid/index.js +1 -0
  45. package/src/components/CnDetailPage/CnDetailPage.vue +432 -0
  46. package/src/components/CnDetailPage/index.js +1 -0
  47. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +234 -223
  48. package/src/components/CnFacetSidebar/index.js +1 -1
  49. package/src/components/CnFilterBar/CnFilterBar.vue +153 -152
  50. package/src/components/CnFilterBar/index.js +1 -1
  51. package/src/components/CnFormDialog/CnFormDialog.vue +1047 -0
  52. package/src/components/CnFormDialog/index.js +1 -0
  53. package/src/components/CnIcon/CnIcon.vue +89 -0
  54. package/src/components/CnIcon/index.js +1 -0
  55. package/src/components/CnIndexPage/CnIndexPage.vue +980 -682
  56. package/src/components/CnIndexPage/index.js +1 -1
  57. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +536 -0
  58. package/src/components/CnIndexSidebar/index.js +1 -0
  59. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  60. package/src/components/CnInfoWidget/index.js +1 -0
  61. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  62. package/src/components/CnItemCard/index.js +1 -0
  63. package/src/components/CnJsonViewer/CnJsonViewer.vue +312 -0
  64. package/src/components/CnJsonViewer/index.js +1 -0
  65. package/src/components/CnKpiGrid/CnKpiGrid.vue +93 -89
  66. package/src/components/CnKpiGrid/index.js +1 -1
  67. package/src/components/CnMassActionBar/CnMassActionBar.vue +161 -160
  68. package/src/components/CnMassActionBar/index.js +1 -1
  69. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +327 -320
  70. package/src/components/CnMassCopyDialog/index.js +1 -1
  71. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +245 -238
  72. package/src/components/CnMassDeleteDialog/index.js +1 -1
  73. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +191 -190
  74. package/src/components/CnMassExportDialog/index.js +1 -1
  75. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +494 -491
  76. package/src/components/CnMassImportDialog/index.js +1 -1
  77. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  78. package/src/components/CnNoteCard/index.js +1 -0
  79. package/src/components/CnNotesCard/CnNotesCard.vue +416 -0
  80. package/src/components/CnNotesCard/index.js +1 -0
  81. package/src/components/CnObjectCard/CnObjectCard.vue +294 -292
  82. package/src/components/CnObjectCard/index.js +1 -1
  83. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +854 -0
  84. package/src/components/CnObjectDataWidget/index.js +1 -0
  85. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +289 -0
  86. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  87. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +369 -0
  88. package/src/components/CnObjectSidebar/CnFilesTab.vue +287 -0
  89. package/src/components/CnObjectSidebar/CnNotesTab.vue +250 -0
  90. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +255 -0
  91. package/src/components/CnObjectSidebar/CnTagsTab.vue +259 -0
  92. package/src/components/CnObjectSidebar/CnTasksTab.vue +483 -0
  93. package/src/components/CnObjectSidebar/index.js +6 -0
  94. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  95. package/src/components/CnPageHeader/index.js +1 -0
  96. package/src/components/CnPagination/CnPagination.vue +253 -252
  97. package/src/components/CnPagination/index.js +1 -1
  98. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  99. package/src/components/CnProgressBar/index.js +1 -0
  100. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +793 -0
  101. package/src/components/CnRegisterMapping/index.js +1 -0
  102. package/src/components/CnRowActions/CnRowActions.vue +95 -73
  103. package/src/components/CnRowActions/index.js +1 -1
  104. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +788 -0
  106. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  107. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  108. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  109. package/src/components/CnSchemaFormDialog/index.js +1 -0
  110. package/src/components/CnSettingsCard/CnSettingsCard.vue +92 -92
  111. package/src/components/CnSettingsCard/index.js +1 -1
  112. package/src/components/CnSettingsSection/CnSettingsSection.vue +267 -266
  113. package/src/components/CnSettingsSection/index.js +1 -1
  114. package/src/components/CnStatsBlock/CnStatsBlock.vue +437 -366
  115. package/src/components/CnStatsBlock/index.js +1 -1
  116. package/src/components/CnStatsPanel/CnStatsPanel.vue +321 -0
  117. package/src/components/CnStatsPanel/index.js +1 -0
  118. package/src/components/CnStatusBadge/CnStatusBadge.vue +90 -77
  119. package/src/components/CnStatusBadge/index.js +1 -1
  120. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +545 -0
  121. package/src/components/CnTabbedFormDialog/index.js +1 -0
  122. package/src/components/CnTableWidget/CnTableWidget.vue +333 -0
  123. package/src/components/CnTableWidget/index.js +1 -0
  124. package/src/components/CnTasksCard/CnTasksCard.vue +374 -0
  125. package/src/components/CnTasksCard/index.js +1 -0
  126. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  127. package/src/components/CnTileWidget/index.js +1 -0
  128. package/src/components/CnTimelineStages/CnTimelineStages.vue +294 -0
  129. package/src/components/CnTimelineStages/index.js +1 -0
  130. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +436 -0
  131. package/src/components/CnUserActionMenu/index.js +1 -0
  132. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +313 -312
  133. package/src/components/CnVersionInfoCard/index.js +1 -1
  134. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  135. package/src/components/CnWidgetRenderer/index.js +1 -0
  136. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +248 -0
  137. package/src/components/CnWidgetWrapper/index.js +1 -0
  138. package/src/components/index.js +57 -25
  139. package/src/composables/index.js +5 -3
  140. package/src/composables/useContextMenu.js +126 -0
  141. package/src/composables/useDashboardView.js +286 -0
  142. package/src/composables/useDetailView.js +290 -132
  143. package/src/composables/useListView.js +364 -153
  144. package/src/composables/useSubResource.js +142 -142
  145. package/src/constants/metadata.js +30 -0
  146. package/src/css/CnSchemaFormDialog.css +546 -0
  147. package/src/css/__sample_nextcloud_tokens.css +110 -0
  148. package/src/css/actions-bar.css +54 -0
  149. package/src/css/badge.css +83 -51
  150. package/src/css/card.css +129 -128
  151. package/src/css/context-menu.css +20 -0
  152. package/src/css/dashboard.css +70 -0
  153. package/src/css/detail-page.css +235 -0
  154. package/src/css/detail.css +68 -68
  155. package/src/css/index-page.css +44 -0
  156. package/src/css/index-sidebar.css +193 -0
  157. package/src/css/index.css +17 -8
  158. package/src/css/layout.css +90 -90
  159. package/src/css/page-header.css +35 -0
  160. package/src/css/pagination.css +72 -72
  161. package/src/css/table.css +142 -143
  162. package/src/css/timeline-stages.css +220 -0
  163. package/src/css/utilities.css +46 -46
  164. package/src/index.js +95 -50
  165. package/src/l10n/index.js +12 -0
  166. package/src/mixins/gridLayout.js +118 -0
  167. package/src/store/createCrudStore.d.ts +350 -0
  168. package/src/store/createCrudStore.js +413 -0
  169. package/src/store/createSubResourcePlugin.js +125 -135
  170. package/src/store/index.js +4 -3
  171. package/src/store/pluginMerge.js +55 -0
  172. package/src/store/plugins/auditTrails.js +357 -17
  173. package/src/store/plugins/files.js +250 -186
  174. package/src/store/plugins/index.js +8 -4
  175. package/src/store/plugins/lifecycle.js +180 -180
  176. package/src/store/plugins/logs.d.ts +22 -0
  177. package/src/store/plugins/logs.js +172 -0
  178. package/src/store/plugins/registerMapping.js +195 -0
  179. package/src/store/plugins/relations.js +68 -68
  180. package/src/store/plugins/search.js +385 -0
  181. package/src/store/plugins/selection.js +104 -0
  182. package/src/store/useObjectStore.js +793 -625
  183. package/src/types/auditTrail.d.ts +32 -32
  184. package/src/types/file.d.ts +23 -23
  185. package/src/types/index.d.ts +67 -35
  186. package/src/types/notification.d.ts +36 -36
  187. package/src/types/object.d.ts +40 -40
  188. package/src/types/organisation.d.ts +41 -41
  189. package/src/types/register.d.ts +25 -25
  190. package/src/types/schema.d.ts +39 -39
  191. package/src/types/shared.d.ts +79 -79
  192. package/src/types/source.d.ts +14 -14
  193. package/src/types/task.d.ts +31 -31
  194. package/src/utils/errors.js +96 -96
  195. package/src/utils/getTheme.js +9 -0
  196. package/src/utils/headers.js +80 -44
  197. package/src/utils/id.js +13 -0
  198. package/src/utils/index.js +4 -3
  199. package/src/utils/schema.js +423 -287
  200. package/src/utils/widgetVisibility.js +162 -0
  201. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  202. package/src/components/CnDetailViewLayout/index.js +0 -1
  203. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  204. package/src/components/CnEmptyState/index.js +0 -1
  205. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  206. package/src/components/CnListViewLayout/index.js +0 -1
  207. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  208. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -1 +1 @@
1
- export { default as CnStatsBlock } from './CnStatsBlock.vue'
1
+ export { default as CnStatsBlock } from './CnStatsBlock.vue'
@@ -0,0 +1,321 @@
1
+ <template>
2
+ <div class="cn-stats-panel">
3
+ <!-- Header slot for filters/selectors -->
4
+ <div v-if="$slots.header" class="cn-stats-panel__header">
5
+ <slot name="header" />
6
+ </div>
7
+
8
+ <!-- Global loading state -->
9
+ <div v-if="loading" class="cn-stats-panel__loading">
10
+ <NcLoadingIcon :size="20" />
11
+ <span>{{ loadingLabel }}</span>
12
+ </div>
13
+
14
+ <!-- Sections -->
15
+ <template v-else>
16
+ <div
17
+ v-for="section in sections"
18
+ :key="section.id"
19
+ class="cn-stats-panel__section">
20
+ <!-- Section title -->
21
+ <h4 v-if="section.title" class="cn-stats-panel__section-title">
22
+ {{ section.title }}
23
+ </h4>
24
+
25
+ <!-- Section-level loading -->
26
+ <div v-if="section.loading" class="cn-stats-panel__loading">
27
+ <NcLoadingIcon :size="20" />
28
+ <span>{{ loadingLabel }}</span>
29
+ </div>
30
+
31
+ <!-- Empty section -->
32
+ <div v-else-if="!section.items || !section.items.length" class="cn-stats-panel__empty">
33
+ {{ section.emptyLabel || emptyLabel }}
34
+ </div>
35
+
36
+ <!-- Stats section -->
37
+ <template v-else-if="section.type === 'stats'">
38
+ <slot :name="'section-' + section.id" :section="section">
39
+ <!-- Stack layout -->
40
+ <div v-if="section.layout === 'stack'" class="cn-stats-panel__stack">
41
+ <CnStatsBlock
42
+ v-for="(item, index) in section.items"
43
+ :key="index"
44
+ :title="item.title"
45
+ :count="item.count"
46
+ :count-label="item.countLabel"
47
+ :variant="item.variant || 'default'"
48
+ :icon="isComponentIcon(item.icon) ? item.icon : null"
49
+ :icon-size="item.iconSize || 24"
50
+ :horizontal="item.horizontal !== undefined ? item.horizontal : true"
51
+ :show-zero-count="item.showZeroCount !== undefined ? item.showZeroCount : true"
52
+ :breakdown="item.breakdown || null"
53
+ :route="item.route || null"
54
+ :clickable="item.clickable || false"
55
+ :loading="item.loading || false"
56
+ @click="$emit('stat-click', { section: section.id, item, index })">
57
+ <template v-if="typeof item.icon === 'string'" #icon>
58
+ <CnIcon :name="item.icon" :size="item.iconSize || 24" />
59
+ </template>
60
+ </CnStatsBlock>
61
+ </div>
62
+
63
+ <!-- Grid layout -->
64
+ <CnKpiGrid
65
+ v-else-if="section.layout === 'grid'"
66
+ grid-class="remove-margin"
67
+ :columns="section.columns || 2">
68
+ <CnStatsBlock
69
+ v-for="(item, index) in section.items"
70
+ :key="index"
71
+ :title="item.title"
72
+ :count="item.count"
73
+ :count-label="item.countLabel"
74
+ :variant="item.variant || 'default'"
75
+ :icon="isComponentIcon(item.icon) ? item.icon : null"
76
+ :icon-size="item.iconSize || 24"
77
+ :horizontal="item.horizontal !== undefined ? item.horizontal : false"
78
+ :show-zero-count="item.showZeroCount !== undefined ? item.showZeroCount : true"
79
+ :breakdown="item.breakdown || null"
80
+ :route="item.route || null"
81
+ :clickable="item.clickable || false"
82
+ :loading="item.loading || false"
83
+ @click="$emit('stat-click', { section: section.id, item, index })">
84
+ <template v-if="typeof item.icon === 'string'" #icon>
85
+ <CnIcon :name="item.icon" :size="item.iconSize || 24" />
86
+ </template>
87
+ </CnStatsBlock>
88
+ </CnKpiGrid>
89
+ </slot>
90
+ </template>
91
+
92
+ <!-- Progress section -->
93
+ <template v-else-if="section.type === 'progress'">
94
+ <slot :name="'section-' + section.id" :section="section">
95
+ <CnProgressBar
96
+ :items="section.items"
97
+ :variant="section.variant || 'primary'"
98
+ :bar-height="section.barHeight || 8"
99
+ :rounded="section.rounded !== undefined ? section.rounded : true"
100
+ :show-percentage="section.showPercentage || false" />
101
+ </slot>
102
+ </template>
103
+
104
+ <!-- List section -->
105
+ <template v-else-if="section.type === 'list'">
106
+ <slot :name="'section-' + section.id" :section="section">
107
+ <div class="cn-stats-panel__list">
108
+ <NcListItem
109
+ v-for="item in section.items"
110
+ :key="item.key"
111
+ :name="item.name"
112
+ :bold="item.bold || false"
113
+ @click="$emit('list-click', { section: section.id, item })">
114
+ <template #icon>
115
+ <slot :name="'item-icon-' + section.id" :item="item">
116
+ <CnIcon
117
+ v-if="typeof item.icon === 'string'"
118
+ :name="item.icon"
119
+ :size="item.iconSize || 32" />
120
+ <component
121
+ :is="item.icon"
122
+ v-else-if="item.icon"
123
+ :size="item.iconSize || 32" />
124
+ </slot>
125
+ </template>
126
+ <template #subname>
127
+ <slot :name="'item-subname-' + section.id" :item="item">
128
+ {{ item.subname }}
129
+ </slot>
130
+ </template>
131
+ </NcListItem>
132
+ </div>
133
+ </slot>
134
+ </template>
135
+ </div>
136
+ </template>
137
+
138
+ <!-- Footer slot -->
139
+ <div v-if="$slots.footer" class="cn-stats-panel__footer">
140
+ <slot name="footer" />
141
+ </div>
142
+ </div>
143
+ </template>
144
+
145
+ <script>
146
+ import { translate as t } from '@nextcloud/l10n'
147
+ import { NcLoadingIcon, NcListItem } from '@nextcloud/vue'
148
+ import { CnStatsBlock } from '../CnStatsBlock/index.js'
149
+ import { CnKpiGrid } from '../CnKpiGrid/index.js'
150
+ import { CnIcon } from '../CnIcon/index.js'
151
+ import { CnProgressBar } from '../CnProgressBar/index.js'
152
+
153
+ /**
154
+ * CnStatsPanel — Configurable statistics panel with sections of stat blocks and list items.
155
+ *
156
+ * Renders statistics content from a declarative sections array. Each section can be
157
+ * either a 'stats' section (renders CnStatsBlocks in stack or grid layout) or a
158
+ * 'list' section (renders NcListItems). Suitable for sidebar tabs, dashboard widgets,
159
+ * or any panel that displays statistics.
160
+ *
161
+ * @example Stats stack (vertical)
162
+ * <CnStatsPanel :sections="[{
163
+ * type: 'stats',
164
+ * id: 'totals',
165
+ * title: 'System Totals',
166
+ * layout: 'stack',
167
+ * items: [
168
+ * { title: 'Objects', count: 42, countLabel: 'objects', variant: 'primary', icon: PackageIcon },
169
+ * { title: 'Files', count: 128, countLabel: 'files', icon: FileIcon },
170
+ * ],
171
+ * }]" />
172
+ *
173
+ * @example Stats grid (2-column)
174
+ * <CnStatsPanel :sections="[{
175
+ * type: 'stats',
176
+ * id: 'operations',
177
+ * title: 'Operations',
178
+ * layout: 'grid',
179
+ * columns: 2,
180
+ * items: [
181
+ * { title: 'Create', count: 10, countLabel: 'ops', variant: 'success', icon: PlusIcon },
182
+ * { title: 'Delete', count: 3, countLabel: 'ops', variant: 'error', icon: DeleteIcon },
183
+ * ],
184
+ * }]" />
185
+ *
186
+ * @example List section
187
+ * <CnStatsPanel :sections="[{
188
+ * type: 'list',
189
+ * id: 'topObjects',
190
+ * title: 'Most Active',
191
+ * items: [
192
+ * { key: '1', name: 'Object A', subname: '42 entries', icon: CogIcon },
193
+ * ],
194
+ * }]" />
195
+ *
196
+ * @example With header slot for filters
197
+ * <CnStatsPanel :sections="sections">
198
+ * <template #header>
199
+ * <NcSelect v-bind="registerOptions" />
200
+ * </template>
201
+ * </CnStatsPanel>
202
+ */
203
+ export default {
204
+ name: 'CnStatsPanel',
205
+
206
+ components: {
207
+ NcLoadingIcon,
208
+ NcListItem,
209
+ CnStatsBlock,
210
+ CnKpiGrid,
211
+ CnIcon,
212
+ CnProgressBar,
213
+ },
214
+
215
+ props: {
216
+ /**
217
+ * Array of section definitions to render.
218
+ * Each section has a `type` of 'stats', 'list', or 'progress'.
219
+ *
220
+ * Stats sections: `{ type: 'stats', id, title, layout: 'stack'|'grid', columns?, loading?, items: StatItem[] }`
221
+ * List sections: `{ type: 'list', id, title, loading?, items: ListItem[] }`
222
+ * Progress sections: `{ type: 'progress', id, title, variant?, barHeight?, rounded?, showPercentage?, loading?, items: ProgressItem[] }`
223
+ *
224
+ * StatItem: `{ title, count, countLabel, variant?, icon?, iconSize?, horizontal?, showZeroCount?, breakdown?, route?, clickable?, loading? }`
225
+ * ListItem: `{ key, name, subname?, bold?, icon?, iconSize? }`
226
+ * ProgressItem: `{ key?, label, count?, percentage?, variant?, tooltip? }`
227
+ */
228
+ sections: {
229
+ type: Array,
230
+ default: () => [],
231
+ },
232
+
233
+ /** Whether the entire panel is in a loading state */
234
+ loading: {
235
+ type: Boolean,
236
+ default: false,
237
+ },
238
+
239
+ /** Label shown during loading state */
240
+ loadingLabel: {
241
+ type: String,
242
+ default: () => t('nextcloud-vue', 'Loading...'),
243
+ },
244
+
245
+ /** Default text shown when a section has no items. Can be overridden per section via `section.emptyLabel`. */
246
+ emptyLabel: {
247
+ type: String,
248
+ default: () => t('nextcloud-vue', 'No data available'),
249
+ },
250
+ },
251
+
252
+ emits: ['stat-click', 'list-click', 'progress-click'],
253
+
254
+ methods: {
255
+ /**
256
+ * Check if an icon value is a component reference (not a string name).
257
+ * @param {*} icon - Icon value to check
258
+ * @return {boolean}
259
+ */
260
+ isComponentIcon(icon) {
261
+ return icon != null && typeof icon !== 'string'
262
+ },
263
+ },
264
+ }
265
+ </script>
266
+
267
+ <style scoped>
268
+ .cn-stats-panel__section {
269
+ padding: 12px 0;
270
+ border-bottom: 1px solid var(--color-border);
271
+ }
272
+
273
+ .remove-margin {
274
+ margin: 0;
275
+ }
276
+
277
+ .cn-stats-panel__section:last-child {
278
+ border-bottom: none;
279
+ }
280
+
281
+ .cn-stats-panel__section-title {
282
+ color: var(--color-text-maxcontrast);
283
+ font-size: 14px;
284
+ font-weight: bold;
285
+ padding: 0 16px;
286
+ margin: 0 0 12px 0;
287
+ }
288
+
289
+ .cn-stats-panel__stack {
290
+ display: flex;
291
+ flex-direction: column;
292
+ gap: 12px;
293
+ }
294
+
295
+ .cn-stats-panel__loading {
296
+ display: flex;
297
+ align-items: center;
298
+ gap: 8px;
299
+ padding: 0 16px;
300
+ color: var(--color-text-maxcontrast);
301
+ }
302
+
303
+ .cn-stats-panel__empty {
304
+ padding: 0 16px;
305
+ color: var(--color-text-maxcontrast);
306
+ font-style: italic;
307
+ }
308
+
309
+ .cn-stats-panel__header {
310
+ padding-bottom: 12px;
311
+ border-bottom: 1px solid var(--color-border);
312
+ }
313
+
314
+ .cn-stats-panel__footer {
315
+ padding-top: 12px;
316
+ }
317
+
318
+ .cn-stats-panel__list {
319
+ margin-top: 4px;
320
+ }
321
+ </style>
@@ -0,0 +1 @@
1
+ export { default as CnStatsPanel } from './CnStatsPanel.vue'
@@ -1,77 +1,90 @@
1
- <template>
2
- <span
3
- class="cn-status-badge"
4
- :class="badgeClasses">
5
- <slot>{{ label }}</slot>
6
- </span>
7
- </template>
8
-
9
- <script>
10
- /**
11
- * CnStatusBadge — Color-coded pill badge for status, priority, or category display.
12
- *
13
- * Replaces the various .status-badge / .priority-badge CSS patterns duplicated
14
- * across Pipelinq and Procest. Supports a colorMap for automatic variant lookup.
15
- *
16
- * @example
17
- * <CnStatusBadge label="Open" variant="success" />
18
- * <CnStatusBadge label="Urgent" variant="error" size="small" />
19
- *
20
- * @example
21
- * <!-- With colorMap: variant auto-resolved from label -->
22
- * <CnStatusBadge
23
- * label="overdue"
24
- * :color-map="{ open: 'success', closed: 'default', overdue: 'error' }" />
25
- */
26
- export default {
27
- name: 'CnStatusBadge',
28
-
29
- props: {
30
- /** Badge label text */
31
- label: {
32
- type: String,
33
- default: '',
34
- },
35
- /**
36
- * Color variant: 'default', 'primary', 'success', 'warning', 'error', 'info'
37
- */
38
- variant: {
39
- type: String,
40
- default: 'default',
41
- validator: (v) => ['default', 'primary', 'success', 'warning', 'error', 'info'].includes(v),
42
- },
43
- /** Size: 'small' or 'medium' */
44
- size: {
45
- type: String,
46
- default: 'medium',
47
- validator: (v) => ['small', 'medium'].includes(v),
48
- },
49
- /**
50
- * Map of label values to variants. When provided, the variant is resolved
51
- * from this map using the label (case-insensitive). Falls back to the variant prop.
52
- * @example { open: 'success', closed: 'default', overdue: 'error' }
53
- */
54
- colorMap: {
55
- type: Object,
56
- default: null,
57
- },
58
- },
59
-
60
- computed: {
61
- resolvedVariant() {
62
- if (this.colorMap && this.label) {
63
- const key = this.label.toLowerCase()
64
- return this.colorMap[key] || this.variant
65
- }
66
- return this.variant
67
- },
68
-
69
- badgeClasses() {
70
- return {
71
- ['cn-status-badge--' + this.resolvedVariant]: true,
72
- 'cn-status-badge--small': this.size === 'small',
73
- }
74
- },
75
- },
76
- }
77
- </script>
1
+ <template>
2
+ <span
3
+ class="cn-status-badge"
4
+ :class="badgeClasses">
5
+ <slot>
6
+ <slot name="icon" />
7
+ {{ label }}
8
+ </slot>
9
+ </span>
10
+ </template>
11
+
12
+ <script>
13
+ /**
14
+ * CnStatusBadge Color-coded pill badge for status, priority, or category display.
15
+ *
16
+ * Replaces the various .status-badge / .priority-badge CSS patterns duplicated
17
+ * across Pipelinq and Procest. Supports a colorMap for automatic variant lookup.
18
+ *
19
+ * @example
20
+ * <CnStatusBadge label="Open" variant="success" />
21
+ * <CnStatusBadge label="Urgent" variant="error" size="small" />
22
+ *
23
+ * @example
24
+ * <!-- With colorMap: variant auto-resolved from label -->
25
+ * <CnStatusBadge
26
+ * label="overdue"
27
+ * :color-map="{ open: 'success', closed: 'default', overdue: 'error' }" />
28
+ */
29
+ export default {
30
+ name: 'CnStatusBadge',
31
+
32
+ props: {
33
+ /** Badge label text */
34
+ label: {
35
+ type: String,
36
+ default: '',
37
+ },
38
+ /**
39
+ * Color variant: 'default', 'primary', 'success', 'warning', 'error', 'info'
40
+ */
41
+ variant: {
42
+ type: String,
43
+ default: 'default',
44
+ validator: (v) => ['default', 'primary', 'success', 'warning', 'error', 'info'].includes(v),
45
+ },
46
+ /** Size: 'small' or 'medium' */
47
+ size: {
48
+ type: String,
49
+ default: 'medium',
50
+ validator: (v) => ['small', 'medium'].includes(v),
51
+ },
52
+ /**
53
+ * Use solid background with white text instead of light background with colored text.
54
+ * Useful when the badge is placed on a colored background (e.g., an active card).
55
+ */
56
+ solid: {
57
+ type: Boolean,
58
+ default: false,
59
+ },
60
+ /**
61
+ * Map of label values to variants. When provided, the variant is resolved
62
+ * from this map using the label (case-insensitive). Falls back to the variant prop.
63
+ * @example { open: 'success', closed: 'default', overdue: 'error' }
64
+ */
65
+ colorMap: {
66
+ type: Object,
67
+ default: null,
68
+ },
69
+ },
70
+
71
+ computed: {
72
+ resolvedVariant() {
73
+ if (this.colorMap && this.label) {
74
+ const key = this.label.toLowerCase()
75
+ const normalizedColorMap = Object.fromEntries(Object.entries(this.colorMap).map(([k, v]) => [k.toLowerCase(), v]))
76
+ return normalizedColorMap[key] || this.variant
77
+ }
78
+ return this.variant
79
+ },
80
+
81
+ badgeClasses() {
82
+ return {
83
+ ['cn-status-badge--' + this.resolvedVariant]: true,
84
+ 'cn-status-badge--small': this.size === 'small',
85
+ 'cn-status-badge--solid': this.solid,
86
+ }
87
+ },
88
+ },
89
+ }
90
+ </script>
@@ -1 +1 @@
1
- export { default as CnStatusBadge } from './CnStatusBadge.vue'
1
+ export { default as CnStatusBadge } from './CnStatusBadge.vue'