@conduction/nextcloud-vue 0.1.0-beta.6 → 0.1.0-beta.7

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 (82) hide show
  1. package/dist/nextcloud-vue.cjs.js +13606 -1918
  2. package/dist/nextcloud-vue.cjs.js.map +1 -1
  3. package/dist/nextcloud-vue.css +1238 -270
  4. package/dist/nextcloud-vue.esm.js +13548 -1880
  5. package/dist/nextcloud-vue.esm.js.map +1 -1
  6. package/package.json +9 -4
  7. package/src/components/CnActionsBar/CnActionsBar.vue +6 -1
  8. package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +1 -11
  9. package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +5 -1
  10. package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +1 -1
  11. package/src/components/CnCard/CnCard.vue +415 -0
  12. package/src/components/CnCard/index.js +1 -0
  13. package/src/components/CnCardGrid/CnCardGrid.vue +20 -20
  14. package/src/components/CnChartWidget/CnChartWidget.vue +3 -1
  15. package/src/components/CnCopyDialog/CnCopyDialog.vue +7 -1
  16. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +4 -0
  17. package/src/components/CnDashboardPage/CnDashboardPage.vue +2 -0
  18. package/src/components/CnDataTable/CnDataTable.vue +6 -2
  19. package/src/components/CnDeleteDialog/CnDeleteDialog.vue +7 -1
  20. package/src/components/CnDetailCard/CnDetailCard.vue +12 -1
  21. package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
  22. package/src/components/CnDetailGrid/index.js +1 -0
  23. package/src/components/CnDetailPage/CnDetailPage.vue +157 -11
  24. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +3 -1
  25. package/src/components/CnFormDialog/CnFormDialog.vue +934 -920
  26. package/src/components/CnIcon/CnIcon.vue +1 -1
  27. package/src/components/CnIndexPage/CnIndexPage.vue +51 -9
  28. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +37 -9
  29. package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
  30. package/src/components/CnInfoWidget/index.js +1 -0
  31. package/src/components/CnJsonViewer/CnJsonViewer.vue +283 -0
  32. package/src/components/CnJsonViewer/index.js +1 -0
  33. package/src/components/CnKpiGrid/CnKpiGrid.vue +5 -1
  34. package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +7 -1
  35. package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +7 -1
  36. package/src/components/CnMassExportDialog/CnMassExportDialog.vue +1 -1
  37. package/src/components/CnMassImportDialog/CnMassImportDialog.vue +1 -1
  38. package/src/components/CnObjectCard/CnObjectCard.vue +1 -1
  39. package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +368 -0
  40. package/src/components/CnObjectSidebar/CnFilesTab.vue +286 -0
  41. package/src/components/CnObjectSidebar/CnNotesTab.vue +249 -0
  42. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +45 -668
  43. package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
  44. package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
  45. package/src/components/CnObjectSidebar/index.js +5 -0
  46. package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
  47. package/src/components/CnProgressBar/index.js +1 -0
  48. package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +1 -1
  49. package/src/components/CnStatsBlock/CnStatsBlock.vue +27 -11
  50. package/src/components/CnStatsPanel/CnStatsPanel.vue +320 -0
  51. package/src/components/CnStatsPanel/index.js +1 -0
  52. package/src/components/CnStatusBadge/CnStatusBadge.vue +15 -2
  53. package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +5 -1
  54. package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
  55. package/src/components/CnTableWidget/index.js +1 -0
  56. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +36 -1
  57. package/src/components/index.js +11 -0
  58. package/src/composables/useDashboardView.js +58 -12
  59. package/src/composables/useDetailView.js +3 -2
  60. package/src/composables/useListView.js +7 -6
  61. package/src/composables/useSubResource.js +3 -3
  62. package/src/css/badge.css +32 -0
  63. package/src/css/card.css +1 -0
  64. package/src/css/detail-page.css +74 -7
  65. package/src/index.js +16 -0
  66. package/src/mixins/gridLayout.js +118 -0
  67. package/src/store/createCrudStore.js +360 -0
  68. package/src/store/createSubResourcePlugin.js +5 -15
  69. package/src/store/index.js +1 -0
  70. package/src/store/plugins/auditTrails.js +346 -6
  71. package/src/store/plugins/lifecycle.js +4 -4
  72. package/src/store/plugins/registerMapping.js +18 -8
  73. package/src/store/plugins/relations.js +1 -1
  74. package/src/store/plugins/search.js +21 -8
  75. package/src/store/useObjectStore.js +30 -36
  76. package/src/utils/getTheme.js +9 -0
  77. package/src/utils/headers.js +13 -3
  78. package/src/utils/index.js +1 -0
  79. package/src/utils/schema.js +3 -3
  80. package/src/utils/widgetVisibility.js +162 -0
  81. package/src/components/CnObjectCard/eslint-setup.md +0 -235
  82. package/src/components/CnObjectCard/package.json-or.json +0 -132
