@ditojs/admin 3.2.7 → 3.3.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.css +1 -1
- package/dist/dito-admin.es.js +6011 -5826
- package/dist/dito-admin.umd.js +3 -7
- package/package.json +18 -17
- package/src/DitoAdmin.js +44 -24
- package/src/DitoContext.js +28 -2
- package/src/DitoTypeComponent.js +1 -0
- package/src/appState.js +6 -3
- package/src/components/DitoAccount.vue +35 -27
- package/src/components/DitoAffixes.vue +9 -2
- package/src/components/DitoClipboard.vue +59 -93
- package/src/components/DitoConfirmMessage.vue +18 -0
- package/src/components/DitoContainer.vue +56 -18
- package/src/components/DitoCreateButton.vue +36 -84
- package/src/components/DitoDialog.vue +20 -15
- package/src/components/DitoDragHandle.vue +44 -0
- package/src/components/DitoDraggable.vue +43 -16
- package/src/components/DitoEditButtons.vue +48 -24
- package/src/components/DitoErrors.vue +9 -56
- package/src/components/DitoForm.vue +82 -42
- package/src/components/DitoInputAffixes.vue +50 -0
- package/src/components/DitoLabel.vue +1 -15
- package/src/components/DitoMenu.vue +45 -52
- package/src/components/DitoNotifications.vue +38 -14
- package/src/components/DitoOptionList.vue +81 -0
- package/src/components/DitoOptionsEditButtons.vue +57 -0
- package/src/components/DitoPagination.vue +1 -8
- package/src/components/DitoPane.vue +51 -39
- package/src/components/DitoPanel.vue +12 -26
- package/src/components/DitoPanels.vue +11 -5
- package/src/components/DitoResizeHandle.vue +47 -0
- package/src/components/DitoRoot.vue +113 -320
- package/src/components/DitoSchema.vue +72 -63
- package/src/components/DitoSchemaInlined.vue +8 -9
- package/src/components/DitoScopes.vue +14 -18
- package/src/components/DitoSidebar.vue +4 -29
- package/src/components/DitoSourceItem.vue +114 -0
- package/src/components/DitoTableCell.vue +4 -0
- package/src/components/DitoTableHead.vue +15 -17
- package/src/components/DitoTabs.vue +25 -0
- package/src/components/DitoTrail.vue +25 -25
- package/src/components/DitoTreeItem.vue +102 -141
- package/src/components/DitoUploadFile.vue +5 -2
- package/src/components/DitoView.vue +33 -24
- package/src/index.js +4 -1
- package/src/mixins/DitoMixin.js +77 -110
- package/src/mixins/DomMixin.js +12 -14
- package/src/mixins/EmitterMixin.js +3 -2
- package/src/mixins/ItemMixin.js +38 -94
- package/src/mixins/OptionsMixin.js +38 -25
- package/src/mixins/ResourceMixin.js +182 -111
- package/src/mixins/RouteMixin.js +61 -44
- package/src/mixins/SchemaParentMixin.js +4 -1
- package/src/mixins/SourceMixin.js +118 -100
- package/src/mixins/TypeMixin.js +42 -40
- package/src/mixins/ValidationMixin.js +16 -4
- package/src/mixins/ValidatorMixin.js +1 -1
- package/src/styles/_settings.scss +4 -0
- package/src/styles/_tippy.scss +0 -11
- package/src/styles/style.scss +0 -1
- package/src/types/DitoTypeButton.vue +11 -14
- package/src/types/DitoTypeCheckboxes.vue +35 -17
- package/src/types/DitoTypeCode.vue +19 -41
- package/src/types/DitoTypeColor.vue +67 -19
- package/src/types/DitoTypeDate.vue +11 -14
- package/src/types/DitoTypeList.vue +50 -62
- package/src/types/DitoTypeMarkup.vue +41 -54
- package/src/types/DitoTypeMultiselect.vue +82 -52
- package/src/types/DitoTypeNumber.vue +12 -15
- package/src/types/DitoTypeObject.vue +4 -38
- package/src/types/DitoTypeRadio.vue +19 -6
- package/src/types/DitoTypeSection.vue +23 -9
- package/src/types/DitoTypeSelect.vue +39 -23
- package/src/types/DitoTypeSlider.vue +9 -1
- package/src/types/DitoTypeSwitch.vue +1 -1
- package/src/types/DitoTypeText.vue +11 -14
- package/src/types/DitoTypeTreeList.vue +46 -8
- package/src/types/DitoTypeUpload.vue +190 -67
- package/src/utils/DataModel.js +368 -146
- package/src/utils/FileDropTargets.js +97 -0
- package/src/utils/ItemStores.js +31 -0
- package/src/utils/ListQuery.js +115 -0
- package/src/utils/LoadingTracker.js +76 -0
- package/src/utils/SchemaGraph.js +3 -2
- package/src/utils/Session.js +151 -0
- package/src/utils/ViewRegistry.js +85 -0
- package/src/utils/accessor.js +12 -4
- package/src/utils/affixes.js +33 -0
- package/src/utils/changeOnceEdited.js +33 -0
- package/src/utils/clipboard.js +55 -0
- package/src/utils/data.js +10 -5
- package/src/utils/dialogs.js +59 -0
- package/src/utils/dragResize.js +61 -0
- package/src/utils/filter.js +36 -2
- package/src/utils/html.js +9 -0
- package/src/utils/list.js +10 -0
- package/src/utils/options.js +4 -0
- package/src/utils/registration.js +18 -0
- package/src/utils/request.js +108 -13
- package/src/utils/route.js +6 -17
- package/src/utils/schema/data.js +24 -2
- package/src/utils/schema/events.js +19 -0
- package/src/utils/schema/item.js +114 -0
- package/src/utils/schema/lookup.js +39 -14
- package/src/utils/schema/setup.js +5 -5
- package/src/utils/schema/validation.js +16 -2
- package/src/utils/uid.js +105 -8
- package/src/validators/_decimals.js +16 -5
- package/types/index.d.ts +168 -41
- package/src/mixins/LoadingMixin.js +0 -23
- package/src/mixins/PulldownMixin.js +0 -72
- package/src/styles/_pulldown.scss +0 -38
|
@@ -1,51 +1,69 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
2
|
+
DitoOptionList.dito-checkboxes(
|
|
3
3
|
:id="componentPath"
|
|
4
4
|
role="group"
|
|
5
5
|
:aria-label="label"
|
|
6
|
-
:
|
|
6
|
+
:options="options"
|
|
7
|
+
:isGrouped="!!groupBy"
|
|
8
|
+
:layout="schema.layout"
|
|
7
9
|
)
|
|
8
|
-
|
|
9
|
-
v-for="option in options"
|
|
10
|
-
)
|
|
10
|
+
template(#option="{ option, isFirstOption }")
|
|
11
11
|
label
|
|
12
12
|
.dito-checkbox
|
|
13
13
|
input(
|
|
14
|
-
ref="element"
|
|
15
|
-
v-model="
|
|
14
|
+
:ref="isFirstOption ? 'element' : undefined"
|
|
15
|
+
v-model="checkedValues"
|
|
16
16
|
type="checkbox"
|
|
17
17
|
:value="getValueForOption(option)"
|
|
18
18
|
v-bind="attributes"
|
|
19
19
|
)
|
|
20
20
|
span {{ getLabelForOption(option) }}
|
|
21
|
+
DitoOptionsEditButtons(
|
|
22
|
+
v-if="editable"
|
|
23
|
+
:schema="schema"
|
|
24
|
+
:dataPath="dataPath"
|
|
25
|
+
:data="data"
|
|
26
|
+
:meta="meta"
|
|
27
|
+
:store="store"
|
|
28
|
+
:parentContext="context"
|
|
29
|
+
:optionValue="getValueForOption(option)"
|
|
30
|
+
)
|
|
21
31
|
</template>
|
|
22
32
|
|
|
23
33
|
<script>
|
|
24
34
|
import DitoTypeComponent from '../DitoTypeComponent.js'
|
|
25
35
|
import OptionsMixin from '../mixins/OptionsMixin.js'
|
|
36
|
+
import DitoOptionList from '../components/DitoOptionList.vue'
|
|
37
|
+
import DitoOptionsEditButtons from '../components/DitoOptionsEditButtons.vue'
|
|
38
|
+
import { getMultipleValue } from '../utils/schema/data.js'
|
|
26
39
|
|
|
27
40
|
// @vue/component
|
|
28
41
|
export default DitoTypeComponent.register('checkboxes', {
|
|
29
42
|
mixins: [OptionsMixin],
|
|
43
|
+
components: { DitoOptionList, DitoOptionsEditButtons },
|
|
30
44
|
|
|
31
45
|
nativeField: true,
|
|
32
|
-
defaultValue: [],
|
|
46
|
+
defaultValue: ({ schema }) => (getMultipleValue(schema) ? [] : null),
|
|
33
47
|
defaultWidth: 'auto',
|
|
34
48
|
defaultMultiple: true,
|
|
35
49
|
|
|
36
50
|
computed: {
|
|
37
|
-
//
|
|
38
|
-
multiple
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
selectedOptions: {
|
|
51
|
+
// The values of the checked checkboxes, as an array for their `v-model`,
|
|
52
|
+
// also with `multiple: false`.
|
|
53
|
+
checkedValues: {
|
|
43
54
|
get() {
|
|
44
|
-
|
|
55
|
+
const { selectedValue } = this
|
|
56
|
+
return this.multiple
|
|
57
|
+
? (selectedValue || []).filter(value => value != null)
|
|
58
|
+
: selectedValue != null
|
|
59
|
+
? [selectedValue]
|
|
60
|
+
: []
|
|
45
61
|
},
|
|
46
62
|
|
|
47
|
-
set(
|
|
48
|
-
|
|
63
|
+
set(values) {
|
|
64
|
+
// With `multiple: false`, checking a checkbox unchecks the checked
|
|
65
|
+
// one, as the `v-model` of checkboxes appends checked values.
|
|
66
|
+
this.selectedValue = this.multiple ? values : (values.at(-1) ?? null)
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
69
|
}
|
|
@@ -4,21 +4,23 @@
|
|
|
4
4
|
:style="style"
|
|
5
5
|
)
|
|
6
6
|
.dito-code__editor(ref="editor")
|
|
7
|
-
|
|
7
|
+
DitoResizeHandle(
|
|
8
8
|
v-if="resizable"
|
|
9
|
-
|
|
9
|
+
:getElement="() => $el"
|
|
10
|
+
@resize="height = `${$event}px`"
|
|
10
11
|
)
|
|
11
12
|
</template>
|
|
12
13
|
|
|
13
14
|
<script>
|
|
14
15
|
import DitoTypeComponent from '../DitoTypeComponent.js'
|
|
15
|
-
import DomMixin from '../mixins/DomMixin.js'
|
|
16
16
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
17
|
+
import { createChangeOnceEdited } from '../utils/changeOnceEdited.js'
|
|
18
|
+
import DitoResizeHandle from '../components/DitoResizeHandle.vue'
|
|
17
19
|
import CodeFlask from 'codeflask'
|
|
18
20
|
|
|
19
21
|
// @vue/component
|
|
20
22
|
export default DitoTypeComponent.register('code', {
|
|
21
|
-
|
|
23
|
+
components: { DitoResizeHandle },
|
|
22
24
|
|
|
23
25
|
data() {
|
|
24
26
|
return {
|
|
@@ -61,28 +63,26 @@ export default DitoTypeComponent.register('code', {
|
|
|
61
63
|
lineNumbers: false
|
|
62
64
|
})
|
|
63
65
|
|
|
64
|
-
let changed = false
|
|
65
66
|
let ignoreWatch = false
|
|
66
67
|
let ignoreUpdate = false
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
69
|
+
// Emits the change of the value once the editor isn't focused anymore.
|
|
70
|
+
const changeOnceEdited = createChangeOnceEdited({
|
|
71
|
+
isEditing: () => this.focused,
|
|
72
|
+
emitChange: () => this.onChange()
|
|
73
|
+
})
|
|
74
74
|
|
|
75
75
|
const onFocus = () => this.onFocus()
|
|
76
76
|
|
|
77
77
|
const onBlur = () => {
|
|
78
78
|
this.onBlur()
|
|
79
|
-
|
|
79
|
+
changeOnceEdited.emitIfDone()
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
// The textarea is owned by the editor, so its handlers go with it:
|
|
83
|
+
const textarea = this.$refs.editor.querySelector('textarea')
|
|
84
|
+
textarea.addEventListener('focus', onFocus)
|
|
85
|
+
textarea.addEventListener('blur', onBlur)
|
|
86
86
|
|
|
87
87
|
const setCode = code => {
|
|
88
88
|
if (code !== flask.code) {
|
|
@@ -95,8 +95,9 @@ export default DitoTypeComponent.register('code', {
|
|
|
95
95
|
if (value !== this.value) {
|
|
96
96
|
ignoreWatch = true
|
|
97
97
|
this.value = value
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
changeOnceEdited.markEdited()
|
|
99
|
+
this.onInput()
|
|
100
|
+
changeOnceEdited.emitIfDone()
|
|
100
101
|
}
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -137,29 +138,6 @@ export default DitoTypeComponent.register('code', {
|
|
|
137
138
|
|
|
138
139
|
blurElement() {
|
|
139
140
|
this.$el.querySelector('textarea')?.blur()
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
onDragResize(event) {
|
|
143
|
-
const getPoint = ({ clientX: x, clientY: y }) => ({ x, y })
|
|
144
|
-
|
|
145
|
-
let prevY = getPoint(event).y
|
|
146
|
-
let height = parseFloat(getComputedStyle(this.$el).height)
|
|
147
|
-
|
|
148
|
-
const mousemove = event => {
|
|
149
|
-
const { y } = getPoint(event)
|
|
150
|
-
height += y - prevY
|
|
151
|
-
prevY = y
|
|
152
|
-
this.height = `${Math.max(height, 0)}px`
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const handlers = this.domOn(document, {
|
|
156
|
-
mousemove,
|
|
157
|
-
|
|
158
|
-
mouseup(event) {
|
|
159
|
-
mousemove(event)
|
|
160
|
-
handlers.remove()
|
|
161
|
-
}
|
|
162
|
-
})
|
|
163
141
|
}
|
|
164
142
|
}
|
|
165
143
|
})
|
|
@@ -14,22 +14,14 @@ DitoTrigger.dito-color(
|
|
|
14
14
|
v-bind="attributes"
|
|
15
15
|
)
|
|
16
16
|
template(#prefix)
|
|
17
|
-
|
|
18
|
-
:items="schema.prefix"
|
|
17
|
+
DitoInputAffixes(
|
|
19
18
|
position="prefix"
|
|
20
|
-
|
|
21
|
-
:disabled="disabled"
|
|
22
|
-
:parentContext="context"
|
|
19
|
+
v-bind="inputAffixesProps.prefix"
|
|
23
20
|
)
|
|
24
21
|
template(#suffix)
|
|
25
|
-
|
|
26
|
-
:items="schema.suffix"
|
|
22
|
+
DitoInputAffixes(
|
|
27
23
|
position="suffix"
|
|
28
|
-
|
|
29
|
-
:clearable="showClearButton"
|
|
30
|
-
:disabled="disabled"
|
|
31
|
-
:inlineInfo="inlineInfo"
|
|
32
|
-
:parentContext="context"
|
|
24
|
+
v-bind="inputAffixesProps.suffix"
|
|
33
25
|
@clear="clear"
|
|
34
26
|
)
|
|
35
27
|
template(#append)
|
|
@@ -52,12 +44,15 @@ DitoTrigger.dito-color(
|
|
|
52
44
|
import { SketchPicker, tinycolor } from 'vue-color'
|
|
53
45
|
import { DitoTrigger, DitoInput } from '@ditojs/ui/src'
|
|
54
46
|
import DitoTypeComponent from '../DitoTypeComponent.js'
|
|
55
|
-
import
|
|
47
|
+
import TypeMixin from '../mixins/TypeMixin.js'
|
|
48
|
+
import DitoInputAffixes from '../components/DitoInputAffixes.vue'
|
|
49
|
+
import { getInputAffixesProps } from '../utils/affixes.js'
|
|
56
50
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
51
|
+
import { createChangeOnceEdited } from '../utils/changeOnceEdited.js'
|
|
57
52
|
|
|
58
53
|
// @vue/component
|
|
59
54
|
export default DitoTypeComponent.register('color', {
|
|
60
|
-
components: { DitoTrigger, DitoInput,
|
|
55
|
+
components: { DitoTrigger, DitoInput, DitoInputAffixes, SketchPicker },
|
|
61
56
|
|
|
62
57
|
data() {
|
|
63
58
|
return {
|
|
@@ -67,6 +62,10 @@ export default DitoTypeComponent.register('color', {
|
|
|
67
62
|
},
|
|
68
63
|
|
|
69
64
|
computed: {
|
|
65
|
+
inputAffixesProps() {
|
|
66
|
+
return getInputAffixesProps(this)
|
|
67
|
+
},
|
|
68
|
+
|
|
70
69
|
canUpdateValue() {
|
|
71
70
|
return !this.focused || this.readonly
|
|
72
71
|
},
|
|
@@ -86,7 +85,9 @@ export default DitoTypeComponent.register('color', {
|
|
|
86
85
|
!value ||
|
|
87
86
|
color.toHex8String() !== tinycolor(value).toHex8String()
|
|
88
87
|
) {
|
|
89
|
-
this.
|
|
88
|
+
this.setEditedValue(toTinyColorFormat(color, this.colorFormat))
|
|
89
|
+
// The input emits its own input events, the picker doesn't:
|
|
90
|
+
this.onInput()
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
93
|
},
|
|
@@ -107,7 +108,7 @@ export default DitoTypeComponent.register('color', {
|
|
|
107
108
|
if (color.isValid()) {
|
|
108
109
|
const convertedValue = convertColor(value, this.colorFormat)
|
|
109
110
|
if (this.canUpdateValue) {
|
|
110
|
-
this.
|
|
111
|
+
this.setEditedValue(convertedValue)
|
|
111
112
|
} else {
|
|
112
113
|
// Store to change later, once `canUpdateValue` is true again.
|
|
113
114
|
// See `watch` below.
|
|
@@ -161,13 +162,60 @@ export default DitoTypeComponent.register('color', {
|
|
|
161
162
|
},
|
|
162
163
|
|
|
163
164
|
watch: {
|
|
164
|
-
value: 'onChange',
|
|
165
|
-
|
|
166
165
|
canUpdateValue(canUpdateValue) {
|
|
167
166
|
if (canUpdateValue && this.convertedValue !== null) {
|
|
168
|
-
this.
|
|
167
|
+
this.setEditedValue(this.convertedValue)
|
|
169
168
|
this.convertedValue = null
|
|
170
169
|
}
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
showPopup(showPopup) {
|
|
173
|
+
if (!showPopup) {
|
|
174
|
+
this.changeOnceEdited.emitIfDone()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
created() {
|
|
180
|
+
// Emits the change of the value once the editing is done, i.e. once
|
|
181
|
+
// neither the input is focused nor the picker is open.
|
|
182
|
+
this.changeOnceEdited = createChangeOnceEdited({
|
|
183
|
+
isEditing: () => this.focused || this.showPopup,
|
|
184
|
+
emitChange: () => this.onChange()
|
|
185
|
+
})
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
methods: {
|
|
189
|
+
// @override
|
|
190
|
+
getEvents() {
|
|
191
|
+
// The input's native change events don't tell when the editing is done,
|
|
192
|
+
// as the picker edits the value too, see `changeOnceEdited`. They
|
|
193
|
+
// are handled to keep them from emitting the schema's change events.
|
|
194
|
+
const { onFocus, onBlur, onInput } = this
|
|
195
|
+
return { onFocus, onBlur, onInput, onChange: () => {} }
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
// @override
|
|
199
|
+
onBlur() {
|
|
200
|
+
TypeMixin.methods.onBlur.call(this)
|
|
201
|
+
this.changeOnceEdited.emitIfDone()
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
// @override
|
|
205
|
+
clear() {
|
|
206
|
+
// Clearing replaces the edits that are pending, see `hexValue` and
|
|
207
|
+
// `changeOnceEdited`, and emits its own change event.
|
|
208
|
+
this.convertedValue = null
|
|
209
|
+
this.changeOnceEdited.reset()
|
|
210
|
+
TypeMixin.methods.clear.call(this)
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// Sets a value that the user edited, through the input or the picker.
|
|
214
|
+
// Values changed by code don't emit change events.
|
|
215
|
+
setEditedValue(value) {
|
|
216
|
+
this.value = value
|
|
217
|
+
this.changeOnceEdited.markEdited()
|
|
218
|
+
this.changeOnceEdited.emitIfDone()
|
|
171
219
|
}
|
|
172
220
|
}
|
|
173
221
|
})
|
|
@@ -10,24 +10,16 @@
|
|
|
10
10
|
v-bind="attributes"
|
|
11
11
|
)
|
|
12
12
|
template(#prefix)
|
|
13
|
-
|
|
14
|
-
:items="schema.prefix"
|
|
13
|
+
DitoInputAffixes(
|
|
15
14
|
position="prefix"
|
|
16
|
-
|
|
15
|
+
v-bind="inputAffixesProps.prefix"
|
|
17
16
|
absolute
|
|
18
|
-
:disabled="disabled"
|
|
19
|
-
:parentContext="context"
|
|
20
17
|
)
|
|
21
18
|
template(#suffix)
|
|
22
|
-
|
|
23
|
-
:items="schema.suffix"
|
|
19
|
+
DitoInputAffixes(
|
|
24
20
|
position="suffix"
|
|
25
|
-
|
|
21
|
+
v-bind="inputAffixesProps.suffix"
|
|
26
22
|
absolute
|
|
27
|
-
:clearable="showClearButton"
|
|
28
|
-
:disabled="disabled"
|
|
29
|
-
:inlineInfo="inlineInfo"
|
|
30
|
-
:parentContext="context"
|
|
31
23
|
@clear="clear"
|
|
32
24
|
)
|
|
33
25
|
</template>
|
|
@@ -35,7 +27,8 @@
|
|
|
35
27
|
<script>
|
|
36
28
|
import DitoTypeComponent from '../DitoTypeComponent.js'
|
|
37
29
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
38
|
-
import
|
|
30
|
+
import DitoInputAffixes from '../components/DitoInputAffixes.vue'
|
|
31
|
+
import { getInputAffixesProps } from '../utils/affixes.js'
|
|
39
32
|
import {
|
|
40
33
|
DitoDatePicker,
|
|
41
34
|
DitoTimePicker,
|
|
@@ -52,7 +45,7 @@ export default DitoTypeComponent.register(
|
|
|
52
45
|
['date', 'datetime', 'time'],
|
|
53
46
|
// @vue/component
|
|
54
47
|
{
|
|
55
|
-
components: {
|
|
48
|
+
components: { DitoInputAffixes },
|
|
56
49
|
// TODO: This is only here so we get placeholder added. Come up with a
|
|
57
50
|
// better way to support attributes per component (a list of actually
|
|
58
51
|
// supported attributes)
|
|
@@ -60,6 +53,10 @@ export default DitoTypeComponent.register(
|
|
|
60
53
|
textField: true,
|
|
61
54
|
|
|
62
55
|
computed: {
|
|
56
|
+
inputAffixesProps() {
|
|
57
|
+
return getInputAffixesProps(this)
|
|
58
|
+
},
|
|
59
|
+
|
|
63
60
|
dateValue: {
|
|
64
61
|
get() {
|
|
65
62
|
const { value } = this
|
|
@@ -73,14 +73,13 @@
|
|
|
73
73
|
v-else
|
|
74
74
|
)
|
|
75
75
|
td
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
:label="getItemLabel(schema, item, { index, asObject: true })"
|
|
79
|
-
:schema="getItemFormSchema(schema, item, context)"
|
|
76
|
+
DitoSourceItem(
|
|
77
|
+
:schema="schema"
|
|
80
78
|
:dataPath="getDataPath(index)"
|
|
81
79
|
:data="item"
|
|
80
|
+
:index="index"
|
|
82
81
|
:meta="nestedMeta"
|
|
83
|
-
:store="getItemStore(
|
|
82
|
+
:store="getItemStore(item)"
|
|
84
83
|
:disabled="disabled || isLoading"
|
|
85
84
|
:collapsed="collapsed"
|
|
86
85
|
:collapsible="collapsible"
|
|
@@ -91,75 +90,50 @@
|
|
|
91
90
|
:createPath="createPath"
|
|
92
91
|
:insertIndex="creatable && draggable ? index : null"
|
|
93
92
|
@delete="deleteItem(item, index)"
|
|
94
|
-
|
|
95
|
-
component(
|
|
96
|
-
v-else-if="schema.component"
|
|
97
|
-
:is="schema.component"
|
|
98
|
-
:dataPath="getDataPath(index)"
|
|
99
|
-
:data="item"
|
|
100
|
-
:nested="false"
|
|
101
|
-
)
|
|
102
|
-
span(
|
|
103
|
-
v-else-if="render"
|
|
104
|
-
v-html="render(getContext(item, index))"
|
|
105
|
-
)
|
|
106
|
-
span(
|
|
107
|
-
v-else
|
|
108
|
-
v-html="getItemLabel(schema, item, { index })"
|
|
93
|
+
@move="delta => moveItem(item, delta)"
|
|
109
94
|
)
|
|
110
95
|
td.dito-table__buttons(
|
|
111
96
|
v-if="hasCellEditButtons"
|
|
112
97
|
)
|
|
113
98
|
DitoEditButtons(
|
|
114
99
|
nested
|
|
115
|
-
:schema="
|
|
100
|
+
:schema="schema"
|
|
101
|
+
:formSchema="getItemFormSchema(schema, item, context)"
|
|
116
102
|
:dataPath="getDataPath(index)"
|
|
117
103
|
:data="item"
|
|
118
104
|
:meta="nestedMeta"
|
|
119
|
-
:store="getItemStore(
|
|
105
|
+
:store="getItemStore(item)"
|
|
120
106
|
:disabled="disabled || isLoading"
|
|
121
107
|
:deletable="deletable"
|
|
122
108
|
:draggable="draggable"
|
|
123
109
|
:editable="editable"
|
|
124
110
|
:editPath="getEditPath(item, index)"
|
|
125
111
|
@delete="deleteItem(item, index)"
|
|
112
|
+
@move="delta => moveItem(item, delta)"
|
|
126
113
|
)
|
|
127
|
-
//- Render
|
|
114
|
+
//- Render the list buttons inside the table when not in a single
|
|
115
|
+
//- component view, with the item that holds the list as their data:
|
|
128
116
|
tfoot(
|
|
129
117
|
v-if="hasListButtons && !single"
|
|
130
118
|
)
|
|
131
119
|
tr
|
|
132
120
|
td.dito-table__buttons(:colspan="numColumns")
|
|
133
121
|
DitoEditButtons(
|
|
134
|
-
|
|
135
|
-
:schema="schema"
|
|
136
|
-
:dataPath="dataPath"
|
|
122
|
+
v-bind="listButtonsAttributes"
|
|
137
123
|
:data="data"
|
|
138
|
-
:meta="meta"
|
|
139
|
-
:store="store"
|
|
140
|
-
:nested="nested"
|
|
141
|
-
:disabled="disabled || isLoading"
|
|
142
|
-
:creatable="creatable"
|
|
143
|
-
:createPath="createPath"
|
|
144
124
|
)
|
|
145
|
-
//-
|
|
125
|
+
//- ...and outside, sticky to the bottom, when in a single component view,
|
|
126
|
+
//- with the list data as their data, e.g. for buttons that store its order:
|
|
146
127
|
DitoEditButtons.dito-buttons--large.dito-buttons--main.dito-buttons--sticky(
|
|
147
128
|
v-if="hasListButtons && single"
|
|
148
|
-
|
|
149
|
-
:schema="schema"
|
|
150
|
-
:dataPath="dataPath"
|
|
129
|
+
v-bind="listButtonsAttributes"
|
|
151
130
|
:data="listData"
|
|
152
|
-
:meta="meta"
|
|
153
|
-
:store="store"
|
|
154
|
-
:disabled="disabled || isLoading"
|
|
155
|
-
:creatable="creatable"
|
|
156
|
-
:createPath="createPath"
|
|
157
131
|
)
|
|
158
132
|
</template>
|
|
159
133
|
|
|
160
134
|
<script>
|
|
161
135
|
import DitoTypeComponent from '../DitoTypeComponent.js'
|
|
162
|
-
import
|
|
136
|
+
import DitoSourceItem from '../components/DitoSourceItem.vue'
|
|
163
137
|
import SourceMixin from '../mixins/SourceMixin.js'
|
|
164
138
|
import SortableMixin from '../mixins/SortableMixin.js'
|
|
165
139
|
import {
|
|
@@ -167,14 +141,16 @@ import {
|
|
|
167
141
|
resolveSchemaComponents
|
|
168
142
|
} from '../utils/schema/setup.js'
|
|
169
143
|
import { getViewEditPath } from '../utils/schema/lookup.js'
|
|
170
|
-
import { createFiltersPanel } from '../utils/filter.js'
|
|
144
|
+
import { createFiltersPanel, getFiltersDataErrors } from '../utils/filter.js'
|
|
171
145
|
import { appendDataPath } from '../utils/data.js'
|
|
172
|
-
import {
|
|
146
|
+
import { getListWithMovedItem } from '../utils/list.js'
|
|
147
|
+
import { hyphenate } from '@ditojs/utils'
|
|
173
148
|
import { computed } from 'vue'
|
|
174
149
|
|
|
175
150
|
// @vue/component
|
|
176
151
|
export default DitoTypeComponent.register('list', {
|
|
177
152
|
mixins: [SourceMixin, SortableMixin],
|
|
153
|
+
components: { DitoSourceItem },
|
|
178
154
|
|
|
179
155
|
getSourceType(type) {
|
|
180
156
|
// No need for transformation here. See TypeTreeList for details.
|
|
@@ -190,19 +166,17 @@ export default DitoTypeComponent.register('list', {
|
|
|
190
166
|
api,
|
|
191
167
|
filters,
|
|
192
168
|
dataPath,
|
|
193
|
-
// Pass a computed value to get / set the query, see
|
|
169
|
+
// Pass a computed value to get / set the query, see
|
|
170
|
+
// `createFiltersPanel()`.
|
|
194
171
|
computed({
|
|
195
172
|
get() {
|
|
196
173
|
return component.query
|
|
197
174
|
},
|
|
198
175
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
component.query = query
|
|
204
|
-
component.loadData(false)
|
|
205
|
-
}
|
|
176
|
+
// The panel clears the page, but it's only reset when the filters
|
|
177
|
+
// change the query, as the filtered list then has other pages.
|
|
178
|
+
set({ page, ...query }) {
|
|
179
|
+
component.listQuery.update(query, { resetPage: true })
|
|
206
180
|
}
|
|
207
181
|
})
|
|
208
182
|
)
|
|
@@ -218,6 +192,20 @@ export default DitoTypeComponent.register('list', {
|
|
|
218
192
|
return !!(this.buttonSchemas || this.creatable)
|
|
219
193
|
},
|
|
220
194
|
|
|
195
|
+
listButtonsAttributes() {
|
|
196
|
+
return {
|
|
197
|
+
buttons: this.buttonSchemas,
|
|
198
|
+
schema: this.schema,
|
|
199
|
+
dataPath: this.dataPath,
|
|
200
|
+
meta: this.meta,
|
|
201
|
+
store: this.store,
|
|
202
|
+
nested: this.nested,
|
|
203
|
+
disabled: this.disabled || this.isLoading,
|
|
204
|
+
creatable: this.creatable,
|
|
205
|
+
createPath: this.createPath
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
221
209
|
hasEditButtons() {
|
|
222
210
|
const { listData } = this
|
|
223
211
|
return (
|
|
@@ -265,24 +253,24 @@ export default DitoTypeComponent.register('list', {
|
|
|
265
253
|
return null
|
|
266
254
|
},
|
|
267
255
|
|
|
268
|
-
|
|
269
|
-
|
|
256
|
+
// Moves the item by `delta` positions, see `DitoDragHandle`.
|
|
257
|
+
moveItem(item, delta) {
|
|
258
|
+
const listData = getListWithMovedItem(this.listData, item, delta)
|
|
259
|
+
if (listData) {
|
|
260
|
+
this.listData = listData
|
|
261
|
+
this.onChange()
|
|
262
|
+
}
|
|
270
263
|
},
|
|
271
264
|
|
|
272
|
-
|
|
273
|
-
return
|
|
274
|
-
data: item,
|
|
275
|
-
value: item,
|
|
276
|
-
index,
|
|
277
|
-
dataPath: this.getDataPath(index)
|
|
278
|
-
})
|
|
265
|
+
getCellClass(column) {
|
|
266
|
+
return `dito-cell--${hyphenate(column.name)}`
|
|
279
267
|
},
|
|
280
268
|
|
|
281
269
|
onFilterErrors(errors) {
|
|
282
270
|
const filtersDataPath = appendDataPath(this.dataPath, '$filters')
|
|
283
271
|
const panel = this.schemaComponent.getPanelByDataPath(filtersDataPath)
|
|
284
272
|
if (panel) {
|
|
285
|
-
panel.showValidationErrors(errors, true)
|
|
273
|
+
panel.showValidationErrors(getFiltersDataErrors(errors), true)
|
|
286
274
|
return true
|
|
287
275
|
}
|
|
288
276
|
}
|