@ditojs/admin 2.23.1 → 2.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dito-admin.es.js +805 -793
- package/dist/dito-admin.umd.js +5 -5
- package/package.json +7 -7
- package/src/components/DitoForm.vue +3 -1
- package/src/components/DitoNotifications.vue +7 -2
- package/src/components/DitoRoot.vue +8 -8
- package/src/components/DitoSchema.vue +13 -15
- package/src/mixins/DataMixin.js +15 -6
- package/src/mixins/ResourceMixin.js +2 -1
- package/src/mixins/SourceMixin.js +12 -9
- package/src/types/DitoTypeUpload.vue +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.24.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
|
|
6
6
|
"repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.
|
|
37
|
-
"@ditojs/utils": "^2.
|
|
36
|
+
"@ditojs/ui": "^2.24.1",
|
|
37
|
+
"@ditojs/utils": "^2.24.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^3.1.4",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
40
|
"@tiptap/core": "^2.2.2",
|
|
@@ -67,23 +67,23 @@
|
|
|
67
67
|
"sortablejs": "^1.15.2",
|
|
68
68
|
"tinycolor2": "^1.6.0",
|
|
69
69
|
"tippy.js": "^6.3.7",
|
|
70
|
-
"type-fest": "^4.
|
|
70
|
+
"type-fest": "^4.10.2",
|
|
71
71
|
"vue": "3.4.10",
|
|
72
72
|
"vue-multiselect": "^3.0.0-beta.3",
|
|
73
73
|
"vue-router": "^4.2.5",
|
|
74
74
|
"vue-upload-component": "^3.1.8"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@ditojs/build": "^2.
|
|
77
|
+
"@ditojs/build": "^2.24.0",
|
|
78
78
|
"@vitejs/plugin-vue": "^5.0.3",
|
|
79
79
|
"@vue/compiler-sfc": "3.4.10",
|
|
80
80
|
"pug": "^3.0.2",
|
|
81
81
|
"sass": "1.70.0",
|
|
82
82
|
"typescript": "^5.3.3",
|
|
83
|
-
"vite": "^5.1.
|
|
83
|
+
"vite": "^5.1.1"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "47db476cbe26eb80eea031cb07133ec76b2d10b1",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -431,10 +431,11 @@ export default DitoComponent.component('DitoForm', {
|
|
|
431
431
|
]
|
|
432
432
|
})
|
|
433
433
|
},
|
|
434
|
-
notifyError:
|
|
434
|
+
notifyError: error => {
|
|
435
435
|
const verb = getVerb(true)
|
|
436
436
|
this.notify({
|
|
437
437
|
type: 'error',
|
|
438
|
+
error,
|
|
438
439
|
title: 'Request Error',
|
|
439
440
|
text: `Unable to ${verb} ${this.itemLabel}.`
|
|
440
441
|
})
|
|
@@ -460,6 +461,7 @@ export default DitoComponent.component('DitoForm', {
|
|
|
460
461
|
const verb = getVerb(true)
|
|
461
462
|
this.notify({
|
|
462
463
|
type: 'error',
|
|
464
|
+
error,
|
|
463
465
|
title: 'Request Error',
|
|
464
466
|
text: [
|
|
465
467
|
`Unable to ${verb} ${this.itemLabel}${error ? ':' : ''}`,
|
|
@@ -23,7 +23,7 @@ export default DitoComponent.component('DitoNotifications', {
|
|
|
23
23
|
},
|
|
24
24
|
|
|
25
25
|
methods: {
|
|
26
|
-
notify({ type = 'info', title, text } = {}) {
|
|
26
|
+
notify({ type = 'info', title, text, error } = {}) {
|
|
27
27
|
title ||= (
|
|
28
28
|
{
|
|
29
29
|
warning: 'Warning',
|
|
@@ -46,7 +46,12 @@ export default DitoComponent.component('DitoNotifications', {
|
|
|
46
46
|
'error'
|
|
47
47
|
)
|
|
48
48
|
// eslint-disable-next-line no-console
|
|
49
|
-
console[log](
|
|
49
|
+
console[log](
|
|
50
|
+
...[
|
|
51
|
+
stripTags(text),
|
|
52
|
+
...(type === 'error' && error ? [error] : [])
|
|
53
|
+
]
|
|
54
|
+
)
|
|
50
55
|
const { notifications = true } = this.api
|
|
51
56
|
if (notifications) {
|
|
52
57
|
// Calculate display-duration for the notification based on its content
|
|
@@ -233,8 +233,8 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
233
233
|
})
|
|
234
234
|
},
|
|
235
235
|
|
|
236
|
-
notify({ type = 'info', title, text } = {}) {
|
|
237
|
-
this.notifications.notify({ type, title, text })
|
|
236
|
+
notify({ type = 'info', title, text, error } = {}) {
|
|
237
|
+
this.notifications.notify({ type, title, text, error })
|
|
238
238
|
},
|
|
239
239
|
|
|
240
240
|
closeNotifications() {
|
|
@@ -325,15 +325,13 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
325
325
|
await this.resolveViews()
|
|
326
326
|
}
|
|
327
327
|
} catch (err) {
|
|
328
|
-
const error = err.response?.data?.error
|
|
328
|
+
const error = err.response?.data?.error || err
|
|
329
329
|
this.notify({
|
|
330
330
|
type: 'error',
|
|
331
|
+
error,
|
|
331
332
|
title: 'Authentication Error',
|
|
332
|
-
text: error
|
|
333
|
+
text: error
|
|
333
334
|
})
|
|
334
|
-
if (!error) {
|
|
335
|
-
console.error(err, err.response)
|
|
336
|
-
}
|
|
337
335
|
this.login()
|
|
338
336
|
}
|
|
339
337
|
}
|
|
@@ -367,10 +365,12 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
367
365
|
})
|
|
368
366
|
user = response.data.user || null
|
|
369
367
|
} catch (err) {
|
|
368
|
+
const error = err.response?.data?.error || err
|
|
370
369
|
this.notify({
|
|
371
370
|
type: 'error',
|
|
371
|
+
error,
|
|
372
372
|
title: 'Authentication Error',
|
|
373
|
-
text:
|
|
373
|
+
text: error
|
|
374
374
|
})
|
|
375
375
|
}
|
|
376
376
|
this.setUser(user)
|
|
@@ -166,7 +166,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
166
166
|
? data(this.context)
|
|
167
167
|
: data
|
|
168
168
|
),
|
|
169
|
-
|
|
169
|
+
selectedTab: null,
|
|
170
170
|
componentsRegistry: {},
|
|
171
171
|
panesRegistry: {},
|
|
172
172
|
panelsRegistry: {},
|
|
@@ -195,16 +195,6 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
195
195
|
return getNamedSchemas(this.schema.tabs)
|
|
196
196
|
},
|
|
197
197
|
|
|
198
|
-
selectedTab: {
|
|
199
|
-
get() {
|
|
200
|
-
return this.currentTab || this.defaultTab || null
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
set(selectedTab) {
|
|
204
|
-
this.currentTab = selectedTab
|
|
205
|
-
}
|
|
206
|
-
},
|
|
207
|
-
|
|
208
198
|
defaultTab() {
|
|
209
199
|
let first = null
|
|
210
200
|
if (this.tabs) {
|
|
@@ -219,6 +209,10 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
219
209
|
return first
|
|
220
210
|
},
|
|
221
211
|
|
|
212
|
+
routeTab() {
|
|
213
|
+
return this.$route.hash?.slice(1) || null
|
|
214
|
+
},
|
|
215
|
+
|
|
222
216
|
clipboard() {
|
|
223
217
|
return this.schema?.clipboard ?? null
|
|
224
218
|
},
|
|
@@ -367,21 +361,21 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
367
361
|
},
|
|
368
362
|
|
|
369
363
|
watch: {
|
|
370
|
-
|
|
364
|
+
routeTab: {
|
|
371
365
|
immediate: true,
|
|
372
366
|
// https://github.com/vuejs/vue-router/issues/3393#issuecomment-1158470149
|
|
373
367
|
flush: 'post',
|
|
374
|
-
handler(
|
|
368
|
+
handler(routeTab) {
|
|
375
369
|
// Remember the current path to know if tab changes should still be
|
|
376
370
|
// handled, but remove the trailing `/create` or `/:id` from it so that
|
|
377
371
|
// tabs informs that stay open after creation still work.
|
|
378
372
|
if (this.hasRootTabs) {
|
|
379
|
-
this.
|
|
373
|
+
this.selectedTab = routeTab
|
|
380
374
|
}
|
|
381
375
|
}
|
|
382
376
|
},
|
|
383
377
|
|
|
384
|
-
|
|
378
|
+
selectedTab(newTab, oldTab) {
|
|
385
379
|
if (this.scrollable) {
|
|
386
380
|
const { content } = this.$refs
|
|
387
381
|
this.scrollPositions[oldTab] = content.scrollTop
|
|
@@ -412,6 +406,10 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
412
406
|
}
|
|
413
407
|
},
|
|
414
408
|
|
|
409
|
+
mounted() {
|
|
410
|
+
this.selectedTab = this.routeTab || this.defaultTab
|
|
411
|
+
},
|
|
412
|
+
|
|
415
413
|
unmounted() {
|
|
416
414
|
this.emitEvent('destroy')
|
|
417
415
|
this._register(false)
|
package/src/mixins/DataMixin.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
normalizeDataPath,
|
|
6
6
|
getValueAtDataPath
|
|
7
7
|
} from '@ditojs/utils'
|
|
8
|
-
import {
|
|
8
|
+
import { markRaw, ref } from 'vue'
|
|
9
9
|
import LoadingMixin from './LoadingMixin.js'
|
|
10
10
|
|
|
11
11
|
// @vue/component
|
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
data() {
|
|
16
16
|
return {
|
|
17
17
|
isLoading: false,
|
|
18
|
-
asyncDataEntries: {}
|
|
18
|
+
asyncDataEntries: markRaw({})
|
|
19
19
|
}
|
|
20
20
|
},
|
|
21
21
|
|
|
@@ -25,16 +25,22 @@ export default {
|
|
|
25
25
|
schema = { data: schema }
|
|
26
26
|
}
|
|
27
27
|
let { data = undefined, dataPath = null } = schema
|
|
28
|
-
//
|
|
29
|
-
|
|
28
|
+
// Create a reactive entry for the async data, if it doesn't exist yet.
|
|
29
|
+
// NOTE: Use `markRaw()` to avoid reactivity on the entry itself, as
|
|
30
|
+
// reactivity is only desired on the `reactiveVersion` property, which is
|
|
31
|
+
// used to trigger controlled reevaluation of the computed getter.
|
|
32
|
+
const asyncEntry = (this.asyncDataEntries[name] ??= {
|
|
33
|
+
reactiveVersion: ref(1),
|
|
30
34
|
dependencyFunction: null,
|
|
31
35
|
resolvedData: undefined,
|
|
32
36
|
resolving: false,
|
|
33
37
|
resolved: false
|
|
34
|
-
})
|
|
38
|
+
})
|
|
35
39
|
// If the data callback provided a dependency function when it was called,
|
|
36
40
|
// cal it in every call of `handleDataSchema()` to force Vue to keep track
|
|
37
|
-
// of the async dependencies.
|
|
41
|
+
// of the async dependencies. Also access `reactiveVersion.value` right
|
|
42
|
+
// away, to ensure that the reactive property is tracked as a dependency:
|
|
43
|
+
asyncEntry.reactiveVersion.value &&
|
|
38
44
|
asyncEntry.dependencyFunction?.(this.context)
|
|
39
45
|
|
|
40
46
|
if (asyncEntry.resolved) {
|
|
@@ -80,6 +86,9 @@ export default {
|
|
|
80
86
|
asyncEntry.resolvedData = data
|
|
81
87
|
asyncEntry.resolving = false
|
|
82
88
|
asyncEntry.resolved = true
|
|
89
|
+
// Trigger reevaluation of the computed getter by increasing the
|
|
90
|
+
// `reactiveVersion` value.
|
|
91
|
+
asyncEntry.reactiveVersion.value++
|
|
83
92
|
})
|
|
84
93
|
.catch(error => {
|
|
85
94
|
console.error(error)
|
|
@@ -261,7 +261,7 @@ export default {
|
|
|
261
261
|
? labelize(data.type)
|
|
262
262
|
: 'Error'
|
|
263
263
|
const text = data?.message ?? error
|
|
264
|
-
this.notify({ type: 'error', title, text })
|
|
264
|
+
this.notify({ type: 'error', error, title, text })
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
}
|
|
@@ -309,6 +309,7 @@ export default {
|
|
|
309
309
|
notifyError = error =>
|
|
310
310
|
this.notify({
|
|
311
311
|
type: 'error',
|
|
312
|
+
error,
|
|
312
313
|
title: 'Request Error',
|
|
313
314
|
text: [
|
|
314
315
|
`Unable to send request${error ? ':' : ''}`,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
parseDataPath,
|
|
28
28
|
normalizeDataPath
|
|
29
29
|
} from '@ditojs/utils'
|
|
30
|
+
import { raw } from '@ditojs/ui'
|
|
30
31
|
|
|
31
32
|
// @vue/component
|
|
32
33
|
export default {
|
|
@@ -45,7 +46,7 @@ export default {
|
|
|
45
46
|
data() {
|
|
46
47
|
return {
|
|
47
48
|
wrappedPrimitives: null,
|
|
48
|
-
unwrappingPrimitives: false
|
|
49
|
+
unwrappingPrimitives: raw(false)
|
|
49
50
|
}
|
|
50
51
|
},
|
|
51
52
|
|
|
@@ -95,16 +96,18 @@ export default {
|
|
|
95
96
|
data ||= []
|
|
96
97
|
const { wrapPrimitives } = this
|
|
97
98
|
if (wrapPrimitives) {
|
|
98
|
-
if (this.unwrappingPrimitives) {
|
|
99
|
+
if (this.unwrappingPrimitives.value) {
|
|
99
100
|
// We're done unwrapping once `listData` is reevaluated, so set
|
|
100
101
|
// this to `false` again. See `wrappedPrimitives` watcher above.
|
|
101
102
|
// TODO: Fix side-effects
|
|
102
|
-
// eslint-disable-next-line
|
|
103
|
-
|
|
103
|
+
// eslint-disable-next-line max-len
|
|
104
|
+
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
105
|
+
this.unwrappingPrimitives.value = false
|
|
104
106
|
} else {
|
|
105
107
|
// Convert data to a list of wrapped primitives, and return it.
|
|
106
108
|
// TODO: Fix side-effects
|
|
107
|
-
// eslint-disable-next-line
|
|
109
|
+
// eslint-disable-next-line max-len
|
|
110
|
+
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
|
108
111
|
this.wrappedPrimitives = data.map(value => ({
|
|
109
112
|
[wrapPrimitives]: value
|
|
110
113
|
}))
|
|
@@ -337,11 +340,11 @@ export default {
|
|
|
337
340
|
const { wrapPrimitives } = this
|
|
338
341
|
// Skip the initial setting of wrappedPrimitives array
|
|
339
342
|
if (wrapPrimitives && from !== null) {
|
|
340
|
-
// Whenever the wrappedPrimitives change, map their values back to
|
|
341
|
-
//
|
|
342
|
-
// But set `unwrappingPrimitives
|
|
343
|
+
// Whenever the wrappedPrimitives change, map their values back to the
|
|
344
|
+
// array of primitives, in a primitive way :)
|
|
345
|
+
// But set `unwrappingPrimitives` to true, so the `listData` computed
|
|
343
346
|
// property knows about it, which sets it to `false` again.
|
|
344
|
-
this.unwrappingPrimitives = true
|
|
347
|
+
this.unwrappingPrimitives.value = true
|
|
345
348
|
this.value = to.map(object => object[wrapPrimitives])
|
|
346
349
|
}
|
|
347
350
|
}
|