@ditojs/admin 1.30.0 → 2.0.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 +5291 -6856
- package/dist/dito-admin.umd.js +5 -5
- package/dist/style.css +1 -1
- package/package.json +37 -22
- package/src/DitoAdmin.js +44 -58
- package/src/DitoComponent.js +18 -50
- package/src/DitoContext.js +7 -3
- package/src/TypeComponent.js +15 -13
- package/src/appState.js +4 -2
- package/src/components/DitoAccount.vue +14 -14
- package/src/components/DitoButtons.vue +18 -10
- package/src/components/DitoClipboard.vue +16 -16
- package/src/components/DitoContainer.vue +32 -32
- package/src/components/DitoCreateButton.vue +22 -23
- package/src/components/DitoDialog.vue +73 -18
- package/src/components/DitoEditButtons.vue +31 -31
- package/src/components/DitoElement.vue +6 -6
- package/src/components/DitoErrors.vue +6 -6
- package/src/components/DitoForm.vue +42 -43
- package/src/components/DitoFormNested.vue +7 -3
- package/src/components/DitoHeader.vue +19 -19
- package/src/components/DitoLabel.vue +25 -25
- package/src/components/DitoMenu.vue +9 -9
- package/src/components/DitoPagination.vue +5 -5
- package/src/components/DitoPane.vue +32 -32
- package/src/components/DitoPanel.vue +18 -18
- package/src/components/DitoPanels.vue +5 -3
- package/src/components/DitoRoot.vue +107 -30
- package/src/components/DitoSchema.vue +76 -74
- package/src/components/DitoSchemaInlined.vue +29 -29
- package/src/components/DitoScopes.vue +14 -13
- package/src/components/DitoSpinner.vue +101 -0
- package/src/components/DitoTableCell.vue +19 -25
- package/src/components/DitoTableHead.vue +10 -7
- package/src/components/DitoTabs.vue +7 -6
- package/src/components/DitoTreeItem.vue +89 -85
- package/src/components/DitoVNode.vue +9 -7
- package/src/components/DitoView.vue +25 -21
- package/src/mixins/DataMixin.js +2 -2
- package/src/mixins/DitoMixin.js +43 -46
- package/src/mixins/DomMixin.js +1 -1
- package/src/mixins/EmitterMixin.js +11 -11
- package/src/mixins/RouteMixin.js +20 -10
- package/src/mixins/SchemaParentMixin.js +2 -2
- package/src/mixins/SourceMixin.js +7 -9
- package/src/mixins/TypeMixin.js +29 -34
- package/src/mixins/ValidationMixin.js +4 -19
- package/src/types/TypeButton.vue +11 -15
- package/src/types/TypeCheckbox.vue +7 -8
- package/src/types/TypeCheckboxes.vue +14 -15
- package/src/types/TypeCode.vue +5 -5
- package/src/types/TypeColor.vue +9 -12
- package/src/types/TypeComponent.vue +12 -7
- package/src/types/TypeComputed.vue +13 -12
- package/src/types/TypeDate.vue +10 -11
- package/src/types/TypeLabel.vue +1 -1
- package/src/types/TypeList.vue +115 -92
- package/src/types/TypeMarkup.vue +166 -125
- package/src/types/TypeMultiselect.vue +37 -47
- package/src/types/TypeNumber.vue +10 -11
- package/src/types/TypeObject.vue +62 -46
- package/src/types/TypeProgress.vue +7 -8
- package/src/types/TypeRadio.vue +15 -14
- package/src/types/TypeSection.vue +10 -10
- package/src/types/TypeSelect.vue +32 -33
- package/src/types/TypeSlider.vue +20 -22
- package/src/types/TypeSwitch.vue +8 -9
- package/src/types/TypeText.vue +7 -8
- package/src/types/TypeTextarea.vue +8 -9
- package/src/types/TypeTreeList.vue +40 -34
- package/src/types/TypeUpload.vue +61 -61
- package/src/utils/accessor.js +1 -1
- package/src/utils/data.js +0 -4
- package/src/utils/options.js +48 -0
- package/src/utils/path.js +5 -0
- package/src/utils/schema.js +73 -56
- package/src/utils/vue.js +11 -0
- package/types/index.d.ts +1 -1
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
button.dito-button(
|
|
5
|
-
type="button"
|
|
6
|
-
@mousedown.stop="onPulldownMouseDown()"
|
|
7
|
-
:class="`dito-button-${verb}`"
|
|
8
|
-
:title="labelize(verb)"
|
|
9
|
-
) {{ text }}
|
|
10
|
-
ul.dito-pulldown(
|
|
11
|
-
:class="{ 'dito-open': pulldown.open }"
|
|
12
|
-
)
|
|
13
|
-
li(v-for="(form, type) in forms")
|
|
14
|
-
a(
|
|
15
|
-
v-if="isCreatable(form)"
|
|
16
|
-
:class="`dito-type-${type}`"
|
|
17
|
-
@mousedown.stop="onPulldownMouseDown(type)"
|
|
18
|
-
@mouseup="onPulldownMouseUp(type)"
|
|
19
|
-
) {{ getLabel(form) }}
|
|
2
|
+
.dito-create-button
|
|
3
|
+
template(v-if="showPulldown")
|
|
20
4
|
button.dito-button(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@click="createItem(forms.default)"
|
|
5
|
+
type="button"
|
|
6
|
+
@mousedown.stop="onPulldownMouseDown()"
|
|
24
7
|
:class="`dito-button-${verb}`"
|
|
25
8
|
:title="labelize(verb)"
|
|
26
9
|
) {{ text }}
|
|
10
|
+
ul.dito-pulldown(
|
|
11
|
+
:class="{ 'dito-open': pulldown.open }"
|
|
12
|
+
)
|
|
13
|
+
li(v-for="(form, type) in forms")
|
|
14
|
+
a(
|
|
15
|
+
v-if="isCreatable(form)"
|
|
16
|
+
:class="`dito-type-${type}`"
|
|
17
|
+
@mousedown.stop="onPulldownMouseDown(type)"
|
|
18
|
+
@mouseup="onPulldownMouseUp(type)"
|
|
19
|
+
) {{ getLabel(form) }}
|
|
20
|
+
button.dito-button(
|
|
21
|
+
v-else
|
|
22
|
+
:type="isInlined ? 'button' : 'submit'"
|
|
23
|
+
@click="createItem(forms.default)"
|
|
24
|
+
:class="`dito-button-${verb}`"
|
|
25
|
+
:title="labelize(verb)"
|
|
26
|
+
) {{ text }}
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<style lang="sass">
|
|
@@ -76,8 +76,7 @@ export default DitoComponent.component('dito-create-button', {
|
|
|
76
76
|
} else {
|
|
77
77
|
this.$router.push({
|
|
78
78
|
path: `${this.path}/create`,
|
|
79
|
-
query: { type }
|
|
80
|
-
append: true
|
|
79
|
+
query: { type }
|
|
81
80
|
})
|
|
82
81
|
}
|
|
83
82
|
} else {
|
|
@@ -1,19 +1,63 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
2
|
+
.dito-dialog(
|
|
3
|
+
role="dialog"
|
|
4
|
+
aria-expanded="true"
|
|
5
|
+
aria-modal="true"
|
|
6
|
+
:style="{ '--width': `${settings.width}px` }"
|
|
7
|
+
@click="settings.clickToClose && close()"
|
|
8
|
+
)
|
|
9
|
+
form.dito-scroll-parent(@submit.prevent="submit")
|
|
3
10
|
dito-schema.dito-scroll(
|
|
4
11
|
:schema="schema"
|
|
5
12
|
:data="dialogData"
|
|
6
13
|
)
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
template(#buttons)
|
|
15
|
+
dito-buttons.dito-buttons-large(
|
|
16
|
+
:buttons="buttonSchemas"
|
|
17
|
+
:data="dialogData"
|
|
18
|
+
)
|
|
12
19
|
</template>
|
|
13
20
|
|
|
14
21
|
<style lang="sass">
|
|
15
|
-
|
|
22
|
+
@import '../styles/_imports'
|
|
23
|
+
|
|
24
|
+
.dito-dialog
|
|
25
|
+
position: fixed
|
|
26
|
+
display: flex
|
|
27
|
+
inset: 0
|
|
16
28
|
z-index: 2000
|
|
29
|
+
padding: $content-padding
|
|
30
|
+
align-items: center
|
|
31
|
+
justify-content: center
|
|
32
|
+
// Prevent scrolling of the page behind the dialog:
|
|
33
|
+
overflow: hidden
|
|
34
|
+
background: rgba(0, 0, 0, 0.2)
|
|
35
|
+
|
|
36
|
+
// TODO: `&__inner`
|
|
37
|
+
form
|
|
38
|
+
position: relative
|
|
39
|
+
display: flex
|
|
40
|
+
overflow: hidden
|
|
41
|
+
box-sizing: border-box
|
|
42
|
+
background: white
|
|
43
|
+
border-radius: $border-radius
|
|
44
|
+
max-width: var(--width, 480px)
|
|
45
|
+
max-height: 100%
|
|
46
|
+
box-shadow: 0 20px 60px -2px rgba(27, 33, 58, 0.4)
|
|
47
|
+
|
|
48
|
+
.dito-dialog-enter-active,
|
|
49
|
+
.dito-dialog-leave-active
|
|
50
|
+
transition: opacity 0.15s
|
|
51
|
+
|
|
52
|
+
form
|
|
53
|
+
transition: transform 0.25s
|
|
54
|
+
|
|
55
|
+
.dito-dialog-enter-from,
|
|
56
|
+
.dito-dialog-leave-to
|
|
57
|
+
opacity: 0
|
|
58
|
+
|
|
59
|
+
form
|
|
60
|
+
transform: translateY(-20px)
|
|
17
61
|
</style>
|
|
18
62
|
|
|
19
63
|
<script>
|
|
@@ -34,7 +78,14 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
34
78
|
components: { type: Object, required: true },
|
|
35
79
|
buttons: { type: Object, required: true },
|
|
36
80
|
promise: { type: Object, required: true },
|
|
37
|
-
data: { type: Object, default: () => ({}) }
|
|
81
|
+
data: { type: Object, default: () => ({}) },
|
|
82
|
+
settings: {
|
|
83
|
+
type: Object,
|
|
84
|
+
default: () => ({
|
|
85
|
+
width: 480,
|
|
86
|
+
clickToClose: false
|
|
87
|
+
})
|
|
88
|
+
}
|
|
38
89
|
},
|
|
39
90
|
|
|
40
91
|
data() {
|
|
@@ -56,10 +107,6 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
56
107
|
return this
|
|
57
108
|
},
|
|
58
109
|
|
|
59
|
-
name() {
|
|
60
|
-
return this.$parent.name
|
|
61
|
-
},
|
|
62
|
-
|
|
63
110
|
schema() {
|
|
64
111
|
return {
|
|
65
112
|
components: this.components
|
|
@@ -86,6 +133,10 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
86
133
|
)
|
|
87
134
|
},
|
|
88
135
|
|
|
136
|
+
hasButtons() {
|
|
137
|
+
return Object.keys(this.buttonSchemas).length > 0
|
|
138
|
+
},
|
|
139
|
+
|
|
89
140
|
hasCancel() {
|
|
90
141
|
return !!this.buttonSchemas.cancel
|
|
91
142
|
}
|
|
@@ -94,30 +145,30 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
94
145
|
mounted() {
|
|
95
146
|
this.windowEvents = addEvents(window, {
|
|
96
147
|
keyup: event => {
|
|
97
|
-
if (this.hasCancel && event.keyCode === 27) {
|
|
148
|
+
if ((this.hasCancel || !this.hasButtons) && event.keyCode === 27) {
|
|
98
149
|
this.cancel()
|
|
99
150
|
}
|
|
100
151
|
}
|
|
101
152
|
})
|
|
102
153
|
},
|
|
103
154
|
|
|
104
|
-
|
|
155
|
+
unmounted() {
|
|
105
156
|
this.windowEvents.remove()
|
|
106
157
|
},
|
|
107
158
|
|
|
108
159
|
methods: {
|
|
109
|
-
|
|
110
|
-
this.$
|
|
160
|
+
remove() {
|
|
161
|
+
this.$emit('remove')
|
|
111
162
|
},
|
|
112
163
|
|
|
113
164
|
resolve(value) {
|
|
114
165
|
this.promise.resolve(value)
|
|
115
|
-
this.
|
|
166
|
+
this.remove()
|
|
116
167
|
},
|
|
117
168
|
|
|
118
169
|
reject(value) {
|
|
119
170
|
this.promise.reject(value)
|
|
120
|
-
this.
|
|
171
|
+
this.remove()
|
|
121
172
|
},
|
|
122
173
|
|
|
123
174
|
submit() {
|
|
@@ -126,6 +177,10 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
126
177
|
|
|
127
178
|
cancel() {
|
|
128
179
|
this.resolve(null)
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
close() {
|
|
183
|
+
this.cancel()
|
|
129
184
|
}
|
|
130
185
|
}
|
|
131
186
|
})
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
dito-buttons.dito-edit-buttons.dito-buttons-round(
|
|
3
|
+
:buttons="buttons"
|
|
4
|
+
:dataPath="dataPath"
|
|
5
|
+
:data="data"
|
|
6
|
+
:meta="meta"
|
|
7
|
+
:store="store"
|
|
8
|
+
/* Prevent click events from bubbling to dito-label: */
|
|
9
|
+
@click.stop
|
|
10
|
+
)
|
|
11
|
+
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
12
|
+
a.dito-button(
|
|
13
|
+
v-if="isDraggable"
|
|
14
|
+
v-bind="getButtonAttributes(verbs.drag)"
|
|
15
|
+
)
|
|
16
|
+
router-link.dito-button(
|
|
17
|
+
v-if="isEditable"
|
|
18
|
+
:to="{ path: editPath }"
|
|
19
|
+
v-bind="getButtonAttributes(verbs.edit)"
|
|
20
|
+
)
|
|
21
|
+
dito-create-button(
|
|
22
|
+
v-if="isCreatable"
|
|
23
|
+
:schema="schema"
|
|
24
|
+
:path="createPath"
|
|
25
|
+
:verb="verbs.create"
|
|
26
|
+
:text="createButtonText"
|
|
27
|
+
)
|
|
28
|
+
button.dito-button(
|
|
29
|
+
v-if="isDeletable"
|
|
30
|
+
type="button"
|
|
31
|
+
v-bind="getButtonAttributes(verbs.delete)"
|
|
32
|
+
@click="$emit('delete')"
|
|
10
33
|
)
|
|
11
|
-
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
12
|
-
a.dito-button(
|
|
13
|
-
v-if="isDraggable"
|
|
14
|
-
v-bind="getButtonAttributes(verbs.drag)"
|
|
15
|
-
)
|
|
16
|
-
router-link.dito-button(
|
|
17
|
-
v-if="isEditable"
|
|
18
|
-
:to="{ path: editPath }" append
|
|
19
|
-
v-bind="getButtonAttributes(verbs.edit)"
|
|
20
|
-
)
|
|
21
|
-
dito-create-button(
|
|
22
|
-
v-if="isCreatable"
|
|
23
|
-
:schema="schema"
|
|
24
|
-
:path="createPath"
|
|
25
|
-
:verb="verbs.create"
|
|
26
|
-
:text="createButtonText"
|
|
27
|
-
)
|
|
28
|
-
button.dito-button(
|
|
29
|
-
v-if="isDeletable"
|
|
30
|
-
type="button"
|
|
31
|
-
v-bind="getButtonAttributes(verbs.delete)"
|
|
32
|
-
@click="$emit('delete')"
|
|
33
|
-
)
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
36
|
<style lang="sass">
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
component(
|
|
3
|
+
v-if="content"
|
|
4
|
+
:is="options.tag || tag"
|
|
5
|
+
:class="classes"
|
|
6
|
+
:style="styles"
|
|
7
|
+
) {{ options.text }}
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
10
|
<script>
|
|
@@ -3,29 +3,20 @@
|
|
|
3
3
|
:class="{ 'dito-form-nested': isNestedRoute }"
|
|
4
4
|
:data-resource="sourceSchema.path"
|
|
5
5
|
)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
//- NOTE: Nested form components are kept alive by using `v-show` instead of
|
|
7
|
+
//- `v-if` here, so event handling and other things still work with nested
|
|
8
|
+
//- editing. Only render a router-view here if this isn't the last data route
|
|
9
|
+
//- and not a nested form route, which will appear elsewhere in its own view.
|
|
10
10
|
router-view(
|
|
11
11
|
v-if="!(isLastUnnestedRoute || isNestedRoute)"
|
|
12
12
|
v-show="!isActive"
|
|
13
13
|
)
|
|
14
|
-
|
|
14
|
+
//- Use a <div> for inlined forms, as we shouldn't nest actual <form> tags.
|
|
15
15
|
component.dito-scroll(
|
|
16
16
|
v-show="isActive"
|
|
17
17
|
:is="isNestedRoute ? 'div' : 'form'"
|
|
18
18
|
@submit.prevent
|
|
19
19
|
)
|
|
20
|
-
// Prevent implicit submission of the form, for example when typing enter
|
|
21
|
-
// in an input field.
|
|
22
|
-
// https://stackoverflow.com/a/51507806
|
|
23
|
-
button(
|
|
24
|
-
v-show="false"
|
|
25
|
-
type="submit"
|
|
26
|
-
disabled="true"
|
|
27
|
-
aria-hidden="true"
|
|
28
|
-
)
|
|
29
20
|
dito-schema(
|
|
30
21
|
:schema="schema"
|
|
31
22
|
:dataPath="dataPath"
|
|
@@ -35,15 +26,23 @@
|
|
|
35
26
|
:disabled="isLoading"
|
|
36
27
|
:menuHeader="true"
|
|
37
28
|
)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
29
|
+
template(#buttons)
|
|
30
|
+
dito-buttons.dito-buttons-round.dito-buttons-main.dito-buttons-large(
|
|
31
|
+
:buttons="buttonSchemas"
|
|
32
|
+
:dataPath="dataPath"
|
|
33
|
+
:data="data"
|
|
34
|
+
:meta="meta"
|
|
35
|
+
:store="store"
|
|
36
|
+
:disabled="isLoading"
|
|
37
|
+
)
|
|
38
|
+
//- Prevent implicit submission of the form, for example when typing enter
|
|
39
|
+
//- in an input field.
|
|
40
|
+
//- https://stackoverflow.com/a/51507806
|
|
41
|
+
button(
|
|
42
|
+
v-show="false"
|
|
43
|
+
type="submit"
|
|
44
|
+
disabled
|
|
45
|
+
)
|
|
47
46
|
</template>
|
|
48
47
|
|
|
49
48
|
<script>
|
|
@@ -53,6 +52,7 @@ import RouteMixin from '../mixins/RouteMixin.js'
|
|
|
53
52
|
import ResourceMixin from '../mixins/ResourceMixin.js'
|
|
54
53
|
import { getResource, getMemberResource } from '../utils/resource.js'
|
|
55
54
|
import { getButtonSchemas, isObjectSource } from '../utils/schema.js'
|
|
55
|
+
import { resolvePath } from '../utils/path.js'
|
|
56
56
|
|
|
57
57
|
// @vue/component
|
|
58
58
|
export default DitoComponent.component('dito-form', {
|
|
@@ -104,7 +104,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
106
|
|
|
107
|
-
submit: !this.
|
|
107
|
+
submit: !this.isMutating && {
|
|
108
108
|
type: 'submit',
|
|
109
109
|
// Submit buttons close the form by default:
|
|
110
110
|
closeForm: true,
|
|
@@ -132,18 +132,18 @@ export default DitoComponent.component('dito-form', {
|
|
|
132
132
|
},
|
|
133
133
|
|
|
134
134
|
isDirty() {
|
|
135
|
-
return !this.
|
|
135
|
+
return !this.isMutating && !!this.mainSchemaComponent?.isDirty
|
|
136
136
|
},
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
return this.mainSchemaComponent?.selectedTab || null
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
doesMutate() {
|
|
138
|
+
isMutating() {
|
|
143
139
|
// When `sourceSchema.mutate` is true, the form edits the inherited data
|
|
144
|
-
// directly instead of making a copy for
|
|
140
|
+
// directly instead of making a copy for persistence upon submission.
|
|
145
141
|
// See `inheritedData()` computed property for more details.
|
|
146
|
-
return this.sourceSchema.mutate
|
|
142
|
+
return !!this.sourceSchema.mutate
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
selectedTab() {
|
|
146
|
+
return this.mainSchemaComponent?.selectedTab || null
|
|
147
147
|
},
|
|
148
148
|
|
|
149
149
|
type() {
|
|
@@ -190,7 +190,9 @@ export default DitoComponent.component('dito-form', {
|
|
|
190
190
|
// Possible parents are DitoForm for forms, or DitoView for root lists.
|
|
191
191
|
// Both have a data property which abstracts away loading and inheriting
|
|
192
192
|
// of data.
|
|
193
|
-
|
|
193
|
+
// Forms that are about to be destroyed due to navigation loose their
|
|
194
|
+
// route-record, but might still trigger this getter. Filter those out.
|
|
195
|
+
let data = this.routeRecord ? this.parentRouteComponent.data : null
|
|
194
196
|
if (data) {
|
|
195
197
|
// Handle nested data by splitting the dataPath, iterate through the
|
|
196
198
|
// actual data and look nest child-data up.
|
|
@@ -240,7 +242,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
240
242
|
this.sourceKey !== null
|
|
241
243
|
) {
|
|
242
244
|
let data = this.sourceData[this.sourceKey]
|
|
243
|
-
if (!this.
|
|
245
|
+
if (!this.isMutating) {
|
|
244
246
|
// Use a trick to store cloned inherited data in clonedData, to make
|
|
245
247
|
// it reactive and prevent it from being cloned multiple times.
|
|
246
248
|
this.clonedData = data = clone(data)
|
|
@@ -251,7 +253,8 @@ export default DitoComponent.component('dito-form', {
|
|
|
251
253
|
isObjectSource(this.sourceSchema)
|
|
252
254
|
) {
|
|
253
255
|
// If data of an object source is null, redirect to its create route.
|
|
254
|
-
|
|
256
|
+
// TODO: This is a hack, move to a watcher!
|
|
257
|
+
this.$router.push({ path: `${this.path}/create` })
|
|
255
258
|
}
|
|
256
259
|
return data
|
|
257
260
|
}
|
|
@@ -298,11 +301,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
298
301
|
setSourceData(data) {
|
|
299
302
|
if (this.sourceData && this.sourceKey !== null) {
|
|
300
303
|
const { mainSchemaComponent } = this
|
|
301
|
-
this
|
|
302
|
-
this.sourceData,
|
|
303
|
-
this.sourceKey,
|
|
304
|
-
mainSchemaComponent.filterData(data)
|
|
305
|
-
)
|
|
304
|
+
this.sourceData[this.sourceKey] = mainSchemaComponent.filterData(data)
|
|
306
305
|
mainSchemaComponent.onChange()
|
|
307
306
|
return true
|
|
308
307
|
}
|
|
@@ -332,9 +331,9 @@ export default DitoComponent.component('dito-form', {
|
|
|
332
331
|
}
|
|
333
332
|
},
|
|
334
333
|
|
|
335
|
-
clearClonedData(
|
|
334
|
+
clearClonedData(to, from) {
|
|
336
335
|
// Only clear if the watched sourceData itself changes in the form.
|
|
337
|
-
if (
|
|
336
|
+
if (to !== from) {
|
|
338
337
|
this.clonedData = undefined
|
|
339
338
|
}
|
|
340
339
|
},
|
|
@@ -433,7 +432,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
433
432
|
} else if (this.isCreating) {
|
|
434
433
|
// Redirect to the form editing the newly created item:
|
|
435
434
|
const id = this.getItemId(this.schema, this.data)
|
|
436
|
-
this.$router.replace({ path:
|
|
435
|
+
this.$router.replace({ path: resolvePath(`${this.path}/../${id}`) })
|
|
437
436
|
}
|
|
438
437
|
}
|
|
439
438
|
return success
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
.dito-form-nested
|
|
3
3
|
&,
|
|
4
4
|
.dito-scroll
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
//- No scrolling inside nested forms, and prevent open .multiselect from
|
|
6
|
+
//- being cropped.
|
|
7
7
|
overflow: visible
|
|
8
8
|
</style>
|
|
9
9
|
|
|
10
10
|
<script>
|
|
11
|
+
import DitoComponent from '../DitoComponent.js'
|
|
11
12
|
import DitoForm from './DitoForm.vue'
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
// @vue/component
|
|
15
|
+
export default DitoComponent.component('dito-form-nested', {
|
|
16
|
+
extends: DitoForm
|
|
17
|
+
})
|
|
14
18
|
</script>
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
nav.dito-header
|
|
3
|
+
.dito-trail
|
|
4
|
+
ul
|
|
5
|
+
li(
|
|
6
|
+
v-for="(component, index) in trail"
|
|
7
|
+
)
|
|
8
|
+
template(v-if="index === trail.length - 1")
|
|
9
|
+
span(:class="getBreadcrumbClass(component)")
|
|
10
|
+
| {{ component.breadcrumb }}
|
|
11
|
+
router-link.dito-breadcrumb(v-else, :to="component.path")
|
|
12
|
+
span(:class="getBreadcrumbClass(component)")
|
|
13
|
+
| {{ component.breadcrumb }}
|
|
14
|
+
dito-spinner(v-if="isLoading")
|
|
15
|
+
slot
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<style lang="sass">
|
|
@@ -82,13 +82,11 @@
|
|
|
82
82
|
|
|
83
83
|
<script>
|
|
84
84
|
import DitoComponent from '../DitoComponent.js'
|
|
85
|
-
import
|
|
86
|
-
|
|
87
|
-
const Spinner = DitoComponent.component('spinner', PulseLoader)
|
|
85
|
+
import DitoSpinner from './DitoSpinner.vue'
|
|
88
86
|
|
|
89
87
|
// @vue/component
|
|
90
88
|
export default DitoComponent.component('dito-header', {
|
|
91
|
-
components: {
|
|
89
|
+
components: { DitoSpinner },
|
|
92
90
|
|
|
93
91
|
props: {
|
|
94
92
|
spinner: {
|
|
@@ -114,7 +112,9 @@ export default DitoComponent.component('dito-header', {
|
|
|
114
112
|
size = '8px',
|
|
115
113
|
color = '#999'
|
|
116
114
|
} = this.spinner || {}
|
|
117
|
-
|
|
115
|
+
// TODO: This is a hack to set the default props for the DitoSpinner.
|
|
116
|
+
// Pass them on through the template instead!
|
|
117
|
+
const { props } = DitoSpinner
|
|
118
118
|
props.size.default = size
|
|
119
119
|
props.color.default = color
|
|
120
120
|
},
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
component.dito-label(
|
|
3
|
+
v-if="text || collapsible"
|
|
4
|
+
:is="tag"
|
|
5
|
+
v-bind="attributes"
|
|
6
|
+
:class="{ 'dito-active': isActive }"
|
|
7
|
+
)
|
|
8
|
+
.dito-chevron(
|
|
9
|
+
v-if="collapsible"
|
|
10
|
+
:class="{ 'dito-opened': !collapsed }"
|
|
7
11
|
)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
:key="`suffix-${index}`"
|
|
23
|
-
:content="suffix"
|
|
24
|
-
)
|
|
25
|
-
slot(name="edit-buttons")
|
|
12
|
+
dito-element.dito-label-prefix(
|
|
13
|
+
v-for="(prefix, index) of prefixes"
|
|
14
|
+
tag="span"
|
|
15
|
+
:key="`prefix-${index}`"
|
|
16
|
+
:content="prefix"
|
|
17
|
+
)
|
|
18
|
+
label(:for="dataPath" v-html="text")
|
|
19
|
+
dito-element.dito-label-suffix(
|
|
20
|
+
v-for="(suffix, index) of suffixes"
|
|
21
|
+
tag="span"
|
|
22
|
+
:key="`suffix-${index}`"
|
|
23
|
+
:content="suffix"
|
|
24
|
+
)
|
|
25
|
+
slot(name="edit-buttons")
|
|
26
26
|
</template>
|
|
27
27
|
|
|
28
28
|
<style lang="sass">
|
|
@@ -129,10 +129,10 @@ export default DitoComponent.component('dito-label', {
|
|
|
129
129
|
return asArray(this.label?.suffix)
|
|
130
130
|
},
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
attributes() {
|
|
133
133
|
return {
|
|
134
134
|
...(this.collapsible && {
|
|
135
|
-
|
|
135
|
+
onClick: this.onClick
|
|
136
136
|
})
|
|
137
137
|
}
|
|
138
138
|
},
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
nav.dito-menu.dito-scroll-parent
|
|
3
|
+
h1 {{ appState.title }}
|
|
4
|
+
ul.dito-scroll
|
|
5
|
+
li(v-for="view in views")
|
|
6
|
+
router-link.dito-link(
|
|
7
|
+
v-if="shouldRender(view)"
|
|
8
|
+
:to="`/${view.path}`"
|
|
9
|
+
active-class="dito-active"
|
|
10
|
+
) {{ getLabel(view) }}
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<style lang="sass">
|