@ditojs/admin 2.8.1 → 2.9.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 +2799 -2702
- package/dist/dito-admin.umd.js +6 -6
- package/dist/style.css +1 -1
- package/package.json +5 -5
- package/src/appState.js +2 -0
- package/src/components/DitoClipboard.vue +40 -56
- package/src/components/DitoContainer.vue +5 -7
- package/src/components/DitoDialog.vue +3 -7
- package/src/components/DitoDraggable.vue +74 -2
- package/src/components/DitoEditButtons.vue +6 -6
- package/src/components/DitoLabel.vue +2 -1
- package/src/components/DitoPane.vue +23 -10
- package/src/components/DitoRoot.vue +32 -8
- package/src/components/DitoSchema.vue +12 -6
- package/src/components/DitoSchemaInlined.vue +3 -10
- package/src/components/DitoSidebar.vue +29 -4
- package/src/components/DitoTreeItem.vue +2 -2
- package/src/components/DitoUploadFile.vue +1 -1
- package/src/mixins/DitoMixin.js +4 -3
- package/src/mixins/SortableMixin.js +9 -8
- package/src/styles/_layout.scss +1 -1
- package/src/styles/style.scss +0 -1
- package/src/types/DitoTypeCheckbox.vue +8 -7
- package/src/types/DitoTypeCheckboxes.vue +10 -9
- package/src/types/DitoTypeList.vue +1 -1
- package/src/types/DitoTypeMultiselect.vue +26 -21
- package/src/types/DitoTypeUpload.vue +1 -1
- package/src/utils/agent.js +47 -0
- package/src/utils/schema.js +12 -9
- package/src/styles/_sortable.scss +0 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.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.9.0",
|
|
37
|
+
"@ditojs/utils": "^2.9.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
40
|
"@tiptap/core": "^2.0.3",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"vue-upload-component": "^3.1.8"
|
|
75
75
|
},
|
|
76
76
|
"devDependencies": {
|
|
77
|
-
"@ditojs/build": "^2.
|
|
77
|
+
"@ditojs/build": "^2.9.0",
|
|
78
78
|
"@vitejs/plugin-vue": "^4.2.1",
|
|
79
79
|
"@vue/compiler-sfc": "^3.2.47",
|
|
80
80
|
"pug": "^3.0.2",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"vite": "^4.3.5"
|
|
84
84
|
},
|
|
85
85
|
"types": "types",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "d2a43cca595a94a317a96c4c2f2cd492a2401b26",
|
|
87
87
|
"scripts": {
|
|
88
88
|
"build": "vite build",
|
|
89
89
|
"watch": "yarn build --mode 'development' --watch",
|
package/src/appState.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { reactive } from 'vue'
|
|
2
|
+
import { parseUserAgent } from './utils/agent'
|
|
2
3
|
|
|
3
4
|
export default reactive({
|
|
4
5
|
title: '',
|
|
5
6
|
routeComponents: [],
|
|
6
7
|
user: null,
|
|
8
|
+
agent: parseUserAgent(navigator.userAgent || ''),
|
|
7
9
|
loadCache: {}, // See TypeMixin.load()
|
|
8
10
|
activeLabel: null,
|
|
9
11
|
clipboardData: null
|
|
@@ -20,15 +20,16 @@
|
|
|
20
20
|
<script>
|
|
21
21
|
import { isObject, clone, deindent } from '@ditojs/utils'
|
|
22
22
|
import DitoComponent from '../DitoComponent.js'
|
|
23
|
-
import DitoContext from '../DitoContext.js'
|
|
24
23
|
import DomMixin from '../mixins/DomMixin.js'
|
|
24
|
+
import DitoContext from '../DitoContext.js'
|
|
25
25
|
|
|
26
26
|
// @vue/component
|
|
27
27
|
export default DitoComponent.component('DitoClipboard', {
|
|
28
28
|
mixins: [DomMixin],
|
|
29
29
|
|
|
30
30
|
props: {
|
|
31
|
-
clipboard: { type: [Boolean, Object],
|
|
31
|
+
clipboard: { type: [Boolean, Object], required: true },
|
|
32
|
+
schema: { type: Object, required: true },
|
|
32
33
|
dataPath: { type: String, required: true },
|
|
33
34
|
data: { type: [Object, Array], default: null }
|
|
34
35
|
},
|
|
@@ -36,8 +37,7 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
36
37
|
data() {
|
|
37
38
|
return {
|
|
38
39
|
copyEnabled: false,
|
|
39
|
-
pasteEnabled: false
|
|
40
|
-
fixClipboard: true
|
|
40
|
+
pasteEnabled: false
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
|
|
@@ -50,12 +50,7 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
50
50
|
const { copy } = this.clipboardOptions
|
|
51
51
|
return copy
|
|
52
52
|
? clipboardData =>
|
|
53
|
-
copy.call(
|
|
54
|
-
this,
|
|
55
|
-
new DitoContext(this, {
|
|
56
|
-
clipboardData
|
|
57
|
-
})
|
|
58
|
-
)
|
|
53
|
+
copy.call(this, new DitoContext(this, { clipboardData }))
|
|
59
54
|
: clipboardData => clone(clipboardData)
|
|
60
55
|
},
|
|
61
56
|
|
|
@@ -63,34 +58,27 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
63
58
|
const { paste } = this.clipboardOptions
|
|
64
59
|
return paste
|
|
65
60
|
? clipboardData =>
|
|
66
|
-
paste.call(
|
|
67
|
-
this,
|
|
68
|
-
new DitoContext(this, {
|
|
69
|
-
clipboardData
|
|
70
|
-
})
|
|
71
|
-
)
|
|
61
|
+
paste.call(this, new DitoContext(this, { clipboardData }))
|
|
72
62
|
: clipboardData => clipboardData
|
|
73
63
|
}
|
|
74
64
|
},
|
|
75
65
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// (re)activated, as those are the moments when the clipboard can change:
|
|
79
|
-
this.domOn(document, {
|
|
80
|
-
copy: this.checkClipboard
|
|
81
|
-
})
|
|
82
|
-
this.domOn(window, {
|
|
83
|
-
focus: this.checkClipboard
|
|
84
|
-
})
|
|
85
|
-
this.$watch('data', {
|
|
66
|
+
watch: {
|
|
67
|
+
'parentComponent.hasData': {
|
|
86
68
|
// Check right away also in case there's already data (e.g. create form).
|
|
87
69
|
immediate: true,
|
|
88
|
-
handler
|
|
89
|
-
|
|
90
|
-
this.checkClipboard()
|
|
91
|
-
}
|
|
70
|
+
handler(hasData) {
|
|
71
|
+
this.copyEnabled = hasData
|
|
92
72
|
}
|
|
93
|
-
}
|
|
73
|
+
},
|
|
74
|
+
'appState.clipboardData': 'updatePaste'
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
mounted() {
|
|
78
|
+
// Check clipboard content whenever something gets copied or the window gets
|
|
79
|
+
// (re)activated, as those are the moments when the clipboard can change:
|
|
80
|
+
this.domOn(document, { copy: this.updatePaste })
|
|
81
|
+
this.domOn(window, { focus: this.updatePaste })
|
|
94
82
|
},
|
|
95
83
|
|
|
96
84
|
methods: {
|
|
@@ -99,12 +87,6 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
99
87
|
let { clipboardData } = this.appState
|
|
100
88
|
try {
|
|
101
89
|
const json = await navigator.clipboard?.readText?.()
|
|
102
|
-
if (this.fixClipboard && json) {
|
|
103
|
-
// This appears to be needed on Safari to prevent a strange "Paste"
|
|
104
|
-
// button from appearing when the clipboard is accessed (why?!).
|
|
105
|
-
await navigator.clipboard?.writeText?.(json)
|
|
106
|
-
this.fixClipboard = false
|
|
107
|
-
}
|
|
108
90
|
if (json) {
|
|
109
91
|
clipboardData = JSON.parse(json)
|
|
110
92
|
}
|
|
@@ -120,27 +102,34 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
120
102
|
}
|
|
121
103
|
}
|
|
122
104
|
const { $schema, ...data } = clipboardData || {}
|
|
123
|
-
return $schema === this.
|
|
105
|
+
return $schema === this.schema.name ? data : null
|
|
124
106
|
},
|
|
125
107
|
|
|
126
|
-
async
|
|
127
|
-
this.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
108
|
+
async updatePaste() {
|
|
109
|
+
this.pasteEnabled = !!this.appState.clipboardData
|
|
110
|
+
if (!this.pasteEnabled && this.appState.agent.chrome) {
|
|
111
|
+
// See if the clipboard content is valid JSON data that is compatible
|
|
112
|
+
// with the current target schema, and only then activate the pasting:
|
|
113
|
+
const data = await this.getClipboardData(false) // Don't report
|
|
114
|
+
this.pasteEnabled = !!data
|
|
115
|
+
}
|
|
131
116
|
},
|
|
132
117
|
|
|
133
118
|
async onCopy() {
|
|
134
|
-
let data = this.
|
|
119
|
+
let data = this.parentComponent.clipboardData
|
|
135
120
|
try {
|
|
136
|
-
|
|
121
|
+
if (data) {
|
|
122
|
+
data = {
|
|
123
|
+
$schema: this.schema.name,
|
|
124
|
+
...this.copyData(data)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
137
127
|
// Keep an internal clipboard as fallback.
|
|
138
128
|
this.appState.clipboardData = data
|
|
129
|
+
this.pasteEnabled = true
|
|
139
130
|
try {
|
|
140
131
|
const json = JSON.stringify(data, null, 2)
|
|
141
132
|
await navigator.clipboard?.writeText?.(json)
|
|
142
|
-
// See if we can activate the paste button, depending on browsers:
|
|
143
|
-
await this.checkClipboard()
|
|
144
133
|
} catch (err) {
|
|
145
134
|
console.error(err, err.name, err.message)
|
|
146
135
|
}
|
|
@@ -151,15 +140,10 @@ export default DitoComponent.component('DitoClipboard', {
|
|
|
151
140
|
},
|
|
152
141
|
|
|
153
142
|
async onPaste() {
|
|
154
|
-
let data = await this.getClipboardData(true) //
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
this.schemaComponent.setData(data)
|
|
159
|
-
}
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.error(error)
|
|
162
|
-
alert(error.message)
|
|
143
|
+
let data = await this.getClipboardData(true) // Report
|
|
144
|
+
data = data && this.pasteData(data)
|
|
145
|
+
if (data) {
|
|
146
|
+
this.parentComponent.clipboardData = data
|
|
163
147
|
}
|
|
164
148
|
}
|
|
165
149
|
}
|
|
@@ -255,26 +255,24 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
255
255
|
// percentages in flex-basis to work.
|
|
256
256
|
padding: $form-spacing-half;
|
|
257
257
|
|
|
258
|
-
.dito-
|
|
259
|
-
|
|
258
|
+
.dito-pane > & {
|
|
259
|
+
.dito-page--width-80 & {
|
|
260
260
|
flex-grow: 1;
|
|
261
261
|
flex-basis: var(--basis-mobile, var(--basis));
|
|
262
262
|
// DEBUG: background: yellow;
|
|
263
263
|
}
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
.dito-page--width-60 & {
|
|
266
266
|
flex-basis: calc(2 * var(--basis));
|
|
267
267
|
// DEBUG: background: orange;
|
|
268
268
|
}
|
|
269
|
-
}
|
|
270
269
|
|
|
271
|
-
|
|
272
|
-
@container (width < #{$sidebar-max-width}) {
|
|
270
|
+
.dito-sidebar--width-99 & {
|
|
273
271
|
flex-grow: 1;
|
|
274
272
|
// DEBUG: background: yellow;
|
|
275
273
|
}
|
|
276
274
|
|
|
277
|
-
|
|
275
|
+
.dito-sidebar--width-60 & {
|
|
278
276
|
flex-basis: calc(2 * var(--basis));
|
|
279
277
|
// DEBUG: background: orange;
|
|
280
278
|
}
|
|
@@ -31,13 +31,14 @@
|
|
|
31
31
|
|
|
32
32
|
<script>
|
|
33
33
|
import { clone } from '@ditojs/utils'
|
|
34
|
-
import { addEvents } from '@ditojs/ui/src'
|
|
35
34
|
import DitoComponent from '../DitoComponent.js'
|
|
35
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
36
36
|
import { getButtonSchemas } from '../utils/schema.js'
|
|
37
37
|
import { UseFocusTrap } from '@vueuse/integrations/useFocusTrap/component'
|
|
38
38
|
|
|
39
39
|
// @vue/component
|
|
40
40
|
export default DitoComponent.component('DitoDialog', {
|
|
41
|
+
mixins: [DomMixin],
|
|
41
42
|
components: { UseFocusTrap },
|
|
42
43
|
emits: ['remove'],
|
|
43
44
|
|
|
@@ -70,7 +71,6 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
return {
|
|
73
|
-
windowEvents: null,
|
|
74
74
|
dialogData
|
|
75
75
|
}
|
|
76
76
|
},
|
|
@@ -125,7 +125,7 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
125
125
|
},
|
|
126
126
|
|
|
127
127
|
mounted() {
|
|
128
|
-
this.
|
|
128
|
+
this.domOn(window, {
|
|
129
129
|
keyup: event => {
|
|
130
130
|
if ((this.hasCancel || !this.hasButtons) && event.keyCode === 27) {
|
|
131
131
|
this.cancel()
|
|
@@ -134,10 +134,6 @@ export default DitoComponent.component('DitoDialog', {
|
|
|
134
134
|
})
|
|
135
135
|
},
|
|
136
136
|
|
|
137
|
-
unmounted() {
|
|
138
|
-
this.windowEvents.remove()
|
|
139
|
-
},
|
|
140
|
-
|
|
141
137
|
methods: {
|
|
142
138
|
remove() {
|
|
143
139
|
this.$emit('remove')
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
UseSortable(
|
|
2
|
+
UseSortable.dito-draggable(
|
|
3
3
|
v-if="draggable"
|
|
4
|
+
:class="{ 'dito-draggable--dragging': isDragging }"
|
|
4
5
|
:tag="tag"
|
|
5
6
|
:modelValue="modelValue"
|
|
6
|
-
:options="options"
|
|
7
|
+
:options="{ ...options, onStart, onEnd }"
|
|
7
8
|
@update:modelValue="$emit('update:modelValue', $event)"
|
|
8
9
|
)
|
|
9
10
|
slot
|
|
@@ -16,10 +17,12 @@ component(
|
|
|
16
17
|
|
|
17
18
|
<script>
|
|
18
19
|
import DitoComponent from '../DitoComponent'
|
|
20
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
19
21
|
import { UseSortable } from '@vueuse/integrations/useSortable/component'
|
|
20
22
|
|
|
21
23
|
// @vue/component
|
|
22
24
|
export default DitoComponent.component('DitoDraggable', {
|
|
25
|
+
mixins: [DomMixin],
|
|
23
26
|
components: { UseSortable },
|
|
24
27
|
emits: ['update:modelValue'],
|
|
25
28
|
|
|
@@ -40,6 +43,75 @@ export default DitoComponent.component('DitoDraggable', {
|
|
|
40
43
|
type: Boolean,
|
|
41
44
|
default: true
|
|
42
45
|
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
data() {
|
|
49
|
+
return {
|
|
50
|
+
mouseEvents: null,
|
|
51
|
+
isDragging: false
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
methods: {
|
|
56
|
+
onStart(event) {
|
|
57
|
+
this.isDragging = true
|
|
58
|
+
this.options.onStart?.(event)
|
|
59
|
+
this.mouseEvents?.remove()
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
onEnd(event) {
|
|
63
|
+
this.options.onEnd?.(event)
|
|
64
|
+
// Keep `isDragging` true until the next mouse interaction so that
|
|
65
|
+
// confused hover states are cleared before removing the hover catcher.
|
|
66
|
+
this.mouseEvents = this.domOn(this.$el, {
|
|
67
|
+
mousedown: this.onMouse,
|
|
68
|
+
mousemove: this.onMouse,
|
|
69
|
+
mouseleave: this.onMouse
|
|
70
|
+
})
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
onMouse() {
|
|
74
|
+
this.isDragging = false
|
|
75
|
+
this.mouseEvents.remove()
|
|
76
|
+
this.mouseEvents = null
|
|
77
|
+
}
|
|
43
78
|
}
|
|
44
79
|
})
|
|
45
80
|
</script>
|
|
81
|
+
|
|
82
|
+
<style lang="scss">
|
|
83
|
+
@import '../styles/_imports';
|
|
84
|
+
|
|
85
|
+
.dito-draggable {
|
|
86
|
+
// Overlay a hover catcher while we're dragging to prevent hover states from
|
|
87
|
+
// getting stuck / confused. Safari struggles with this, so disable it there.
|
|
88
|
+
@include browser-query(('chrome', 'firefox')) {
|
|
89
|
+
&:has(&__chosen),
|
|
90
|
+
&--dragging {
|
|
91
|
+
> * {
|
|
92
|
+
position: relative;
|
|
93
|
+
|
|
94
|
+
> :first-child::after {
|
|
95
|
+
content: '';
|
|
96
|
+
position: absolute;
|
|
97
|
+
inset: 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&__fallback {
|
|
104
|
+
filter: drop-shadow(0 2px 4px $color-shadow);
|
|
105
|
+
|
|
106
|
+
// Nested <td> need to also switch to `display: flex` style during dragging.
|
|
107
|
+
&,
|
|
108
|
+
td {
|
|
109
|
+
display: flex;
|
|
110
|
+
|
|
111
|
+
> * {
|
|
112
|
+
flex: 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
@@ -78,19 +78,19 @@ export default DitoComponent.component('DitoEditButtons', {
|
|
|
78
78
|
return this.disabled || !this.hasSchemaOption('deletable')
|
|
79
79
|
},
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
isEditableDisabled() {
|
|
82
82
|
return (
|
|
83
83
|
this.disabled ||
|
|
84
|
-
!this.
|
|
85
|
-
!this.hasSchemaOption('
|
|
84
|
+
!this.editPath ||
|
|
85
|
+
!this.hasSchemaOption('editable')
|
|
86
86
|
)
|
|
87
87
|
},
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
isCreatableDisabled() {
|
|
90
90
|
return (
|
|
91
91
|
this.disabled ||
|
|
92
|
-
!this.
|
|
93
|
-
!this.hasSchemaOption('
|
|
92
|
+
!this.createPath ||
|
|
93
|
+
!this.hasSchemaOption('creatable')
|
|
94
94
|
)
|
|
95
95
|
},
|
|
96
96
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<template lang="pug">
|
|
3
3
|
.dito-pane(
|
|
4
4
|
v-if="isPopulated && componentSchemas.length > 0"
|
|
5
|
+
v-resize="onResizePane"
|
|
5
6
|
:class=`{
|
|
6
7
|
'dito-pane--single': isSingleComponent
|
|
7
8
|
}`
|
|
@@ -22,8 +23,9 @@
|
|
|
22
23
|
)
|
|
23
24
|
DitoContainer(
|
|
24
25
|
v-if="shouldRenderSchema(schema)"
|
|
26
|
+
ref="containers"
|
|
25
27
|
:key="nestedDataPath"
|
|
26
|
-
|
|
28
|
+
:data-index="index"
|
|
27
29
|
:schema="schema"
|
|
28
30
|
:dataPath="dataPath"
|
|
29
31
|
:data="data"
|
|
@@ -196,15 +198,26 @@ export default DitoComponent.component('DitoPane', {
|
|
|
196
198
|
}
|
|
197
199
|
},
|
|
198
200
|
|
|
199
|
-
|
|
200
|
-
this
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
onResizePane() {
|
|
202
|
+
this.$nextTick(() => {
|
|
203
|
+
for (const container of this.$refs.containers) {
|
|
204
|
+
const node = container.$el
|
|
205
|
+
const index = +node.dataset.index
|
|
206
|
+
const bounds = node.getBoundingClientRect()
|
|
207
|
+
const style = getComputedStyle(node)
|
|
208
|
+
const padding = parseFloat(style.padding)
|
|
209
|
+
const fontSize = parseFloat(style.fontSize)
|
|
210
|
+
const height = bounds.height - 2 * padding
|
|
211
|
+
this.positions[index] =
|
|
212
|
+
height <= 0
|
|
213
|
+
? null
|
|
214
|
+
: {
|
|
215
|
+
top: bounds.y,
|
|
216
|
+
height: height / fontSize,
|
|
217
|
+
node
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
})
|
|
208
221
|
},
|
|
209
222
|
|
|
210
223
|
isInLabeledRow(index) {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<template lang="pug">
|
|
2
|
-
.dito-root
|
|
2
|
+
.dito-root(
|
|
3
|
+
:data-agent-browser="appState.agent.browser"
|
|
4
|
+
:data-agent-platform="appState.agent.platform"
|
|
5
|
+
:data-agent-version="appState.agent.versionNumber"
|
|
6
|
+
)
|
|
3
7
|
VueNotifications.dito-notifications(
|
|
4
8
|
ref="notifications"
|
|
5
9
|
position="top right"
|
|
@@ -21,7 +25,10 @@
|
|
|
21
25
|
@remove="removeDialog(key)"
|
|
22
26
|
)
|
|
23
27
|
DitoNavigation
|
|
24
|
-
main.dito-page.dito-scroll-parent(
|
|
28
|
+
main.dito-page.dito-scroll-parent(
|
|
29
|
+
v-resize="onResizePage"
|
|
30
|
+
:class="pageClasses"
|
|
31
|
+
)
|
|
25
32
|
DitoHeader(
|
|
26
33
|
:spinner="options.spinner"
|
|
27
34
|
:isLoading="isLoading"
|
|
@@ -43,10 +50,10 @@
|
|
|
43
50
|
import { delegate as tippyDelegate } from 'tippy.js'
|
|
44
51
|
import { asArray, mapConcurrently, stripTags } from '@ditojs/utils'
|
|
45
52
|
import DitoComponent from '../DitoComponent.js'
|
|
53
|
+
import DomMixin from '../mixins/DomMixin.js'
|
|
46
54
|
import DitoUser from '../DitoUser.js'
|
|
47
55
|
import DitoView from '../components/DitoView.vue'
|
|
48
56
|
import DitoDialog from './DitoDialog.vue'
|
|
49
|
-
import DomMixin from '../mixins/DomMixin.js'
|
|
50
57
|
import {
|
|
51
58
|
processView,
|
|
52
59
|
resolveViews,
|
|
@@ -74,8 +81,9 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
74
81
|
resolvedViews: {},
|
|
75
82
|
removeRoutes: null,
|
|
76
83
|
dialogs: {},
|
|
77
|
-
|
|
84
|
+
pageWidth: 0,
|
|
78
85
|
loadingCount: 0,
|
|
86
|
+
allowLogin: false,
|
|
79
87
|
isDraggingFiles: false
|
|
80
88
|
}
|
|
81
89
|
},
|
|
@@ -87,6 +95,19 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
87
95
|
|
|
88
96
|
isLoading() {
|
|
89
97
|
return this.loadingCount > 0
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
pageClasses() {
|
|
101
|
+
const prefix = 'dito-page'
|
|
102
|
+
// NOTE: Keep synced with $content-width in SCSS:
|
|
103
|
+
const contentWidth = 900
|
|
104
|
+
return [
|
|
105
|
+
this.appState.pageClass,
|
|
106
|
+
{
|
|
107
|
+
[`${prefix}--width-80`]: this.pageWidth <= contentWidth * 0.8,
|
|
108
|
+
[`${prefix}--width-60`]: this.pageWidth <= contentWidth * 0.6
|
|
109
|
+
}
|
|
110
|
+
]
|
|
90
111
|
}
|
|
91
112
|
},
|
|
92
113
|
|
|
@@ -103,7 +124,7 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
103
124
|
tippyDelegate(this.$el, {
|
|
104
125
|
target: '.dito-info',
|
|
105
126
|
theme: 'info',
|
|
106
|
-
appendTo: '
|
|
127
|
+
appendTo: node => node.closest('.dito-pane'),
|
|
107
128
|
animation: 'shift-away-subtle',
|
|
108
129
|
interactive: true,
|
|
109
130
|
delay: 250,
|
|
@@ -438,6 +459,10 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
438
459
|
...routes.flat()
|
|
439
460
|
])
|
|
440
461
|
this.$router.replace(fullPath)
|
|
462
|
+
},
|
|
463
|
+
|
|
464
|
+
onResizePage({ contentRect: { width } }) {
|
|
465
|
+
this.pageWidth = width
|
|
441
466
|
}
|
|
442
467
|
}
|
|
443
468
|
})
|
|
@@ -475,10 +500,9 @@ function addRoutes(router, routes) {
|
|
|
475
500
|
|
|
476
501
|
flex: 0 1 var(--max-page-width);
|
|
477
502
|
background: $content-color-background;
|
|
503
|
+
min-width: 0%;
|
|
478
504
|
max-width: var(--max-page-width);
|
|
479
505
|
overflow: visible; // For .dito-header full-width background.
|
|
480
|
-
// For the `@container` rule in `.dito-container` to work:
|
|
481
|
-
container-type: inline-size;
|
|
482
506
|
|
|
483
507
|
&--wide {
|
|
484
508
|
--max-content-width: #{$content-width-wide};
|
|
@@ -505,9 +529,9 @@ function addRoutes(router, routes) {
|
|
|
505
529
|
position: fixed;
|
|
506
530
|
top: 0;
|
|
507
531
|
left: 0;
|
|
508
|
-
z-index: $z-index-drag-overlay;
|
|
509
532
|
width: 100%;
|
|
510
533
|
height: 100%;
|
|
534
|
+
z-index: $z-index-drag-overlay;
|
|
511
535
|
background: rgba(0, 0, 0, 0.25);
|
|
512
536
|
pointer-events: none;
|
|
513
537
|
backdrop-filter: blur(8px);
|
|
@@ -39,7 +39,9 @@ slot(name="before")
|
|
|
39
39
|
:tabs="tabs"
|
|
40
40
|
)
|
|
41
41
|
DitoClipboard(
|
|
42
|
+
v-if="clipboard"
|
|
42
43
|
:clipboard="clipboard"
|
|
44
|
+
:schema="schema"
|
|
43
45
|
:dataPath="dataPath"
|
|
44
46
|
:data="data"
|
|
45
47
|
)
|
|
@@ -214,7 +216,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
214
216
|
},
|
|
215
217
|
|
|
216
218
|
clipboard() {
|
|
217
|
-
return this.schema?.clipboard
|
|
219
|
+
return this.schema?.clipboard ?? null
|
|
218
220
|
},
|
|
219
221
|
|
|
220
222
|
hasHeader() {
|
|
@@ -236,10 +238,13 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
236
238
|
return this.processData({ target: 'server', schemaOnly: true })
|
|
237
239
|
},
|
|
238
240
|
|
|
239
|
-
clipboardData
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
clipboardData: {
|
|
242
|
+
get() {
|
|
243
|
+
return this.processData({ target: 'clipboard', schemaOnly: true })
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
set(data) {
|
|
247
|
+
this.setData(data)
|
|
243
248
|
}
|
|
244
249
|
},
|
|
245
250
|
|
|
@@ -676,6 +681,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
676
681
|
{
|
|
677
682
|
// Needed for DitoContext handling inside `processData` and
|
|
678
683
|
// `processSchemaData()`:
|
|
684
|
+
rootData: this.rootData,
|
|
679
685
|
component: this,
|
|
680
686
|
schemaOnly,
|
|
681
687
|
target
|
|
@@ -772,7 +778,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
772
778
|
grid-template-rows: min-content;
|
|
773
779
|
grid-template-columns: 100%;
|
|
774
780
|
|
|
775
|
-
>
|
|
781
|
+
> :only-child {
|
|
776
782
|
grid-row-end: none;
|
|
777
783
|
}
|
|
778
784
|
}
|
|
@@ -82,17 +82,10 @@ export default DitoComponent.component('DitoSchemaInlined', {
|
|
|
82
82
|
grid-template-rows: min-content;
|
|
83
83
|
grid-template-columns: 100%;
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
&:not(:hover, .dito-schema--open) {
|
|
86
86
|
> .dito-schema-header {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
.dito-label {
|
|
91
|
-
width: 100%;
|
|
92
|
-
margin: 0;
|
|
93
|
-
// Prevent collapsing to min-height when alone in
|
|
94
|
-
// .dito-schema-content, due to grid-template-rows: min-content
|
|
95
|
-
min-height: $input-height;
|
|
87
|
+
> .dito-clipboard {
|
|
88
|
+
display: none;
|
|
96
89
|
}
|
|
97
90
|
}
|
|
98
91
|
}
|