@conduction/nextcloud-vue 0.1.0-beta.1 → 0.1.0-beta.2
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/dist/nextcloud-vue.cjs.js +7039 -2409
- package/dist/nextcloud-vue.cjs.js.map +1 -1
- package/dist/nextcloud-vue.css +237 -52
- package/dist/nextcloud-vue.esm.js +7012 -2386
- package/dist/nextcloud-vue.esm.js.map +1 -1
- package/package.json +2 -4
- package/src/components/CnActionsBar/CnActionsBar.vue +225 -0
- package/src/components/CnActionsBar/index.js +1 -0
- package/src/components/CnCopyDialog/CnCopyDialog.vue +250 -0
- package/src/components/CnCopyDialog/index.js +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +0 -5
- package/src/components/CnDeleteDialog/CnDeleteDialog.vue +170 -0
- package/src/components/CnDeleteDialog/index.js +1 -0
- package/src/components/CnFormDialog/CnFormDialog.vue +629 -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 +434 -300
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +484 -0
- package/src/components/CnIndexSidebar/index.js +1 -0
- package/src/components/CnPageHeader/CnPageHeader.vue +57 -0
- package/src/components/CnPageHeader/index.js +1 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +792 -0
- package/src/components/CnRegisterMapping/index.js +1 -0
- package/src/components/index.js +8 -4
- package/src/constants/metadata.js +30 -0
- package/src/css/actions-bar.css +48 -0
- package/src/css/badge.css +4 -4
- package/src/css/card.css +23 -23
- package/src/css/detail.css +13 -13
- package/src/css/index-page.css +32 -0
- package/src/css/index-sidebar.css +187 -0
- package/src/css/index.css +4 -0
- package/src/css/layout.css +14 -14
- package/src/css/page-header.css +33 -0
- package/src/css/pagination.css +12 -12
- package/src/css/table.css +21 -22
- package/src/css/utilities.css +2 -2
- package/src/index.js +11 -8
- package/src/store/plugins/index.js +1 -0
- package/src/store/plugins/registerMapping.js +185 -0
- package/src/store/useObjectStore.js +122 -61
- package/src/utils/headers.js +7 -1
- package/src/utils/index.js +1 -1
- package/src/utils/schema.js +133 -1
- 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
package/src/css/pagination.css
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
display: flex;
|
|
7
7
|
justify-content: space-between;
|
|
8
8
|
align-items: center;
|
|
9
|
-
gap:
|
|
10
|
-
margin-top:
|
|
11
|
-
padding:
|
|
9
|
+
gap: calc(4 * var(--default-grid-baseline));
|
|
10
|
+
margin-top: calc(8 * var(--default-grid-baseline));
|
|
11
|
+
padding: calc(5 * var(--default-grid-baseline));
|
|
12
12
|
flex-wrap: nowrap;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
.cn-pagination__nav {
|
|
27
27
|
display: flex;
|
|
28
28
|
align-items: center;
|
|
29
|
-
gap:
|
|
29
|
+
gap: calc(2 * var(--default-grid-baseline));
|
|
30
30
|
flex-grow: 1;
|
|
31
31
|
justify-content: center;
|
|
32
32
|
}
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
.cn-pagination__numbers {
|
|
35
35
|
display: flex;
|
|
36
36
|
align-items: center;
|
|
37
|
-
gap:
|
|
37
|
+
gap: var(--default-grid-baseline);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
.cn-pagination__ellipsis {
|
|
41
|
-
padding: 0
|
|
41
|
+
padding: 0 var(--default-grid-baseline);
|
|
42
42
|
color: var(--color-text-maxcontrast);
|
|
43
43
|
font-size: 0.9rem;
|
|
44
44
|
}
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
.cn-pagination__page-size {
|
|
47
47
|
display: flex;
|
|
48
48
|
align-items: center;
|
|
49
|
-
gap:
|
|
49
|
+
gap: calc(2 * var(--default-grid-baseline));
|
|
50
50
|
flex-shrink: 0;
|
|
51
51
|
min-width: 0;
|
|
52
52
|
}
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/* Backwards compatibility aliases */
|
|
66
|
-
.viewPagination { display: flex; justify-content: space-between; align-items: center; gap:
|
|
66
|
+
.viewPagination { display: flex; justify-content: space-between; align-items: center; gap: calc(4 * var(--default-grid-baseline)); margin-top: calc(8 * var(--default-grid-baseline)); padding: calc(5 * var(--default-grid-baseline)); flex-wrap: nowrap; }
|
|
67
67
|
.viewPaginationInfo { display: flex; align-items: center; flex-shrink: 0; }
|
|
68
68
|
.viewPageInfo { color: var(--color-text-maxcontrast); font-size: 0.9rem; }
|
|
69
|
-
.viewPaginationNav { display: flex; align-items: center; gap:
|
|
70
|
-
.viewPaginationNumbers { display: flex; align-items: center; gap:
|
|
71
|
-
.viewPaginationEllipsis { padding: 0
|
|
72
|
-
.viewPaginationPageSize { display: flex; align-items: center; gap:
|
|
69
|
+
.viewPaginationNav { display: flex; align-items: center; gap: calc(2 * var(--default-grid-baseline)); flex-grow: 1; justify-content: center; }
|
|
70
|
+
.viewPaginationNumbers { display: flex; align-items: center; gap: var(--default-grid-baseline); }
|
|
71
|
+
.viewPaginationEllipsis { padding: 0 var(--default-grid-baseline); color: var(--color-text-maxcontrast); font-size: 0.9rem; }
|
|
72
|
+
.viewPaginationPageSize { display: flex; align-items: center; gap: calc(2 * var(--default-grid-baseline)); flex-shrink: 0; min-width: 0; }
|
package/src/css/table.css
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
/* Table Container */
|
|
6
6
|
.cn-table-container {
|
|
7
|
-
background: var(--
|
|
8
|
-
border-radius: var(--
|
|
7
|
+
background: var(--color-main-background);
|
|
8
|
+
border-radius: var(--border-radius);
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
box-shadow: 0 2px 4px var(--color-box-shadow);
|
|
11
|
-
border: 1px solid var(--
|
|
12
|
-
margin-bottom:
|
|
11
|
+
border: 1px solid var(--color-border);
|
|
12
|
+
margin-bottom: calc(5 * var(--default-grid-baseline));
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
.cn-table-container.cn-table-container--scrollable {
|
|
@@ -21,28 +21,27 @@
|
|
|
21
21
|
.cn-data-table {
|
|
22
22
|
width: 100%;
|
|
23
23
|
border-collapse: collapse;
|
|
24
|
-
background-color: var(--
|
|
24
|
+
background-color: var(--color-main-background);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.cn-data-table th,
|
|
28
28
|
.cn-data-table td {
|
|
29
|
-
padding: var(--
|
|
30
|
-
var(--nldesign-component-table-cell-padding-inline, 12px);
|
|
29
|
+
padding: calc(3 * var(--default-grid-baseline));
|
|
31
30
|
text-align: left;
|
|
32
|
-
border-bottom: 1px solid var(--
|
|
31
|
+
border-bottom: 1px solid var(--color-border);
|
|
33
32
|
vertical-align: middle;
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
.cn-data-table th {
|
|
37
|
-
background: var(--
|
|
38
|
-
font-weight:
|
|
36
|
+
background: var(--color-background-dark);
|
|
37
|
+
font-weight: 500;
|
|
39
38
|
color: var(--color-text-maxcontrast);
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
.cn-data-table th.cn-table-header--sortable {
|
|
43
42
|
cursor: pointer;
|
|
44
43
|
user-select: none;
|
|
45
|
-
transition: background-color
|
|
44
|
+
transition: background-color var(--animation-quick) ease;
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
.cn-data-table th.cn-table-header--sortable:hover {
|
|
@@ -50,19 +49,19 @@
|
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
.cn-table-sort-indicator {
|
|
53
|
-
margin-left:
|
|
52
|
+
margin-left: var(--default-grid-baseline);
|
|
54
53
|
opacity: 0.6;
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
/* Row States */
|
|
58
57
|
.cn-table-row {
|
|
59
|
-
border-bottom: 1px solid var(--
|
|
58
|
+
border-bottom: 1px solid var(--color-border);
|
|
60
59
|
cursor: pointer;
|
|
61
|
-
transition: background-color
|
|
60
|
+
transition: background-color var(--animation-quick) ease;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
.cn-table-row:hover {
|
|
65
|
-
background: var(--
|
|
64
|
+
background: var(--color-background-hover);
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
.cn-table-row--selected {
|
|
@@ -109,18 +108,18 @@
|
|
|
109
108
|
/* Loading State */
|
|
110
109
|
.cn-table-loading {
|
|
111
110
|
text-align: center;
|
|
112
|
-
padding:
|
|
111
|
+
padding: calc(12 * var(--default-grid-baseline));
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
.cn-table-loading p {
|
|
116
|
-
margin-top:
|
|
115
|
+
margin-top: calc(5 * var(--default-grid-baseline));
|
|
117
116
|
color: var(--color-text-maxcontrast);
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
/* Empty State (inside table) */
|
|
121
120
|
.cn-table-empty td {
|
|
122
121
|
text-align: center;
|
|
123
|
-
padding:
|
|
122
|
+
padding: calc(12 * var(--default-grid-baseline)) calc(6 * var(--default-grid-baseline));
|
|
124
123
|
color: var(--color-text-maxcontrast);
|
|
125
124
|
}
|
|
126
125
|
|
|
@@ -128,12 +127,12 @@
|
|
|
128
127
|
Backwards compatibility aliases
|
|
129
128
|
(legacy OpenRegister CSS class names)
|
|
130
129
|
======================================== */
|
|
131
|
-
.viewTableContainer { background: var(--
|
|
130
|
+
.viewTableContainer { background: var(--color-main-background); border-radius: var(--border-radius); overflow: hidden; box-shadow: 0 2px 4px var(--color-box-shadow); border: 1px solid var(--color-border); margin-bottom: calc(5 * var(--default-grid-baseline)); }
|
|
132
131
|
.viewTableContainer.scrollable { max-height: 400px; overflow-y: auto; }
|
|
133
|
-
.viewTable { width: 100%; border-collapse: collapse; background-color: var(--
|
|
134
|
-
.viewTable th, .viewTable td { padding:
|
|
132
|
+
.viewTable { width: 100%; border-collapse: collapse; background-color: var(--color-main-background); }
|
|
133
|
+
.viewTable th, .viewTable td { padding: calc(3 * var(--default-grid-baseline)); text-align: left; border-bottom: 1px solid var(--color-border); vertical-align: middle; }
|
|
135
134
|
.viewTable th { background: var(--color-background-hover); font-weight: 500; color: var(--color-text-maxcontrast); background-color: var(--color-background-dark); }
|
|
136
|
-
.viewTableRow { border-bottom: 1px solid var(--color-border); cursor: pointer; transition: background-color
|
|
135
|
+
.viewTableRow { border-bottom: 1px solid var(--color-border); cursor: pointer; transition: background-color var(--animation-quick) ease; }
|
|
137
136
|
.viewTableRow:hover { background: var(--color-background-hover); }
|
|
138
137
|
.viewTableRow.active, .viewTableRowSelected { background: var(--color-primary-light); }
|
|
139
138
|
.tableColumnCheckbox { width: 50px; text-align: center; }
|
package/src/css/utilities.css
CHANGED
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
|
|
22
22
|
/* Vue Transition Animations */
|
|
23
23
|
.cn-slide-fade-enter-active {
|
|
24
|
-
transition: all
|
|
24
|
+
transition: all var(--animation-slow) cubic-bezier(0.4, 0, 0.2, 1);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.cn-slide-fade-leave-active {
|
|
28
|
-
transition: all
|
|
28
|
+
transition: all var(--animation-quick) cubic-bezier(0.4, 0, 1, 1);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.cn-slide-fade-enter,
|
package/src/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
// CSS — auto-imported so consumers get styles with components
|
|
2
|
+
import './css/index.css'
|
|
3
|
+
|
|
1
4
|
// Components
|
|
2
5
|
export {
|
|
3
6
|
CnDataTable,
|
|
4
7
|
CnFilterBar,
|
|
5
|
-
CnListViewLayout,
|
|
6
|
-
CnDetailViewLayout,
|
|
7
8
|
CnStatusBadge,
|
|
8
|
-
CnEmptyState,
|
|
9
9
|
CnPagination,
|
|
10
10
|
CnSettingsCard,
|
|
11
11
|
CnSettingsSection,
|
|
@@ -16,15 +16,20 @@ export {
|
|
|
16
16
|
CnObjectCard,
|
|
17
17
|
CnCardGrid,
|
|
18
18
|
CnFacetSidebar,
|
|
19
|
-
CnViewModeToggle,
|
|
20
19
|
CnRowActions,
|
|
21
20
|
CnIndexPage,
|
|
22
21
|
CnMassActionBar,
|
|
22
|
+
CnDeleteDialog,
|
|
23
|
+
CnCopyDialog,
|
|
24
|
+
CnFormDialog,
|
|
23
25
|
CnMassDeleteDialog,
|
|
24
26
|
CnMassCopyDialog,
|
|
25
27
|
CnKpiGrid,
|
|
26
28
|
CnMassExportDialog,
|
|
27
29
|
CnMassImportDialog,
|
|
30
|
+
CnIndexSidebar,
|
|
31
|
+
CnRegisterMapping,
|
|
32
|
+
registerIcons,
|
|
28
33
|
} from './components/index.js'
|
|
29
34
|
|
|
30
35
|
// Store
|
|
@@ -37,6 +42,7 @@ export {
|
|
|
37
42
|
relationsPlugin,
|
|
38
43
|
filesPlugin,
|
|
39
44
|
lifecyclePlugin,
|
|
45
|
+
registerMappingPlugin,
|
|
40
46
|
} from './store/plugins/index.js'
|
|
41
47
|
|
|
42
48
|
// Composables
|
|
@@ -44,7 +50,4 @@ export { useListView, useDetailView, useSubResource } from './composables/index.
|
|
|
44
50
|
|
|
45
51
|
// Utilities
|
|
46
52
|
export { buildHeaders, buildQueryString, parseResponseError, networkError, genericError } from './utils/index.js'
|
|
47
|
-
export { columnsFromSchema, formatValue, filtersFromSchema } from './utils/index.js'
|
|
48
|
-
|
|
49
|
-
// CSS (consumers should import separately)
|
|
50
|
-
// import '@conduction/nextcloud-vue/src/css/index.css'
|
|
53
|
+
export { columnsFromSchema, formatValue, filtersFromSchema, fieldsFromSchema } from './utils/index.js'
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { buildHeaders } 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 {Object<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
|
+
/** @return {Array} Raw register list */
|
|
41
|
+
getRegisters: (state) => state.registers,
|
|
42
|
+
|
|
43
|
+
/** @return {boolean} Whether registers are loading */
|
|
44
|
+
isRegistersLoading: (state) => state.registersLoading,
|
|
45
|
+
|
|
46
|
+
/** @return {string|null} Last error */
|
|
47
|
+
getRegistersError: (state) => state.registersError,
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Registers as NcSelect-compatible options.
|
|
51
|
+
*
|
|
52
|
+
* @return {Array<{label: string, value: string}>}
|
|
53
|
+
*/
|
|
54
|
+
registerOptions: (state) => state.registers.map((r) => ({
|
|
55
|
+
label: r.title || r.slug || `Register ${r.id}`,
|
|
56
|
+
value: String(r.id),
|
|
57
|
+
})),
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
actions: {
|
|
61
|
+
/**
|
|
62
|
+
* Get schemas for a register as NcSelect options.
|
|
63
|
+
*
|
|
64
|
+
* @param {string|number} registerId Register ID
|
|
65
|
+
* @return {Array<{label: string, value: string}>}
|
|
66
|
+
*/
|
|
67
|
+
schemaOptions(registerId) {
|
|
68
|
+
const id = String(registerId)
|
|
69
|
+
return (this.registerSchemas[id] || []).map((s) => ({
|
|
70
|
+
label: s.title || s.slug || `Schema ${s.id}`,
|
|
71
|
+
value: String(s.id),
|
|
72
|
+
}))
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Fetch all registers from OpenRegister with expanded schemas.
|
|
77
|
+
*
|
|
78
|
+
* @param {boolean} [withSchemas=true] Include schemas in response
|
|
79
|
+
* @return {Promise<Array>} Fetched registers
|
|
80
|
+
*/
|
|
81
|
+
async fetchRegisters(withSchemas = true) {
|
|
82
|
+
this.registersLoading = true
|
|
83
|
+
this.registersError = null
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
let url = '/apps/openregister/api/registers'
|
|
87
|
+
if (withSchemas) {
|
|
88
|
+
url += '?_extend[]=schemas'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const response = await fetch(url, {
|
|
92
|
+
method: 'GET',
|
|
93
|
+
headers: buildHeaders(),
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
this.registersError = `Failed to fetch registers: ${response.statusText}`
|
|
98
|
+
return []
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const data = await response.json()
|
|
102
|
+
const results = data.results || data
|
|
103
|
+
this.registers = Array.isArray(results) ? results : []
|
|
104
|
+
|
|
105
|
+
// Cache expanded schemas by register ID
|
|
106
|
+
if (withSchemas) {
|
|
107
|
+
for (const reg of this.registers) {
|
|
108
|
+
if (Array.isArray(reg.schemas) && reg.schemas.length > 0) {
|
|
109
|
+
this.registerSchemas = {
|
|
110
|
+
...this.registerSchemas,
|
|
111
|
+
[String(reg.id)]: reg.schemas.filter(
|
|
112
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
113
|
+
),
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return this.registers
|
|
120
|
+
} catch (error) {
|
|
121
|
+
this.registersError = error.message || 'Network error fetching registers'
|
|
122
|
+
return []
|
|
123
|
+
} finally {
|
|
124
|
+
this.registersLoading = false
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Fetch schemas for a specific register.
|
|
130
|
+
* Returns cached data if already fetched via expanded registers.
|
|
131
|
+
*
|
|
132
|
+
* @param {string|number} registerId Register ID
|
|
133
|
+
* @return {Promise<Array>} Schemas for the register
|
|
134
|
+
*/
|
|
135
|
+
async fetchSchemasForRegister(registerId) {
|
|
136
|
+
const id = String(registerId)
|
|
137
|
+
|
|
138
|
+
// Return cached if available and non-empty
|
|
139
|
+
if (this.registerSchemas[id]?.length > 0) {
|
|
140
|
+
return this.registerSchemas[id]
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Check registers array for expanded schemas
|
|
144
|
+
const register = this.registers.find((r) => String(r.id) === id)
|
|
145
|
+
if (register?.schemas?.length > 0) {
|
|
146
|
+
const schemas = register.schemas.filter(
|
|
147
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
148
|
+
)
|
|
149
|
+
if (schemas.length > 0) {
|
|
150
|
+
this.registerSchemas = { ...this.registerSchemas, [id]: schemas }
|
|
151
|
+
return schemas
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Fetch from API as fallback
|
|
156
|
+
try {
|
|
157
|
+
const response = await fetch(
|
|
158
|
+
`/apps/openregister/api/registers/${id}?_extend[]=schemas`,
|
|
159
|
+
{ method: 'GET', headers: buildHeaders() },
|
|
160
|
+
)
|
|
161
|
+
if (!response.ok) return []
|
|
162
|
+
|
|
163
|
+
const data = await response.json()
|
|
164
|
+
const schemas = (data.schemas || []).filter(
|
|
165
|
+
(s) => s && typeof s === 'object' && s.id,
|
|
166
|
+
)
|
|
167
|
+
this.registerSchemas = { ...this.registerSchemas, [id]: schemas }
|
|
168
|
+
return schemas
|
|
169
|
+
} catch {
|
|
170
|
+
return []
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Clear all register mapping state.
|
|
176
|
+
*/
|
|
177
|
+
clearRegisterMapping() {
|
|
178
|
+
this.registers = []
|
|
179
|
+
this.registerSchemas = {}
|
|
180
|
+
this.registersLoading = false
|
|
181
|
+
this.registersError = null
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
}
|