@ditojs/admin 2.8.0 → 2.8.1
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 +457 -454
- package/dist/dito-admin.umd.js +5 -5
- package/dist/style.css +1 -1
- package/package.json +2 -2
- package/src/components/DitoCreateButton.vue +17 -1
- package/src/components/DitoEditButtons.vue +31 -25
- package/src/components/DitoElement.vue +2 -2
- package/src/components/DitoLabel.vue +3 -2
- package/src/components/DitoPane.vue +8 -4
- package/src/components/DitoSchema.vue +16 -14
- package/src/mixins/TypeMixin.js +9 -30
- package/src/types/DitoTypeMultiselect.vue +2 -1
- package/src/types/DitoTypeSelect.vue +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.1",
|
|
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",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.5"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "26db3d0a7ebbed92b052bd7cffa078e9cdae7497",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -40,6 +40,15 @@ export default DitoComponent.component('DitoCreateButton', {
|
|
|
40
40
|
|
|
41
41
|
props: {
|
|
42
42
|
schema: { type: Object, required: true },
|
|
43
|
+
// The next four props are there for `DitoContext` and the `context()`
|
|
44
|
+
// getter in `DitoMixin`.
|
|
45
|
+
// TODO: Should they be moved to shared mixin that defines them as required
|
|
46
|
+
// and also provides the `context()` getter, perhaps `ContextMixin`?
|
|
47
|
+
// `schema` could be included as well, and `ContextMixin` could be used in
|
|
48
|
+
// `DitoForm`, `DitoView`, `DitoPanel`, `DitoSchema`, `DitoEditButtons`,
|
|
49
|
+
// etc? But the problem with the root components is that they don't have
|
|
50
|
+
// these props. We could add a `contextAttributes()` getter for easy passing
|
|
51
|
+
// on as `v-bind="contextAttributes"`.
|
|
43
52
|
dataPath: { type: String, required: true },
|
|
44
53
|
data: { type: [Object, Array], default: null },
|
|
45
54
|
meta: { type: Object, required: true },
|
|
@@ -72,7 +81,14 @@ export default DitoComponent.component('DitoCreateButton', {
|
|
|
72
81
|
isFormCreatable(form) {
|
|
73
82
|
// Forms can be excluded from the list by providing `if: false` or
|
|
74
83
|
// `creatable: false`.
|
|
75
|
-
return
|
|
84
|
+
return (
|
|
85
|
+
this.shouldRenderSchema(form) &&
|
|
86
|
+
this.getSchemaValue('creatable', {
|
|
87
|
+
type: Boolean,
|
|
88
|
+
default: true,
|
|
89
|
+
schema: form
|
|
90
|
+
})
|
|
91
|
+
)
|
|
76
92
|
},
|
|
77
93
|
|
|
78
94
|
createItem(form, type = null) {
|
|
@@ -10,18 +10,18 @@ DitoButtons.dito-edit-buttons.dito-buttons-round(
|
|
|
10
10
|
)
|
|
11
11
|
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
12
12
|
a.dito-button(
|
|
13
|
-
v-if="
|
|
14
|
-
:class="{ 'dito-disabled':
|
|
13
|
+
v-if="draggable"
|
|
14
|
+
:class="{ 'dito-disabled': isDraggableDisabled }"
|
|
15
15
|
v-bind="getButtonAttributes(verbs.drag)"
|
|
16
16
|
)
|
|
17
17
|
RouterLink.dito-button(
|
|
18
|
-
v-if="
|
|
19
|
-
:class="{ 'dito-disabled':
|
|
18
|
+
v-if="editable"
|
|
19
|
+
:class="{ 'dito-disabled': isEditableDisabled }"
|
|
20
20
|
:to="editPath ? { path: editPath } : {}"
|
|
21
21
|
v-bind="getButtonAttributes(verbs.edit)"
|
|
22
22
|
)
|
|
23
23
|
DitoCreateButton(
|
|
24
|
-
v-if="
|
|
24
|
+
v-if="creatable"
|
|
25
25
|
:schema="schema"
|
|
26
26
|
:dataPath="dataPath"
|
|
27
27
|
:data="data"
|
|
@@ -30,12 +30,12 @@ DitoButtons.dito-edit-buttons.dito-buttons-round(
|
|
|
30
30
|
:path="createPath"
|
|
31
31
|
:verb="verbs.create"
|
|
32
32
|
:text="createButtonText"
|
|
33
|
-
:disabled="
|
|
33
|
+
:disabled="isCreatableDisabled"
|
|
34
34
|
)
|
|
35
35
|
button.dito-button(
|
|
36
|
-
v-if="
|
|
36
|
+
v-if="deletable"
|
|
37
37
|
type="button"
|
|
38
|
-
:disabled="
|
|
38
|
+
:disabled="isDeletableDisabled"
|
|
39
39
|
v-bind="getButtonAttributes(verbs.delete)"
|
|
40
40
|
@click="$emit('delete')"
|
|
41
41
|
)
|
|
@@ -70,24 +70,28 @@ export default DitoComponent.component('DitoEditButtons', {
|
|
|
70
70
|
return this.getLabel(this.schema.form)
|
|
71
71
|
},
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
return this.
|
|
73
|
+
isDraggableDisabled() {
|
|
74
|
+
return this.disabled || !this.hasSchemaOption('draggable')
|
|
75
75
|
},
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
return this.
|
|
77
|
+
isDeletableDisabled() {
|
|
78
|
+
return this.disabled || !this.hasSchemaOption('deletable')
|
|
79
79
|
},
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
isCreatableDisabled() {
|
|
82
|
+
return (
|
|
83
|
+
this.disabled ||
|
|
84
|
+
!this.createPath ||
|
|
85
|
+
!this.hasSchemaOption('creatable')
|
|
86
|
+
)
|
|
87
87
|
},
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
return
|
|
89
|
+
isEditableDisabled() {
|
|
90
|
+
return (
|
|
91
|
+
this.disabled ||
|
|
92
|
+
!this.editPath ||
|
|
93
|
+
!this.hasSchemaOption('editable')
|
|
94
|
+
)
|
|
91
95
|
},
|
|
92
96
|
|
|
93
97
|
createButtonText() {
|
|
@@ -105,11 +109,13 @@ export default DitoComponent.component('DitoEditButtons', {
|
|
|
105
109
|
},
|
|
106
110
|
|
|
107
111
|
methods: {
|
|
108
|
-
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
hasSchemaOption(name) {
|
|
113
|
+
// All options can be disabled on a per-form basis by setting
|
|
114
|
+
// `schema[name]` to `false` or a callback returning `false`.
|
|
115
|
+
return this.getSchemaValue(name, {
|
|
116
|
+
type: Boolean,
|
|
117
|
+
default: true
|
|
118
|
+
})
|
|
113
119
|
}
|
|
114
120
|
}
|
|
115
121
|
})
|
|
@@ -26,14 +26,14 @@ export default DitoComponent.component('DitoElement', {
|
|
|
26
26
|
|
|
27
27
|
classes() {
|
|
28
28
|
return {
|
|
29
|
-
...this.$attrs.class,
|
|
29
|
+
...asObject(this.$attrs.class),
|
|
30
30
|
...asObject(this.options.class)
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
|
|
34
34
|
styles() {
|
|
35
35
|
return {
|
|
36
|
-
...this.$attrs.style,
|
|
36
|
+
...asObject(this.$attrs.style),
|
|
37
37
|
...asObject(this.options.style)
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -123,8 +123,6 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
123
123
|
label {
|
|
124
124
|
cursor: inherit;
|
|
125
125
|
font-weight: bold;
|
|
126
|
-
white-space: nowrap;
|
|
127
|
-
line-height: $input-height;
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
label,
|
|
@@ -132,6 +130,9 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
132
130
|
&__suffix {
|
|
133
131
|
@include user-select(none);
|
|
134
132
|
@include ellipsis;
|
|
133
|
+
|
|
134
|
+
white-space: nowrap;
|
|
135
|
+
line-height: $input-height;
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
&__prefix + label,
|
|
@@ -219,6 +219,7 @@ export default DitoComponent.component('DitoPane', {
|
|
|
219
219
|
|
|
220
220
|
.dito-pane {
|
|
221
221
|
$self: &;
|
|
222
|
+
$root-padding: $content-padding - $form-spacing-half;
|
|
222
223
|
|
|
223
224
|
display: flex;
|
|
224
225
|
position: relative;
|
|
@@ -240,7 +241,7 @@ export default DitoComponent.component('DitoPane', {
|
|
|
240
241
|
margin: 0;
|
|
241
242
|
// Move the negative margin used to remove the padding added by
|
|
242
243
|
// `.dito-container` inside `.dito-pane` to the padding:
|
|
243
|
-
padding: $
|
|
244
|
+
padding: $root-padding;
|
|
244
245
|
|
|
245
246
|
&#{$self}--single {
|
|
246
247
|
padding: $content-padding;
|
|
@@ -260,9 +261,9 @@ export default DitoComponent.component('DitoPane', {
|
|
|
260
261
|
content: '';
|
|
261
262
|
width: 100%;
|
|
262
263
|
border-bottom: $border-style;
|
|
263
|
-
//
|
|
264
|
-
margin: (-$
|
|
265
|
-
|
|
264
|
+
// Shift ruler up by $root-padding to exclude removed $form-spacing-half.
|
|
265
|
+
margin: (-$root-padding) $form-spacing-half $root-padding;
|
|
266
|
+
padding: $form-spacing-half;
|
|
266
267
|
}
|
|
267
268
|
}
|
|
268
269
|
|
|
@@ -273,6 +274,9 @@ export default DitoComponent.component('DitoPane', {
|
|
|
273
274
|
}
|
|
274
275
|
|
|
275
276
|
.dito-break {
|
|
277
|
+
// `.dito-break` is rendered as <span> so we can use the
|
|
278
|
+
// `.dito-container:first-of-type` selector to match the first container
|
|
279
|
+
// even if it has a break before it.
|
|
276
280
|
display: block;
|
|
277
281
|
flex: 100%;
|
|
278
282
|
height: 0;
|
|
@@ -53,22 +53,24 @@ slot(name="before")
|
|
|
53
53
|
template(
|
|
54
54
|
v-if="hasTabs"
|
|
55
55
|
)
|
|
56
|
-
|
|
56
|
+
template(
|
|
57
57
|
v-for="(tabSchema, tab) in tabs"
|
|
58
|
-
v-show="selectedTab === tab"
|
|
59
|
-
ref="tabs"
|
|
60
|
-
:key="tab"
|
|
61
|
-
:tab="tab"
|
|
62
|
-
:schema="tabSchema"
|
|
63
|
-
:dataPath="dataPath"
|
|
64
|
-
:data="data"
|
|
65
|
-
:meta="meta"
|
|
66
|
-
:store="store"
|
|
67
|
-
:single="!inlined && !hasMainPane"
|
|
68
|
-
:disabled="disabled"
|
|
69
|
-
:generateLabels="generateLabels"
|
|
70
|
-
:accumulatedBasis="accumulatedBasis"
|
|
71
58
|
)
|
|
59
|
+
DitoPane.dito-pane__tab(
|
|
60
|
+
v-if="selectedTab === tab"
|
|
61
|
+
ref="tabs"
|
|
62
|
+
:key="tab"
|
|
63
|
+
:tab="tab"
|
|
64
|
+
:schema="tabSchema"
|
|
65
|
+
:dataPath="dataPath"
|
|
66
|
+
:data="data"
|
|
67
|
+
:meta="meta"
|
|
68
|
+
:store="store"
|
|
69
|
+
:single="!inlined && !hasMainPane"
|
|
70
|
+
:disabled="disabled"
|
|
71
|
+
:generateLabels="generateLabels"
|
|
72
|
+
:accumulatedBasis="accumulatedBasis"
|
|
73
|
+
)
|
|
72
74
|
DitoPane.dito-pane__main(
|
|
73
75
|
v-if="hasMainPane"
|
|
74
76
|
ref="components"
|
package/src/mixins/TypeMixin.js
CHANGED
|
@@ -28,7 +28,6 @@ export default {
|
|
|
28
28
|
data() {
|
|
29
29
|
return {
|
|
30
30
|
parsedValue: undefined,
|
|
31
|
-
changedValue: undefined,
|
|
32
31
|
focused: false
|
|
33
32
|
}
|
|
34
33
|
},
|
|
@@ -48,37 +47,27 @@ export default {
|
|
|
48
47
|
|
|
49
48
|
value: {
|
|
50
49
|
get() {
|
|
51
|
-
|
|
50
|
+
const value = computeValue(
|
|
52
51
|
this.schema,
|
|
53
52
|
this.data,
|
|
54
53
|
this.name,
|
|
55
54
|
this.dataPath,
|
|
56
55
|
{ component: this }
|
|
57
56
|
)
|
|
58
|
-
const { formatValue } = this.$options
|
|
59
|
-
if (formatValue) {
|
|
60
|
-
value = formatValue(this.schema, value, this.dataPath)
|
|
61
|
-
}
|
|
62
57
|
const { format } = this.schema
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return value
|
|
58
|
+
return format
|
|
59
|
+
? format(new DitoContext(this, { value }))
|
|
60
|
+
: value
|
|
67
61
|
},
|
|
68
62
|
|
|
69
63
|
set(value) {
|
|
70
|
-
const { parseValue } = this.$options
|
|
71
|
-
if (parseValue) {
|
|
72
|
-
value = parseValue(this.schema, value, this.dataPath)
|
|
73
|
-
}
|
|
74
64
|
const { parse } = this.schema
|
|
75
65
|
if (parse) {
|
|
76
66
|
value = parse(new DitoContext(this, { value }))
|
|
77
67
|
}
|
|
68
|
+
this.parsedValue = value
|
|
78
69
|
// eslint-disable-next-line vue/no-mutating-props
|
|
79
70
|
this.data[this.name] = value
|
|
80
|
-
this.parsedValue = value
|
|
81
|
-
this.changedValue = undefined
|
|
82
71
|
}
|
|
83
72
|
},
|
|
84
73
|
|
|
@@ -295,7 +284,6 @@ export default {
|
|
|
295
284
|
|
|
296
285
|
clear() {
|
|
297
286
|
this.value = null
|
|
298
|
-
this.changedValue = undefined
|
|
299
287
|
this.blur()
|
|
300
288
|
this.onChange()
|
|
301
289
|
},
|
|
@@ -318,21 +306,12 @@ export default {
|
|
|
318
306
|
},
|
|
319
307
|
|
|
320
308
|
onChange() {
|
|
321
|
-
const value =
|
|
322
|
-
this.parsedValue !== undefined ? this.parsedValue : this.value
|
|
323
|
-
|
|
324
|
-
if (this.$options.nativeField) {
|
|
325
|
-
// For some odd reason, the native change event now sometimes fires
|
|
326
|
-
// twice on Vue3. Filter out second call.
|
|
327
|
-
// TODO: Investigate why this happens, and if it's a bug in Vue3.
|
|
328
|
-
if (value === this.changedValue) return
|
|
329
|
-
this.changedValue = value
|
|
330
|
-
}
|
|
331
|
-
|
|
332
309
|
this.markDirty()
|
|
333
310
|
this.emitEvent('change', {
|
|
334
|
-
|
|
335
|
-
|
|
311
|
+
context: {
|
|
312
|
+
// Prevent endless parse recursion:
|
|
313
|
+
value: this.parsedValue !== undefined ? this.parsedValue : this.value
|
|
314
|
+
},
|
|
336
315
|
// Pass `schemaComponent` as parent, so change events can propagate up.
|
|
337
316
|
parent: this.schemaComponent
|
|
338
317
|
})
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
:disabled="disabled"
|
|
39
39
|
@click="clear"
|
|
40
40
|
)
|
|
41
|
+
//- Edit button is never disabled, even if the field is disabled.
|
|
41
42
|
DitoEditButtons(
|
|
42
43
|
v-if="editable"
|
|
43
44
|
:schema="schema"
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
:data="data"
|
|
46
47
|
:meta="meta"
|
|
47
48
|
:store="store"
|
|
48
|
-
:disabled="
|
|
49
|
+
:disabled="false"
|
|
49
50
|
:editable="editable"
|
|
50
51
|
:editPath="editPath"
|
|
51
52
|
)
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
:disabled="disabled"
|
|
38
38
|
@click="clear"
|
|
39
39
|
)
|
|
40
|
+
//- Edit button is never disabled, even if the field is disabled.
|
|
40
41
|
DitoEditButtons(
|
|
41
42
|
v-if="editable"
|
|
42
43
|
:schema="schema"
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
:data="data"
|
|
45
46
|
:meta="meta"
|
|
46
47
|
:store="store"
|
|
47
|
-
:disabled="
|
|
48
|
+
:disabled="false"
|
|
48
49
|
:editable="editable"
|
|
49
50
|
:editPath="editPath"
|
|
50
51
|
)
|