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

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 (197) hide show
  1. package/README.md +226 -0
  2. package/css/index.css +5 -0
  3. package/dist/nextcloud-vue.cjs +67614 -0
  4. package/dist/nextcloud-vue.cjs.js +76311 -5905
  5. package/dist/nextcloud-vue.cjs.js.map +1 -1
  6. package/dist/nextcloud-vue.cjs.map +1 -0
  7. package/dist/nextcloud-vue.css +3279 -203
  8. package/dist/nextcloud-vue.esm.js +76240 -5882
  9. package/dist/nextcloud-vue.esm.js.map +1 -1
  10. package/package.json +89 -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 +569 -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 +23 -20
  22. package/src/components/CnCardGrid/index.js +1 -1
  23. package/src/components/CnCellRenderer/index.js +1 -1
  24. package/src/components/CnChartWidget/CnChartWidget.vue +318 -0
  25. package/src/components/CnChartWidget/index.js +1 -0
  26. package/src/components/CnConfigurationCard/index.js +1 -1
  27. package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
  28. package/src/components/CnContextMenu/index.js +1 -0
  29. package/src/components/CnCopyDialog/CnCopyDialog.vue +257 -0
  30. package/src/components/CnCopyDialog/index.js +1 -0
  31. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
  32. package/src/components/CnDashboardGrid/index.js +1 -0
  33. package/src/components/CnDashboardPage/CnDashboardPage.vue +396 -0
  34. package/src/components/CnDashboardPage/index.js +1 -0
  35. package/src/components/CnDataTable/CnDataTable.vue +24 -16
  36. package/src/components/CnDataTable/index.js +1 -1
  37. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
  38. package/src/components/CnDeleteDialog/index.js +1 -0
  39. package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
  40. package/src/components/CnDetailCard/index.js +1 -0
  41. package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
  42. package/src/components/CnDetailGrid/index.js +1 -0
  43. package/src/components/CnDetailPage/CnDetailPage.vue +431 -0
  44. package/src/components/CnDetailPage/index.js +1 -0
  45. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +12 -2
  46. package/src/components/CnFacetSidebar/index.js +1 -1
  47. package/src/components/CnFilterBar/index.js +1 -1
  48. package/src/components/CnFormDialog/CnFormDialog.vue +934 -0
  49. package/src/components/CnFormDialog/index.js +1 -0
  50. package/src/components/CnIcon/CnIcon.vue +89 -0
  51. package/src/components/CnIcon/index.js +1 -0
  52. package/src/components/CnIndexPage/CnIndexPage.vue +589 -291
  53. package/src/components/CnIndexPage/index.js +1 -1
  54. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +535 -0
  55. package/src/components/CnIndexSidebar/index.js +1 -0
  56. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  57. package/src/components/CnInfoWidget/index.js +1 -0
  58. package/src/components/CnItemCard/CnItemCard.vue +134 -0
  59. package/src/components/CnItemCard/index.js +1 -0
  60. package/src/components/CnJsonViewer/CnJsonViewer.vue +283 -0
  61. package/src/components/CnJsonViewer/index.js +1 -0
  62. package/src/components/CnKpiGrid/CnKpiGrid.vue +5 -1
  63. package/src/components/CnKpiGrid/index.js +1 -1
  64. package/src/components/CnMassActionBar/CnMassActionBar.vue +6 -5
  65. package/src/components/CnMassActionBar/index.js +1 -1
  66. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +16 -9
  67. package/src/components/CnMassCopyDialog/index.js +1 -1
  68. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +16 -9
  69. package/src/components/CnMassDeleteDialog/index.js +1 -1
  70. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +8 -7
  71. package/src/components/CnMassExportDialog/index.js +1 -1
  72. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +20 -17
  73. package/src/components/CnMassImportDialog/index.js +1 -1
  74. package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
  75. package/src/components/CnNoteCard/index.js +1 -0
  76. package/src/components/CnNotesCard/CnNotesCard.vue +415 -0
  77. package/src/components/CnNotesCard/index.js +1 -0
  78. package/src/components/CnObjectCard/CnObjectCard.vue +3 -1
  79. package/src/components/CnObjectCard/index.js +1 -1
  80. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +853 -0
  81. package/src/components/CnObjectDataWidget/index.js +1 -0
  82. package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +288 -0
  83. package/src/components/CnObjectMetadataWidget/index.js +1 -0
  84. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +368 -0
  85. package/src/components/CnObjectSidebar/CnFilesTab.vue +286 -0
  86. package/src/components/CnObjectSidebar/CnNotesTab.vue +249 -0
  87. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +254 -0
  88. package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
  89. package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
  90. package/src/components/CnObjectSidebar/index.js +6 -0
  91. package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
  92. package/src/components/CnPageHeader/index.js +1 -0
  93. package/src/components/CnPagination/CnPagination.vue +7 -6
  94. package/src/components/CnPagination/index.js +1 -1
  95. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  96. package/src/components/CnProgressBar/index.js +1 -0
  97. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -0
  98. package/src/components/CnRegisterMapping/index.js +1 -0
  99. package/src/components/CnRowActions/CnRowActions.vue +25 -3
  100. package/src/components/CnRowActions/index.js +1 -1
  101. package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
  102. package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
  103. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
  104. package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
  105. package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
  106. package/src/components/CnSchemaFormDialog/index.js +1 -0
  107. package/src/components/CnSettingsCard/index.js +1 -1
  108. package/src/components/CnSettingsSection/index.js +1 -1
  109. package/src/components/CnStatsBlock/CnStatsBlock.vue +89 -19
  110. package/src/components/CnStatsBlock/index.js +1 -1
  111. package/src/components/CnStatsPanel/CnStatsPanel.vue +320 -0
  112. package/src/components/CnStatsPanel/index.js +1 -0
  113. package/src/components/CnStatusBadge/CnStatusBadge.vue +15 -2
  114. package/src/components/CnStatusBadge/index.js +1 -1
  115. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +544 -0
  116. package/src/components/CnTabbedFormDialog/index.js +1 -0
  117. package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
  118. package/src/components/CnTableWidget/index.js +1 -0
  119. package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
  120. package/src/components/CnTasksCard/index.js +1 -0
  121. package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
  122. package/src/components/CnTileWidget/index.js +1 -0
  123. package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
  124. package/src/components/CnTimelineStages/index.js +1 -0
  125. package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
  126. package/src/components/CnUserActionMenu/index.js +1 -0
  127. package/src/components/CnVersionInfoCard/index.js +1 -1
  128. package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
  129. package/src/components/CnWidgetRenderer/index.js +1 -0
  130. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +246 -0
  131. package/src/components/CnWidgetWrapper/index.js +1 -0
  132. package/src/components/index.js +57 -25
  133. package/src/composables/index.js +5 -3
  134. package/src/composables/useContextMenu.js +126 -0
  135. package/src/composables/useDashboardView.js +286 -0
  136. package/src/composables/useDetailView.js +290 -132
  137. package/src/composables/useListView.js +364 -153
  138. package/src/composables/useSubResource.js +142 -142
  139. package/src/constants/metadata.js +30 -0
  140. package/src/css/CnSchemaFormDialog.css +546 -0
  141. package/src/css/__sample_nextcloud_tokens.css +110 -0
  142. package/src/css/actions-bar.css +54 -0
  143. package/src/css/badge.css +83 -51
  144. package/src/css/card.css +129 -128
  145. package/src/css/context-menu.css +20 -0
  146. package/src/css/dashboard.css +70 -0
  147. package/src/css/detail-page.css +235 -0
  148. package/src/css/detail.css +68 -68
  149. package/src/css/index-page.css +44 -0
  150. package/src/css/index-sidebar.css +193 -0
  151. package/src/css/index.css +17 -8
  152. package/src/css/layout.css +90 -90
  153. package/src/css/page-header.css +35 -0
  154. package/src/css/pagination.css +72 -72
  155. package/src/css/table.css +142 -143
  156. package/src/css/timeline-stages.css +220 -0
  157. package/src/css/utilities.css +46 -46
  158. package/src/index.js +91 -50
  159. package/src/mixins/gridLayout.js +118 -0
  160. package/src/store/createCrudStore.js +360 -0
  161. package/src/store/createSubResourcePlugin.js +125 -135
  162. package/src/store/index.js +4 -3
  163. package/src/store/plugins/auditTrails.js +357 -17
  164. package/src/store/plugins/files.js +250 -186
  165. package/src/store/plugins/index.js +7 -4
  166. package/src/store/plugins/lifecycle.js +180 -180
  167. package/src/store/plugins/registerMapping.js +195 -0
  168. package/src/store/plugins/relations.js +68 -68
  169. package/src/store/plugins/search.js +385 -0
  170. package/src/store/plugins/selection.js +104 -0
  171. package/src/store/useObjectStore.js +823 -625
  172. package/src/types/auditTrail.d.ts +32 -32
  173. package/src/types/file.d.ts +23 -23
  174. package/src/types/index.d.ts +35 -35
  175. package/src/types/notification.d.ts +36 -36
  176. package/src/types/object.d.ts +40 -40
  177. package/src/types/organisation.d.ts +41 -41
  178. package/src/types/register.d.ts +25 -25
  179. package/src/types/schema.d.ts +39 -39
  180. package/src/types/shared.d.ts +79 -79
  181. package/src/types/source.d.ts +14 -14
  182. package/src/types/task.d.ts +31 -31
  183. package/src/utils/errors.js +96 -96
  184. package/src/utils/getTheme.js +9 -0
  185. package/src/utils/headers.js +80 -44
  186. package/src/utils/id.js +13 -0
  187. package/src/utils/index.js +4 -3
  188. package/src/utils/schema.js +422 -287
  189. package/src/utils/widgetVisibility.js +162 -0
  190. package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
  191. package/src/components/CnDetailViewLayout/index.js +0 -1
  192. package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
  193. package/src/components/CnEmptyState/index.js +0 -1
  194. package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
  195. package/src/components/CnListViewLayout/index.js +0 -1
  196. package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
  197. package/src/components/CnViewModeToggle/index.js +0 -1
