@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
package/src/mixins/DitoMixin.js
CHANGED
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
getValueAtDataPath, labelize, hyphenate, format
|
|
4
4
|
} from '@ditojs/utils'
|
|
5
5
|
import appState from '../appState.js'
|
|
6
|
-
import DitoComponent from '../DitoComponent.js'
|
|
7
6
|
import DitoContext from '../DitoContext.js'
|
|
8
7
|
import EmitterMixin from './EmitterMixin.js'
|
|
9
8
|
import { isMatchingType, convertType } from '../utils/type.js'
|
|
10
9
|
import { getResource, getMemberResource } from '../utils/resource.js'
|
|
10
|
+
import { reactive } from 'vue'
|
|
11
11
|
|
|
12
12
|
// @vue/component
|
|
13
13
|
export default {
|
|
@@ -18,6 +18,7 @@ export default {
|
|
|
18
18
|
'$verbs',
|
|
19
19
|
'$views',
|
|
20
20
|
'$isPopulated',
|
|
21
|
+
'$parentComponent',
|
|
21
22
|
'$schemaComponent',
|
|
22
23
|
'$routeComponent',
|
|
23
24
|
'$dataComponent',
|
|
@@ -30,8 +31,13 @@ export default {
|
|
|
30
31
|
|
|
31
32
|
provide() {
|
|
32
33
|
return this.providesData
|
|
33
|
-
? {
|
|
34
|
-
|
|
34
|
+
? {
|
|
35
|
+
$parentComponent: () => this,
|
|
36
|
+
$dataComponent: () => this
|
|
37
|
+
}
|
|
38
|
+
: {
|
|
39
|
+
$parentComponent: () => this
|
|
40
|
+
}
|
|
35
41
|
},
|
|
36
42
|
|
|
37
43
|
data() {
|
|
@@ -42,6 +48,11 @@ export default {
|
|
|
42
48
|
},
|
|
43
49
|
|
|
44
50
|
computed: {
|
|
51
|
+
providesData() {
|
|
52
|
+
// NOTE: This is overridden in ResourceMixin, used by lists.
|
|
53
|
+
return false
|
|
54
|
+
},
|
|
55
|
+
|
|
45
56
|
sourceSchema() {
|
|
46
57
|
return this.meta?.schema
|
|
47
58
|
},
|
|
@@ -74,18 +85,20 @@ export default {
|
|
|
74
85
|
},
|
|
75
86
|
|
|
76
87
|
rootComponent() {
|
|
77
|
-
return this.$root.$
|
|
88
|
+
return this.$root.$refs.root
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// Use computed properties as links to injects, so DitoSchema can
|
|
92
|
+
// override the property and return `this` instead of the parent.
|
|
93
|
+
parentComponent() {
|
|
94
|
+
return this.$parentComponent()
|
|
78
95
|
},
|
|
79
96
|
|
|
80
97
|
schemaComponent() {
|
|
81
|
-
// Use computed properties as links to injects, so DitoSchema can
|
|
82
|
-
// override the property and return `this` instead of the parent.
|
|
83
98
|
return this.$schemaComponent()
|
|
84
99
|
},
|
|
85
100
|
|
|
86
101
|
routeComponent() {
|
|
87
|
-
// Use computed properties as links to injects, so RouteMixin can
|
|
88
|
-
// override the property and return `this` instead of the parent.
|
|
89
102
|
return this.$routeComponent()
|
|
90
103
|
},
|
|
91
104
|
|
|
@@ -127,15 +140,15 @@ export default {
|
|
|
127
140
|
},
|
|
128
141
|
|
|
129
142
|
parentSchemaComponent() {
|
|
130
|
-
return this.schemaComponent
|
|
143
|
+
return this.schemaComponent?.parentComponent.schemaComponent
|
|
131
144
|
},
|
|
132
145
|
|
|
133
146
|
parentRouteComponent() {
|
|
134
|
-
return this.routeComponent
|
|
147
|
+
return this.routeComponent?.parentComponent.routeComponent
|
|
135
148
|
},
|
|
136
149
|
|
|
137
150
|
parentFormComponent() {
|
|
138
|
-
return this.formComponent
|
|
151
|
+
return this.formComponent?.parentComponent.formComponent
|
|
139
152
|
},
|
|
140
153
|
|
|
141
154
|
// Returns the data of the first route component in the chain of parents
|
|
@@ -146,7 +159,10 @@ export default {
|
|
|
146
159
|
},
|
|
147
160
|
|
|
148
161
|
beforeCreate() {
|
|
149
|
-
|
|
162
|
+
const uid = nextUid++
|
|
163
|
+
Object.defineProperty(this, '$uid', {
|
|
164
|
+
get() { return uid }
|
|
165
|
+
})
|
|
150
166
|
},
|
|
151
167
|
|
|
152
168
|
methods: {
|
|
@@ -163,11 +179,12 @@ export default {
|
|
|
163
179
|
},
|
|
164
180
|
|
|
165
181
|
setStore(key, value) {
|
|
166
|
-
|
|
182
|
+
this.store[key] = value
|
|
183
|
+
return value
|
|
167
184
|
},
|
|
168
185
|
|
|
169
186
|
getChildStore(key) {
|
|
170
|
-
return this.getStore(key) || this.setStore(key, {})
|
|
187
|
+
return this.getStore(key) || this.setStore(key, reactive({}))
|
|
171
188
|
},
|
|
172
189
|
|
|
173
190
|
getSchemaValue(
|
|
@@ -241,6 +258,7 @@ export default {
|
|
|
241
258
|
}
|
|
242
259
|
},
|
|
243
260
|
|
|
261
|
+
// TODO: Rename *Link() to *Route().
|
|
244
262
|
getQueryLink(query) {
|
|
245
263
|
return {
|
|
246
264
|
query,
|
|
@@ -257,30 +275,6 @@ export default {
|
|
|
257
275
|
})
|
|
258
276
|
},
|
|
259
277
|
|
|
260
|
-
showDialog({
|
|
261
|
-
components,
|
|
262
|
-
buttons,
|
|
263
|
-
data,
|
|
264
|
-
settings = {
|
|
265
|
-
width: 480,
|
|
266
|
-
height: 'auto',
|
|
267
|
-
clickToClose: false
|
|
268
|
-
}
|
|
269
|
-
}) {
|
|
270
|
-
// Shows a dito-dialog component through vue-js-modal, and wraps it in a
|
|
271
|
-
// promise so that the buttons in the dialog can use `dialog.resolve()`
|
|
272
|
-
// and `dialog.reject()` to close the modal dialog and resolve / reject
|
|
273
|
-
// the promise at once.
|
|
274
|
-
return new Promise((resolve, reject) => {
|
|
275
|
-
this.$modal.show(DitoComponent.component('dito-dialog'), {
|
|
276
|
-
components,
|
|
277
|
-
buttons,
|
|
278
|
-
data,
|
|
279
|
-
promise: { resolve, reject }
|
|
280
|
-
}, settings)
|
|
281
|
-
})
|
|
282
|
-
},
|
|
283
|
-
|
|
284
278
|
getResourcePath(resource) {
|
|
285
279
|
resource = getResource(resource)
|
|
286
280
|
// Resources without a parent inherit the one from `dataComponent`
|
|
@@ -315,6 +309,15 @@ export default {
|
|
|
315
309
|
return response
|
|
316
310
|
},
|
|
317
311
|
|
|
312
|
+
showDialog({ components, buttons, data, settings }) {
|
|
313
|
+
return this.rootComponent.showDialog({
|
|
314
|
+
components,
|
|
315
|
+
buttons,
|
|
316
|
+
data,
|
|
317
|
+
settings
|
|
318
|
+
})
|
|
319
|
+
},
|
|
320
|
+
|
|
318
321
|
request({ cache, ...options }) {
|
|
319
322
|
// Allow caching of loaded data on two levels:
|
|
320
323
|
// - 'global': cache globally, for the entire admin session
|
|
@@ -367,13 +370,7 @@ export default {
|
|
|
367
370
|
},
|
|
368
371
|
|
|
369
372
|
async navigate(location) {
|
|
370
|
-
return
|
|
371
|
-
this.$router.push(
|
|
372
|
-
location,
|
|
373
|
-
() => resolve(true),
|
|
374
|
-
() => resolve(false)
|
|
375
|
-
)
|
|
376
|
-
})
|
|
373
|
+
return this.$router.push(location)
|
|
377
374
|
},
|
|
378
375
|
|
|
379
376
|
download(options = {}) {
|
|
@@ -506,4 +503,4 @@ export default {
|
|
|
506
503
|
}
|
|
507
504
|
}
|
|
508
505
|
|
|
509
|
-
let
|
|
506
|
+
let nextUid = 0
|
package/src/mixins/DomMixin.js
CHANGED
|
@@ -4,14 +4,14 @@ import { isArray, isPlainObject } from '@ditojs/utils'
|
|
|
4
4
|
export default {
|
|
5
5
|
data() {
|
|
6
6
|
return {
|
|
7
|
-
|
|
7
|
+
listeners: null
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
10
|
|
|
11
11
|
methods: {
|
|
12
|
-
// Async
|
|
13
|
-
//
|
|
14
|
-
//
|
|
12
|
+
// Async on() and $off() methods that keep track of the events added /
|
|
13
|
+
// removed, and provide a hasListeners() method that checks if the component
|
|
14
|
+
// has listeners for a given event.
|
|
15
15
|
|
|
16
16
|
// Also adds proper handling of async events, including a async emit() that
|
|
17
17
|
// deals with proper event queueing.
|
|
@@ -25,8 +25,8 @@ export default {
|
|
|
25
25
|
this.on(key, event[key])
|
|
26
26
|
}
|
|
27
27
|
} else {
|
|
28
|
-
const
|
|
29
|
-
const { callbacks } =
|
|
28
|
+
const listeners = (this.listeners ||= Object.create(null))
|
|
29
|
+
const { callbacks } = (listeners[event] ||= {
|
|
30
30
|
callbacks: [],
|
|
31
31
|
queue: []
|
|
32
32
|
})
|
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
off(event, callback) {
|
|
48
48
|
if (!arguments.length) {
|
|
49
49
|
// Remove all events
|
|
50
|
-
delete this
|
|
50
|
+
delete this.listeners
|
|
51
51
|
} else if (isArray(event)) {
|
|
52
52
|
for (const ev of event) {
|
|
53
53
|
this.off(ev, callback)
|
|
@@ -58,11 +58,11 @@ export default {
|
|
|
58
58
|
}
|
|
59
59
|
} else {
|
|
60
60
|
// Remove specific event
|
|
61
|
-
const entry = this
|
|
61
|
+
const entry = this.listeners?.[event]
|
|
62
62
|
if (entry) {
|
|
63
63
|
if (!callback) {
|
|
64
64
|
// Remove all handlers for this event
|
|
65
|
-
delete this
|
|
65
|
+
delete this.listeners[event]
|
|
66
66
|
} else {
|
|
67
67
|
// Remove a specific handler: find the index in callbacks
|
|
68
68
|
const { callbacks } = entry
|
|
@@ -81,7 +81,7 @@ export default {
|
|
|
81
81
|
|
|
82
82
|
emit(event, ...args) {
|
|
83
83
|
// Only queue event if there actually are listeners for it.
|
|
84
|
-
const entry = this
|
|
84
|
+
const entry = this.listeners?.[event]
|
|
85
85
|
if (entry) {
|
|
86
86
|
const { queue, callbacks } = entry
|
|
87
87
|
return new Promise(resolve => {
|
|
@@ -129,7 +129,7 @@ export default {
|
|
|
129
129
|
}
|
|
130
130
|
return event.length > 0
|
|
131
131
|
} else {
|
|
132
|
-
return !!this
|
|
132
|
+
return !!this.listeners?.[event]
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
135
|
|
package/src/mixins/RouteMixin.js
CHANGED
|
@@ -12,11 +12,11 @@ export default {
|
|
|
12
12
|
},
|
|
13
13
|
|
|
14
14
|
beforeRouteUpdate(to, from, next) {
|
|
15
|
-
this
|
|
15
|
+
this?.beforeRouteChange(to, from, next)
|
|
16
16
|
},
|
|
17
17
|
|
|
18
18
|
beforeRouteLeave(to, from, next) {
|
|
19
|
-
this
|
|
19
|
+
this?.beforeRouteChange(to, from, next)
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
data() {
|
|
@@ -36,11 +36,17 @@ export default {
|
|
|
36
36
|
return this
|
|
37
37
|
},
|
|
38
38
|
|
|
39
|
+
routeLevel() {
|
|
40
|
+
let level = 0
|
|
41
|
+
let routeComponent = this
|
|
42
|
+
while ((routeComponent = routeComponent.parentComponent.routeComponent)) {
|
|
43
|
+
level++
|
|
44
|
+
}
|
|
45
|
+
return level
|
|
46
|
+
},
|
|
47
|
+
|
|
39
48
|
routeRecord() {
|
|
40
|
-
|
|
41
|
-
// Retrieve the route-record to which this component was mapped to:
|
|
42
|
-
// https://github.com/vuejs/vue-router/issues/1338#issuecomment-296381459
|
|
43
|
-
return this.$route.matched[this.$vnode.data.routerViewDepth]
|
|
49
|
+
return this.$route.matched[this.routeLevel]
|
|
44
50
|
},
|
|
45
51
|
|
|
46
52
|
isLastRoute() {
|
|
@@ -66,8 +72,12 @@ export default {
|
|
|
66
72
|
return this.meta.nested
|
|
67
73
|
},
|
|
68
74
|
|
|
75
|
+
isView() {
|
|
76
|
+
return false
|
|
77
|
+
},
|
|
78
|
+
|
|
69
79
|
meta() {
|
|
70
|
-
return this.routeRecord
|
|
80
|
+
return this.routeRecord.meta
|
|
71
81
|
},
|
|
72
82
|
|
|
73
83
|
path() {
|
|
@@ -95,7 +105,7 @@ export default {
|
|
|
95
105
|
},
|
|
96
106
|
|
|
97
107
|
// @overridable, see DitoForm
|
|
98
|
-
|
|
108
|
+
isMutating() {
|
|
99
109
|
return false
|
|
100
110
|
}
|
|
101
111
|
},
|
|
@@ -107,7 +117,7 @@ export default {
|
|
|
107
117
|
this.appState.routeComponents.push(this)
|
|
108
118
|
},
|
|
109
119
|
|
|
110
|
-
|
|
120
|
+
unmounted() {
|
|
111
121
|
const { routeComponents } = this.appState
|
|
112
122
|
routeComponents.splice(routeComponents.indexOf(this), 1)
|
|
113
123
|
},
|
|
@@ -131,7 +141,7 @@ export default {
|
|
|
131
141
|
)
|
|
132
142
|
)
|
|
133
143
|
if (isClosing) {
|
|
134
|
-
if (this.
|
|
144
|
+
if (this.isMutating) {
|
|
135
145
|
// For active directly mutating (nested) forms that were not validated
|
|
136
146
|
// yet, validate them once. If the user then still wants to leave
|
|
137
147
|
// them, they can click close / navigate away again.
|
|
@@ -19,8 +19,8 @@ export default {
|
|
|
19
19
|
},
|
|
20
20
|
|
|
21
21
|
methods: {
|
|
22
|
-
// This method is called by `DitoSchema.created()/
|
|
23
|
-
//
|
|
22
|
+
// This method is called by `DitoSchema.created()/unmounted()` on its
|
|
23
|
+
// `$schemaParentComponent`, if the parent uses the `SchemaParentMixin`:
|
|
24
24
|
_registerSchemaComponent(schemaComponent, add) {
|
|
25
25
|
const { schemaComponents } = this
|
|
26
26
|
if (add) {
|
|
@@ -313,16 +313,16 @@ export default {
|
|
|
313
313
|
|
|
314
314
|
wrappedPrimitives: {
|
|
315
315
|
deep: true,
|
|
316
|
-
handler(
|
|
316
|
+
handler(to, from) {
|
|
317
317
|
const { wrapPrimitives } = this
|
|
318
318
|
// Skip the initial setting of wrappedPrimitives array
|
|
319
|
-
if (wrapPrimitives &&
|
|
319
|
+
if (wrapPrimitives && from !== null) {
|
|
320
320
|
// Whenever the wrappedPrimitives change, map their values back to
|
|
321
321
|
// the array of primitives, in a primitive way :)
|
|
322
322
|
// But set `unwrappingPrimitives = true`, so the `listData` computed
|
|
323
323
|
// property knows about it, which sets it to `false` again.
|
|
324
324
|
this.unwrappingPrimitives = true
|
|
325
|
-
this.value =
|
|
325
|
+
this.value = to.map(object => object[wrapPrimitives])
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
328
|
}
|
|
@@ -509,15 +509,13 @@ export default {
|
|
|
509
509
|
callOnComplete()
|
|
510
510
|
} else {
|
|
511
511
|
// Navigate to the component's path, then call `onComplete()`_:
|
|
512
|
-
this.$router.push(
|
|
513
|
-
|
|
512
|
+
this.$router.push({ path })
|
|
513
|
+
.catch(reject)
|
|
514
514
|
// Wait for the last route component to be mounted in the next
|
|
515
515
|
// tick before calling `onComplete()`
|
|
516
|
-
() => {
|
|
516
|
+
.then(() => {
|
|
517
517
|
this.$nextTick(callOnComplete)
|
|
518
|
-
}
|
|
519
|
-
reject
|
|
520
|
-
)
|
|
518
|
+
})
|
|
521
519
|
}
|
|
522
520
|
}
|
|
523
521
|
// Keep removing the last part until we find a match.
|
package/src/mixins/TypeMixin.js
CHANGED
|
@@ -3,7 +3,7 @@ import ValidationMixin from './ValidationMixin.js'
|
|
|
3
3
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
4
4
|
import { computeValue } from '../utils/schema.js'
|
|
5
5
|
import { getItem, getParentItem } from '../utils/data.js'
|
|
6
|
-
import { isString, asArray } from '@ditojs/utils'
|
|
6
|
+
import { isString, asArray, camelize } from '@ditojs/utils'
|
|
7
7
|
|
|
8
8
|
// @vue/component
|
|
9
9
|
export default {
|
|
@@ -38,10 +38,6 @@ export default {
|
|
|
38
38
|
return this.schema.type
|
|
39
39
|
},
|
|
40
40
|
|
|
41
|
-
component() {
|
|
42
|
-
return this.resolveTypeComponent(this.schema.component)
|
|
43
|
-
},
|
|
44
|
-
|
|
45
41
|
context() {
|
|
46
42
|
return new DitoContext(this, { nested: this.nested })
|
|
47
43
|
},
|
|
@@ -70,7 +66,8 @@ export default {
|
|
|
70
66
|
this.parsedValue = parse
|
|
71
67
|
? parse.call(this, new DitoContext(this, { value }))
|
|
72
68
|
: value
|
|
73
|
-
|
|
69
|
+
// eslint-disable-next-line vue/no-mutating-props
|
|
70
|
+
this.data[this.name] = this.parsedValue
|
|
74
71
|
}
|
|
75
72
|
},
|
|
76
73
|
|
|
@@ -119,7 +116,7 @@ export default {
|
|
|
119
116
|
visible: getSchemaAccessor('visible', {
|
|
120
117
|
type: Boolean,
|
|
121
118
|
default() {
|
|
122
|
-
return this.
|
|
119
|
+
return this.$options.defaultVisible
|
|
123
120
|
}
|
|
124
121
|
}),
|
|
125
122
|
|
|
@@ -178,20 +175,26 @@ export default {
|
|
|
178
175
|
attributes.autocomplete = this.autocomplete
|
|
179
176
|
}
|
|
180
177
|
}
|
|
181
|
-
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
...Object.fromEntries(
|
|
181
|
+
Object.entries(this.$attrs).filter(([key]) => key.startsWith('on'))
|
|
182
|
+
),
|
|
183
|
+
...this.events,
|
|
184
|
+
...attributes
|
|
185
|
+
}
|
|
182
186
|
},
|
|
183
187
|
|
|
184
|
-
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
188
|
+
events() {
|
|
189
|
+
const events = this.getEvents()
|
|
190
|
+
// Register callbacks for all provides non-recognized events,
|
|
191
|
+
// assuming they are native events.
|
|
192
|
+
// TODO: Move to vue3-style `on[A-Z]` event handlers naming that aren't
|
|
193
|
+
// namespaced in `schema.events` once the transition is complete.
|
|
194
|
+
for (const event of Object.keys(this.schema.events || {})) {
|
|
195
|
+
events[`on${camelize(event, true)}`] ||= () => this.emitEvent(event)
|
|
193
196
|
}
|
|
194
|
-
return
|
|
197
|
+
return events
|
|
195
198
|
},
|
|
196
199
|
|
|
197
200
|
validations() {
|
|
@@ -210,11 +213,6 @@ export default {
|
|
|
210
213
|
return validations
|
|
211
214
|
},
|
|
212
215
|
|
|
213
|
-
providesData() {
|
|
214
|
-
// NOTE: This is overridden in ResourceMixin, used by lists.
|
|
215
|
-
return false
|
|
216
|
-
},
|
|
217
|
-
|
|
218
216
|
showClearButton() {
|
|
219
217
|
return this.clearable && this.value != null
|
|
220
218
|
}
|
|
@@ -225,7 +223,7 @@ export default {
|
|
|
225
223
|
this.setupSchemaFields()
|
|
226
224
|
},
|
|
227
225
|
|
|
228
|
-
|
|
226
|
+
beforeUnmount() {
|
|
229
227
|
this._register(false)
|
|
230
228
|
},
|
|
231
229
|
|
|
@@ -234,20 +232,13 @@ export default {
|
|
|
234
232
|
// Prevent unnested type components from overriding parent data paths
|
|
235
233
|
if (this.nested) {
|
|
236
234
|
this.schemaComponent._registerComponent(this, add)
|
|
237
|
-
// Install / remove the field events to watch of changes and handle
|
|
238
|
-
// validation flags. `events` is provided by `ValidationMixin.events()`
|
|
239
|
-
this[add ? 'on' : 'off'](this.events)
|
|
240
235
|
}
|
|
241
236
|
},
|
|
242
237
|
|
|
243
238
|
// @overridable
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
blur: this.onBlur,
|
|
248
|
-
input: this.onInput,
|
|
249
|
-
change: this.onChange
|
|
250
|
-
}
|
|
239
|
+
getEvents() {
|
|
240
|
+
const { onFocus, onBlur, onInput, onChange } = this
|
|
241
|
+
return { onFocus, onBlur, onInput, onChange }
|
|
251
242
|
},
|
|
252
243
|
|
|
253
244
|
// @overridable
|
|
@@ -284,19 +275,23 @@ export default {
|
|
|
284
275
|
|
|
285
276
|
onFocus() {
|
|
286
277
|
this.focused = true
|
|
278
|
+
this.markTouched()
|
|
287
279
|
this.emitEvent('focus')
|
|
288
280
|
},
|
|
289
281
|
|
|
290
282
|
onBlur() {
|
|
291
283
|
this.focused = false
|
|
284
|
+
this.validate()
|
|
292
285
|
this.emitEvent('blur')
|
|
293
286
|
},
|
|
294
287
|
|
|
295
288
|
onInput() {
|
|
289
|
+
this.markDirty()
|
|
296
290
|
this.emitEvent('input')
|
|
297
291
|
},
|
|
298
292
|
|
|
299
293
|
onChange() {
|
|
294
|
+
this.markDirty()
|
|
300
295
|
this.emitEvent('change', {
|
|
301
296
|
context: this.parsedValue !== undefined
|
|
302
297
|
? { value: this.parsedValue }
|
|
@@ -13,25 +13,6 @@ export default {
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
|
|
16
|
-
computed: {
|
|
17
|
-
events() {
|
|
18
|
-
return {
|
|
19
|
-
focus: () => {
|
|
20
|
-
this.isTouched = true
|
|
21
|
-
},
|
|
22
|
-
blur: () => {
|
|
23
|
-
this.validate()
|
|
24
|
-
},
|
|
25
|
-
change: () => {
|
|
26
|
-
this.markDirty()
|
|
27
|
-
},
|
|
28
|
-
input: () => {
|
|
29
|
-
this.markDirty()
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
|
|
35
16
|
methods: {
|
|
36
17
|
resetValidation() {
|
|
37
18
|
this.isTouched = false
|
|
@@ -74,6 +55,10 @@ export default {
|
|
|
74
55
|
return this.validate(false)
|
|
75
56
|
},
|
|
76
57
|
|
|
58
|
+
markTouched() {
|
|
59
|
+
this.isTouched = true
|
|
60
|
+
},
|
|
61
|
+
|
|
77
62
|
markDirty() {
|
|
78
63
|
this.isDirty = true
|
|
79
64
|
this.isValidated = false
|
package/src/types/TypeButton.vue
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
) {{ text }}
|
|
2
|
+
button.dito-button(
|
|
3
|
+
ref="element"
|
|
4
|
+
:id="dataPath"
|
|
5
|
+
:type="type"
|
|
6
|
+
:title="text"
|
|
7
|
+
:class="`dito-button-${verb}`"
|
|
8
|
+
v-bind="attributes"
|
|
9
|
+
) {{ text }}
|
|
11
10
|
</template>
|
|
12
11
|
|
|
13
12
|
<script>
|
|
@@ -47,12 +46,9 @@ export default TypeComponent.register([
|
|
|
47
46
|
|
|
48
47
|
methods: {
|
|
49
48
|
// @override
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
blur: this.onBlur,
|
|
54
|
-
click: this.onClick
|
|
55
|
-
}
|
|
49
|
+
getEvents() {
|
|
50
|
+
const { onFocus, onBlur, onClick } = this
|
|
51
|
+
return { onFocus, onBlur, onClick }
|
|
56
52
|
},
|
|
57
53
|
|
|
58
54
|
async submit(options) {
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
2
|
+
input.dito-checkbox(
|
|
3
|
+
ref="element"
|
|
4
|
+
:id="dataPath"
|
|
5
|
+
type="checkbox"
|
|
6
|
+
v-model="value"
|
|
7
|
+
v-bind="attributes"
|
|
8
|
+
)
|
|
10
9
|
</template>
|
|
11
10
|
|
|
12
11
|
<style lang="sass">
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
| {{ getLabelForOption(option) }}
|
|
2
|
+
ul.dito-checkboxes(
|
|
3
|
+
:id="dataPath"
|
|
4
|
+
:class="`dito-layout-${schema.layout || 'vertical'}`"
|
|
5
|
+
)
|
|
6
|
+
li(v-for="option in options")
|
|
7
|
+
label
|
|
8
|
+
input.dito-checkbox(
|
|
9
|
+
ref="element"
|
|
10
|
+
type="checkbox"
|
|
11
|
+
:value="getValueForOption(option)"
|
|
12
|
+
v-model="selectedOptions"
|
|
13
|
+
v-bind="attributes"
|
|
14
|
+
)
|
|
15
|
+
| {{ getLabelForOption(option) }}
|
|
17
16
|
</template>
|
|
18
17
|
|
|
19
18
|
<style lang="sass">
|
package/src/types/TypeCode.vue
CHANGED