@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.
- package/dist/nextcloud-vue.cjs.js +13606 -1918
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.css +1238 -270
- package/dist/nextcloud-vue.esm.js +13548 -1880
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/package.json +9 -4
- package/src/components/CnActionsBar/CnActionsBar.vue +6 -1
- package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +1 -11
- package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +5 -1
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +1 -1
- package/src/components/CnCard/CnCard.vue +415 -0
- package/src/components/CnCard/index.js +1 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +20 -20
- package/src/components/CnChartWidget/CnChartWidget.vue +3 -1
- package/src/components/CnCopyDialog/CnCopyDialog.vue +7 -1
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +4 -0
- package/src/components/CnDashboardPage/CnDashboardPage.vue +2 -0
- package/src/components/CnDataTable/CnDataTable.vue +6 -2
- package/src/components/CnDeleteDialog/CnDeleteDialog.vue +7 -1
- package/src/components/CnDetailCard/CnDetailCard.vue +12 -1
- package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
- package/src/components/CnDetailGrid/index.js +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +157 -11
- package/src/components/CnFacetSidebar/CnFacetSidebar.vue +3 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +934 -920
- package/src/components/CnIcon/CnIcon.vue +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +51 -9
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +37 -9
- package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
- package/src/components/CnInfoWidget/index.js +1 -0
- package/src/components/CnJsonViewer/CnJsonViewer.vue +283 -0
- package/src/components/CnJsonViewer/index.js +1 -0
- package/src/components/CnKpiGrid/CnKpiGrid.vue +5 -1
- package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +7 -1
- package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +7 -1
- package/src/components/CnMassExportDialog/CnMassExportDialog.vue +1 -1
- package/src/components/CnMassImportDialog/CnMassImportDialog.vue +1 -1
- package/src/components/CnObjectCard/CnObjectCard.vue +1 -1
- package/src/components/CnObjectSidebar/CnAuditTrailTab.vue +368 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +286 -0
- package/src/components/CnObjectSidebar/CnNotesTab.vue +249 -0
- package/src/components/CnObjectSidebar/CnObjectSidebar.vue +45 -668
- package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
- package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
- package/src/components/CnObjectSidebar/index.js +5 -0
- package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
- package/src/components/CnProgressBar/index.js +1 -0
- package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +1 -1
- package/src/components/CnStatsBlock/CnStatsBlock.vue +27 -11
- package/src/components/CnStatsPanel/CnStatsPanel.vue +320 -0
- package/src/components/CnStatsPanel/index.js +1 -0
- package/src/components/CnStatusBadge/CnStatusBadge.vue +15 -2
- package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +5 -1
- package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
- package/src/components/CnTableWidget/index.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +36 -1
- package/src/components/index.js +11 -0
- package/src/composables/useDashboardView.js +58 -12
- package/src/composables/useDetailView.js +3 -2
- package/src/composables/useListView.js +7 -6
- package/src/composables/useSubResource.js +3 -3
- package/src/css/badge.css +32 -0
- package/src/css/card.css +1 -0
- package/src/css/detail-page.css +74 -7
- package/src/index.js +16 -0
- package/src/mixins/gridLayout.js +118 -0
- package/src/store/createCrudStore.js +360 -0
- package/src/store/createSubResourcePlugin.js +5 -15
- package/src/store/index.js +1 -0
- package/src/store/plugins/auditTrails.js +346 -6
- package/src/store/plugins/lifecycle.js +4 -4
- package/src/store/plugins/registerMapping.js +18 -8
- package/src/store/plugins/relations.js +1 -1
- package/src/store/plugins/search.js +21 -8
- package/src/store/useObjectStore.js +30 -36
- package/src/utils/getTheme.js +9 -0
- package/src/utils/headers.js +13 -3
- package/src/utils/index.js +1 -0
- package/src/utils/schema.js +3 -3
- package/src/utils/widgetVisibility.js +162 -0
- package/src/components/CnObjectCard/eslint-setup.md +0 -235
- 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
|
|
17
|
+
* @param {object} [options] Composable options
|
|
18
18
|
* @param {Function} [options.transform] Transform function applied to each result item
|
|
19
|
-
* @param {number} [options.limit
|
|
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
|
|
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
package/src/css/detail-page.css
CHANGED
|
@@ -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:
|
|
15
|
+
align-items: center;
|
|
15
16
|
margin-bottom: calc(4 * var(--default-grid-baseline));
|
|
16
17
|
flex-wrap: wrap;
|
|
17
|
-
gap: calc(
|
|
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(
|
|
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:
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|