@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
@@ -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=null] 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[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
- }
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
+ }