@ditojs/admin 2.23.0 → 2.24.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 +800 -783
- package/dist/dito-admin.umd.js +5 -5
- package/package.json +9 -9
- 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 +9 -5
- package/src/mixins/DataMixin.js +13 -4
- 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.0",
|
|
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.0",
|
|
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.
|
|
71
|
-
"vue": "3.4.
|
|
70
|
+
"type-fest": "^4.10.2",
|
|
71
|
+
"vue": "^3.4.18",
|
|
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
|
-
"@vue/compiler-sfc": "3.4.
|
|
79
|
+
"@vue/compiler-sfc": "^3.4.18",
|
|
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": "cd3083bf66a2f1b3fdb568fbb85e58ba0c202287",
|
|
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)
|
|
@@ -209,6 +209,10 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
209
209
|
return first
|
|
210
210
|
},
|
|
211
211
|
|
|
212
|
+
routeTab() {
|
|
213
|
+
return this.$route.hash?.slice(1) || null
|
|
214
|
+
},
|
|
215
|
+
|
|
212
216
|
clipboard() {
|
|
213
217
|
return this.schema?.clipboard ?? null
|
|
214
218
|
},
|
|
@@ -357,21 +361,21 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
357
361
|
},
|
|
358
362
|
|
|
359
363
|
watch: {
|
|
360
|
-
|
|
364
|
+
routeTab: {
|
|
361
365
|
immediate: true,
|
|
362
366
|
// https://github.com/vuejs/vue-router/issues/3393#issuecomment-1158470149
|
|
363
367
|
flush: 'post',
|
|
364
|
-
handler(
|
|
368
|
+
handler(routeTab) {
|
|
365
369
|
// Remember the current path to know if tab changes should still be
|
|
366
370
|
// handled, but remove the trailing `/create` or `/:id` from it so that
|
|
367
371
|
// tabs informs that stay open after creation still work.
|
|
368
372
|
if (this.hasRootTabs) {
|
|
369
|
-
this.selectedTab =
|
|
373
|
+
this.selectedTab = routeTab
|
|
370
374
|
}
|
|
371
375
|
}
|
|
372
376
|
},
|
|
373
377
|
|
|
374
|
-
|
|
378
|
+
selectedTab(newTab, oldTab) {
|
|
375
379
|
if (this.scrollable) {
|
|
376
380
|
const { content } = this.$refs
|
|
377
381
|
this.scrollPositions[oldTab] = content.scrollTop
|
|
@@ -403,7 +407,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
403
407
|
},
|
|
404
408
|
|
|
405
409
|
mounted() {
|
|
406
|
-
this.selectedTab = this.defaultTab
|
|
410
|
+
this.selectedTab = this.routeTab || this.defaultTab
|
|
407
411
|
},
|
|
408
412
|
|
|
409
413
|
unmounted() {
|
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
|
|
@@ -25,8 +25,12 @@ 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] ||= markRaw({
|
|
33
|
+
reactiveVersion: ref(1),
|
|
30
34
|
dependencyFunction: null,
|
|
31
35
|
resolvedData: undefined,
|
|
32
36
|
resolving: false,
|
|
@@ -34,7 +38,9 @@ export default {
|
|
|
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
|
}
|