@ditojs/admin 2.3.0 → 2.3.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 +1347 -1306
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/components/DitoEditButtons.vue +13 -11
- package/src/components/DitoForm.vue +3 -2
- package/src/components/DitoPanel.vue +3 -3
- package/src/mixins/OptionsMixin.js +18 -0
- package/src/styles/_button.scss +5 -5
- package/src/types/DitoTypeButton.vue +0 -4
- package/src/types/DitoTypeList.vue +4 -2
- package/src/types/DitoTypeMultiselect.vue +54 -31
- package/src/types/DitoTypeSelect.vue +58 -37
- package/src/utils/schema.js +13 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.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",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.3.
|
|
36
|
+
"@ditojs/ui": "^2.3.1",
|
|
37
37
|
"@ditojs/utils": "^2.3.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.1"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "1b5f5121a2e8e6d3741f0bb2b81d38c2343810d6",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -10,23 +10,25 @@ 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="
|
|
13
|
+
v-if="hasDraggable"
|
|
14
14
|
v-bind="getButtonAttributes(verbs.drag)"
|
|
15
15
|
)
|
|
16
16
|
RouterLink.dito-button(
|
|
17
|
-
v-if="
|
|
18
|
-
:
|
|
17
|
+
v-if="hasEditable"
|
|
18
|
+
:class="{ 'dito-disabled': !editPath }"
|
|
19
|
+
:to="editPath ? { path: editPath } : {}"
|
|
19
20
|
v-bind="getButtonAttributes(verbs.edit)"
|
|
20
21
|
)
|
|
21
22
|
DitoCreateButton(
|
|
22
|
-
v-if="
|
|
23
|
+
v-if="hasCreatable"
|
|
24
|
+
:class="{ 'dito-disabled': !createPath }"
|
|
23
25
|
:schema="schema"
|
|
24
26
|
:path="createPath"
|
|
25
27
|
:verb="verbs.create"
|
|
26
28
|
:text="createButtonText"
|
|
27
29
|
)
|
|
28
30
|
button.dito-button(
|
|
29
|
-
v-if="
|
|
31
|
+
v-if="hasDeletable"
|
|
30
32
|
type="button"
|
|
31
33
|
v-bind="getButtonAttributes(verbs.delete)"
|
|
32
34
|
@click="$emit('delete')"
|
|
@@ -61,19 +63,19 @@ export default DitoComponent.component('DitoEditButtons', {
|
|
|
61
63
|
return this.getLabel(this.schema.form)
|
|
62
64
|
},
|
|
63
65
|
|
|
64
|
-
|
|
66
|
+
hasDraggable() {
|
|
65
67
|
return this.hasOption('draggable')
|
|
66
68
|
},
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
return this.hasOption('editable')
|
|
70
|
+
hasEditable() {
|
|
71
|
+
return this.hasOption('editable')
|
|
70
72
|
},
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
return this.hasOption('creatable')
|
|
74
|
+
hasCreatable() {
|
|
75
|
+
return this.hasOption('creatable')
|
|
74
76
|
},
|
|
75
77
|
|
|
76
|
-
|
|
78
|
+
hasDeletable() {
|
|
77
79
|
return this.hasOption('deletable')
|
|
78
80
|
},
|
|
79
81
|
|
|
@@ -289,8 +289,9 @@ export default DitoComponent.component('DitoForm', {
|
|
|
289
289
|
if (
|
|
290
290
|
param &&
|
|
291
291
|
this.providesData &&
|
|
292
|
-
from.
|
|
293
|
-
|
|
292
|
+
from.matched[0].path === to.matched[0].path && // Staying on same form?
|
|
293
|
+
from.params[param] !== 'create' && // But haven't been creating?
|
|
294
|
+
to.params[param] !== from.params[param] // Going to a different entity?
|
|
294
295
|
) {
|
|
295
296
|
this.loadData(true)
|
|
296
297
|
}
|
|
@@ -224,10 +224,10 @@ export default DitoComponent.component('DitoPanel', {
|
|
|
224
224
|
> .dito-schema-content {
|
|
225
225
|
> .dito-pane {
|
|
226
226
|
padding: $form-spacing-half $form-spacing;
|
|
227
|
-
}
|
|
228
227
|
|
|
229
|
-
|
|
230
|
-
|
|
228
|
+
> .dito-container {
|
|
229
|
+
padding: $form-spacing-half;
|
|
230
|
+
}
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
.dito-object {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import DitoContext from '../DitoContext.js'
|
|
2
2
|
import DataMixin from './DataMixin.js'
|
|
3
|
+
import { hasViewSchema, getViewEditPath } from '../utils/schema.js'
|
|
3
4
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
4
5
|
import { setTemporaryId, isReference } from '../utils/data.js'
|
|
5
6
|
import {
|
|
@@ -145,6 +146,23 @@ export default {
|
|
|
145
146
|
}
|
|
146
147
|
}),
|
|
147
148
|
|
|
149
|
+
editable: getSchemaAccessor('editable', {
|
|
150
|
+
type: Boolean,
|
|
151
|
+
default: false,
|
|
152
|
+
get(editable) {
|
|
153
|
+
return (
|
|
154
|
+
editable &&
|
|
155
|
+
hasViewSchema(this.schema, this.context)
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
}),
|
|
159
|
+
|
|
160
|
+
editPath() {
|
|
161
|
+
return this.editable && this.selectedValue
|
|
162
|
+
? getViewEditPath(this.schema, this.selectedValue, this.context)
|
|
163
|
+
: null
|
|
164
|
+
},
|
|
165
|
+
|
|
148
166
|
groupByLabel() {
|
|
149
167
|
return this.groupBy ? 'label' : null
|
|
150
168
|
},
|
package/src/styles/_button.scss
CHANGED
|
@@ -191,18 +191,18 @@
|
|
|
191
191
|
cursor: pointer;
|
|
192
192
|
|
|
193
193
|
&.dito-button-clear {
|
|
194
|
+
$self: &;
|
|
195
|
+
|
|
194
196
|
width: $input-height;
|
|
195
197
|
z-index: 1;
|
|
196
198
|
background: $color-white;
|
|
197
199
|
display: none;
|
|
198
200
|
|
|
199
|
-
$button-clear: &;
|
|
200
|
-
|
|
201
201
|
@at-root .dito-component:hover {
|
|
202
202
|
// Support two levels of nesting inside .dito-component, used by TypeColor
|
|
203
|
-
& > #{$
|
|
204
|
-
& > * > #{$
|
|
205
|
-
& > * > * > #{$
|
|
203
|
+
& > #{$self},
|
|
204
|
+
& > * > #{$self},
|
|
205
|
+
& > * > * > #{$self} {
|
|
206
206
|
display: block;
|
|
207
207
|
}
|
|
208
208
|
}
|
|
@@ -251,9 +251,11 @@ export default DitoTypeComponent.register('list', {
|
|
|
251
251
|
|
|
252
252
|
getEditPath(item, index) {
|
|
253
253
|
if (this.editable) {
|
|
254
|
-
const path = getViewEditPath(this.schema, this.context) || this.path
|
|
255
254
|
const id = this.getItemId(this.schema, item, index)
|
|
256
|
-
return
|
|
255
|
+
return (
|
|
256
|
+
getViewEditPath(this.schema, id, this.context) ||
|
|
257
|
+
`${this.path}/${id}`
|
|
258
|
+
)
|
|
257
259
|
}
|
|
258
260
|
return null
|
|
259
261
|
},
|
|
@@ -5,37 +5,48 @@
|
|
|
5
5
|
'dito-multiselect-multiple': multiple
|
|
6
6
|
}`
|
|
7
7
|
)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
8
|
+
.dito-multiselect__inner
|
|
9
|
+
VueMultiselect(
|
|
10
|
+
ref="element"
|
|
11
|
+
v-model="selectedOptions"
|
|
12
|
+
:class="{ 'multiselect--show-highlight': showHighlight }"
|
|
13
|
+
:showLabels="false"
|
|
14
|
+
:placeholder="placeholder"
|
|
15
|
+
tagPlaceholder="Press enter to add new tag"
|
|
16
|
+
:options="populate && activeOptions || []"
|
|
17
|
+
:customLabel="getLabelForOption"
|
|
18
|
+
:trackBy="optionValue"
|
|
19
|
+
:groupLabel="groupByLabel"
|
|
20
|
+
:groupValues="groupByOptions"
|
|
21
|
+
:multiple="multiple"
|
|
22
|
+
:taggable="taggable"
|
|
23
|
+
:searchable="searchable"
|
|
24
|
+
:internalSearch="!searchFilter"
|
|
25
|
+
:preserveSearch="!!searchFilter"
|
|
26
|
+
:clearOnSelect="!searchFilter"
|
|
27
|
+
:closeOnSelect="!stayOpen"
|
|
28
|
+
:loading="isLoading"
|
|
29
|
+
v-bind="attributes"
|
|
30
|
+
@open="onOpen"
|
|
31
|
+
@close="onClose"
|
|
32
|
+
@tag="onAddTag"
|
|
33
|
+
@search-change="onSearchChange"
|
|
34
|
+
)
|
|
35
|
+
button.dito-button-clear.dito-button-overlay(
|
|
36
|
+
v-if="showClearButton"
|
|
37
|
+
type="button"
|
|
38
|
+
:disabled="disabled"
|
|
39
|
+
@click="clear"
|
|
40
|
+
)
|
|
41
|
+
DitoEditButtons(
|
|
42
|
+
v-if="editable"
|
|
43
|
+
:editable="editable"
|
|
44
|
+
:editPath="editPath"
|
|
45
|
+
:schema="schema"
|
|
46
|
+
:dataPath="dataPath"
|
|
47
|
+
:data="data"
|
|
48
|
+
:meta="meta"
|
|
49
|
+
:store="store"
|
|
39
50
|
)
|
|
40
51
|
</template>
|
|
41
52
|
|
|
@@ -218,12 +229,20 @@ $tag-padding: 3px;
|
|
|
218
229
|
$tag-line-height: 1em;
|
|
219
230
|
|
|
220
231
|
.dito-multiselect {
|
|
232
|
+
display: inline-flex;
|
|
221
233
|
position: relative;
|
|
222
234
|
|
|
235
|
+
&__inner {
|
|
236
|
+
flex: 1;
|
|
237
|
+
position: relative;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// TODO: BEM
|
|
223
241
|
&.dito-multiselect-single {
|
|
224
242
|
--input-width: 100%;
|
|
225
243
|
}
|
|
226
244
|
|
|
245
|
+
// TODO: BEM
|
|
227
246
|
&.dito-multiselect-multiple {
|
|
228
247
|
--input-width: auto;
|
|
229
248
|
}
|
|
@@ -234,6 +253,10 @@ $tag-line-height: 1em;
|
|
|
234
253
|
}
|
|
235
254
|
}
|
|
236
255
|
|
|
256
|
+
.dito-edit-buttons {
|
|
257
|
+
margin-left: $form-spacing-half;
|
|
258
|
+
}
|
|
259
|
+
|
|
237
260
|
.dito-button-clear {
|
|
238
261
|
width: $spinner-width;
|
|
239
262
|
}
|
|
@@ -1,40 +1,51 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
//- Nesting is needed to make an arrow appear over the select item:
|
|
3
3
|
.dito-select
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
template(
|
|
13
|
-
v-if="populate"
|
|
4
|
+
.dito-select__inner
|
|
5
|
+
select(
|
|
6
|
+
:id="dataPath"
|
|
7
|
+
ref="element"
|
|
8
|
+
v-model="selectedValue"
|
|
9
|
+
v-bind="attributes"
|
|
10
|
+
@mousedown="populate = true"
|
|
11
|
+
@focus="populate = true"
|
|
14
12
|
)
|
|
15
13
|
template(
|
|
16
|
-
v-
|
|
14
|
+
v-if="populate"
|
|
17
15
|
)
|
|
18
|
-
|
|
19
|
-
v-
|
|
20
|
-
:label="option[groupByLabel]"
|
|
16
|
+
template(
|
|
17
|
+
v-for="option in options"
|
|
21
18
|
)
|
|
19
|
+
optgroup(
|
|
20
|
+
v-if="groupBy"
|
|
21
|
+
:label="option[groupByLabel]"
|
|
22
|
+
)
|
|
23
|
+
option(
|
|
24
|
+
v-for="opt in option[groupByOptions]"
|
|
25
|
+
:value="getValueForOption(opt)"
|
|
26
|
+
) {{ getLabelForOption(opt) }}
|
|
22
27
|
option(
|
|
23
|
-
v-
|
|
24
|
-
:value="getValueForOption(
|
|
25
|
-
) {{ getLabelForOption(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
) {{ getLabelForOption(
|
|
30
|
-
|
|
31
|
-
v-
|
|
28
|
+
v-else
|
|
29
|
+
:value="getValueForOption(option)"
|
|
30
|
+
) {{ getLabelForOption(option) }}
|
|
31
|
+
template(
|
|
32
|
+
v-else-if="selectedOption"
|
|
33
|
+
)
|
|
34
|
+
option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
|
|
35
|
+
button.dito-button-clear.dito-button-overlay(
|
|
36
|
+
v-if="showClearButton"
|
|
37
|
+
:disabled="disabled"
|
|
38
|
+
@click="clear"
|
|
32
39
|
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
:
|
|
37
|
-
|
|
40
|
+
DitoEditButtons(
|
|
41
|
+
v-if="editable"
|
|
42
|
+
:editable="editable"
|
|
43
|
+
:editPath="editPath"
|
|
44
|
+
:schema="schema"
|
|
45
|
+
:dataPath="dataPath"
|
|
46
|
+
:data="data"
|
|
47
|
+
:meta="meta"
|
|
48
|
+
:store="store"
|
|
38
49
|
)
|
|
39
50
|
</template>
|
|
40
51
|
|
|
@@ -65,12 +76,30 @@ export default DitoTypeComponent.register('select', {
|
|
|
65
76
|
$select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
|
|
66
77
|
|
|
67
78
|
.dito-select {
|
|
68
|
-
display: inline-
|
|
79
|
+
display: inline-flex;
|
|
69
80
|
position: relative;
|
|
70
81
|
|
|
71
82
|
select {
|
|
72
83
|
padding-right: $select-arrow-width;
|
|
73
84
|
}
|
|
85
|
+
|
|
86
|
+
&__inner {
|
|
87
|
+
flex: 1;
|
|
88
|
+
position: relative;
|
|
89
|
+
|
|
90
|
+
&::after {
|
|
91
|
+
position: absolute;
|
|
92
|
+
@include arrow($select-arrow-size);
|
|
93
|
+
|
|
94
|
+
bottom: $select-arrow-bottom;
|
|
95
|
+
right: calc(#{$select-arrow-right} + #{$border-width});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.dito-edit-buttons {
|
|
100
|
+
margin-left: $form-spacing-half;
|
|
101
|
+
}
|
|
102
|
+
|
|
74
103
|
// Handle .dito-width-fill separately due to required nesting of select:
|
|
75
104
|
&.dito-width-fill {
|
|
76
105
|
select {
|
|
@@ -78,14 +107,6 @@ $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
|
|
|
78
107
|
}
|
|
79
108
|
}
|
|
80
109
|
|
|
81
|
-
&::after {
|
|
82
|
-
position: absolute;
|
|
83
|
-
@include arrow($select-arrow-size);
|
|
84
|
-
|
|
85
|
-
bottom: $select-arrow-bottom;
|
|
86
|
-
right: calc(#{$select-arrow-right} + #{$border-width});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
110
|
&.dito-disabled::after {
|
|
90
111
|
border-color: $border-color;
|
|
91
112
|
}
|
package/src/utils/schema.js
CHANGED
|
@@ -416,13 +416,19 @@ export function getViewSchema(schema, context) {
|
|
|
416
416
|
: null
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
-
export function
|
|
419
|
+
export function hasViewSchema(schema, context) {
|
|
420
|
+
return !!getViewSchema(schema, context)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export function getViewEditPath(schema, id, context) {
|
|
420
424
|
const view = getViewSchema(schema, context)
|
|
421
|
-
|
|
422
|
-
|
|
425
|
+
if (view) {
|
|
426
|
+
const path = isSingleComponentView(view)
|
|
423
427
|
? `/${view.path}`
|
|
424
428
|
: `/${view.path}/${view.path}`
|
|
425
|
-
|
|
429
|
+
return `${path}/${id}`
|
|
430
|
+
}
|
|
431
|
+
return null
|
|
426
432
|
}
|
|
427
433
|
|
|
428
434
|
export function getFormSchemas(schema, context, modifyForm) {
|
|
@@ -595,7 +601,7 @@ export function computeValue(schema, data, name, dataPath, {
|
|
|
595
601
|
const { compute } = schema
|
|
596
602
|
if (compute) {
|
|
597
603
|
const value = compute(
|
|
598
|
-
DitoContext
|
|
604
|
+
new DitoContext(component, {
|
|
599
605
|
schema,
|
|
600
606
|
// Override value to prevent endless recursion through calling the
|
|
601
607
|
// getter for `this.value` in `DitoContext`:
|
|
@@ -691,7 +697,7 @@ export function processData(schema, sourceSchema, data, dataPath, {
|
|
|
691
697
|
|
|
692
698
|
// NOTE: We don't cache this context, since `value` is changing.
|
|
693
699
|
const getContext = () =>
|
|
694
|
-
DitoContext
|
|
700
|
+
new DitoContext(component, {
|
|
695
701
|
schema,
|
|
696
702
|
value,
|
|
697
703
|
name,
|
|
@@ -782,7 +788,7 @@ export function processSchemaData(
|
|
|
782
788
|
index !== null
|
|
783
789
|
? getDataPath(componentDataPath, index)
|
|
784
790
|
: componentDataPath
|
|
785
|
-
const context = DitoContext
|
|
791
|
+
const context = new DitoContext(options.component, {
|
|
786
792
|
schema: componentSchema,
|
|
787
793
|
data,
|
|
788
794
|
value: item,
|