@@ -0,0 +1,286 @@
1
+ import { ref, computed, onMounted } from 'vue'
2
+ import axios from '@nextcloud/axios'
3
+ import { generateOcsUrl } from '@nextcloud/router'
4
+ import { filterWidgetsByVisibility } from '../utils/widgetVisibility.js'
5
+
6
+ /**
7
+ * Composable for managing dashboard view state.
8
+ *
9
+ * Handles widget definition loading (including NC Dashboard API widgets),
10
+ * layout management, edit mode, and role-based widget visibility filtering.
11
+ *
12
+ * Widgets can specify a `visibility` property to control which users see them:
13
+ * ```js
14
+ * {
15
+ * id: 'kcc-search',
16
+ * type: 'custom',
17
+ * title: 'Quick Search',
18
+ * visibility: {
19
+ * users: ['admin'], // specific user IDs (optional)
20
+ * groups: ['KCC', 'Admins'], // Nextcloud group names (optional)
21
+ * }
22
+ * }
23
+ * ```
24
+ * If `visibility` is not set or both arrays are empty, the widget is visible to everyone.
25
+ *
26
+ * @param {object} [options] Configuration options
27
+ * @param {Array} [options.widgets] Static widget definitions from the app
28
+ * @param {Array} [options.defaultLayout] Default layout if no saved layout exists
29
+ * @param {Function} [options.loadLayout] Async function that returns saved layout array, or null
30
+ * @param {Function} [options.saveLayout] Async function that persists layout: (layout) => Promise
31
+ * @param {boolean} [options.includeNcWidgets] Whether to also load NC Dashboard API widgets
32
+ * @param {number} [options.columns] Grid columns
33
+ * @return {object} Reactive state and methods for CnDashboardPage
34
+ *
35
+ * @example Basic usage with static widgets
36
+ * const { widgets, layout, loading, onLayoutChange } = useDashboardView({
37
+ * widgets: [
38
+ * { id: 'kpis', title: 'KPIs', type: 'custom' },
39
+ * { id: 'chart', title: 'Status Chart', type: 'custom' },
40
+ * ],
41
+ * defaultLayout: [
42
+ * { id: 1, widgetId: 'kpis', gridX: 0, gridY: 0, gridWidth: 12, gridHeight: 2 },
43
+ * { id: 2, widgetId: 'chart', gridX: 0, gridY: 2, gridWidth: 6, gridHeight: 4 },
44
+ * ],
45
+ * })
46
+ *
47
+ * @example With persistence and NC widgets
48
+ * const dashboard = useDashboardView({
49
+ * widgets: myWidgets,
50
+ * defaultLayout: defaultLayout,
51
+ * loadLayout: () => fetch('/api/dashboard-layout').then(r => r.json()),
52
+ * saveLayout: (layout) => fetch('/api/dashboard-layout', { method: 'PUT', body: JSON.stringify(layout) }),
53
+ * includeNcWidgets: true,
54
+ * })
55
+ *
56
+ * @example With role-based visibility
57
+ * const dashboard = useDashboardView({
58
+ * widgets: [
59
+ * { id: 'admin-panel', title: 'Admin Panel', type: 'custom', visibility: { groups: ['admin'] } },
60
+ * { id: 'kcc-search', title: 'KCC Search', type: 'custom', visibility: { groups: ['KCC'] } },
61
+ * { id: 'public-info', title: 'Info', type: 'custom' }, // visible to everyone
62
+ * ],
63
+ * defaultLayout: [...],
64
+ * })
65
+ */
66
+ export function useDashboardView(options = {}) {
67
+ const opts = {
68
+ widgets: [],
69
+ defaultLayout: [],
70
+ loadLayout: null,
71
+ saveLayout: null,
72
+ includeNcWidgets: false,
73
+ columns: 12,
74
+ ...options,
75
+ }
76
+
77
+ // ── State ────────────────────────────────────────────────────────────
78
+ const appWidgets = ref(opts.widgets)
79
+ const ncWidgets = ref([])
80
+ const visibleAppWidgets = ref([])
81
+ const visibleNcWidgets = ref([])
82
+ const layout = ref([])
83
+ const loading = ref(false)
84
+ const saving = ref(false)
85
+ const isEditing = ref(false)
86
+
87
+ // ── Computed ─────────────────────────────────────────────────────────
88
+
89
+ /** All available widgets (app + NC Dashboard API), filtered by visibility */
90
+ const widgets = computed(() => {
91
+ return [...visibleAppWidgets.value, ...visibleNcWidgets.value]
92
+ })
93
+
94
+ /** Widget IDs currently on the dashboard */
95
+ const activeWidgetIds = computed(() => {
96
+ return layout.value.map(item => item.widgetId)
97
+ })
98
+
99
+ /** Widgets not yet placed on the dashboard */
100
+ const availableWidgets = computed(() => {
101
+ return widgets.value.filter(w => !activeWidgetIds.value.includes(w.id))
102
+ })
103
+
104
+ // ── Methods ──────────────────────────────────────────────────────────
105
+
106
+ /**
107
+ * Apply visibility filtering to the current widget sets and update
108
+ * the layout to remove items whose widgets are no longer visible.
109
+ */
110
+ async function applyVisibilityFilter() {
111
+ visibleAppWidgets.value = await filterWidgetsByVisibility(appWidgets.value)
112
+ visibleNcWidgets.value = await filterWidgetsByVisibility(ncWidgets.value)
113
+
114
+ // Remove layout items that reference widgets the user cannot see
115
+ const visibleIds = new Set(widgets.value.map(w => w.id))
116
+ const filteredLayout = layout.value.filter(item => visibleIds.has(item.widgetId))
117
+ if (filteredLayout.length !== layout.value.length) {
118
+ layout.value = filteredLayout
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Load NC Dashboard API widgets from the OCS endpoint.
124
+ */
125
+ async function loadNcWidgets() {
126
+ try {
127
+ const url = generateOcsUrl('/apps/dashboard/api/v1/widgets')
128
+ const response = await axios.get(url)
129
+ const data = response.data?.ocs?.data || {}
130
+
131
+ ncWidgets.value = Object.values(data).map(w => ({
132
+ id: w.id,
133
+ title: w.title,
134
+ iconClass: w.icon_class,
135
+ iconUrl: w.icon_url,
136
+ widgetUrl: w.widget_url,
137
+ itemApiVersions: w.item_api_versions || [],
138
+ itemIconsRound: w.item_icons_round || false,
139
+ reloadInterval: w.reload_interval || 0,
140
+ buttons: w.buttons || [],
141
+ type: 'nc-widget',
142
+ }))
143
+ } catch (error) {
144
+ console.error('[useDashboardView] Failed to load NC widgets:', error)
145
+ ncWidgets.value = []
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Initialize the dashboard: load layout and optionally NC widgets.
151
+ */
152
+ async function init() {
153
+ loading.value = true
154
+ try {
155
+ const tasks = []
156
+
157
+ if (opts.includeNcWidgets) {
158
+ tasks.push(loadNcWidgets())
159
+ }
160
+
161
+ if (opts.loadLayout) {
162
+ tasks.push(
163
+ opts.loadLayout().then(saved => {
164
+ if (saved && saved.length > 0) {
165
+ layout.value = saved
166
+ } else {
167
+ layout.value = [...opts.defaultLayout]
168
+ }
169
+ }),
170
+ )
171
+ } else {
172
+ layout.value = [...opts.defaultLayout]
173
+ }
174
+
175
+ await Promise.all(tasks)
176
+
177
+ // Apply visibility filtering after all data is loaded
178
+ await applyVisibilityFilter()
179
+ } catch (error) {
180
+ console.error('[useDashboardView] Init failed:', error)
181
+ layout.value = [...opts.defaultLayout]
182
+ } finally {
183
+ loading.value = false
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Handle layout change from the grid. Persists if saveLayout is provided.
189
+ *
190
+ * @param {Array} newLayout Updated layout array
191
+ */
192
+ async function onLayoutChange(newLayout) {
193
+ layout.value = newLayout
194
+
195
+ if (opts.saveLayout) {
196
+ saving.value = true
197
+ try {
198
+ await opts.saveLayout(newLayout)
199
+ } catch (error) {
200
+ console.error('[useDashboardView] Failed to save layout:', error)
201
+ } finally {
202
+ saving.value = false
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Add a widget to the dashboard at the next available position.
209
+ *
210
+ * @param {string} widgetId Widget ID to add
211
+ * @param {object} [position] Override position { gridX, gridY, gridWidth, gridHeight }
212
+ */
213
+ function addWidget(widgetId, position = {}) {
214
+ const maxId = layout.value.reduce((max, item) => {
215
+ const num = typeof item.id === 'number' ? item.id : 0
216
+ return num > max ? num : max
217
+ }, 0)
218
+
219
+ const maxY = layout.value.reduce((max, item) => {
220
+ const bottom = (item.gridY || 0) + (item.gridHeight || 3)
221
+ return bottom > max ? bottom : max
222
+ }, 0)
223
+
224
+ const newItem = {
225
+ id: maxId + 1,
226
+ widgetId,
227
+ gridX: position.gridX ?? 0,
228
+ gridY: position.gridY ?? maxY,
229
+ gridWidth: position.gridWidth ?? 6,
230
+ gridHeight: position.gridHeight ?? 3,
231
+ }
232
+
233
+ const newLayout = [...layout.value, newItem]
234
+ onLayoutChange(newLayout)
235
+ }
236
+
237
+ /**
238
+ * Remove a widget from the dashboard by layout item ID.
239
+ *
240
+ * @param {string|number} itemId Layout item ID to remove
241
+ */
242
+ function removeWidget(itemId) {
243
+ const newLayout = layout.value.filter(item => item.id !== itemId)
244
+ onLayoutChange(newLayout)
245
+ }
246
+
247
+ /**
248
+ * Update app widget definitions (e.g., when data changes).
249
+ * Re-applies visibility filtering after update.
250
+ *
251
+ * @param {Array} newWidgets Updated widget definitions
252
+ */
253
+ async function setWidgets(newWidgets) {
254
+ appWidgets.value = newWidgets
255
+ await applyVisibilityFilter()
256
+ }
257
+
258
+ // ── Lifecycle ────────────────────────────────────────────────────────
259
+
260
+ onMounted(async () => {
261
+ await init()
262
+ })
263
+
264
+ // ── Return ───────────────────────────────────────────────────────────
265
+
266
+ return {
267
+ // State
268
+ widgets,
269
+ layout,
270
+ loading,
271
+ saving,
272
+ isEditing,
273
+
274
+ // Derived
275
+ activeWidgetIds,
276
+ availableWidgets,
277
+ ncWidgets,
278
+
279
+ // Methods
280
+ onLayoutChange,
281
+ addWidget,
282
+ removeWidget,
283
+ setWidgets,
284
+ init,
285
+ }
286
+ }