@@ -14,9 +14,9 @@ import { parseResponseError, networkError } from '../utils/errors.js'
14
14
  *
15
15
  * @param {object} store The object store instance (must have objectTypeRegistry and _options)
16
16
  * @param {string} endpoint URL path segment appended to the object URL (e.g. 'tasks')
17
- * @param {object} [options={}] Composable options
17
+ * @param {object} [options] Composable options
18
18
  * @param {Function} [options.transform] Transform function applied to each result item
19
- * @param {number} [options.limit=20] Default page size
19
+ * @param {number} [options.limit] Default page size
20
20
  * @return {object} Reactive state and methods
21
21
  *
22
22
  * @example
@@ -71,7 +71,7 @@ export function useSubResource(store, endpoint, options = {}) {
71
71
  *
72
72
  * @param {string} type The registered object type slug
73
73
  * @param {string} objectId The parent object ID
74
- * @param {object} [params={}] Query parameters (_search, _limit, _page)
74
+ * @param {object} [params] Query parameters (_search, _limit, _page)
75
75
  * @return {Promise<Array>} The fetched results
76
76
  */
77
77
  async function fetchData(type, objectId, params = {}) {
package/src/css/badge.css CHANGED
@@ -5,6 +5,7 @@
5
5
  .cn-status-badge {
6
6
  display: inline-flex;
7
7
  align-items: center;
8
+ gap: calc(0.5 * var(--default-grid-baseline));
8
9
  padding: calc(0.5 * var(--default-grid-baseline)) calc(2.5 * var(--default-grid-baseline));
9
10
  border-radius: var(--border-radius-pill);
10
11
  font-size: 0.85em;
@@ -49,3 +50,34 @@
49
50
  background-color: var(--color-info-light, rgba(0, 130, 201, 0.15));
50
51
  color: var(--color-info, #0082c9);
51
52
  }
53
+
54
+ /* Solid variants — solid background with white text for use on colored backgrounds */
55
+ .cn-status-badge--solid.cn-status-badge--default {
56
+ background-color: var(--color-background-dark);
57
+ color: var(--color-main-text);
58
+ }
59
+
60
+ .cn-status-badge--solid.cn-status-badge--primary {
61
+ background-color: var(--color-primary-element);
62
+ color: white;
63
+ }
64
+
65
+ .cn-status-badge--solid.cn-status-badge--success {
66
+ background-color: var(--color-success);
67
+ color: white;
68
+ }
69
+
70
+ .cn-status-badge--solid.cn-status-badge--warning {
71
+ background-color: var(--color-warning);
72
+ color: var(--color-primary-text);
73
+ }
74
+
75
+ .cn-status-badge--solid.cn-status-badge--error {
76
+ background-color: var(--color-error);
77
+ color: white;
78
+ }
79
+
80
+ .cn-status-badge--solid.cn-status-badge--info {
81
+ background-color: var(--color-info, #0082c9);
82
+ color: white;
83
+ }
package/src/css/card.css CHANGED
@@ -7,6 +7,7 @@
7
7
  display: grid;
8
8
  gap: calc(4 * var(--default-grid-baseline));
9
9
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
10
+ padding: 0.25rem;
10
11
  }
11
12
 
12
13
  /* Base Card */
@@ -5,22 +5,23 @@
5
5
  .cn-detail-page {
6
6
  margin-inline: auto;
7
7
  padding: calc(5 * var(--default-grid-baseline));
8
+ position: relative;
8
9
  }
9
10
 
10
11
  /* Header */
11
12
  .cn-detail-page__header {
12
13
  display: flex;
13
14
  justify-content: space-between;
14
- align-items: flex-start;
15
+ align-items: center;
15
16
  margin-bottom: calc(4 * var(--default-grid-baseline));
16
17
  flex-wrap: wrap;
17
- gap: calc(2 * var(--default-grid-baseline));
18
+ gap: calc(4 * var(--default-grid-baseline));
18
19
  }
19
20
 
20
21
  .cn-detail-page__header-left {
21
22
  display: flex;
22
23
  align-items: center;
23
- gap: calc(2 * var(--default-grid-baseline));
24
+ gap: calc(3 * var(--default-grid-baseline));
24
25
  min-width: 0;
25
26
  }
26
27
 
@@ -32,11 +33,28 @@
32
33
  flex-shrink: 0;
33
34
  }
34
35
 
36
+ .cn-detail-page__title-group {
37
+ display: flex;
38
+ align-items: baseline;
39
+ gap: calc(3 * var(--default-grid-baseline));
40
+ min-width: 0;
41
+ }
42
+
35
43
  .cn-detail-page__title {
36
44
  margin: 0;
37
- font-size: 20px;
45
+ font-size: 22px;
38
46
  font-weight: 700;
47
+ line-height: 1.3;
39
48
  color: var(--color-main-text);
49
+ white-space: nowrap;
50
+ overflow: hidden;
51
+ text-overflow: ellipsis;
52
+ }
53
+
54
+ .cn-detail-page__subtitle {
55
+ font-size: 14px;
56
+ color: var(--color-text-maxcontrast);
57
+ white-space: nowrap;
40
58
  }
41
59
 
42
60
  .cn-detail-page__description {
@@ -47,7 +65,7 @@
47
65
 
48
66
  .cn-detail-page__header-actions {
49
67
  display: flex;
50
- gap: calc(1 * var(--default-grid-baseline));
68
+ gap: calc(2 * var(--default-grid-baseline));
51
69
  flex-wrap: wrap;
52
70
  flex-shrink: 0;
53
71
  }
@@ -133,17 +151,56 @@
133
151
 
134
152
  /* Body & content */
135
153
  .cn-detail-page__body {
136
- /* Wrapper for all content when not in loading/error/empty state */
154
+ display: flex;
155
+ flex-direction: column;
156
+ gap: calc(5 * var(--default-grid-baseline));
137
157
  }
138
158
 
139
159
  .cn-detail-page__content {
140
- /* Content area inherits spacing from parent */
160
+ flex: 1;
161
+ min-width: 0;
162
+ display: flex;
163
+ flex-direction: column;
164
+ gap: calc(4 * var(--default-grid-baseline));
165
+ }
166
+
167
+ /* Grid layout mode */
168
+ .cn-detail-page__content--grid {
169
+ display: grid;
170
+ grid-template-columns: repeat(12, 1fr);
171
+ gap: calc(4 * var(--default-grid-baseline));
172
+ }
173
+
174
+ .cn-detail-page__grid-item {
175
+ min-width: 0;
176
+ }
177
+
178
+ .cn-detail-page__widget-title {
179
+ margin: 0 0 calc(2 * var(--default-grid-baseline)) 0;
180
+ font-size: 16px;
181
+ font-weight: 600;
182
+ line-height: 1.4;
141
183
  }
142
184
 
143
185
  .cn-detail-page__sections {
144
186
  margin-top: calc(4 * var(--default-grid-baseline));
145
187
  }
146
188
 
189
+ /* Sidebar */
190
+ .cn-detail-page__sidebar {
191
+ width: 340px;
192
+ flex-shrink: 0;
193
+ position: sticky;
194
+ top: calc(5 * var(--default-grid-baseline));
195
+ }
196
+
197
+ .cn-detail-page__sidebar-toggle {
198
+ position: fixed;
199
+ right: calc(5 * var(--default-grid-baseline));
200
+ top: 80px;
201
+ z-index: 10;
202
+ }
203
+
147
204
  /* Footer */
148
205
  .cn-detail-page__footer {
149
206
  margin-top: calc(4 * var(--default-grid-baseline));
@@ -164,5 +221,15 @@
164
221
  .cn-detail-page__header-actions {
165
222
  width: 100%;
166
223
  }
224
+ }
225
+
226
+ @media (max-width: 600px) {
227
+ .cn-detail-page__content--grid {
228
+ grid-template-columns: 1fr;
229
+ }
167
230
 
231
+ .cn-detail-page__content--grid .cn-detail-page__grid-item {
232
+ grid-column: 1 / -1 !important;
233
+ grid-row: auto !important;
234
+ }
168
235
  }
package/src/index.js CHANGED
@@ -42,12 +42,27 @@ export {
42
42
  CnUserActionMenu,
43
43
  CnNotesCard,
44
44
  CnTasksCard,
45
+ CnDetailCard,
45
46
  CnDetailPage,
47
+ CnCard,
48
+ CnStatsPanel,
49
+ CnJsonViewer,
50
+ CnDetailGrid,
51
+ CnProgressBar,
52
+ CnChartWidget,
53
+ CnObjectSidebar,
54
+ CnInfoWidget,
55
+ CnTableWidget,
56
+ CnActionsBar,
57
+ CnIcon,
58
+ CnPageHeader,
59
+ CnNoteCard,
46
60
  registerIcons,
47
61
  } from './components/index.js'
48
62
 
49
63
  // Store
50
64
  export { useObjectStore, createObjectStore } from './store/index.js'
65
+ export { createCrudStore } from './store/index.js'
51
66
  export { createSubResourcePlugin, emptyPaginated } from './store/index.js'
52
67
 
53
68
  // Store plugins
@@ -70,3 +85,4 @@ export { useListView, useDetailView, useSubResource, useDashboardView } from './
70
85
  // Utilities
71
86
  export { buildHeaders, buildQueryString, parseResponseError, networkError, genericError } from './utils/index.js'
72
87
  export { columnsFromSchema, formatValue, filtersFromSchema, fieldsFromSchema } from './utils/index.js'
88
+ export { filterWidgetsByVisibility, isWidgetVisible, getCurrentUserId, getCurrentUserGroups, resetVisibilityCache } from './utils/index.js'
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Grid layout mixin for static 12-column CSS grid layouts.
3
+ *
4
+ * Provides a shared grid engine for components that render widget-based layouts
5
+ * using CSS Grid (as opposed to GridStack's absolute positioning). Used by
6
+ * CnDetailPage for static grid layout mode.
7
+ *
8
+ * @mixin gridLayout
9
+ *
10
+ * @example
11
+ * import { gridLayout } from '@conduction/nextcloud-vue/src/mixins/gridLayout.js'
12
+ *
13
+ * export default {
14
+ * mixins: [gridLayout],
15
+ * // Use this.sortedLayout and this.widgetGridStyle(item) in template
16
+ * }
17
+ */
18
+ export const gridLayout = {
19
+ props: {
20
+ /**
21
+ * Grid layout definition. Array of placement objects defining where each widget
22
+ * appears in the 12-column grid.
23
+ *
24
+ * @type {{ id: number, widgetId: string, gridX: number, gridY: number, gridWidth: number, gridHeight?: number, showTitle?: boolean }[]}
25
+ */
26
+ layout: {
27
+ type: Array,
28
+ default: () => [],
29
+ },
30
+ /**
31
+ * Widget definitions. Array of widget objects with id and title.
32
+ *
33
+ * @type {{ id: string, title: string, type?: string }[]}
34
+ */
35
+ widgets: {
36
+ type: Array,
37
+ default: () => [],
38
+ },
39
+ /**
40
+ * Number of grid columns.
41
+ *
42
+ * @type {number}
43
+ */
44
+ columns: {
45
+ type: Number,
46
+ default: 12,
47
+ },
48
+ },
49
+
50
+ computed: {
51
+ /**
52
+ * Layout items sorted by gridY (row) then gridX (column) for proper
53
+ * rendering order. Ensures DOM order matches visual order for
54
+ * accessibility (WCAG 2.4.3 Focus Order).
55
+ *
56
+ * @return {Array} Sorted copy of the layout array.
57
+ */
58
+ sortedLayout() {
59
+ if (!this.layout) return []
60
+ return [...this.layout].sort((a, b) => {
61
+ if (a.gridY !== b.gridY) {
62
+ return a.gridY - b.gridY
63
+ }
64
+ return a.gridX - b.gridX
65
+ })
66
+ },
67
+
68
+ /**
69
+ * Whether grid layout mode is active (layout array is provided and non-empty).
70
+ *
71
+ * @return {boolean}
72
+ */
73
+ hasGridLayout() {
74
+ return Array.isArray(this.layout) && this.layout.length > 0
75
+ },
76
+ },
77
+
78
+ methods: {
79
+ /**
80
+ * Compute CSS grid placement styles for a layout item.
81
+ *
82
+ * Maps the layout item's gridX and gridWidth to CSS grid-column values,
83
+ * and gridY + gridHeight to grid-row values.
84
+ *
85
+ * @param {{ gridX: number, gridWidth: number, gridY?: number, gridHeight?: number }} item - Layout item.
86
+ * @return {object} CSS style object for grid-column and grid-row placement.
87
+ */
88
+ widgetGridStyle(item) {
89
+ const colStart = (item.gridX || 0) + 1
90
+ const colEnd = colStart + (item.gridWidth || this.columns)
91
+
92
+ const style = {
93
+ gridColumn: `${colStart} / ${colEnd}`,
94
+ }
95
+
96
+ // Only set grid-row if explicit height is provided
97
+ if (item.gridY !== undefined && item.gridHeight) {
98
+ const rowStart = item.gridY + 1
99
+ const rowEnd = rowStart + item.gridHeight
100
+ style.gridRow = `${rowStart} / ${rowEnd}`
101
+ }
102
+
103
+ return style
104
+ },
105
+
106
+ /**
107
+ * Find the widget definition for a layout item.
108
+ *
109
+ * @param {{ widgetId: string }} item - Layout item with widgetId reference.
110
+ * @return {object|undefined} The matching widget definition.
111
+ */
112
+ findWidget(item) {
113
+ return this.widgets.find(w => w.id === item.widgetId)
114
+ },
115
+ },
116
+ }
117
+
118
+ export default gridLayout