@ditojs/admin 2.0.4 → 2.1.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 +2065 -1969
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +32 -31
- package/src/DitoAdmin.js +66 -31
- package/src/DitoComponent.js +4 -1
- package/src/DitoContext.js +13 -5
- package/src/{TypeComponent.js → DitoTypeComponent.js} +8 -5
- package/src/components/DitoAccount.vue +20 -19
- package/src/components/DitoButtons.vue +14 -12
- package/src/components/DitoClipboard.vue +16 -8
- package/src/components/DitoContainer.vue +56 -43
- package/src/components/DitoCreateButton.vue +20 -15
- package/src/components/DitoDialog.vue +78 -53
- package/src/components/DitoEditButtons.vue +16 -14
- package/src/components/DitoElement.vue +2 -3
- package/src/components/DitoErrors.vue +18 -13
- package/src/components/DitoForm.vue +41 -24
- package/src/components/DitoFormNested.vue +12 -10
- package/src/components/DitoHeader.vue +103 -69
- package/src/components/DitoLabel.vue +108 -81
- package/src/components/DitoMenu.vue +52 -36
- package/src/components/DitoPagination.vue +9 -7
- package/src/components/DitoPane.vue +53 -45
- package/src/components/DitoPanel.vue +62 -42
- package/src/components/DitoPanels.vue +11 -10
- package/src/components/DitoRoot.vue +57 -46
- package/src/components/DitoSchema.vue +179 -131
- package/src/components/DitoSchemaInlined.vue +39 -28
- package/src/components/DitoScopes.vue +41 -31
- package/src/components/DitoSpinner.vue +31 -40
- package/src/components/DitoTableCell.vue +9 -9
- package/src/components/DitoTableHead.vue +52 -37
- package/src/components/DitoTabs.vue +39 -29
- package/src/components/DitoTreeItem.vue +140 -86
- package/src/components/DitoVNode.vue +1 -1
- package/src/components/DitoView.vue +13 -11
- package/src/mixins/DataMixin.js +11 -9
- package/src/mixins/DitoMixin.js +47 -25
- package/src/mixins/EmitterMixin.js +2 -1
- package/src/mixins/ItemMixin.js +15 -10
- package/src/mixins/LoadingMixin.js +2 -1
- package/src/mixins/NumberMixin.js +15 -10
- package/src/mixins/OptionsMixin.js +24 -12
- package/src/mixins/ResourceMixin.js +42 -34
- package/src/mixins/RouteMixin.js +8 -8
- package/src/mixins/SortableMixin.js +1 -1
- package/src/mixins/SourceMixin.js +68 -34
- package/src/mixins/TypeMixin.js +5 -4
- package/src/mixins/ValidationMixin.js +3 -0
- package/src/styles/_base.scss +17 -0
- package/src/styles/_button.scss +212 -0
- package/src/styles/_imports.scss +2 -0
- package/src/styles/_layout.scss +22 -0
- package/src/styles/_notifications.scss +54 -0
- package/src/styles/_pulldown.scss +39 -0
- package/src/styles/_scroll.scss +15 -0
- package/src/styles/_settings.scss +68 -0
- package/src/styles/_sortable.scss +13 -0
- package/src/styles/_table.scss +224 -0
- package/src/styles/style.scss +9 -0
- package/src/types/DitoTypeButton.vue +72 -0
- package/src/types/{TypeCheckbox.vue → DitoTypeCheckbox.vue} +12 -11
- package/src/types/{TypeCheckboxes.vue → DitoTypeCheckboxes.vue} +21 -15
- package/src/types/{TypeCode.vue → DitoTypeCode.vue} +46 -34
- package/src/types/{TypeColor.vue → DitoTypeColor.vue} +71 -52
- package/src/types/{TypeComponent.vue → DitoTypeComponent.vue} +2 -2
- package/src/types/DitoTypeComputed.vue +54 -0
- package/src/types/DitoTypeDate.vue +64 -0
- package/src/types/DitoTypeLabel.vue +23 -0
- package/src/types/{TypeList.vue → DitoTypeList.vue} +83 -61
- package/src/types/{TypeMarkup.vue → DitoTypeMarkup.vue} +172 -122
- package/src/types/DitoTypeMultiselect.vue +434 -0
- package/src/types/DitoTypeNumber.vue +46 -0
- package/src/types/{TypeObject.vue → DitoTypeObject.vue} +41 -26
- package/src/types/{TypePanel.vue → DitoTypePanel.vue} +2 -2
- package/src/types/{TypeProgress.vue → DitoTypeProgress.vue} +4 -6
- package/src/types/{TypeRadio.vue → DitoTypeRadio.vue} +17 -13
- package/src/types/{TypeSection.vue → DitoTypeSection.vue} +17 -17
- package/src/types/{TypeSelect.vue → DitoTypeSelect.vue} +39 -35
- package/src/types/{TypeSlider.vue → DitoTypeSlider.vue} +29 -23
- package/src/types/{TypeSwitch.vue → DitoTypeSwitch.vue} +15 -13
- package/src/types/DitoTypeText.vue +77 -0
- package/src/types/{TypeTextarea.vue → DitoTypeTextarea.vue} +17 -14
- package/src/types/DitoTypeTreeList.vue +191 -0
- package/src/types/{TypeUpload.vue → DitoTypeUpload.vue} +92 -65
- package/src/types/index.js +26 -26
- package/src/utils/SchemaGraph.js +21 -13
- package/src/utils/accessor.js +17 -9
- package/src/utils/data.js +4 -1
- package/src/utils/filter.js +8 -10
- package/src/utils/options.js +3 -3
- package/src/utils/resource.js +12 -10
- package/src/utils/schema.js +190 -125
- package/src/utils/type.js +31 -20
- package/src/validations/_decimals.js +1 -2
- package/types/index.d.ts +27 -23
- package/src/styles/_base.sass +0 -15
- package/src/styles/_button.sass +0 -127
- package/src/styles/_imports.sass +0 -2
- package/src/styles/_layout.sass +0 -13
- package/src/styles/_notifications.sass +0 -33
- package/src/styles/_pulldown.sass +0 -26
- package/src/styles/_scroll.sass +0 -13
- package/src/styles/_settings.sass +0 -55
- package/src/styles/_sortable.sass +0 -9
- package/src/styles/_table.sass +0 -153
- package/src/styles/style.sass +0 -10
- package/src/types/TypeButton.vue +0 -73
- package/src/types/TypeComputed.vue +0 -53
- package/src/types/TypeDate.vue +0 -64
- package/src/types/TypeLabel.vue +0 -19
- package/src/types/TypeMultiselect.vue +0 -376
- package/src/types/TypeNumber.vue +0 -44
- package/src/types/TypeText.vue +0 -67
- package/src/types/TypeTreeList.vue +0 -164
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
.dito-create-button
|
|
3
|
-
template(
|
|
3
|
+
template(
|
|
4
|
+
v-if="showPulldown"
|
|
5
|
+
)
|
|
4
6
|
button.dito-button(
|
|
5
7
|
type="button"
|
|
6
|
-
@mousedown.stop="onPulldownMouseDown()"
|
|
7
8
|
:class="`dito-button-${verb}`"
|
|
8
9
|
:title="labelize(verb)"
|
|
10
|
+
@mousedown.stop="onPulldownMouseDown()"
|
|
9
11
|
) {{ text }}
|
|
10
|
-
ul.dito-pulldown(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
ul.dito-pulldown(:class="{ 'dito-open': pulldown.open }")
|
|
13
|
+
li(
|
|
14
|
+
v-for="(form, type) in forms"
|
|
15
|
+
)
|
|
14
16
|
a(
|
|
15
17
|
v-if="isCreatable(form)"
|
|
16
18
|
:class="`dito-type-${type}`"
|
|
@@ -20,26 +22,19 @@
|
|
|
20
22
|
button.dito-button(
|
|
21
23
|
v-else
|
|
22
24
|
:type="isInlined ? 'button' : 'submit'"
|
|
23
|
-
@click="createItem(forms.default)"
|
|
24
25
|
:class="`dito-button-${verb}`"
|
|
25
26
|
:title="labelize(verb)"
|
|
27
|
+
@click="createItem(forms.default)"
|
|
26
28
|
) {{ text }}
|
|
27
29
|
</template>
|
|
28
30
|
|
|
29
|
-
<style lang="sass">
|
|
30
|
-
.dito-create-button
|
|
31
|
-
position: relative
|
|
32
|
-
.dito-pulldown
|
|
33
|
-
right: 0
|
|
34
|
-
</style>
|
|
35
|
-
|
|
36
31
|
<script>
|
|
37
32
|
import DitoComponent from '../DitoComponent.js'
|
|
38
33
|
import PulldownMixin from '../mixins/PulldownMixin.js'
|
|
39
34
|
import { getFormSchemas, isInlined } from '../utils/schema.js'
|
|
40
35
|
|
|
41
36
|
// @vue/component
|
|
42
|
-
export default DitoComponent.component('
|
|
37
|
+
export default DitoComponent.component('DitoCreateButton', {
|
|
43
38
|
mixins: [PulldownMixin],
|
|
44
39
|
|
|
45
40
|
props: {
|
|
@@ -91,3 +86,13 @@ export default DitoComponent.component('dito-create-button', {
|
|
|
91
86
|
}
|
|
92
87
|
})
|
|
93
88
|
</script>
|
|
89
|
+
|
|
90
|
+
<style lang="scss">
|
|
91
|
+
.dito-create-button {
|
|
92
|
+
position: relative;
|
|
93
|
+
|
|
94
|
+
.dito-pulldown {
|
|
95
|
+
right: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -1,73 +1,41 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
2
|
.dito-dialog(
|
|
3
|
+
ref="dialog"
|
|
3
4
|
role="dialog"
|
|
4
5
|
aria-expanded="true"
|
|
5
6
|
aria-modal="true"
|
|
6
7
|
:style="{ '--width': `${settings.width}px` }"
|
|
7
|
-
@
|
|
8
|
+
@mouseup="onMouseUp"
|
|
8
9
|
)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
UseFocusTrap.dito-dialog__focus-trap(
|
|
11
|
+
:options="{ immediate: true, fallbackFocus: () => $refs.dialog }"
|
|
12
|
+
)
|
|
13
|
+
form.dito-scroll-parent(
|
|
14
|
+
@submit.prevent="submit"
|
|
13
15
|
)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
16
|
+
DitoSchema.dito-scroll(
|
|
17
|
+
:schema="schema"
|
|
18
|
+
:data="dialogData"
|
|
19
|
+
)
|
|
20
|
+
template(#buttons)
|
|
21
|
+
DitoButtons.dito-buttons-large(
|
|
22
|
+
:buttons="buttonSchemas"
|
|
23
|
+
:data="dialogData"
|
|
24
|
+
)
|
|
19
25
|
</template>
|
|
20
26
|
|
|
21
|
-
<style lang="sass">
|
|
22
|
-
@import '../styles/_imports'
|
|
23
|
-
|
|
24
|
-
.dito-dialog
|
|
25
|
-
position: fixed
|
|
26
|
-
display: flex
|
|
27
|
-
inset: 0
|
|
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)
|
|
61
|
-
</style>
|
|
62
|
-
|
|
63
27
|
<script>
|
|
64
28
|
import { clone } from '@ditojs/utils'
|
|
65
29
|
import { addEvents } from '@ditojs/ui/src'
|
|
66
30
|
import DitoComponent from '../DitoComponent.js'
|
|
67
31
|
import { getButtonSchemas } from '../utils/schema.js'
|
|
32
|
+
import { UseFocusTrap } from '@vueuse/integrations/useFocusTrap/component'
|
|
68
33
|
|
|
69
34
|
// @vue/component
|
|
70
|
-
export default DitoComponent.component('
|
|
35
|
+
export default DitoComponent.component('DitoDialog', {
|
|
36
|
+
components: { UseFocusTrap },
|
|
37
|
+
emits: ['remove'],
|
|
38
|
+
|
|
71
39
|
provide() {
|
|
72
40
|
return {
|
|
73
41
|
$dialogComponent: () => this
|
|
@@ -181,7 +149,64 @@ export default DitoComponent.component('dito-dialog', {
|
|
|
181
149
|
|
|
182
150
|
close() {
|
|
183
151
|
this.cancel()
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
onMouseUp() {
|
|
155
|
+
if (this.settings.clickToClose) {
|
|
156
|
+
this.close()
|
|
157
|
+
}
|
|
184
158
|
}
|
|
185
159
|
}
|
|
186
160
|
})
|
|
187
161
|
</script>
|
|
162
|
+
|
|
163
|
+
<style lang="scss">
|
|
164
|
+
@import '../styles/_imports';
|
|
165
|
+
|
|
166
|
+
.dito-dialog {
|
|
167
|
+
position: fixed;
|
|
168
|
+
display: flex;
|
|
169
|
+
inset: 0;
|
|
170
|
+
z-index: 2000;
|
|
171
|
+
padding: $content-padding;
|
|
172
|
+
align-items: center;
|
|
173
|
+
justify-content: center;
|
|
174
|
+
// Prevent scrolling of the page behind the dialog:
|
|
175
|
+
overflow: hidden;
|
|
176
|
+
background: rgba(0, 0, 0, 0.2);
|
|
177
|
+
|
|
178
|
+
&__focus-trap {
|
|
179
|
+
height: 100%;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// TODO: `&__inner`
|
|
183
|
+
form {
|
|
184
|
+
position: relative;
|
|
185
|
+
display: flex;
|
|
186
|
+
box-sizing: border-box;
|
|
187
|
+
background: white;
|
|
188
|
+
border-radius: $border-radius;
|
|
189
|
+
max-width: var(--width, 480px);
|
|
190
|
+
max-height: 100%;
|
|
191
|
+
box-shadow: 0 20px 60px -2px rgba(27, 33, 58, 0.4);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.dito-dialog-enter-active,
|
|
196
|
+
.dito-dialog-leave-active {
|
|
197
|
+
transition: opacity 0.15s;
|
|
198
|
+
|
|
199
|
+
form {
|
|
200
|
+
transition: transform 0.25s;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.dito-dialog-enter-from,
|
|
205
|
+
.dito-dialog-leave-to {
|
|
206
|
+
opacity: 0;
|
|
207
|
+
|
|
208
|
+
form {
|
|
209
|
+
transform: translateY(-20px);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
</style>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
2
|
+
//- Set `@click.stop` to prevent click events from bubbling to dito-label.
|
|
3
|
+
DitoButtons.dito-edit-buttons.dito-buttons-round(
|
|
3
4
|
:buttons="buttons"
|
|
4
5
|
:dataPath="dataPath"
|
|
5
6
|
:data="data"
|
|
6
7
|
:meta="meta"
|
|
7
8
|
:store="store"
|
|
8
|
-
/* Prevent click events from bubbling to dito-label: */
|
|
9
9
|
@click.stop
|
|
10
10
|
)
|
|
11
11
|
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
@@ -13,12 +13,12 @@ dito-buttons.dito-edit-buttons.dito-buttons-round(
|
|
|
13
13
|
v-if="isDraggable"
|
|
14
14
|
v-bind="getButtonAttributes(verbs.drag)"
|
|
15
15
|
)
|
|
16
|
-
|
|
16
|
+
RouterLink.dito-button(
|
|
17
17
|
v-if="isEditable"
|
|
18
18
|
:to="{ path: editPath }"
|
|
19
19
|
v-bind="getButtonAttributes(verbs.edit)"
|
|
20
20
|
)
|
|
21
|
-
|
|
21
|
+
DitoCreateButton(
|
|
22
22
|
v-if="isCreatable"
|
|
23
23
|
:schema="schema"
|
|
24
24
|
:path="createPath"
|
|
@@ -33,19 +33,14 @@ dito-buttons.dito-edit-buttons.dito-buttons-round(
|
|
|
33
33
|
)
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
|
-
<style lang="sass">
|
|
37
|
-
.dito-edit-buttons
|
|
38
|
-
// Override cursor from collapsible dito-label:
|
|
39
|
-
cursor: default
|
|
40
|
-
flex: none
|
|
41
|
-
</style>
|
|
42
|
-
|
|
43
36
|
<script>
|
|
44
37
|
import DitoComponent from '../DitoComponent.js'
|
|
45
38
|
import { capitalize } from '@ditojs/utils'
|
|
46
39
|
|
|
47
40
|
// @vue/component
|
|
48
|
-
export default DitoComponent.component('
|
|
41
|
+
export default DitoComponent.component('DitoEditButtons', {
|
|
42
|
+
emits: ['delete'],
|
|
43
|
+
|
|
49
44
|
props: {
|
|
50
45
|
draggable: { type: Boolean, default: false },
|
|
51
46
|
editable: { type: Boolean, default: false },
|
|
@@ -85,8 +80,7 @@ export default DitoComponent.component('dito-edit-buttons', {
|
|
|
85
80
|
createButtonText() {
|
|
86
81
|
return (
|
|
87
82
|
// Allow schema to override create button through creatable object:
|
|
88
|
-
this.schema.creatable?.label ||
|
|
89
|
-
(
|
|
83
|
+
this.schema.creatable?.label || (
|
|
90
84
|
// Auto-generate create button labels from from labels for list
|
|
91
85
|
// sources with only one form:
|
|
92
86
|
this.formLabel &&
|
|
@@ -107,3 +101,11 @@ export default DitoComponent.component('dito-edit-buttons', {
|
|
|
107
101
|
}
|
|
108
102
|
})
|
|
109
103
|
</script>
|
|
104
|
+
|
|
105
|
+
<style lang="scss">
|
|
106
|
+
.dito-edit-buttons {
|
|
107
|
+
// Override cursor from collapsible dito-label:
|
|
108
|
+
cursor: default;
|
|
109
|
+
flex: none;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
@@ -12,10 +12,10 @@ import DitoComponent from '../DitoComponent.js'
|
|
|
12
12
|
import { isObject, isString, asArray } from '@ditojs/utils'
|
|
13
13
|
|
|
14
14
|
// @vue/component
|
|
15
|
-
export default DitoComponent.component('
|
|
15
|
+
export default DitoComponent.component('DitoElement', {
|
|
16
16
|
props: {
|
|
17
17
|
tag: { type: String, default: 'span' },
|
|
18
|
-
content: { type: [String, Object] }
|
|
18
|
+
content: { type: [String, Object], default: null }
|
|
19
19
|
},
|
|
20
20
|
|
|
21
21
|
computed: {
|
|
@@ -50,5 +50,4 @@ function asObject(value) {
|
|
|
50
50
|
return object
|
|
51
51
|
}, {})
|
|
52
52
|
}
|
|
53
|
-
|
|
54
53
|
</script>
|
|
@@ -3,28 +3,33 @@
|
|
|
3
3
|
v-if="errors"
|
|
4
4
|
)
|
|
5
5
|
ul
|
|
6
|
-
li(
|
|
6
|
+
li(
|
|
7
|
+
v-for="error of errors"
|
|
8
|
+
)
|
|
7
9
|
| {{ error }}
|
|
8
10
|
</template>
|
|
9
11
|
|
|
10
|
-
<style lang="sass">
|
|
11
|
-
@import '../styles/_imports'
|
|
12
|
-
|
|
13
|
-
.dito-errors
|
|
14
|
-
position: absolute
|
|
15
|
-
z-index: 1
|
|
16
|
-
ul
|
|
17
|
-
margin-top: 1px
|
|
18
|
-
color: $color-error
|
|
19
|
-
</style>
|
|
20
|
-
|
|
21
12
|
<script>
|
|
22
13
|
import DitoComponent from '../DitoComponent.js'
|
|
23
14
|
|
|
24
15
|
// @vue/component
|
|
25
|
-
export default DitoComponent.component('
|
|
16
|
+
export default DitoComponent.component('DitoErrors', {
|
|
26
17
|
props: {
|
|
27
18
|
errors: { type: Array, default: null }
|
|
28
19
|
}
|
|
29
20
|
})
|
|
30
21
|
</script>
|
|
22
|
+
|
|
23
|
+
<style lang="scss">
|
|
24
|
+
@import '../styles/_imports';
|
|
25
|
+
|
|
26
|
+
.dito-errors {
|
|
27
|
+
position: absolute;
|
|
28
|
+
z-index: 1;
|
|
29
|
+
|
|
30
|
+
ul {
|
|
31
|
+
margin-top: 1px;
|
|
32
|
+
color: $color-error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//- `v-if` here, so event handling and other things still work with nested
|
|
8
8
|
//- editing. Only render a router-view here if this isn't the last data route
|
|
9
9
|
//- and not a nested form route, which will appear elsewhere in its own view.
|
|
10
|
-
|
|
10
|
+
RouterView(
|
|
11
11
|
v-if="!(isLastUnnestedRoute || isNestedRoute)"
|
|
12
12
|
v-show="!isActive"
|
|
13
13
|
)
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
:is="isNestedRoute ? 'div' : 'form'"
|
|
18
18
|
@submit.prevent
|
|
19
19
|
)
|
|
20
|
-
|
|
20
|
+
DitoSchema(
|
|
21
21
|
:schema="schema"
|
|
22
22
|
:dataPath="dataPath"
|
|
23
23
|
:data="data"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
:menuHeader="true"
|
|
28
28
|
)
|
|
29
29
|
template(#buttons)
|
|
30
|
-
|
|
30
|
+
DitoButtons.dito-buttons-round.dito-buttons-main.dito-buttons-large(
|
|
31
31
|
:buttons="buttonSchemas"
|
|
32
32
|
:dataPath="dataPath"
|
|
33
33
|
:data="data"
|
|
@@ -55,7 +55,7 @@ import { getButtonSchemas, isObjectSource } from '../utils/schema.js'
|
|
|
55
55
|
import { resolvePath } from '../utils/path.js'
|
|
56
56
|
|
|
57
57
|
// @vue/component
|
|
58
|
-
export default DitoComponent.component('
|
|
58
|
+
export default DitoComponent.component('DitoForm', {
|
|
59
59
|
mixins: [RouteMixin, ResourceMixin],
|
|
60
60
|
|
|
61
61
|
data() {
|
|
@@ -84,13 +84,15 @@ export default DitoComponent.component('dito-form', {
|
|
|
84
84
|
},
|
|
85
85
|
|
|
86
86
|
schema() {
|
|
87
|
-
return
|
|
88
|
-
this.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
return (
|
|
88
|
+
this.getItemFormSchema(
|
|
89
|
+
this.sourceSchema,
|
|
90
|
+
// If there is no data yet, provide an empty object with just the
|
|
91
|
+
// right type set, so the form can always be determined.
|
|
92
|
+
this.data || { type: this.type },
|
|
93
|
+
this.context
|
|
94
|
+
) || {}
|
|
95
|
+
) // Always return a schema object so we don't need to check for it.
|
|
94
96
|
},
|
|
95
97
|
|
|
96
98
|
buttonSchemas() {
|
|
@@ -154,7 +156,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
154
156
|
itemId() {
|
|
155
157
|
return this.isCreating
|
|
156
158
|
? null
|
|
157
|
-
:
|
|
159
|
+
: this.param ?? null
|
|
158
160
|
},
|
|
159
161
|
|
|
160
162
|
method() {
|
|
@@ -203,6 +205,8 @@ export default DitoComponent.component('dito-form', {
|
|
|
203
205
|
// parts that need to be treated like ids and mapped to indices in data.
|
|
204
206
|
const pathParts = this.routeRecord.path.split('/')
|
|
205
207
|
const routeParts = pathParts.slice(pathParts.length - dataParts.length)
|
|
208
|
+
// TODO: Fix side-effects
|
|
209
|
+
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
206
210
|
this.sourceKey = null
|
|
207
211
|
const lastDataPart = dataParts[dataParts.length - 1]
|
|
208
212
|
if (isObjectSource(this.sourceSchema) && lastDataPart === 'create') {
|
|
@@ -222,6 +226,8 @@ export default DitoComponent.component('dito-form', {
|
|
|
222
226
|
// Skip the final lookup but remember `sourceKey`, as we want the
|
|
223
227
|
// parent data so we can replace the entry at `sourceKey` on it.
|
|
224
228
|
if (i === l - 1) {
|
|
229
|
+
// TODO: Fix side-effects
|
|
230
|
+
// eslint-disable-next-line
|
|
225
231
|
this.sourceKey = key
|
|
226
232
|
} else {
|
|
227
233
|
data = data[key]
|
|
@@ -245,6 +251,8 @@ export default DitoComponent.component('dito-form', {
|
|
|
245
251
|
if (!this.isMutating) {
|
|
246
252
|
// Use a trick to store cloned inherited data in clonedData, to make
|
|
247
253
|
// it reactive and prevent it from being cloned multiple times.
|
|
254
|
+
// TODO: Fix side-effects
|
|
255
|
+
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
248
256
|
this.clonedData = data = clone(data)
|
|
249
257
|
}
|
|
250
258
|
if (
|
|
@@ -253,7 +261,8 @@ export default DitoComponent.component('dito-form', {
|
|
|
253
261
|
isObjectSource(this.sourceSchema)
|
|
254
262
|
) {
|
|
255
263
|
// If data of an object source is null, redirect to its create route.
|
|
256
|
-
// TODO:
|
|
264
|
+
// TODO: Fix side-effects
|
|
265
|
+
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
257
266
|
this.$router.push({ path: `${this.path}/create` })
|
|
258
267
|
}
|
|
259
268
|
return data
|
|
@@ -284,9 +293,11 @@ export default DitoComponent.component('dito-form', {
|
|
|
284
293
|
|
|
285
294
|
getDataPathFrom(route) {
|
|
286
295
|
// Get the data path by denormalizePath the relative route path
|
|
287
|
-
return this.api.denormalizePath(
|
|
288
|
-
|
|
289
|
-
|
|
296
|
+
return this.api.denormalizePath(
|
|
297
|
+
this.path
|
|
298
|
+
// DitoViews have nested routes, so don't remove their path.
|
|
299
|
+
.slice((route.isView ? 0 : route.path.length) + 1)
|
|
300
|
+
)
|
|
290
301
|
},
|
|
291
302
|
|
|
292
303
|
// @override ResourceMixin.setupData()
|
|
@@ -348,8 +359,12 @@ export default DitoComponent.component('dito-form', {
|
|
|
348
359
|
|
|
349
360
|
getSubmitVerb(present = true) {
|
|
350
361
|
return this.isCreating
|
|
351
|
-
? present
|
|
352
|
-
|
|
362
|
+
? present
|
|
363
|
+
? 'create'
|
|
364
|
+
: 'created'
|
|
365
|
+
: present
|
|
366
|
+
? 'submit'
|
|
367
|
+
: 'submitted'
|
|
353
368
|
},
|
|
354
369
|
|
|
355
370
|
async submit(button, { validate = true, closeForm = false } = {}) {
|
|
@@ -370,9 +385,10 @@ export default DitoComponent.component('dito-form', {
|
|
|
370
385
|
if (!buttonResource && this.isTransient) {
|
|
371
386
|
success = await this.submitTransient(button, resource, method, data, {
|
|
372
387
|
onSuccess: () => this.emitSchemaEvent(this.getSubmitVerb()),
|
|
373
|
-
onError: error =>
|
|
374
|
-
|
|
375
|
-
|
|
388
|
+
onError: error =>
|
|
389
|
+
this.emitSchemaEvent('error', {
|
|
390
|
+
context: { error }
|
|
391
|
+
}),
|
|
376
392
|
notifySuccess: () => {
|
|
377
393
|
const verb = getVerb(false)
|
|
378
394
|
this.notify({
|
|
@@ -401,9 +417,10 @@ export default DitoComponent.component('dito-form', {
|
|
|
401
417
|
success = await this.submitResource(button, resource, method, data, {
|
|
402
418
|
setData: true,
|
|
403
419
|
onSuccess: () => this.emitSchemaEvent(this.getSubmitVerb()),
|
|
404
|
-
onError: error =>
|
|
405
|
-
|
|
406
|
-
|
|
420
|
+
onError: error =>
|
|
421
|
+
this.emitSchemaEvent('error', {
|
|
422
|
+
context: { error }
|
|
423
|
+
}),
|
|
407
424
|
notifySuccess: () => {
|
|
408
425
|
const verb = getVerb(false)
|
|
409
426
|
this.notify({
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
<style lang="sass">
|
|
2
|
-
.dito-form-nested
|
|
3
|
-
&,
|
|
4
|
-
.dito-scroll
|
|
5
|
-
//- No scrolling inside nested forms, and prevent open .multiselect from
|
|
6
|
-
//- being cropped.
|
|
7
|
-
overflow: visible
|
|
8
|
-
</style>
|
|
9
|
-
|
|
10
1
|
<script>
|
|
11
2
|
import DitoComponent from '../DitoComponent.js'
|
|
12
3
|
import DitoForm from './DitoForm.vue'
|
|
13
4
|
|
|
14
5
|
// @vue/component
|
|
15
|
-
export default DitoComponent.component('
|
|
6
|
+
export default DitoComponent.component('DitoFormNested', {
|
|
16
7
|
extends: DitoForm
|
|
17
8
|
})
|
|
18
9
|
</script>
|
|
10
|
+
|
|
11
|
+
<style lang="scss">
|
|
12
|
+
.dito-form-nested {
|
|
13
|
+
&,
|
|
14
|
+
.dito-scroll {
|
|
15
|
+
// No scrolling inside nested forms, and prevent open .multiselect from
|
|
16
|
+
// being cropped.
|
|
17
|
+
overflow: visible;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
</style>
|