@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.
- package/README.md +226 -0
- package/css/index.css +5 -0
- package/dist/nextcloud-vue.cjs +67614 -0
- package/dist/nextcloud-vue.cjs.js +76311 -5905
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.cjs.map +1 -0
- package/dist/nextcloud-vue.css +3279 -203
- package/dist/nextcloud-vue.esm.js +76240 -5882
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/package.json +89 -63
- package/src/components/CnActionsBar/CnActionsBar.vue +254 -0
- package/src/components/CnActionsBar/index.js +1 -0
- package/src/components/CnAdvancedFormDialog/CnAdvancedFormDialog.vue +569 -0
- package/src/components/CnAdvancedFormDialog/CnDataTab.vue +217 -0
- package/src/components/CnAdvancedFormDialog/CnMetadataTab.vue +121 -0
- package/src/components/CnAdvancedFormDialog/CnPropertiesTab.vue +422 -0
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +247 -0
- package/src/components/CnAdvancedFormDialog/index.js +1 -0
- package/src/components/CnCard/CnCard.vue +415 -0
- package/src/components/CnCard/index.js +1 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +23 -20
- package/src/components/CnCardGrid/index.js +1 -1
- package/src/components/CnCellRenderer/index.js +1 -1
- package/src/components/CnChartWidget/CnChartWidget.vue +318 -0
- package/src/components/CnChartWidget/index.js +1 -0
- package/src/components/CnConfigurationCard/index.js +1 -1
- package/src/components/CnContextMenu/CnContextMenu.vue +142 -0
- package/src/components/CnContextMenu/index.js +1 -0
- package/src/components/CnCopyDialog/CnCopyDialog.vue +257 -0
- package/src/components/CnCopyDialog/index.js +1 -0
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +229 -0
- package/src/components/CnDashboardGrid/index.js +1 -0
- package/src/components/CnDashboardPage/CnDashboardPage.vue +396 -0
- package/src/components/CnDashboardPage/index.js +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +24 -16
- package/src/components/CnDataTable/index.js +1 -1
- package/src/components/CnDeleteDialog/CnDeleteDialog.vue +177 -0
- package/src/components/CnDeleteDialog/index.js +1 -0
- package/src/components/CnDetailCard/CnDetailCard.vue +225 -0
- package/src/components/CnDetailCard/index.js +1 -0
- package/src/components/CnDetailGrid/CnDetailGrid.vue +254 -0
- package/src/components/CnDetailGrid/index.js +1 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +431 -0
- package/src/components/CnDetailPage/index.js +1 -0
- package/src/components/CnFacetSidebar/CnFacetSidebar.vue +12 -2
- package/src/components/CnFacetSidebar/index.js +1 -1
- package/src/components/CnFilterBar/index.js +1 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +934 -0
- package/src/components/CnFormDialog/index.js +1 -0
- package/src/components/CnIcon/CnIcon.vue +89 -0
- package/src/components/CnIcon/index.js +1 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +589 -291
- package/src/components/CnIndexPage/index.js +1 -1
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +535 -0
- package/src/components/CnIndexSidebar/index.js +1 -0
- package/src/components/CnInfoWidget/CnInfoWidget.vue +219 -0
- package/src/components/CnInfoWidget/index.js +1 -0
- package/src/components/CnItemCard/CnItemCard.vue +134 -0
- package/src/components/CnItemCard/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/CnKpiGrid/index.js +1 -1
- package/src/components/CnMassActionBar/CnMassActionBar.vue +6 -5
- package/src/components/CnMassActionBar/index.js +1 -1
- package/src/components/CnMassCopyDialog/CnMassCopyDialog.vue +16 -9
- package/src/components/CnMassCopyDialog/index.js +1 -1
- package/src/components/CnMassDeleteDialog/CnMassDeleteDialog.vue +16 -9
- package/src/components/CnMassDeleteDialog/index.js +1 -1
- package/src/components/CnMassExportDialog/CnMassExportDialog.vue +8 -7
- package/src/components/CnMassExportDialog/index.js +1 -1
- package/src/components/CnMassImportDialog/CnMassImportDialog.vue +20 -17
- package/src/components/CnMassImportDialog/index.js +1 -1
- package/src/components/CnNoteCard/CnNoteCard.vue +149 -0
- package/src/components/CnNoteCard/index.js +1 -0
- package/src/components/CnNotesCard/CnNotesCard.vue +415 -0
- package/src/components/CnNotesCard/index.js +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +3 -1
- package/src/components/CnObjectCard/index.js +1 -1
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +853 -0
- package/src/components/CnObjectDataWidget/index.js +1 -0
- package/src/components/CnObjectMetadataWidget/CnObjectMetadataWidget.vue +288 -0
- package/src/components/CnObjectMetadataWidget/index.js +1 -0
- 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 +254 -0
- package/src/components/CnObjectSidebar/CnTagsTab.vue +258 -0
- package/src/components/CnObjectSidebar/CnTasksTab.vue +482 -0
- package/src/components/CnObjectSidebar/index.js +6 -0
- package/src/components/CnPageHeader/CnPageHeader.vue +61 -0
- package/src/components/CnPageHeader/index.js +1 -0
- package/src/components/CnPagination/CnPagination.vue +7 -6
- package/src/components/CnPagination/index.js +1 -1
- package/src/components/CnProgressBar/CnProgressBar.vue +262 -0
- package/src/components/CnProgressBar/index.js +1 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -0
- package/src/components/CnRegisterMapping/index.js +1 -0
- package/src/components/CnRowActions/CnRowActions.vue +25 -3
- package/src/components/CnRowActions/index.js +1 -1
- package/src/components/CnSchemaFormDialog/CnSchemaConfigurationTab.vue +226 -0
- package/src/components/CnSchemaFormDialog/CnSchemaFormDialog.vue +787 -0
- package/src/components/CnSchemaFormDialog/CnSchemaPropertiesTab.vue +305 -0
- package/src/components/CnSchemaFormDialog/CnSchemaPropertyActions.vue +1398 -0
- package/src/components/CnSchemaFormDialog/CnSchemaSecurityTab.vue +236 -0
- package/src/components/CnSchemaFormDialog/index.js +1 -0
- package/src/components/CnSettingsCard/index.js +1 -1
- package/src/components/CnSettingsSection/index.js +1 -1
- package/src/components/CnStatsBlock/CnStatsBlock.vue +89 -19
- package/src/components/CnStatsBlock/index.js +1 -1
- 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/CnStatusBadge/index.js +1 -1
- package/src/components/CnTabbedFormDialog/CnTabbedFormDialog.vue +544 -0
- package/src/components/CnTabbedFormDialog/index.js +1 -0
- package/src/components/CnTableWidget/CnTableWidget.vue +332 -0
- package/src/components/CnTableWidget/index.js +1 -0
- package/src/components/CnTasksCard/CnTasksCard.vue +373 -0
- package/src/components/CnTasksCard/index.js +1 -0
- package/src/components/CnTileWidget/CnTileWidget.vue +159 -0
- package/src/components/CnTileWidget/index.js +1 -0
- package/src/components/CnTimelineStages/CnTimelineStages.vue +292 -0
- package/src/components/CnTimelineStages/index.js +1 -0
- package/src/components/CnUserActionMenu/CnUserActionMenu.vue +435 -0
- package/src/components/CnUserActionMenu/index.js +1 -0
- package/src/components/CnVersionInfoCard/index.js +1 -1
- package/src/components/CnWidgetRenderer/CnWidgetRenderer.vue +180 -0
- package/src/components/CnWidgetRenderer/index.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +246 -0
- package/src/components/CnWidgetWrapper/index.js +1 -0
- package/src/components/index.js +57 -25
- package/src/composables/index.js +5 -3
- package/src/composables/useContextMenu.js +126 -0
- package/src/composables/useDashboardView.js +286 -0
- package/src/composables/useDetailView.js +290 -132
- package/src/composables/useListView.js +364 -153
- package/src/composables/useSubResource.js +142 -142
- package/src/constants/metadata.js +30 -0
- package/src/css/CnSchemaFormDialog.css +546 -0
- package/src/css/__sample_nextcloud_tokens.css +110 -0
- package/src/css/actions-bar.css +54 -0
- package/src/css/badge.css +83 -51
- package/src/css/card.css +129 -128
- package/src/css/context-menu.css +20 -0
- package/src/css/dashboard.css +70 -0
- package/src/css/detail-page.css +235 -0
- package/src/css/detail.css +68 -68
- package/src/css/index-page.css +44 -0
- package/src/css/index-sidebar.css +193 -0
- package/src/css/index.css +17 -8
- package/src/css/layout.css +90 -90
- package/src/css/page-header.css +35 -0
- package/src/css/pagination.css +72 -72
- package/src/css/table.css +142 -143
- package/src/css/timeline-stages.css +220 -0
- package/src/css/utilities.css +46 -46
- package/src/index.js +91 -50
- package/src/mixins/gridLayout.js +118 -0
- package/src/store/createCrudStore.js +360 -0
- package/src/store/createSubResourcePlugin.js +125 -135
- package/src/store/index.js +4 -3
- package/src/store/plugins/auditTrails.js +357 -17
- package/src/store/plugins/files.js +250 -186
- package/src/store/plugins/index.js +7 -4
- package/src/store/plugins/lifecycle.js +180 -180
- package/src/store/plugins/registerMapping.js +195 -0
- package/src/store/plugins/relations.js +68 -68
- package/src/store/plugins/search.js +385 -0
- package/src/store/plugins/selection.js +104 -0
- package/src/store/useObjectStore.js +823 -625
- package/src/types/auditTrail.d.ts +32 -32
- package/src/types/file.d.ts +23 -23
- package/src/types/index.d.ts +35 -35
- package/src/types/notification.d.ts +36 -36
- package/src/types/object.d.ts +40 -40
- package/src/types/organisation.d.ts +41 -41
- package/src/types/register.d.ts +25 -25
- package/src/types/schema.d.ts +39 -39
- package/src/types/shared.d.ts +79 -79
- package/src/types/source.d.ts +14 -14
- package/src/types/task.d.ts +31 -31
- package/src/utils/errors.js +96 -96
- package/src/utils/getTheme.js +9 -0
- package/src/utils/headers.js +80 -44
- package/src/utils/id.js +13 -0
- package/src/utils/index.js +4 -3
- package/src/utils/schema.js +422 -287
- package/src/utils/widgetVisibility.js +162 -0
- package/src/components/CnDetailViewLayout/CnDetailViewLayout.vue +0 -88
- package/src/components/CnDetailViewLayout/index.js +0 -1
- package/src/components/CnEmptyState/CnEmptyState.vue +0 -78
- package/src/components/CnEmptyState/index.js +0 -1
- package/src/components/CnListViewLayout/CnListViewLayout.vue +0 -80
- package/src/components/CnListViewLayout/index.js +0 -1
- package/src/components/CnViewModeToggle/CnViewModeToggle.vue +0 -77
- package/src/components/CnViewModeToggle/index.js +0 -1
|
@@ -1,180 +1,180 @@
|
|
|
1
|
-
import { buildHeaders } from '../../utils/headers.js'
|
|
2
|
-
import { parseResponseError, networkError } from '../../utils/errors.js'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Lifecycle plugin for the object store.
|
|
6
|
-
*
|
|
7
|
-
* Adds object lifecycle actions: lock, unlock, publish, depublish, revert, merge.
|
|
8
|
-
* These operate on the object itself (not sub-resources) but share the same
|
|
9
|
-
* URL pattern: POST /{register}/{schema}/{objectId}/{action}
|
|
10
|
-
*
|
|
11
|
-
* State: lifecycleLoading, lifecycleError
|
|
12
|
-
* Actions: lockObject, unlockObject, publishObject, depublishObject, revertObject, mergeObjects
|
|
13
|
-
*
|
|
14
|
-
* @return {Function} Plugin factory
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* const useStore = createObjectStore('object', {
|
|
18
|
-
* plugins: [lifecyclePlugin()],
|
|
19
|
-
* })
|
|
20
|
-
* const store = useStore()
|
|
21
|
-
* await store.lockObject('case', caseId, { process: 'review', duration: 3600 })
|
|
22
|
-
* await store.publishObject('case', caseId, { date: '2025-01-01' })
|
|
23
|
-
*/
|
|
24
|
-
export function lifecyclePlugin() {
|
|
25
|
-
return {
|
|
26
|
-
name: 'Lifecycle',
|
|
27
|
-
|
|
28
|
-
state: () => ({
|
|
29
|
-
lifecycleLoading: false,
|
|
30
|
-
lifecycleError: null,
|
|
31
|
-
}),
|
|
32
|
-
|
|
33
|
-
getters: {
|
|
34
|
-
isLifecycleLoading: (state) => state.lifecycleLoading,
|
|
35
|
-
getLifecycleError: (state) => state.lifecycleError,
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
actions: {
|
|
39
|
-
/**
|
|
40
|
-
* Perform a lifecycle action on an object.
|
|
41
|
-
*
|
|
42
|
-
* @param {string} type The registered object type slug
|
|
43
|
-
* @param {string} objectId The object ID
|
|
44
|
-
* @param {string} action The lifecycle action endpoint (e.g. 'lock', 'publish')
|
|
45
|
-
* @param {object} [body
|
|
46
|
-
* @return {Promise<object|null>} Response data or null on error
|
|
47
|
-
*/
|
|
48
|
-
async _lifecycleAction(type, objectId, action, body = null) {
|
|
49
|
-
this.lifecycleLoading = true
|
|
50
|
-
this.lifecycleError = null
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
const url = this._buildUrl(type, objectId) + '/' + action
|
|
54
|
-
const options = {
|
|
55
|
-
method: 'POST',
|
|
56
|
-
headers: buildHeaders(),
|
|
57
|
-
}
|
|
58
|
-
if (body) {
|
|
59
|
-
options.body = JSON.stringify(body)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const response = await fetch(url, options)
|
|
63
|
-
|
|
64
|
-
if (!response.ok) {
|
|
65
|
-
this.lifecycleError = await parseResponseError(response, action)
|
|
66
|
-
console.error(`Error performing ${action} on ${type}/${objectId}:`, this.lifecycleError)
|
|
67
|
-
return null
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const data = await response.json()
|
|
71
|
-
|
|
72
|
-
if (this.objects[type] && data.id) {
|
|
73
|
-
this.objects[type][data.id]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return data
|
|
77
|
-
} catch (error) {
|
|
78
|
-
this.lifecycleError = error.name === 'TypeError'
|
|
79
|
-
? networkError(error)
|
|
80
|
-
: { status: null, message: error.message, details: null, isValidation: false, fields: null, toString() { return this.message } }
|
|
81
|
-
console.error(`Error performing ${action} on ${type}/${objectId}:`, error)
|
|
82
|
-
return null
|
|
83
|
-
} finally {
|
|
84
|
-
this.lifecycleLoading = false
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Lock an object to prevent concurrent edits.
|
|
90
|
-
*
|
|
91
|
-
* @param {string} type The registered object type slug
|
|
92
|
-
* @param {string} objectId The object ID
|
|
93
|
-
* @param {object} options Lock options
|
|
94
|
-
* @param {string} [options.process] Lock reason/process name
|
|
95
|
-
* @param {number} [options.duration] Lock duration in seconds
|
|
96
|
-
* @return {Promise<object|null>} Updated object or null on error
|
|
97
|
-
*/
|
|
98
|
-
async lockObject(type, objectId, options = {}) {
|
|
99
|
-
return this._lifecycleAction(type, objectId, 'lock', options)
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Unlock an object.
|
|
104
|
-
*
|
|
105
|
-
* @param {string} type The registered object type slug
|
|
106
|
-
* @param {string} objectId The object ID
|
|
107
|
-
* @return {Promise<object|null>} Updated object or null on error
|
|
108
|
-
*/
|
|
109
|
-
async unlockObject(type, objectId) {
|
|
110
|
-
return this._lifecycleAction(type, objectId, 'unlock')
|
|
111
|
-
},
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Publish an object (make it publicly accessible).
|
|
115
|
-
*
|
|
116
|
-
* @param {string} type The registered object type slug
|
|
117
|
-
* @param {string} objectId The object ID
|
|
118
|
-
* @param {object} [options
|
|
119
|
-
* @param {string} [options.date] Publish date (ISO 8601)
|
|
120
|
-
* @return {Promise<object|null>} Updated object or null on error
|
|
121
|
-
*/
|
|
122
|
-
async publishObject(type, objectId, options = {}) {
|
|
123
|
-
return this._lifecycleAction(type, objectId, 'publish', options)
|
|
124
|
-
},
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Depublish an object (revoke public access).
|
|
128
|
-
*
|
|
129
|
-
* @param {string} type The registered object type slug
|
|
130
|
-
* @param {string} objectId The object ID
|
|
131
|
-
* @param {object} [options
|
|
132
|
-
* @param {string} [options.date] Depublish date (ISO 8601)
|
|
133
|
-
* @return {Promise<object|null>} Updated object or null on error
|
|
134
|
-
*/
|
|
135
|
-
async depublishObject(type, objectId, options = {}) {
|
|
136
|
-
return this._lifecycleAction(type, objectId, 'depublish', options)
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Revert an object to a previous version.
|
|
141
|
-
*
|
|
142
|
-
* @param {string} type The registered object type slug
|
|
143
|
-
* @param {string} objectId The object ID
|
|
144
|
-
* @param {object} options Revert options
|
|
145
|
-
* @param {string} [options.datetime] Target datetime
|
|
146
|
-
* @param {string} [options.auditTrailId] Audit trail entry ID to revert to
|
|
147
|
-
* @param {number} [options.version] Target version number
|
|
148
|
-
* @param {boolean} [options.overwriteVersion] Overwrite current version
|
|
149
|
-
* @return {Promise<object|null>} Updated object or null on error
|
|
150
|
-
*/
|
|
151
|
-
async revertObject(type, objectId, options = {}) {
|
|
152
|
-
return this._lifecycleAction(type, objectId, 'revert', options)
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Merge two objects together.
|
|
157
|
-
*
|
|
158
|
-
* @param {string} type The registered object type slug
|
|
159
|
-
* @param {string} sourceId The source object ID (will be merged into target)
|
|
160
|
-
* @param {object} options Merge options
|
|
161
|
-
* @param {string} options.target Target object ID
|
|
162
|
-
* @param {string} [options.fileAction] How to handle files ('move'|'copy'|'skip')
|
|
163
|
-
* @param {string} [options.relationAction] How to handle relations
|
|
164
|
-
* @param {string} [options.referenceAction] How to handle references
|
|
165
|
-
* @return {Promise<object|null>} Merge result or null on error
|
|
166
|
-
*/
|
|
167
|
-
async mergeObjects(type, sourceId, options = {}) {
|
|
168
|
-
return this._lifecycleAction(type, sourceId, 'merge', options)
|
|
169
|
-
},
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Clear lifecycle state.
|
|
173
|
-
*/
|
|
174
|
-
clearLifecycle() {
|
|
175
|
-
this.lifecycleLoading = false
|
|
176
|
-
this.lifecycleError = null
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
}
|
|
180
|
-
}
|
|
1
|
+
import { buildHeaders } from '../../utils/headers.js'
|
|
2
|
+
import { parseResponseError, networkError } from '../../utils/errors.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle plugin for the object store.
|
|
6
|
+
*
|
|
7
|
+
* Adds object lifecycle actions: lock, unlock, publish, depublish, revert, merge.
|
|
8
|
+
* These operate on the object itself (not sub-resources) but share the same
|
|
9
|
+
* URL pattern: POST /{register}/{schema}/{objectId}/{action}
|
|
10
|
+
*
|
|
11
|
+
* State: lifecycleLoading, lifecycleError
|
|
12
|
+
* Actions: lockObject, unlockObject, publishObject, depublishObject, revertObject, mergeObjects
|
|
13
|
+
*
|
|
14
|
+
* @return {Function} Plugin factory
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const useStore = createObjectStore('object', {
|
|
18
|
+
* plugins: [lifecyclePlugin()],
|
|
19
|
+
* })
|
|
20
|
+
* const store = useStore()
|
|
21
|
+
* await store.lockObject('case', caseId, { process: 'review', duration: 3600 })
|
|
22
|
+
* await store.publishObject('case', caseId, { date: '2025-01-01' })
|
|
23
|
+
*/
|
|
24
|
+
export function lifecyclePlugin() {
|
|
25
|
+
return {
|
|
26
|
+
name: 'Lifecycle',
|
|
27
|
+
|
|
28
|
+
state: () => ({
|
|
29
|
+
lifecycleLoading: false,
|
|
30
|
+
lifecycleError: null,
|
|
31
|
+
}),
|
|
32
|
+
|
|
33
|
+
getters: {
|
|
34
|
+
isLifecycleLoading: (state) => state.lifecycleLoading,
|
|
35
|
+
getLifecycleError: (state) => state.lifecycleError,
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
actions: {
|
|
39
|
+
/**
|
|
40
|
+
* Perform a lifecycle action on an object.
|
|
41
|
+
*
|
|
42
|
+
* @param {string} type The registered object type slug
|
|
43
|
+
* @param {string} objectId The object ID
|
|
44
|
+
* @param {string} action The lifecycle action endpoint (e.g. 'lock', 'publish')
|
|
45
|
+
* @param {object} [body] Optional request body
|
|
46
|
+
* @return {Promise<object|null>} Response data or null on error
|
|
47
|
+
*/
|
|
48
|
+
async _lifecycleAction(type, objectId, action, body = null) {
|
|
49
|
+
this.lifecycleLoading = true
|
|
50
|
+
this.lifecycleError = null
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const url = this._buildUrl(type, objectId) + '/' + action
|
|
54
|
+
const options = {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: buildHeaders(),
|
|
57
|
+
}
|
|
58
|
+
if (body) {
|
|
59
|
+
options.body = JSON.stringify(body)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const response = await fetch(url, options)
|
|
63
|
+
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
this.lifecycleError = await parseResponseError(response, action)
|
|
66
|
+
console.error(`Error performing ${action} on ${type}/${objectId}:`, this.lifecycleError)
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const data = await response.json()
|
|
71
|
+
|
|
72
|
+
if (this.objects[type] && data.id) {
|
|
73
|
+
this.objects = { ...this.objects, [type]: { ...this.objects[type], [data.id]: data } }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return data
|
|
77
|
+
} catch (error) {
|
|
78
|
+
this.lifecycleError = error.name === 'TypeError'
|
|
79
|
+
? networkError(error)
|
|
80
|
+
: { status: null, message: error.message, details: null, isValidation: false, fields: null, toString() { return this.message } }
|
|
81
|
+
console.error(`Error performing ${action} on ${type}/${objectId}:`, error)
|
|
82
|
+
return null
|
|
83
|
+
} finally {
|
|
84
|
+
this.lifecycleLoading = false
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Lock an object to prevent concurrent edits.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} type The registered object type slug
|
|
92
|
+
* @param {string} objectId The object ID
|
|
93
|
+
* @param {object} options Lock options
|
|
94
|
+
* @param {string} [options.process] Lock reason/process name
|
|
95
|
+
* @param {number} [options.duration] Lock duration in seconds
|
|
96
|
+
* @return {Promise<object|null>} Updated object or null on error
|
|
97
|
+
*/
|
|
98
|
+
async lockObject(type, objectId, options = {}) {
|
|
99
|
+
return this._lifecycleAction(type, objectId, 'lock', options)
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Unlock an object.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} type The registered object type slug
|
|
106
|
+
* @param {string} objectId The object ID
|
|
107
|
+
* @return {Promise<object|null>} Updated object or null on error
|
|
108
|
+
*/
|
|
109
|
+
async unlockObject(type, objectId) {
|
|
110
|
+
return this._lifecycleAction(type, objectId, 'unlock')
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Publish an object (make it publicly accessible).
|
|
115
|
+
*
|
|
116
|
+
* @param {string} type The registered object type slug
|
|
117
|
+
* @param {string} objectId The object ID
|
|
118
|
+
* @param {object} [options] Publish options
|
|
119
|
+
* @param {string} [options.date] Publish date (ISO 8601)
|
|
120
|
+
* @return {Promise<object|null>} Updated object or null on error
|
|
121
|
+
*/
|
|
122
|
+
async publishObject(type, objectId, options = {}) {
|
|
123
|
+
return this._lifecycleAction(type, objectId, 'publish', options)
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Depublish an object (revoke public access).
|
|
128
|
+
*
|
|
129
|
+
* @param {string} type The registered object type slug
|
|
130
|
+
* @param {string} objectId The object ID
|
|
131
|
+
* @param {object} [options] Depublish options
|
|
132
|
+
* @param {string} [options.date] Depublish date (ISO 8601)
|
|
133
|
+
* @return {Promise<object|null>} Updated object or null on error
|
|
134
|
+
*/
|
|
135
|
+
async depublishObject(type, objectId, options = {}) {
|
|
136
|
+
return this._lifecycleAction(type, objectId, 'depublish', options)
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Revert an object to a previous version.
|
|
141
|
+
*
|
|
142
|
+
* @param {string} type The registered object type slug
|
|
143
|
+
* @param {string} objectId The object ID
|
|
144
|
+
* @param {object} options Revert options
|
|
145
|
+
* @param {string} [options.datetime] Target datetime
|
|
146
|
+
* @param {string} [options.auditTrailId] Audit trail entry ID to revert to
|
|
147
|
+
* @param {number} [options.version] Target version number
|
|
148
|
+
* @param {boolean} [options.overwriteVersion] Overwrite current version
|
|
149
|
+
* @return {Promise<object|null>} Updated object or null on error
|
|
150
|
+
*/
|
|
151
|
+
async revertObject(type, objectId, options = {}) {
|
|
152
|
+
return this._lifecycleAction(type, objectId, 'revert', options)
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Merge two objects together.
|
|
157
|
+
*
|
|
158
|
+
* @param {string} type The registered object type slug
|
|
159
|
+
* @param {string} sourceId The source object ID (will be merged into target)
|
|
160
|
+
* @param {object} options Merge options
|
|
161
|
+
* @param {string} options.target Target object ID
|
|
162
|
+
* @param {string} [options.fileAction] How to handle files ('move'|'copy'|'skip')
|
|
163
|
+
* @param {string} [options.relationAction] How to handle relations
|
|
164
|
+
* @param {string} [options.referenceAction] How to handle references
|
|
165
|
+
* @return {Promise<object|null>} Merge result or null on error
|
|
166
|
+
*/
|
|
167
|
+
async mergeObjects(type, sourceId, options = {}) {
|
|
168
|
+
return this._lifecycleAction(type, sourceId, 'merge', options)
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Clear lifecycle state.
|
|
173
|
+
*/
|
|
174
|
+
clearLifecycle() {
|
|
175
|
+
this.lifecycleLoading = false
|
|
176
|
+
this.lifecycleError = null
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { buildHeaders, prefixUrl } from '../../utils/headers.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Register mapping plugin for the object store.
|
|
5
|
+
*
|
|
6
|
+
* Adds state and actions for fetching OpenRegister registers and their
|
|
7
|
+
* schemas, used by CnRegisterMapping to populate dropdowns.
|
|
8
|
+
*
|
|
9
|
+
* State: registers, registerSchemas, registersLoading, registersError
|
|
10
|
+
* Actions: fetchRegisters, fetchSchemasForRegister, clearRegisterMapping
|
|
11
|
+
* Getters: getRegisters, registerOptions, schemaOptions, isRegistersLoading, getRegistersError
|
|
12
|
+
*
|
|
13
|
+
* @return {Function} Plugin factory
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const useStore = createObjectStore('object', {
|
|
17
|
+
* plugins: [registerMappingPlugin()],
|
|
18
|
+
* })
|
|
19
|
+
* const store = useStore()
|
|
20
|
+
* await store.fetchRegisters()
|
|
21
|
+
* const options = store.registerOptions // [{ label, value }]
|
|
22
|
+
* const schemas = store.schemaOptions('5') // [{ label, value }]
|
|
23
|
+
*/
|
|
24
|
+
export function registerMappingPlugin() {
|
|
25
|
+
return {
|
|
26
|
+
name: 'RegisterMapping',
|
|
27
|
+
|
|
28
|
+
state: () => ({
|
|
29
|
+
/** @type {Array} All available registers from OpenRegister */
|
|
30
|
+
registers: [],
|
|
31
|
+
/** @type {{[key: string]: Array}} Schemas keyed by register ID */
|
|
32
|
+
registerSchemas: {},
|
|
33
|
+
/** @type {boolean} Whether registers are being fetched */
|
|
34
|
+
registersLoading: false,
|
|
35
|
+
/** @type {string|null} Error message from last fetch */
|
|
36
|
+
registersError: null,
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
getters: {
|
|
40
|
+
/**
|
|
41
|
+
* @param {object} state - Pinia state
|
|
42
|
+
* @return {Array} Raw register list
|
|
43
|
+
*/
|
|
44
|
+
getRegisters: (state) => state.registers,
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {object} state - Pinia state
|
|
48
|
+
* @return {boolean} Whether registers are loading
|
|
49
|
+
*/
|
|
50
|
+
isRegistersLoading: (state) => state.registersLoading,
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {object} state - Pinia state
|
|
54
|
+
* @return {string|null} Last error
|
|
55
|
+
*/
|
|
56
|
+
getRegistersError: (state) => state.registersError,
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Registers as NcSelect-compatible options.
|
|
60
|
+
*
|
|
61
|
+
* @param {object} state - Pinia state
|
|
62
|
+
* @return {Array<{label: string, value: string}>}
|
|
63
|
+
*/
|
|
64
|
+
registerOptions: (state) => state.registers.map((r) => ({
|
|
65
|
+
label: r.title || r.slug || `Register ${r.id}`,
|
|
66
|
+
value: String(r.id),
|
|
67
|
+
})),
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
actions: {
|
|
71
|
+
/**
|
|
72
|
+
* Get schemas for a register as NcSelect options.
|
|
73
|
+
*
|
|
74
|
+
* @param {string|number} registerId Register ID
|
|
75
|
+
* @return {Array<{label: string, value: string}>}
|
|
76
|
+
*/
|
|
77
|
+
schemaOptions(registerId) {
|
|
78
|
+
const id = String(registerId)
|
|
79
|
+
return (this.registerSchemas[id] || []).map((s) => ({
|
|
80
|
+
label: s.title || s.slug || `Schema ${s.id}`,
|
|
81
|
+
value: String(s.id),
|
|
82
|
+
}))
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Fetch all registers from OpenRegister with expanded schemas.
|
|
87
|
+
*
|
|
88
|
+
* @param {boolean} [withSchemas] Include schemas in response
|
|
89
|
+
* @return {Promise<Array>} Fetched registers
|
|
90
|
+
*/
|
|
91
|
+
async fetchRegisters(withSchemas = true) {
|
|
92
|
+
this.registersLoading = true
|
|
93
|
+
this.registersError = null
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
let url = prefixUrl('/apps/openregister/api/registers')
|
|
97
|
+
if (withSchemas) {
|
|
98
|
+
url += '?_extend[]=schemas'
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const response = await fetch(url, {
|
|
102
|
+
method: 'GET',
|
|
103
|
+
headers: buildHeaders(),
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
this.registersError = `Failed to fetch registers: ${response.statusText}`
|
|
108
|
+
return []
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const data = await response.json()
|
|
112
|
+
const results = data.results || data
|
|
113
|
+
this.registers = Array.isArray(results) ? results : []
|
|
114
|
+
|
|
115
|
+
// Cache expanded schemas by register ID
|
|
116
|
+
if (withSchemas) {
|
|
117
|
+
for (const reg of this.registers) {
|
|
118
|
+
if (Array.isArray(reg.schemas) && reg.schemas.length > 0) {
|
|
119
|
+
this.registerSchemas = {
|
|
120
|
+
...this.registerSchemas,
|
|
121
|
+
[String(reg.id)]: reg.schemas.filter(
|
|
122
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
123
|
+
),
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return this.registers
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.registersError = error.message || 'Network error fetching registers'
|
|
132
|
+
return []
|
|
133
|
+
} finally {
|
|
134
|
+
this.registersLoading = false
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Fetch schemas for a specific register.
|
|
140
|
+
* Returns cached data if already fetched via expanded registers.
|
|
141
|
+
*
|
|
142
|
+
* @param {string|number} registerId Register ID
|
|
143
|
+
* @return {Promise<Array>} Schemas for the register
|
|
144
|
+
*/
|
|
145
|
+
async fetchSchemasForRegister(registerId) {
|
|
146
|
+
const id = String(registerId)
|
|
147
|
+
|
|
148
|
+
// Return cached if available and non-empty
|
|
149
|
+
if (this.registerSchemas[id]?.length > 0) {
|
|
150
|
+
return this.registerSchemas[id]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check registers array for expanded schemas
|
|
154
|
+
const register = this.registers.find((r) => String(r.id) === id)
|
|
155
|
+
if (register?.schemas?.length > 0) {
|
|
156
|
+
const schemas = register.schemas.filter(
|
|
157
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
158
|
+
)
|
|
159
|
+
if (schemas.length > 0) {
|
|
160
|
+
this.registerSchemas = { ...this.registerSchemas, [id]: schemas }
|
|
161
|
+
return schemas
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Fetch from API as fallback
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(
|
|
168
|
+
prefixUrl(`/apps/openregister/api/registers/${id}?_extend[]=schemas`),
|
|
169
|
+
{ method: 'GET', headers: buildHeaders() },
|
|
170
|
+
)
|
|
171
|
+
if (!response.ok) return []
|
|
172
|
+
|
|
173
|
+
const data = await response.json()
|
|
174
|
+
const schemas = (data.schemas || []).filter(
|
|
175
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
176
|
+
)
|
|
177
|
+
this.registerSchemas = { ...this.registerSchemas, [id]: schemas }
|
|
178
|
+
return schemas
|
|
179
|
+
} catch {
|
|
180
|
+
return []
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Clear all register mapping state.
|
|
186
|
+
*/
|
|
187
|
+
clearRegisterMapping() {
|
|
188
|
+
this.registers = []
|
|
189
|
+
this.registerSchemas = {}
|
|
190
|
+
this.registersLoading = false
|
|
191
|
+
this.registersError = null
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
}
|