@ditojs/admin 2.0.1 → 2.0.3
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 +979 -988
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +25 -26
- package/src/components/DitoLabel.vue +5 -8
- package/src/components/DitoTreeItem.vue +21 -20
- package/src/mixins/TypeMixin.js +9 -26
- package/src/types/TypeButton.vue +6 -5
- package/src/types/TypeList.vue +70 -69
- package/src/types/TypeMultiselect.vue +23 -3
- package/src/types/TypeSwitch.vue +0 -1
- package/src/types/TypeUpload.vue +35 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
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,39 +33,38 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.0.
|
|
36
|
+
"@ditojs/ui": "^2.0.3",
|
|
37
37
|
"@ditojs/utils": "^2.0.1",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
40
|
-
"@tiptap/core": "^2.0.
|
|
41
|
-
"@tiptap/extension-blockquote": "^2.0.
|
|
42
|
-
"@tiptap/extension-bold": "^2.0.
|
|
43
|
-
"@tiptap/extension-bullet-list": "^2.0.
|
|
44
|
-
"@tiptap/extension-code": "^2.0.
|
|
45
|
-
"@tiptap/extension-code-block": "^2.0.
|
|
46
|
-
"@tiptap/extension-document": "^2.0.
|
|
47
|
-
"@tiptap/extension-hard-break": "^2.0.
|
|
48
|
-
"@tiptap/extension-heading": "^2.0.
|
|
49
|
-
"@tiptap/extension-history": "^2.0.
|
|
50
|
-
"@tiptap/extension-horizontal-rule": "^2.0.
|
|
51
|
-
"@tiptap/extension-italic": "^2.0.
|
|
52
|
-
"@tiptap/extension-link": "^2.0.
|
|
53
|
-
"@tiptap/extension-list-item": "^2.0.
|
|
54
|
-
"@tiptap/extension-ordered-list": "^2.0.
|
|
55
|
-
"@tiptap/extension-paragraph": "^2.0.
|
|
56
|
-
"@tiptap/extension-strike": "^2.0.
|
|
57
|
-
"@tiptap/extension-text": "^2.0.
|
|
58
|
-
"@tiptap/extension-underline": "^2.0.
|
|
59
|
-
"@tiptap/pm": "^2.0.
|
|
60
|
-
"@tiptap/vue-3": "^2.0.
|
|
40
|
+
"@tiptap/core": "^2.0.2",
|
|
41
|
+
"@tiptap/extension-blockquote": "^2.0.2",
|
|
42
|
+
"@tiptap/extension-bold": "^2.0.2",
|
|
43
|
+
"@tiptap/extension-bullet-list": "^2.0.2",
|
|
44
|
+
"@tiptap/extension-code": "^2.0.2",
|
|
45
|
+
"@tiptap/extension-code-block": "^2.0.2",
|
|
46
|
+
"@tiptap/extension-document": "^2.0.2",
|
|
47
|
+
"@tiptap/extension-hard-break": "^2.0.2",
|
|
48
|
+
"@tiptap/extension-heading": "^2.0.2",
|
|
49
|
+
"@tiptap/extension-history": "^2.0.2",
|
|
50
|
+
"@tiptap/extension-horizontal-rule": "^2.0.2",
|
|
51
|
+
"@tiptap/extension-italic": "^2.0.2",
|
|
52
|
+
"@tiptap/extension-link": "^2.0.2",
|
|
53
|
+
"@tiptap/extension-list-item": "^2.0.2",
|
|
54
|
+
"@tiptap/extension-ordered-list": "^2.0.2",
|
|
55
|
+
"@tiptap/extension-paragraph": "^2.0.2",
|
|
56
|
+
"@tiptap/extension-strike": "^2.0.2",
|
|
57
|
+
"@tiptap/extension-text": "^2.0.2",
|
|
58
|
+
"@tiptap/extension-underline": "^2.0.2",
|
|
59
|
+
"@tiptap/pm": "^2.0.2",
|
|
60
|
+
"@tiptap/vue-3": "^2.0.2",
|
|
61
61
|
"codeflask": "^1.4.1",
|
|
62
62
|
"filesize": "^10.0.7",
|
|
63
63
|
"filesize-parser": "^1.5.0",
|
|
64
64
|
"nanoid": "^4.0.2",
|
|
65
|
-
"sortablejs": "^1.15.0",
|
|
66
|
-
"sortablejs-vue3": "^1.2.9",
|
|
67
65
|
"tinycolor2": "^1.6.0",
|
|
68
66
|
"vue": "^3.2.47",
|
|
67
|
+
"vue-draggable-plus": "^0.1.1",
|
|
69
68
|
"vue-multiselect": "^3.0.0-beta.1",
|
|
70
69
|
"vue-router": "^4.1.6",
|
|
71
70
|
"vue-upload-component": "^3.1.8"
|
|
@@ -81,7 +80,7 @@
|
|
|
81
80
|
"vite": "^4.2.1"
|
|
82
81
|
},
|
|
83
82
|
"types": "types",
|
|
84
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "5ca73cc4cf410fbaa95a8e7079cb5c264cc67b7c",
|
|
85
84
|
"scripts": {
|
|
86
85
|
"build": "vite build",
|
|
87
86
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -52,7 +52,7 @@ component.dito-label(
|
|
|
52
52
|
// so that buttons always appear right-aligned:
|
|
53
53
|
flex: 1 1 auto
|
|
54
54
|
&::after
|
|
55
|
-
content: '\a0' // &
|
|
55
|
+
content: '\a0' //
|
|
56
56
|
|
|
57
57
|
.dito-label-prefix,
|
|
58
58
|
.dito-label-suffix
|
|
@@ -94,8 +94,9 @@ component.dito-label(
|
|
|
94
94
|
> .dito-schema-content
|
|
95
95
|
> .dito-pane
|
|
96
96
|
> .dito-container
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
display: flex
|
|
98
|
+
flex-flow: row wrap
|
|
99
|
+
align-items: baseline
|
|
99
100
|
</style>
|
|
100
101
|
|
|
101
102
|
<script>
|
|
@@ -130,11 +131,7 @@ export default DitoComponent.component('dito-label', {
|
|
|
130
131
|
},
|
|
131
132
|
|
|
132
133
|
attributes() {
|
|
133
|
-
return {
|
|
134
|
-
...(this.collapsible && {
|
|
135
|
-
onClick: this.onClick
|
|
136
|
-
})
|
|
137
|
-
}
|
|
134
|
+
return this.collapsible ? { onClick: this.onClick } : {}
|
|
138
135
|
},
|
|
139
136
|
|
|
140
137
|
isActive() {
|
|
@@ -60,29 +60,30 @@
|
|
|
60
60
|
:store="store"
|
|
61
61
|
:disabled="disabled"
|
|
62
62
|
)
|
|
63
|
-
vue-
|
|
63
|
+
vue-draggable(
|
|
64
64
|
v-if="childrenSchema"
|
|
65
65
|
v-show="opened"
|
|
66
|
-
:
|
|
67
|
-
:
|
|
68
|
-
:itemKey="item => getItemUid(childrenSchema, item.data)"
|
|
66
|
+
:modelValue="updateOrder(childrenSchema, childrenList)"
|
|
67
|
+
@update:modelValue="value => childrenList = value"
|
|
69
68
|
@start="onStartDrag"
|
|
70
69
|
@end="onEndDrag($event, childrenSchema)"
|
|
70
|
+
v-bind="getDragOptions(childrenDraggable, true)"
|
|
71
71
|
)
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
72
|
+
dito-tree-item(
|
|
73
|
+
v-for="(item, index) in childrenItems"
|
|
74
|
+
:key="getItemUid(childrenSchema, item.data)"
|
|
75
|
+
:schema="childrenSchema"
|
|
76
|
+
:dataPath="getItemDataPath(childrenSchema, index)"
|
|
77
|
+
:data="item.data"
|
|
78
|
+
:path="item.path"
|
|
79
|
+
:open="item.open"
|
|
80
|
+
:active="item.active"
|
|
81
|
+
:draggable="childrenDraggable"
|
|
82
|
+
:label="getItemLabel(childrenSchema, item.data, { index })"
|
|
83
|
+
:level="level + 1"
|
|
84
|
+
)
|
|
85
|
+
//- TODO: Convert dito-tree-item to use dito-label internally, and then
|
|
86
|
+
//- pass `asObject: true` in the `getItemLabel()` call above.
|
|
86
87
|
</template>
|
|
87
88
|
|
|
88
89
|
<style lang="sass">
|
|
@@ -151,7 +152,7 @@
|
|
|
151
152
|
</style>
|
|
152
153
|
|
|
153
154
|
<script>
|
|
154
|
-
import {
|
|
155
|
+
import { VueDraggable } from 'vue-draggable-plus'
|
|
155
156
|
import DitoComponent from '../DitoComponent.js'
|
|
156
157
|
import OrderedMixin from '../mixins/OrderedMixin.js'
|
|
157
158
|
import { appendDataPath } from '../utils/data.js'
|
|
@@ -160,7 +161,7 @@ import { getNamedSchemas, hasFormSchema } from '../utils/schema.js'
|
|
|
160
161
|
|
|
161
162
|
// @vue/component
|
|
162
163
|
export default DitoComponent.component('dito-tree-item', {
|
|
163
|
-
components: {
|
|
164
|
+
components: { VueDraggable },
|
|
164
165
|
mixins: [OrderedMixin],
|
|
165
166
|
inject: ['container'],
|
|
166
167
|
|
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
|
|
6
|
+
import { isString, asArray } from '@ditojs/utils'
|
|
7
7
|
|
|
8
8
|
// @vue/component
|
|
9
9
|
export default {
|
|
@@ -156,10 +156,17 @@ export default {
|
|
|
156
156
|
type: String
|
|
157
157
|
}),
|
|
158
158
|
|
|
159
|
+
// @overridable
|
|
160
|
+
events() {
|
|
161
|
+
const { onFocus, onBlur, onInput, onChange } = this
|
|
162
|
+
return { onFocus, onBlur, onInput, onChange }
|
|
163
|
+
},
|
|
164
|
+
|
|
159
165
|
attributes() {
|
|
160
166
|
const { nativeField, textField } = this.$options
|
|
161
167
|
|
|
162
168
|
const attributes = {
|
|
169
|
+
...this.events,
|
|
163
170
|
disabled: this.disabled
|
|
164
171
|
}
|
|
165
172
|
|
|
@@ -176,25 +183,7 @@ export default {
|
|
|
176
183
|
}
|
|
177
184
|
}
|
|
178
185
|
|
|
179
|
-
return
|
|
180
|
-
...Object.fromEntries(
|
|
181
|
-
Object.entries(this.$attrs).filter(([key]) => key.startsWith('on'))
|
|
182
|
-
),
|
|
183
|
-
...this.events,
|
|
184
|
-
...attributes
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
|
|
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)
|
|
196
|
-
}
|
|
197
|
-
return events
|
|
186
|
+
return attributes
|
|
198
187
|
},
|
|
199
188
|
|
|
200
189
|
validations() {
|
|
@@ -235,12 +224,6 @@ export default {
|
|
|
235
224
|
}
|
|
236
225
|
},
|
|
237
226
|
|
|
238
|
-
// @overridable
|
|
239
|
-
getEvents() {
|
|
240
|
-
const { onFocus, onBlur, onInput, onChange } = this
|
|
241
|
-
return { onFocus, onBlur, onInput, onChange }
|
|
242
|
-
},
|
|
243
|
-
|
|
244
227
|
// @overridable
|
|
245
228
|
getValidations() {
|
|
246
229
|
return null
|
package/src/types/TypeButton.vue
CHANGED
|
@@ -41,16 +41,17 @@ export default TypeComponent.register([
|
|
|
41
41
|
closeForm: getSchemaAccessor('closeForm', {
|
|
42
42
|
type: Boolean,
|
|
43
43
|
default: false
|
|
44
|
-
})
|
|
45
|
-
},
|
|
44
|
+
}),
|
|
46
45
|
|
|
47
|
-
methods: {
|
|
48
46
|
// @override
|
|
49
|
-
|
|
47
|
+
events() {
|
|
50
48
|
const { onFocus, onBlur, onClick } = this
|
|
51
49
|
return { onFocus, onBlur, onClick }
|
|
52
|
-
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
},
|
|
53
53
|
|
|
54
|
+
methods: {
|
|
54
55
|
async submit(options) {
|
|
55
56
|
return this.resourceComponent?.submit(this, options)
|
|
56
57
|
},
|
package/src/types/TypeList.vue
CHANGED
|
@@ -38,86 +38,87 @@
|
|
|
38
38
|
:columns="columns"
|
|
39
39
|
:hasEditButtons="hasEditButtons"
|
|
40
40
|
)
|
|
41
|
-
vue-
|
|
41
|
+
vue-draggable(
|
|
42
42
|
tag="tbody"
|
|
43
|
-
:
|
|
44
|
-
:
|
|
45
|
-
:itemKey="item => getItemUid(schema, item)"
|
|
43
|
+
:modelValue="updateOrder(sourceSchema, listData, paginationRange)"
|
|
44
|
+
@update:modelValue="value => listData = value"
|
|
46
45
|
@start="onStartDrag"
|
|
47
46
|
@end="onEndDrag"
|
|
47
|
+
:v-bind="getDragOptions(draggable)"
|
|
48
48
|
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
v-for="column in columns"
|
|
56
|
-
)
|
|
57
|
-
dito-table-cell(
|
|
58
|
-
v-if="shouldRender(column)"
|
|
59
|
-
:key="column.name"
|
|
60
|
-
:class="getCellClass(column)"
|
|
61
|
-
:cell="column"
|
|
62
|
-
:schema="schema"
|
|
63
|
-
:dataPath="getDataPath(index)"
|
|
64
|
-
:data="item"
|
|
65
|
-
:meta="nestedMeta"
|
|
66
|
-
:store="store"
|
|
67
|
-
:nested="false"
|
|
68
|
-
:disabled="disabled || isLoading"
|
|
69
|
-
)
|
|
49
|
+
tr(
|
|
50
|
+
v-for="item, index in listData"
|
|
51
|
+
:key="getItemUid(schema, item)"
|
|
52
|
+
:id="getDataPath(index)"
|
|
53
|
+
)
|
|
54
|
+
template(v-if="columns")
|
|
70
55
|
template(
|
|
71
|
-
v-
|
|
72
|
-
)
|
|
73
|
-
td
|
|
74
|
-
dito-schema-inlined(
|
|
75
|
-
v-if="isInlined"
|
|
76
|
-
:label="getItemLabel(schema, item, { index, asObject: true })"
|
|
77
|
-
:schema="getItemFormSchema(schema, item, context)"
|
|
78
|
-
:dataPath="getDataPath(index)"
|
|
79
|
-
:data="item"
|
|
80
|
-
:meta="nestedMeta"
|
|
81
|
-
:store="getChildStore(index)"
|
|
82
|
-
:disabled="disabled || isLoading"
|
|
83
|
-
:collapsed="collapsed"
|
|
84
|
-
:collapsible="collapsible"
|
|
85
|
-
:deletable="deletable"
|
|
86
|
-
:draggable="draggable"
|
|
87
|
-
:editable="editable"
|
|
88
|
-
:editPath="getEditPath(item, index)"
|
|
89
|
-
@delete="deleteItem(item, index)"
|
|
90
|
-
)
|
|
91
|
-
component(
|
|
92
|
-
v-else-if="schema.component"
|
|
93
|
-
:is="schema.component"
|
|
94
|
-
:dataPath="getDataPath(index)"
|
|
95
|
-
:data="item"
|
|
96
|
-
:nested="false"
|
|
97
|
-
)
|
|
98
|
-
span(
|
|
99
|
-
v-else-if="render"
|
|
100
|
-
v-html="render(getContext(item, index))"
|
|
101
|
-
)
|
|
102
|
-
span(
|
|
103
|
-
v-else
|
|
104
|
-
v-html="getItemLabel(schema, item, { index })"
|
|
105
|
-
)
|
|
106
|
-
td.dito-cell-edit-buttons(
|
|
107
|
-
v-if="hasCellEditButtons"
|
|
56
|
+
v-for="column in columns"
|
|
108
57
|
)
|
|
109
|
-
dito-
|
|
110
|
-
|
|
111
|
-
:
|
|
112
|
-
:
|
|
113
|
-
:
|
|
58
|
+
dito-table-cell(
|
|
59
|
+
v-if="shouldRender(column)"
|
|
60
|
+
:key="column.name"
|
|
61
|
+
:class="getCellClass(column)"
|
|
62
|
+
:cell="column"
|
|
63
|
+
:schema="schema"
|
|
64
|
+
:dataPath="getDataPath(index)"
|
|
65
|
+
:data="item"
|
|
66
|
+
:meta="nestedMeta"
|
|
67
|
+
:store="store"
|
|
68
|
+
:nested="false"
|
|
69
|
+
:disabled="disabled || isLoading"
|
|
70
|
+
)
|
|
71
|
+
template(
|
|
72
|
+
v-else
|
|
73
|
+
)
|
|
74
|
+
td
|
|
75
|
+
dito-schema-inlined(
|
|
76
|
+
v-if="isInlined"
|
|
77
|
+
:label="getItemLabel(schema, item, { index, asObject: true })"
|
|
114
78
|
:schema="getItemFormSchema(schema, item, context)"
|
|
115
79
|
:dataPath="getDataPath(index)"
|
|
116
80
|
:data="item"
|
|
117
81
|
:meta="nestedMeta"
|
|
118
82
|
:store="getChildStore(index)"
|
|
83
|
+
:disabled="disabled || isLoading"
|
|
84
|
+
:collapsed="collapsed"
|
|
85
|
+
:collapsible="collapsible"
|
|
86
|
+
:deletable="deletable"
|
|
87
|
+
:draggable="draggable"
|
|
88
|
+
:editable="editable"
|
|
89
|
+
:editPath="getEditPath(item, index)"
|
|
119
90
|
@delete="deleteItem(item, index)"
|
|
120
91
|
)
|
|
92
|
+
component(
|
|
93
|
+
v-else-if="schema.component"
|
|
94
|
+
:is="schema.component"
|
|
95
|
+
:dataPath="getDataPath(index)"
|
|
96
|
+
:data="item"
|
|
97
|
+
:nested="false"
|
|
98
|
+
)
|
|
99
|
+
span(
|
|
100
|
+
v-else-if="render"
|
|
101
|
+
v-html="render(getContext(item, index))"
|
|
102
|
+
)
|
|
103
|
+
span(
|
|
104
|
+
v-else
|
|
105
|
+
v-html="getItemLabel(schema, item, { index })"
|
|
106
|
+
)
|
|
107
|
+
td.dito-cell-edit-buttons(
|
|
108
|
+
v-if="hasCellEditButtons"
|
|
109
|
+
)
|
|
110
|
+
dito-edit-buttons(
|
|
111
|
+
:deletable="deletable"
|
|
112
|
+
:draggable="draggable"
|
|
113
|
+
:editable="editable"
|
|
114
|
+
:editPath="getEditPath(item, index)"
|
|
115
|
+
:schema="getItemFormSchema(schema, item, context)"
|
|
116
|
+
:dataPath="getDataPath(index)"
|
|
117
|
+
:data="item"
|
|
118
|
+
:meta="nestedMeta"
|
|
119
|
+
:store="getChildStore(index)"
|
|
120
|
+
@delete="deleteItem(item, index)"
|
|
121
|
+
)
|
|
121
122
|
//- Render create buttons inside table when not in a single component view:
|
|
122
123
|
tfoot(
|
|
123
124
|
v-if="hasListButtons && !single"
|
|
@@ -175,11 +176,11 @@
|
|
|
175
176
|
</style>
|
|
176
177
|
|
|
177
178
|
<script>
|
|
179
|
+
import { VueDraggable } from 'vue-draggable-plus'
|
|
178
180
|
import TypeComponent from '../TypeComponent.js'
|
|
179
181
|
import DitoContext from '../DitoContext.js'
|
|
180
182
|
import SourceMixin from '../mixins/SourceMixin.js'
|
|
181
183
|
import OrderedMixin from '../mixins/OrderedMixin.js'
|
|
182
|
-
import { Sortable as VueSortable } from 'sortablejs-vue3'
|
|
183
184
|
import {
|
|
184
185
|
getNamedSchemas, getViewEditPath,
|
|
185
186
|
resolveSchemaComponent, resolveSchemaComponents
|
|
@@ -190,7 +191,7 @@ import { pickBy, equals, hyphenate } from '@ditojs/utils'
|
|
|
190
191
|
|
|
191
192
|
// @vue/component
|
|
192
193
|
export default TypeComponent.register('list', {
|
|
193
|
-
components: {
|
|
194
|
+
components: { VueDraggable },
|
|
194
195
|
mixins: [SourceMixin, OrderedMixin],
|
|
195
196
|
|
|
196
197
|
getSourceType(type) {
|
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
)
|
|
8
8
|
vue-multiselect(
|
|
9
9
|
ref="element"
|
|
10
|
-
v-model="selectedOptions"
|
|
11
|
-
v-bind="attributes"
|
|
12
10
|
:show-labels="false"
|
|
13
11
|
:placeholder="placeholder"
|
|
14
12
|
tag-placeholder="Press enter to add new tag",
|
|
@@ -25,9 +23,12 @@
|
|
|
25
23
|
:clear-on-select="!searchFilter"
|
|
26
24
|
:close-on-select="!stayOpen"
|
|
27
25
|
:loading="isLoading"
|
|
28
|
-
@open="
|
|
26
|
+
@open="onOpen"
|
|
27
|
+
@close="onClose"
|
|
29
28
|
@tag="onAddTag"
|
|
30
29
|
@search-change="onSearchChange"
|
|
30
|
+
v-model="selectedOptions"
|
|
31
|
+
v-bind="attributes"
|
|
31
32
|
)
|
|
32
33
|
button.dito-button-clear.dito-button-overlay(
|
|
33
34
|
type="button"
|
|
@@ -224,6 +225,7 @@
|
|
|
224
225
|
<script>
|
|
225
226
|
import TypeComponent from '../TypeComponent.js'
|
|
226
227
|
import DitoContext from '../DitoContext.js'
|
|
228
|
+
import TypeMixin from '../mixins/TypeMixin.js'
|
|
227
229
|
import OptionsMixin from '../mixins/OptionsMixin.js'
|
|
228
230
|
import VueMultiselect from 'vue-multiselect'
|
|
229
231
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
@@ -329,6 +331,24 @@ export default TypeComponent.register('multiselect', {
|
|
|
329
331
|
this.$refs.element.activate()
|
|
330
332
|
},
|
|
331
333
|
|
|
334
|
+
onOpen() {
|
|
335
|
+
this.populate = true
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
onClose() {
|
|
339
|
+
// Since we don't fire blur events while the multiselect is open (see
|
|
340
|
+
// below), we need to do it here, when it's actually closed.
|
|
341
|
+
if (this.focused) {
|
|
342
|
+
this.onBlur()
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
onBlur() {
|
|
347
|
+
if (!this.$refs.element.isOpen) {
|
|
348
|
+
TypeMixin.methods.onBlur.call(this)
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
|
|
332
352
|
onAddTag(tag) {
|
|
333
353
|
const option = this.addTagOption(tag)
|
|
334
354
|
if (option) {
|
package/src/types/TypeSwitch.vue
CHANGED
package/src/types/TypeUpload.vue
CHANGED
|
@@ -12,41 +12,42 @@
|
|
|
12
12
|
span Status
|
|
13
13
|
th
|
|
14
14
|
span
|
|
15
|
-
vue-
|
|
15
|
+
vue-draggable(
|
|
16
16
|
tag="tbody"
|
|
17
|
-
:list="files"
|
|
18
|
-
:options="getDragOptions(draggable)"
|
|
19
|
-
itemKey="key"
|
|
20
17
|
@start="onStartDrag"
|
|
21
18
|
@end="onEndDrag"
|
|
19
|
+
v-model="files"
|
|
20
|
+
v-bind="getDragOptions(draggable)"
|
|
22
21
|
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
template(v-else)
|
|
36
|
-
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
22
|
+
tr(
|
|
23
|
+
v-for="(file, index) in files"
|
|
24
|
+
:key="file.key"
|
|
25
|
+
)
|
|
26
|
+
td(v-html="renderFile(file, index)")
|
|
27
|
+
td {{ formatFileSize(file.size) }}
|
|
28
|
+
td
|
|
29
|
+
template(v-if="file.upload")
|
|
30
|
+
template(v-if="file.upload.error")
|
|
31
|
+
| Error: {{ file.upload.error }}
|
|
32
|
+
template(v-else-if="file.upload.active")
|
|
33
|
+
| Uploading...
|
|
34
|
+
template(v-else-if="file.upload.success")
|
|
35
|
+
| Uploaded
|
|
36
|
+
template(v-else)
|
|
37
|
+
| Stored
|
|
38
|
+
td.dito-cell-edit-buttons
|
|
39
|
+
.dito-buttons.dito-buttons-round
|
|
40
|
+
//- Firefox doesn't like <button> here, so use <a> instead:
|
|
41
|
+
a.dito-button(
|
|
42
|
+
v-if="draggable"
|
|
43
|
+
v-bind="getButtonAttributes(verbs.drag)"
|
|
44
|
+
)
|
|
45
|
+
button.dito-button(
|
|
46
|
+
v-if="deletable"
|
|
47
|
+
type="button"
|
|
48
|
+
@click="deleteFile(file, index)"
|
|
49
|
+
v-bind="getButtonAttributes(verbs.delete)"
|
|
50
|
+
)
|
|
50
51
|
tfoot
|
|
51
52
|
tr
|
|
52
53
|
td(:colspan="4")
|
|
@@ -106,11 +107,11 @@
|
|
|
106
107
|
</style>
|
|
107
108
|
|
|
108
109
|
<script>
|
|
110
|
+
import VueUpload from 'vue-upload-component'
|
|
111
|
+
import { VueDraggable } from 'vue-draggable-plus'
|
|
109
112
|
import TypeComponent from '../TypeComponent.js'
|
|
110
113
|
import DitoContext from '../DitoContext.js'
|
|
111
114
|
import OrderedMixin from '../mixins/OrderedMixin.js'
|
|
112
|
-
import VueUpload from 'vue-upload-component'
|
|
113
|
-
import { Sortable as VueSortable } from 'sortablejs-vue3'
|
|
114
115
|
import parseFileSize from 'filesize-parser'
|
|
115
116
|
import { getSchemaAccessor } from '../utils/accessor.js'
|
|
116
117
|
import { formatFileSize } from '../utils/units.js'
|
|
@@ -119,7 +120,7 @@ import { isArray, asArray, escapeHtml } from '@ditojs/utils'
|
|
|
119
120
|
|
|
120
121
|
// @vue/component
|
|
121
122
|
export default TypeComponent.register('upload', {
|
|
122
|
-
components: { VueUpload,
|
|
123
|
+
components: { VueUpload, VueDraggable },
|
|
123
124
|
mixins: [OrderedMixin],
|
|
124
125
|
|
|
125
126
|
data() {
|