@ditojs/admin 2.6.9 → 2.7.0
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/dito-admin.es.js +1469 -1456
- package/dist/dito-admin.umd.js +6 -6
- package/dist/style.css +1 -1
- package/package.json +4 -4
- package/src/DitoAdmin.js +6 -2
- package/src/components/DitoContainer.vue +38 -5
- package/src/components/DitoForm.vue +16 -11
- package/src/components/DitoHeader.vue +1 -1
- package/src/components/DitoLabel.vue +2 -2
- package/src/components/DitoPane.vue +1 -16
- package/src/components/DitoPanel.vue +9 -9
- package/src/components/DitoPanels.vue +2 -2
- package/src/components/DitoRoot.vue +2 -2
- package/src/components/DitoSchema.vue +45 -74
- package/src/components/DitoSchemaInlined.vue +2 -4
- package/src/components/DitoSidebar.vue +1 -0
- package/src/components/DitoTreeItem.vue +2 -1
- package/src/mixins/DitoMixin.js +7 -0
- package/src/mixins/ItemMixin.js +8 -0
- package/src/mixins/SortableMixin.js +0 -4
- package/src/mixins/SourceMixin.js +15 -10
- package/src/mixins/TypeMixin.js +5 -4
- package/src/types/DitoTypeList.vue +17 -22
- package/src/types/DitoTypeUpload.vue +2 -2
- package/src/utils/filter.js +4 -4
- package/src/utils/schema.js +2 -2
- package/src/utils/deprecate.js +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.
|
|
37
|
-
"@ditojs/utils": "^2.
|
|
36
|
+
"@ditojs/ui": "^2.7.0",
|
|
37
|
+
"@ditojs/utils": "^2.7.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
40
|
"@tiptap/core": "^2.0.3",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.4"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "874c68d5807ba97b67867f6b8d13f8fcb4990533",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
package/src/DitoAdmin.js
CHANGED
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
merge,
|
|
8
8
|
hyphenate,
|
|
9
9
|
camelize,
|
|
10
|
-
defaultFormats
|
|
10
|
+
defaultFormats,
|
|
11
|
+
deprecate
|
|
11
12
|
} from '@ditojs/utils'
|
|
12
13
|
import * as components from './components/index.js'
|
|
13
14
|
import * as types from './types/index.js'
|
|
@@ -15,7 +16,6 @@ import DitoRoot from './components/DitoRoot.vue'
|
|
|
15
16
|
import DitoTypeComponent from './DitoTypeComponent.js'
|
|
16
17
|
import ResizeDirective from './directives/resize.js'
|
|
17
18
|
import { getResource } from './utils/resource.js'
|
|
18
|
-
import { deprecate } from './utils/deprecate.js'
|
|
19
19
|
import { formatQuery } from './utils/route.js'
|
|
20
20
|
import verbs from './verbs.js'
|
|
21
21
|
|
|
@@ -194,6 +194,10 @@ export default class DitoAdmin {
|
|
|
194
194
|
})
|
|
195
195
|
}))
|
|
196
196
|
|
|
197
|
+
// Prevent endless loops of error messages during render functions by
|
|
198
|
+
// setting a custom error handler.
|
|
199
|
+
app.config.errorHandler = console.error
|
|
200
|
+
|
|
197
201
|
app.use(VueNotifications, {
|
|
198
202
|
name: 'notify',
|
|
199
203
|
componentName: 'VueNotifications'
|
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
:class="containerClass"
|
|
5
5
|
:style="containerStyle"
|
|
6
6
|
)
|
|
7
|
+
Teleport(
|
|
8
|
+
v-if="isMounted && panelEntries.length > 0"
|
|
9
|
+
to=".dito-sidebar__teleport"
|
|
10
|
+
)
|
|
11
|
+
DitoPanels(
|
|
12
|
+
:panels="panelEntries"
|
|
13
|
+
:data="data"
|
|
14
|
+
:meta="meta"
|
|
15
|
+
:store="store"
|
|
16
|
+
:disabled="disabled"
|
|
17
|
+
)
|
|
7
18
|
DitoLabel(
|
|
8
19
|
v-if="hasLabel"
|
|
9
20
|
:class="componentClass"
|
|
@@ -13,6 +24,7 @@
|
|
|
13
24
|
)
|
|
14
25
|
component.dito-component(
|
|
15
26
|
:is="typeComponent"
|
|
27
|
+
ref="component"
|
|
16
28
|
:class="componentClass"
|
|
17
29
|
:schema="schema"
|
|
18
30
|
:dataPath="dataPath"
|
|
@@ -35,7 +47,12 @@ import { isString, isNumber } from '@ditojs/utils'
|
|
|
35
47
|
import DitoComponent from '../DitoComponent.js'
|
|
36
48
|
import DitoContext from '../DitoContext.js'
|
|
37
49
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
38
|
-
import {
|
|
50
|
+
import {
|
|
51
|
+
getAllPanelEntries,
|
|
52
|
+
getTypeComponent,
|
|
53
|
+
hasLabel,
|
|
54
|
+
omitPadding
|
|
55
|
+
} from '../utils/schema.js'
|
|
39
56
|
import { parseFraction } from '../utils/math.js'
|
|
40
57
|
|
|
41
58
|
// @vue/component
|
|
@@ -56,7 +73,8 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
56
73
|
|
|
57
74
|
data() {
|
|
58
75
|
return {
|
|
59
|
-
errors: null
|
|
76
|
+
errors: null,
|
|
77
|
+
isMounted: false
|
|
60
78
|
}
|
|
61
79
|
},
|
|
62
80
|
|
|
@@ -196,9 +214,23 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
196
214
|
'dito-width-shrink': this.flexShrink,
|
|
197
215
|
'dito-has-errors': !!this.errors
|
|
198
216
|
}
|
|
217
|
+
},
|
|
218
|
+
|
|
219
|
+
panelEntries() {
|
|
220
|
+
return getAllPanelEntries(
|
|
221
|
+
this.api,
|
|
222
|
+
this.schema,
|
|
223
|
+
this.dataPath,
|
|
224
|
+
this.$refs.component,
|
|
225
|
+
this.tabComponent
|
|
226
|
+
)
|
|
199
227
|
}
|
|
200
228
|
},
|
|
201
229
|
|
|
230
|
+
mounted() {
|
|
231
|
+
this.isMounted = true
|
|
232
|
+
},
|
|
233
|
+
|
|
202
234
|
methods: {
|
|
203
235
|
onErrors(errors) {
|
|
204
236
|
this.errors = errors
|
|
@@ -263,9 +295,10 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
263
295
|
}
|
|
264
296
|
|
|
265
297
|
&--label-vertical {
|
|
266
|
-
// For components without labels in rows with other components that
|
|
267
|
-
// labels, add some spacing to the top to align with the other
|
|
268
|
-
|
|
298
|
+
// For plain components without labels in rows with other components that
|
|
299
|
+
// have labels, add some spacing to the top to align with the other
|
|
300
|
+
// components (e.g. buttons):
|
|
301
|
+
> .dito-component:first-child:not(.dito-section, .dito-list, .dito-object) {
|
|
269
302
|
margin-top: $line-height * $font-size + $form-spacing-half;
|
|
270
303
|
}
|
|
271
304
|
}
|
|
@@ -283,17 +283,22 @@ export default DitoComponent.component('DitoForm', {
|
|
|
283
283
|
},
|
|
284
284
|
|
|
285
285
|
watch: {
|
|
286
|
-
$route
|
|
287
|
-
//
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
this.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
286
|
+
$route: {
|
|
287
|
+
// https://github.com/vuejs/vue-router/issues/3393#issuecomment-1158470149
|
|
288
|
+
flush: 'post',
|
|
289
|
+
handler(to, from) {
|
|
290
|
+
// Reload form data when navigating to a different entity in same form.
|
|
291
|
+
const param = this.meta?.param
|
|
292
|
+
if (
|
|
293
|
+
param &&
|
|
294
|
+
this.providesData &&
|
|
295
|
+
// TODO: See if we can remove this due to `flush: 'post'`.
|
|
296
|
+
from.matched[0].path === to.matched[0].path && // Staying on same form
|
|
297
|
+
from.params[param] !== 'create' && // But haven't been creating
|
|
298
|
+
to.params[param] !== from.params[param] // Going to a different entity
|
|
299
|
+
) {
|
|
300
|
+
this.loadData(true)
|
|
301
|
+
}
|
|
297
302
|
}
|
|
298
303
|
},
|
|
299
304
|
|
|
@@ -91,16 +91,16 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
91
91
|
.dito-label {
|
|
92
92
|
$self: &;
|
|
93
93
|
|
|
94
|
-
--label-padding: 0;
|
|
95
94
|
// For buttons and chevron to align right:
|
|
96
95
|
display: flex;
|
|
97
96
|
position: relative;
|
|
98
97
|
// Vertically center all items in the label, e.g. chevron, edit-buttons.
|
|
99
98
|
align-items: center;
|
|
100
|
-
padding: var(--label-padding);
|
|
101
99
|
margin: 0 $form-spacing-half $form-spacing-half 0;
|
|
102
100
|
|
|
103
101
|
.dito-container:not(.dito-container--label-vertical) > & {
|
|
102
|
+
// When labels are not vertical (e.g. compact layout, next to component),
|
|
103
|
+
// clear bottom padding for better vertical alignment.
|
|
104
104
|
margin-bottom: 0;
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<script>
|
|
44
44
|
import DitoComponent from '../DitoComponent.js'
|
|
45
45
|
import { appendDataPath } from '../utils/data.js'
|
|
46
|
-
import {
|
|
46
|
+
import { isNested } from '../utils/schema.js'
|
|
47
47
|
|
|
48
48
|
// @vue/component
|
|
49
49
|
export default DitoComponent.component('DitoPane', {
|
|
@@ -108,21 +108,6 @@ export default DitoComponent.component('DitoPane', {
|
|
|
108
108
|
)
|
|
109
109
|
},
|
|
110
110
|
|
|
111
|
-
panelEntries() {
|
|
112
|
-
// Gather all panel schemas from all component schemas, by finding those
|
|
113
|
-
// that want to provide a panel. See `getAllPanelEntries()` for details.
|
|
114
|
-
return this.componentSchemas.flatMap(
|
|
115
|
-
({ schema, nestedDataPath: dataPath }) =>
|
|
116
|
-
getAllPanelEntries(
|
|
117
|
-
this.api,
|
|
118
|
-
schema,
|
|
119
|
-
dataPath,
|
|
120
|
-
this.schemaComponent,
|
|
121
|
-
this.tabComponent
|
|
122
|
-
)
|
|
123
|
-
)
|
|
124
|
-
},
|
|
125
|
-
|
|
126
111
|
isSingleComponent() {
|
|
127
112
|
return this.single && this.componentSchemas.length === 1
|
|
128
113
|
},
|
|
@@ -184,7 +184,7 @@ export default DitoComponent.component('DitoPanel', {
|
|
|
184
184
|
$form-spacing;
|
|
185
185
|
|
|
186
186
|
position: sticky;
|
|
187
|
-
top:
|
|
187
|
+
top: $content-padding;
|
|
188
188
|
margin-bottom: $margin;
|
|
189
189
|
z-index: 1;
|
|
190
190
|
|
|
@@ -222,20 +222,20 @@ export default DitoComponent.component('DitoPanel', {
|
|
|
222
222
|
border-bottom-right-radius: $border-radius;
|
|
223
223
|
|
|
224
224
|
> .dito-schema-content {
|
|
225
|
-
.dito-pane {
|
|
226
|
-
margin: -$form-spacing-half;
|
|
227
|
-
|
|
228
|
-
> .dito-container:not(.dito-container--single) {
|
|
229
|
-
padding: $form-spacing-half;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
225
|
> .dito-pane {
|
|
234
226
|
padding: $form-spacing;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.dito-pane {
|
|
230
|
+
margin: -$form-spacing-half;
|
|
235
231
|
|
|
236
232
|
&.dito-pane--single {
|
|
237
233
|
margin: 0;
|
|
238
234
|
}
|
|
235
|
+
|
|
236
|
+
> .dito-container:not(.dito-container--single) {
|
|
237
|
+
padding: $form-spacing-half;
|
|
238
|
+
}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
.dito-object {
|
|
@@ -449,8 +449,8 @@ let dialogId = 0
|
|
|
449
449
|
function addRoutes(router, routes) {
|
|
450
450
|
const removers = []
|
|
451
451
|
for (const route of routes) {
|
|
452
|
-
const
|
|
453
|
-
removers.push(
|
|
452
|
+
const remove = router.addRoute(route)
|
|
453
|
+
removers.push(remove)
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
return () => {
|
|
@@ -3,16 +3,27 @@ slot(name="before")
|
|
|
3
3
|
.dito-schema(
|
|
4
4
|
v-bind="$attrs"
|
|
5
5
|
)
|
|
6
|
+
Teleport(
|
|
7
|
+
v-if="isPopulated && panelEntries.length > 0"
|
|
8
|
+
to=".dito-sidebar__teleport"
|
|
9
|
+
)
|
|
10
|
+
DitoPanels(
|
|
11
|
+
:panels="panelEntries"
|
|
12
|
+
:data="data"
|
|
13
|
+
:meta="meta"
|
|
14
|
+
:store="store"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
)
|
|
6
17
|
.dito-schema-content(
|
|
7
18
|
ref="content"
|
|
8
19
|
:class="{ 'dito-scroll': scrollable }"
|
|
9
20
|
)
|
|
10
21
|
Teleport(
|
|
11
|
-
|
|
22
|
+
v-if="hasLabel || hasTabs || clipboard"
|
|
23
|
+
to=".dito-header__teleport"
|
|
12
24
|
:disabled="!headerInMenu"
|
|
13
25
|
)
|
|
14
26
|
.dito-schema-header(
|
|
15
|
-
v-if="hasLabel || hasTabs || clipboard"
|
|
16
27
|
:class="{ 'dito-schema-header--menu': headerInMenu }"
|
|
17
28
|
)
|
|
18
29
|
DitoLabel(
|
|
@@ -83,18 +94,6 @@ slot(name="before")
|
|
|
83
94
|
v-if="!hasLabel"
|
|
84
95
|
name="edit-buttons"
|
|
85
96
|
)
|
|
86
|
-
Teleport(
|
|
87
|
-
v-else-if="isPopulated"
|
|
88
|
-
to=".dito-sidebar"
|
|
89
|
-
)
|
|
90
|
-
DitoPanels(
|
|
91
|
-
:class="{ 'dito-scroll': scrollable }"
|
|
92
|
-
:panels="panelEntries"
|
|
93
|
-
:data="data"
|
|
94
|
-
:meta="meta"
|
|
95
|
-
:store="store"
|
|
96
|
-
:disabled="disabled"
|
|
97
|
-
)
|
|
98
97
|
slot(name="after")
|
|
99
98
|
</template>
|
|
100
99
|
|
|
@@ -116,8 +115,7 @@ import {
|
|
|
116
115
|
getNamedSchemas,
|
|
117
116
|
getPanelEntries,
|
|
118
117
|
setDefaultValues,
|
|
119
|
-
processData
|
|
120
|
-
isForm
|
|
118
|
+
processData
|
|
121
119
|
} from '../utils/schema.js'
|
|
122
120
|
import { getSchemaAccessor, getStoreAccessor } from '../utils/accessor.js'
|
|
123
121
|
|
|
@@ -164,7 +162,6 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
164
162
|
? data(this.context)
|
|
165
163
|
: data
|
|
166
164
|
),
|
|
167
|
-
currentPath: null,
|
|
168
165
|
currentTab: null,
|
|
169
166
|
componentsRegistry: {},
|
|
170
167
|
panesRegistry: {},
|
|
@@ -186,11 +183,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
186
183
|
},
|
|
187
184
|
|
|
188
185
|
panelEntries() {
|
|
189
|
-
|
|
190
|
-
for (const pane of this.panes) {
|
|
191
|
-
panelEntries.push(...pane.panelEntries)
|
|
192
|
-
}
|
|
193
|
-
return panelEntries
|
|
186
|
+
return getPanelEntries(this.schema.panels, '')
|
|
194
187
|
},
|
|
195
188
|
|
|
196
189
|
tabs() {
|
|
@@ -349,21 +342,13 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
349
342
|
watch: {
|
|
350
343
|
'$route.hash': {
|
|
351
344
|
immediate: true,
|
|
345
|
+
// https://github.com/vuejs/vue-router/issues/3393#issuecomment-1158470149
|
|
346
|
+
flush: 'post',
|
|
352
347
|
handler(hash) {
|
|
353
348
|
// Remember the current path to know if tab changes should still be
|
|
354
349
|
// handled, but remove the trailing `/create` or `/:id` from it so that
|
|
355
350
|
// tabs informs that stay open after creation still work.
|
|
356
|
-
|
|
357
|
-
isForm(this.schema)
|
|
358
|
-
? this.$route.path.replace(/\/.\w*$/, '')
|
|
359
|
-
: this.$route.path
|
|
360
|
-
if (
|
|
361
|
-
this.hasTabs && (
|
|
362
|
-
!this.currentPath ||
|
|
363
|
-
this.currentPath === getPath()
|
|
364
|
-
)
|
|
365
|
-
) {
|
|
366
|
-
this.currentPath = getPath()
|
|
351
|
+
if (this.hasTabs) {
|
|
367
352
|
this.currentTab = hash?.slice(1) || null
|
|
368
353
|
if (this.hasErrors) {
|
|
369
354
|
this.repositionErrors()
|
|
@@ -408,48 +393,44 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
408
393
|
},
|
|
409
394
|
|
|
410
395
|
methods: {
|
|
411
|
-
getComponentsByDataPath(dataPath
|
|
412
|
-
return this._getEntriesByDataPath(
|
|
413
|
-
this.componentsByDataPath,
|
|
414
|
-
dataPath,
|
|
415
|
-
match
|
|
416
|
-
)
|
|
396
|
+
getComponentsByDataPath(dataPath) {
|
|
397
|
+
return this._getEntriesByDataPath(this.componentsByDataPath, dataPath)
|
|
417
398
|
},
|
|
418
399
|
|
|
419
|
-
getComponentByDataPath(dataPath
|
|
420
|
-
return this.getComponentsByDataPath(dataPath
|
|
400
|
+
getComponentByDataPath(dataPath) {
|
|
401
|
+
return this.getComponentsByDataPath(dataPath)[0] || null
|
|
421
402
|
},
|
|
422
403
|
|
|
423
|
-
getComponentsByName(dataPath
|
|
424
|
-
return this._getEntriesByName(this.componentsByDataPath, dataPath
|
|
404
|
+
getComponentsByName(dataPath) {
|
|
405
|
+
return this._getEntriesByName(this.componentsByDataPath, dataPath)
|
|
425
406
|
},
|
|
426
407
|
|
|
427
|
-
getComponentByName(name
|
|
428
|
-
return this.getComponentsByName(name
|
|
408
|
+
getComponentByName(name) {
|
|
409
|
+
return this.getComponentsByName(name)[0] || null
|
|
429
410
|
},
|
|
430
411
|
|
|
431
|
-
getComponents(dataPathOrName
|
|
432
|
-
return this._getEntries(this.componentsByDataPath, dataPathOrName
|
|
412
|
+
getComponents(dataPathOrName) {
|
|
413
|
+
return this._getEntries(this.componentsByDataPath, dataPathOrName)
|
|
433
414
|
},
|
|
434
415
|
|
|
435
|
-
getComponent(dataPathOrName
|
|
436
|
-
return this.getComponents(dataPathOrName
|
|
416
|
+
getComponent(dataPathOrName) {
|
|
417
|
+
return this.getComponents(dataPathOrName)[0] || null
|
|
437
418
|
},
|
|
438
419
|
|
|
439
|
-
getPanelsByDataPath(dataPath
|
|
440
|
-
return this._getEntriesByDataPath(this.panelsByDataPath, dataPath
|
|
420
|
+
getPanelsByDataPath(dataPath) {
|
|
421
|
+
return this._getEntriesByDataPath(this.panelsByDataPath, dataPath)
|
|
441
422
|
},
|
|
442
423
|
|
|
443
|
-
getPanelByDataPath(dataPath
|
|
444
|
-
return this.getPanelsByDataPath(dataPath
|
|
424
|
+
getPanelByDataPath(dataPath) {
|
|
425
|
+
return this.getPanelsByDataPath(dataPath)[0] || null
|
|
445
426
|
},
|
|
446
427
|
|
|
447
|
-
getPanels(dataPathOrName
|
|
448
|
-
return this._getEntries(this.panelsByDataPath, dataPathOrName
|
|
428
|
+
getPanels(dataPathOrName) {
|
|
429
|
+
return this._getEntries(this.panelsByDataPath, dataPathOrName)
|
|
449
430
|
},
|
|
450
431
|
|
|
451
|
-
getPanel(dataPathOrName
|
|
452
|
-
return this.getPanels(dataPathOrName
|
|
432
|
+
getPanel(dataPathOrName) {
|
|
433
|
+
return this.getPanels(dataPathOrName)[0] || null
|
|
453
434
|
},
|
|
454
435
|
|
|
455
436
|
someComponent(callback) {
|
|
@@ -728,28 +709,18 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
728
709
|
}, {})
|
|
729
710
|
},
|
|
730
711
|
|
|
731
|
-
_getEntries(entriesByDataPath, dataPath
|
|
712
|
+
_getEntries(entriesByDataPath, dataPath) {
|
|
732
713
|
return normalizeDataPath(dataPath).startsWith(this.dataPath)
|
|
733
|
-
? this._getEntriesByDataPath(entriesByDataPath, dataPath
|
|
734
|
-
: this._getEntriesByName(entriesByDataPath, dataPath
|
|
735
|
-
},
|
|
736
|
-
|
|
737
|
-
_getEntriesByDataPath(entriesByDataPath, dataPath, match) {
|
|
738
|
-
return this._filterEntries(
|
|
739
|
-
entriesByDataPath[normalizeDataPath(dataPath)] || [],
|
|
740
|
-
match
|
|
741
|
-
)
|
|
714
|
+
? this._getEntriesByDataPath(entriesByDataPath, dataPath)
|
|
715
|
+
: this._getEntriesByName(entriesByDataPath, dataPath)
|
|
742
716
|
},
|
|
743
717
|
|
|
744
|
-
|
|
745
|
-
return
|
|
746
|
-
entriesByDataPath[appendDataPath(this.dataPath, name)] || [],
|
|
747
|
-
match
|
|
748
|
-
)
|
|
718
|
+
_getEntriesByDataPath(entriesByDataPath, dataPath) {
|
|
719
|
+
return entriesByDataPath[normalizeDataPath(dataPath)] || []
|
|
749
720
|
},
|
|
750
721
|
|
|
751
|
-
|
|
752
|
-
return
|
|
722
|
+
_getEntriesByName(entriesByDataPath, name) {
|
|
723
|
+
return entriesByDataPath[appendDataPath(this.dataPath, name)] || []
|
|
753
724
|
}
|
|
754
725
|
}
|
|
755
726
|
})
|
|
@@ -78,10 +78,8 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
78
78
|
margin: -$form-spacing;
|
|
79
79
|
|
|
80
80
|
.dito-label {
|
|
81
|
-
// Add removed $form-spacing again
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
margin: 0;
|
|
81
|
+
// Add removed $form-spacing again.
|
|
82
|
+
margin: $form-spacing;
|
|
85
83
|
width: 100%;
|
|
86
84
|
box-sizing: content-box;
|
|
87
85
|
// Prevent collapsing to min-height when alone in
|
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
|
|
100
100
|
<script>
|
|
101
101
|
import DitoComponent from '../DitoComponent.js'
|
|
102
|
+
import ItemMixin from '../mixins/ItemMixin'
|
|
102
103
|
import SortableMixin from '../mixins/SortableMixin.js'
|
|
103
104
|
import { appendDataPath } from '../utils/data.js'
|
|
104
105
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
@@ -106,7 +107,7 @@ import { getNamedSchemas, hasFormSchema } from '../utils/schema.js'
|
|
|
106
107
|
|
|
107
108
|
// @vue/component
|
|
108
109
|
export default DitoComponent.component('DitoTreeItem', {
|
|
109
|
-
mixins: [SortableMixin],
|
|
110
|
+
mixins: [ItemMixin, SortableMixin],
|
|
110
111
|
inject: ['container'],
|
|
111
112
|
|
|
112
113
|
props: {
|
package/src/mixins/DitoMixin.js
CHANGED
|
@@ -235,6 +235,13 @@ export default {
|
|
|
235
235
|
return store
|
|
236
236
|
},
|
|
237
237
|
|
|
238
|
+
removeChildStore(key, index) {
|
|
239
|
+
// GEt the child-store first, so that indices can be transferred over
|
|
240
|
+
// temporary id changes during persistence.
|
|
241
|
+
this.getChildStore(key, index)
|
|
242
|
+
this.removeStore(key)
|
|
243
|
+
},
|
|
244
|
+
|
|
238
245
|
getSchemaValue(
|
|
239
246
|
keyOrDataPath,
|
|
240
247
|
{
|
package/src/mixins/ItemMixin.js
CHANGED
|
@@ -32,6 +32,14 @@ export default {
|
|
|
32
32
|
return dataPath
|
|
33
33
|
},
|
|
34
34
|
|
|
35
|
+
getItemStore(sourceSchema, item, index) {
|
|
36
|
+
return this.getChildStore(this.getItemUid(sourceSchema, item), index)
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
removeItemStore(sourceSchema, item, index) {
|
|
40
|
+
this.removeChildStore(this.getItemUid(sourceSchema, item), index)
|
|
41
|
+
},
|
|
42
|
+
|
|
35
43
|
findItemIdIndex(sourceSchema, data, itemId) {
|
|
36
44
|
const index = this.isTransient
|
|
37
45
|
? // For transient data, the index is used as the id
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import DitoComponent from '../DitoComponent.js'
|
|
2
|
+
import ItemMixin from './ItemMixin.js'
|
|
2
3
|
import ResourceMixin from './ResourceMixin.js'
|
|
3
4
|
import SchemaParentMixin from '../mixins/SchemaParentMixin.js'
|
|
4
5
|
import { getSchemaAccessor, getStoreAccessor } from '../utils/accessor.js'
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
|
|
30
31
|
// @vue/component
|
|
31
32
|
export default {
|
|
32
|
-
mixins: [ResourceMixin, SchemaParentMixin],
|
|
33
|
+
mixins: [ItemMixin, ResourceMixin, SchemaParentMixin],
|
|
33
34
|
|
|
34
35
|
defaultValue(schema) {
|
|
35
36
|
return isListSource(schema) ? [] : null
|
|
@@ -404,18 +405,22 @@ export default {
|
|
|
404
405
|
return item
|
|
405
406
|
},
|
|
406
407
|
|
|
407
|
-
removeItem(item) {
|
|
408
|
+
removeItem(item, index) {
|
|
409
|
+
let removed = false
|
|
408
410
|
if (this.isObjectSource) {
|
|
409
411
|
this.objectData = null
|
|
410
|
-
|
|
412
|
+
removed = true
|
|
411
413
|
} else {
|
|
412
414
|
const { listData } = this
|
|
413
|
-
const index = listData && listData.indexOf(item)
|
|
414
415
|
if (index >= 0) {
|
|
415
416
|
listData.splice(index, 1)
|
|
416
|
-
|
|
417
|
+
removed = true
|
|
417
418
|
}
|
|
418
419
|
}
|
|
420
|
+
if (removed) {
|
|
421
|
+
this.removeItemStore(this.schema, item, index)
|
|
422
|
+
this.onChange()
|
|
423
|
+
}
|
|
419
424
|
},
|
|
420
425
|
|
|
421
426
|
deleteItem(item, index) {
|
|
@@ -444,15 +449,15 @@ export default {
|
|
|
444
449
|
)
|
|
445
450
|
) {
|
|
446
451
|
if (this.isTransient) {
|
|
447
|
-
this.removeItem(item)
|
|
452
|
+
this.removeItem(item, index)
|
|
448
453
|
notify()
|
|
449
454
|
} else {
|
|
450
|
-
const itemId = this.getItemId(this.schema, item)
|
|
455
|
+
const itemId = this.getItemId(this.schema, item, index)
|
|
451
456
|
const resource = getMemberResource(itemId, this.resource)
|
|
452
457
|
if (resource) {
|
|
453
458
|
this.handleRequest({ method: 'delete', resource }, err => {
|
|
454
459
|
if (!err) {
|
|
455
|
-
this.removeItem(item)
|
|
460
|
+
this.removeItem(item, index)
|
|
456
461
|
notify()
|
|
457
462
|
}
|
|
458
463
|
this.reloadData()
|
|
@@ -520,8 +525,8 @@ export default {
|
|
|
520
525
|
this.api.normalizePath(normalizeDataPath(dataPathParts))
|
|
521
526
|
)
|
|
522
527
|
// See if there actually is a route for this sub-component:
|
|
523
|
-
const { matched } = this.$router.
|
|
524
|
-
if (matched.length) {
|
|
528
|
+
const { matched } = this.$router.resolve(path)
|
|
529
|
+
if (matched.length && matched[0].name !== 'catch-all') {
|
|
525
530
|
if (this.$route.path === path) {
|
|
526
531
|
// We're already there, so just call `onComplete()`:
|
|
527
532
|
callOnComplete()
|