@ditojs/admin 2.2.12 → 2.2.14
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 +2264 -2184
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +4 -3
- package/src/components/DitoButtons.vue +1 -1
- package/src/components/DitoContainer.vue +26 -16
- package/src/components/DitoCreateButton.vue +2 -2
- package/src/components/DitoDialog.vue +1 -0
- package/src/components/DitoForm.vue +10 -0
- package/src/components/DitoLabel.vue +41 -34
- package/src/components/DitoPane.vue +1 -1
- package/src/components/DitoPanel.vue +1 -0
- package/src/components/DitoPanels.vue +1 -1
- package/src/components/DitoRoot.vue +10 -1
- package/src/components/DitoSchema.vue +28 -11
- package/src/components/DitoSidebar.vue +1 -1
- package/src/components/DitoTableHead.vue +1 -1
- package/src/components/DitoTabs.vue +1 -1
- package/src/components/DitoView.vue +6 -3
- package/src/mixins/DitoMixin.js +11 -46
- package/src/mixins/SourceMixin.js +1 -1
- package/src/mixins/TypeMixin.js +3 -16
- package/src/styles/_info.scss +32 -0
- package/src/styles/style.scss +1 -0
- package/src/types/DitoTypeButton.vue +41 -1
- package/src/types/DitoTypeList.vue +1 -1
- package/src/utils/schema.js +80 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.14",
|
|
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,7 +33,7 @@
|
|
|
33
33
|
"not ie_mob > 0"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ditojs/ui": "^2.2.
|
|
36
|
+
"@ditojs/ui": "^2.2.14",
|
|
37
37
|
"@ditojs/utils": "^2.2.0",
|
|
38
38
|
"@kyvg/vue3-notification": "^2.9.0",
|
|
39
39
|
"@lk77/vue3-color": "^3.0.6",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"nanoid": "^4.0.2",
|
|
67
67
|
"sortablejs": "^1.15.0",
|
|
68
68
|
"tinycolor2": "^1.6.0",
|
|
69
|
+
"tippy.js": "^6.3.7",
|
|
69
70
|
"type-fest": "^3.8.0",
|
|
70
71
|
"vue": "^3.2.47",
|
|
71
72
|
"vue-multiselect": "^3.0.0-beta.1",
|
|
@@ -82,7 +83,7 @@
|
|
|
82
83
|
"vite": "^4.3.1"
|
|
83
84
|
},
|
|
84
85
|
"types": "types",
|
|
85
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "71b48376ab32cc6ef6cd77bc565501ac264683d7",
|
|
86
87
|
"scripts": {
|
|
87
88
|
"build": "vite build",
|
|
88
89
|
"watch": "yarn build --mode 'development' --watch",
|
|
@@ -6,21 +6,24 @@
|
|
|
6
6
|
)
|
|
7
7
|
DitoLabel(
|
|
8
8
|
v-if="hasLabel"
|
|
9
|
+
:class="componentClass"
|
|
9
10
|
:label="label"
|
|
10
11
|
:dataPath="labelDataPath"
|
|
11
|
-
:
|
|
12
|
+
:info="info"
|
|
12
13
|
)
|
|
13
14
|
component.dito-component(
|
|
14
15
|
:is="typeComponent"
|
|
16
|
+
:class="componentClass"
|
|
15
17
|
:schema="schema"
|
|
16
18
|
:dataPath="dataPath"
|
|
17
19
|
:data="data"
|
|
18
20
|
:meta="meta"
|
|
19
21
|
:store="store"
|
|
22
|
+
:width="width"
|
|
23
|
+
:label="label"
|
|
20
24
|
:single="single"
|
|
21
25
|
:nested="nested"
|
|
22
26
|
:disabled="componentDisabled"
|
|
23
|
-
:class="componentClass"
|
|
24
27
|
@errors="onErrors"
|
|
25
28
|
)
|
|
26
29
|
DitoErrors(:errors="errors")
|
|
@@ -84,7 +87,12 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
84
87
|
return this.nested ? this.dataPath : null
|
|
85
88
|
},
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
info: getSchemaAccessor('info', {
|
|
91
|
+
type: String,
|
|
92
|
+
default: null
|
|
93
|
+
}),
|
|
94
|
+
|
|
95
|
+
width: getSchemaAccessor('width', {
|
|
88
96
|
type: [String, Number],
|
|
89
97
|
default() {
|
|
90
98
|
return this.typeComponent?.defaultWidth
|
|
@@ -99,7 +107,7 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
99
107
|
}
|
|
100
108
|
}),
|
|
101
109
|
|
|
102
|
-
|
|
110
|
+
widthOperator: getSchemaAccessor('width', {
|
|
103
111
|
type: String,
|
|
104
112
|
get(width) {
|
|
105
113
|
return isString(width)
|
|
@@ -143,7 +151,7 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
143
151
|
},
|
|
144
152
|
|
|
145
153
|
componentBasis() {
|
|
146
|
-
const width = this.
|
|
154
|
+
const width = this.width
|
|
147
155
|
// 'auto' = no fitting:
|
|
148
156
|
const basis = [null, 'auto', 'fill'].includes(width)
|
|
149
157
|
? 'auto'
|
|
@@ -158,11 +166,11 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
158
166
|
containerStyle() {
|
|
159
167
|
// Interpret '>50%' as '50%, flex-grow: 1`
|
|
160
168
|
const grow = (
|
|
161
|
-
this.
|
|
162
|
-
this.
|
|
169
|
+
this.widthOperator === '>' ||
|
|
170
|
+
this.width === 'fill'
|
|
163
171
|
)
|
|
164
172
|
// Interpret '<50%' as '50%, flex-shrink: 1`
|
|
165
|
-
const shrink = this.
|
|
173
|
+
const shrink = this.widthOperator === '<'
|
|
166
174
|
return {
|
|
167
175
|
flex: `${grow ? 1 : 0} ${shrink ? 1 : 0} ${this.componentBasis}`
|
|
168
176
|
}
|
|
@@ -174,7 +182,7 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
174
182
|
// TODO: BEM?
|
|
175
183
|
'dito-single': this.single,
|
|
176
184
|
'dito-disabled': this.componentDisabled,
|
|
177
|
-
'dito-width-fill': !basisIsAuto || this.
|
|
185
|
+
'dito-width-fill': !basisIsAuto || this.width === 'fill',
|
|
178
186
|
'dito-has-errors': !!this.errors
|
|
179
187
|
}
|
|
180
188
|
}
|
|
@@ -226,13 +234,15 @@ export default DitoComponent.component('DitoContainer', {
|
|
|
226
234
|
--justify: flex-end;
|
|
227
235
|
}
|
|
228
236
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
237
|
+
&:not(#{$self}--only-in-row) {
|
|
238
|
+
// Now only apply alignment if there are neighbouring components no the
|
|
239
|
+
// same row that also align.
|
|
240
|
+
// Look ahead:
|
|
241
|
+
&:not(#{$self}--last-in-row) + #{&}:not(#{$self}--first-in-row),
|
|
242
|
+
// Look behind:
|
|
243
|
+
&:not(#{$self}--last-in-row):has(+ #{&}:not(#{$self}--first-in-row)) {
|
|
244
|
+
justify-content: var(--justify);
|
|
245
|
+
}
|
|
236
246
|
}
|
|
237
247
|
}
|
|
238
248
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
v-for="(form, type) in forms"
|
|
15
15
|
)
|
|
16
16
|
a(
|
|
17
|
-
v-if="
|
|
17
|
+
v-if="shouldRenderSchema(form)"
|
|
18
18
|
v-show="shouldShow(form)"
|
|
19
19
|
:class="getFormClass(form, type)"
|
|
20
20
|
@mousedown.stop="onPulldownMouseDown(type)"
|
|
@@ -61,7 +61,7 @@ export default DitoComponent.component('DitoCreateButton', {
|
|
|
61
61
|
|
|
62
62
|
methods: {
|
|
63
63
|
createItem(form, type = null) {
|
|
64
|
-
if (this.
|
|
64
|
+
if (this.shouldRenderSchema(form) && !this.shouldDisable(form)) {
|
|
65
65
|
if (this.isInlined) {
|
|
66
66
|
this.sourceComponent.createItem(form, type)
|
|
67
67
|
} else {
|
|
@@ -283,6 +283,16 @@ export default DitoComponent.component('DitoForm', {
|
|
|
283
283
|
},
|
|
284
284
|
|
|
285
285
|
watch: {
|
|
286
|
+
$route(to, from) {
|
|
287
|
+
// Reload form data when navigating to a different entity in same form.
|
|
288
|
+
if (this.providesData) {
|
|
289
|
+
const { param } = this.meta
|
|
290
|
+
if (param && to.params[param] !== from.params[param]) {
|
|
291
|
+
this.loadData(true)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
|
|
286
296
|
sourceData: 'clearClonedData',
|
|
287
297
|
// Needed for the 'create' redirect in `inheritedData()` to work:
|
|
288
298
|
create: 'setupData'
|
|
@@ -9,22 +9,28 @@ component.dito-label(
|
|
|
9
9
|
v-if="collapsible"
|
|
10
10
|
:class="{ 'dito-opened': !collapsed }"
|
|
11
11
|
)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
.dito-label__inner
|
|
13
|
+
DitoElement.dito-label-prefix(
|
|
14
|
+
v-for="(prefix, index) of prefixes"
|
|
15
|
+
:key="`prefix-${index}`"
|
|
16
|
+
tag="span"
|
|
17
|
+
:content="prefix"
|
|
18
|
+
)
|
|
19
|
+
label(
|
|
20
|
+
:for="dataPath"
|
|
21
|
+
v-html="text"
|
|
22
|
+
)
|
|
23
|
+
DitoElement.dito-label-suffix(
|
|
24
|
+
v-for="(suffix, index) of suffixes"
|
|
25
|
+
:key="`suffix-${index}`"
|
|
26
|
+
tag="span"
|
|
27
|
+
:content="suffix"
|
|
28
|
+
)
|
|
29
|
+
.dito-info(
|
|
30
|
+
v-if="info"
|
|
31
|
+
:data-tippy-content="info"
|
|
32
|
+
data-tippy-theme="info"
|
|
33
|
+
)
|
|
28
34
|
slot(name="edit-buttons")
|
|
29
35
|
</template>
|
|
30
36
|
|
|
@@ -40,7 +46,8 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
40
46
|
label: { type: [String, Object], default: null },
|
|
41
47
|
dataPath: { type: String, default: null },
|
|
42
48
|
collapsed: { type: Boolean, default: false },
|
|
43
|
-
collapsible: { type: Boolean, default: false }
|
|
49
|
+
collapsible: { type: Boolean, default: false },
|
|
50
|
+
info: { type: String, default: null }
|
|
44
51
|
},
|
|
45
52
|
|
|
46
53
|
computed: {
|
|
@@ -83,6 +90,8 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
83
90
|
@import '../styles/_imports';
|
|
84
91
|
|
|
85
92
|
.dito-label {
|
|
93
|
+
$self: &;
|
|
94
|
+
|
|
86
95
|
--label-padding: 0;
|
|
87
96
|
// For buttons and chevron to align right:
|
|
88
97
|
display: flex;
|
|
@@ -92,8 +101,13 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
92
101
|
padding: var(--label-padding);
|
|
93
102
|
margin: 0 0 $form-spacing-half 0;
|
|
94
103
|
|
|
104
|
+
&__inner {
|
|
105
|
+
display: flex;
|
|
106
|
+
// Stretch to full available width so that buttons appear right-aligned:
|
|
107
|
+
flex: 1 1 auto;
|
|
108
|
+
}
|
|
109
|
+
|
|
95
110
|
label {
|
|
96
|
-
display: inline;
|
|
97
111
|
cursor: inherit;
|
|
98
112
|
font-weight: bold;
|
|
99
113
|
white-space: nowrap;
|
|
@@ -102,23 +116,14 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
102
116
|
label,
|
|
103
117
|
.dito-label-prefix,
|
|
104
118
|
.dito-label-suffix {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// so that buttons always appear right-aligned:
|
|
108
|
-
flex: 1 1 auto;
|
|
109
|
-
}
|
|
119
|
+
@include user-select(none);
|
|
120
|
+
@include ellipsis;
|
|
110
121
|
|
|
111
122
|
&::after {
|
|
112
|
-
content: '\a0'; //  
|
|
123
|
+
content: '\a0'; //
|
|
113
124
|
}
|
|
114
125
|
}
|
|
115
126
|
|
|
116
|
-
.dito-label-prefix,
|
|
117
|
-
.dito-label-suffix {
|
|
118
|
-
@include user-select(none);
|
|
119
|
-
@include ellipsis;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
127
|
.dito-buttons {
|
|
123
128
|
// Move the label padding inside .dito-buttons, so that it captures all
|
|
124
129
|
// near mouse events:
|
|
@@ -131,11 +136,9 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
131
136
|
width: 100%;
|
|
132
137
|
// In order for ellipsis to work on labels without affecting other layout,
|
|
133
138
|
// we need to position it absolutely inside its container.
|
|
134
|
-
|
|
135
|
-
@include ellipsis;
|
|
136
|
-
|
|
139
|
+
#{$self}__inner {
|
|
137
140
|
position: absolute;
|
|
138
|
-
|
|
141
|
+
inset: 0;
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
&::after {
|
|
@@ -144,6 +147,10 @@ export default DitoComponent.component('DitoLabel', {
|
|
|
144
147
|
content: '\200b'; // zero-width space;
|
|
145
148
|
}
|
|
146
149
|
}
|
|
150
|
+
|
|
151
|
+
.dito-info {
|
|
152
|
+
margin-left: 0.35em;
|
|
153
|
+
}
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
a.dito-label {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
36
|
<script>
|
|
37
|
+
import { delegate as tippyDelegate } from 'tippy.js'
|
|
37
38
|
import { asArray, mapConcurrently, stripTags } from '@ditojs/utils'
|
|
38
39
|
import DitoComponent from '../DitoComponent.js'
|
|
39
40
|
import DitoUser from '../DitoUser.js'
|
|
@@ -90,6 +91,9 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
90
91
|
},
|
|
91
92
|
|
|
92
93
|
async mounted() {
|
|
94
|
+
tippyDelegate(this.$el, {
|
|
95
|
+
target: '[data-tippy-content]'
|
|
96
|
+
})
|
|
93
97
|
// Clear the label marked as active on all mouse and keyboard events, except
|
|
94
98
|
// the ones that DitoLabel itself intercepts.
|
|
95
99
|
this.domOn(document, {
|
|
@@ -172,7 +176,12 @@ export default DitoComponent.component('DitoRoot', {
|
|
|
172
176
|
async (resolve, reject) => {
|
|
173
177
|
// Process components to resolve async schemas.
|
|
174
178
|
const routes = []
|
|
175
|
-
await processSchemaComponents(
|
|
179
|
+
await processSchemaComponents(
|
|
180
|
+
this.api,
|
|
181
|
+
{ type: 'dialog', components },
|
|
182
|
+
routes,
|
|
183
|
+
0
|
|
184
|
+
)
|
|
176
185
|
if (routes.length > 0) {
|
|
177
186
|
throw new Error(
|
|
178
187
|
'Dialogs do not support components that produce routes'
|
|
@@ -155,6 +155,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
155
155
|
? data(this.context)
|
|
156
156
|
: data
|
|
157
157
|
),
|
|
158
|
+
currentTab: null,
|
|
158
159
|
componentsRegistry: {},
|
|
159
160
|
panesRegistry: {},
|
|
160
161
|
panelsRegistry: {}
|
|
@@ -187,17 +188,7 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
187
188
|
},
|
|
188
189
|
|
|
189
190
|
selectedTab() {
|
|
190
|
-
|
|
191
|
-
const tab =
|
|
192
|
-
currentTab && this.shouldRender(this.tabs[currentTab])
|
|
193
|
-
? currentTab
|
|
194
|
-
: this.defaultTab?.name || null
|
|
195
|
-
if (tab !== currentTab) {
|
|
196
|
-
// TODO: Move this watcher!
|
|
197
|
-
// Any tab change needs to be reflected in the router also.
|
|
198
|
-
this.$router.replace({ hash: `#${tab}` })
|
|
199
|
-
}
|
|
200
|
-
return tab
|
|
191
|
+
return this.currentTab || this.defaultTab?.name || null
|
|
201
192
|
},
|
|
202
193
|
|
|
203
194
|
defaultTab() {
|
|
@@ -336,6 +327,32 @@ export default DitoComponent.component('DitoSchema', {
|
|
|
336
327
|
}
|
|
337
328
|
},
|
|
338
329
|
|
|
330
|
+
watch: {
|
|
331
|
+
'$route.hash': {
|
|
332
|
+
immediate: true,
|
|
333
|
+
handler(hash) {
|
|
334
|
+
if (this.hasTabs) {
|
|
335
|
+
this.currentTab = hash?.slice(1) || null
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
|
|
340
|
+
'selectedTab'(selectedTab) {
|
|
341
|
+
if (this.hasTabs) {
|
|
342
|
+
let tab = null
|
|
343
|
+
if (selectedTab !== this.currentTab) {
|
|
344
|
+
// Any tab change needs to be reflected in the router also.
|
|
345
|
+
tab = selectedTab
|
|
346
|
+
} else if (!this.shouldRenderSchema(this.tabs[selectedTab])) {
|
|
347
|
+
tab = this.defaultTab?.name
|
|
348
|
+
}
|
|
349
|
+
if (tab) {
|
|
350
|
+
this.$router.replace({ hash: `#${tab}` })
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
|
|
339
356
|
created() {
|
|
340
357
|
this._register(true)
|
|
341
358
|
this.setupSchemaFields()
|
|
@@ -11,7 +11,7 @@ template(
|
|
|
11
11
|
:key="name"
|
|
12
12
|
)
|
|
13
13
|
.dito-view.dito-scroll-parent(
|
|
14
|
-
v-else-if="
|
|
14
|
+
v-else-if="shouldRenderSchema(viewSchema)"
|
|
15
15
|
:data-resource="sourceSchema.path"
|
|
16
16
|
)
|
|
17
17
|
DitoSchema(
|
|
@@ -28,7 +28,10 @@ template(
|
|
|
28
28
|
<script>
|
|
29
29
|
import DitoComponent from '../DitoComponent.js'
|
|
30
30
|
import RouteMixin from '../mixins/RouteMixin.js'
|
|
31
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
isSingleComponentView,
|
|
33
|
+
someNestedSchemaComponent
|
|
34
|
+
} from '../utils/schema.js'
|
|
32
35
|
import { hasResource } from '../utils/resource.js'
|
|
33
36
|
|
|
34
37
|
// @vue/component
|
|
@@ -93,7 +96,7 @@ export default DitoComponent.component('DitoView', {
|
|
|
93
96
|
},
|
|
94
97
|
|
|
95
98
|
providesData() {
|
|
96
|
-
return
|
|
99
|
+
return someNestedSchemaComponent(this.viewSchema, hasResource)
|
|
97
100
|
}
|
|
98
101
|
},
|
|
99
102
|
|
package/src/mixins/DitoMixin.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isObject,
|
|
3
|
-
isArray,
|
|
4
3
|
isString,
|
|
5
4
|
isFunction,
|
|
6
|
-
asArray,
|
|
7
5
|
equals,
|
|
8
|
-
getValueAtDataPath,
|
|
9
6
|
labelize,
|
|
10
7
|
hyphenate,
|
|
11
8
|
format
|
|
@@ -13,7 +10,7 @@ import {
|
|
|
13
10
|
import appState from '../appState.js'
|
|
14
11
|
import DitoContext from '../DitoContext.js'
|
|
15
12
|
import EmitterMixin from './EmitterMixin.js'
|
|
16
|
-
import {
|
|
13
|
+
import { getSchemaValue, shouldRenderSchema } from '../utils/schema.js'
|
|
17
14
|
import { getResource, getMemberResource } from '../utils/resource.js'
|
|
18
15
|
import { computed, reactive } from 'vue'
|
|
19
16
|
|
|
@@ -201,43 +198,15 @@ export default {
|
|
|
201
198
|
|
|
202
199
|
getSchemaValue(
|
|
203
200
|
keyOrDataPath,
|
|
204
|
-
{ type,
|
|
201
|
+
{ type, schema = this.schema, callback = true, default: def } = {}
|
|
205
202
|
) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
: undefined
|
|
214
|
-
|
|
215
|
-
if (value === undefined && def !== undefined) {
|
|
216
|
-
if (callback && isFunction(def) && !isMatchingType(types, def)) {
|
|
217
|
-
// Support `default()` functions for any type except `Function`:
|
|
218
|
-
def = def.call(this)
|
|
219
|
-
}
|
|
220
|
-
return def
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (isMatchingType(types, value)) {
|
|
224
|
-
return value
|
|
225
|
-
}
|
|
226
|
-
// Any schema value handled through `getSchemaValue()` can provide
|
|
227
|
-
// a function that's resolved when the value is evaluated:
|
|
228
|
-
if (callback && isFunction(value)) {
|
|
229
|
-
value = value(this.context)
|
|
230
|
-
}
|
|
231
|
-
// Now finally see if we can convert to the expect types.
|
|
232
|
-
if (types && value != null && !isMatchingType(types, value)) {
|
|
233
|
-
for (const type of types) {
|
|
234
|
-
const converted = convertType(type, value)
|
|
235
|
-
if (converted !== value) {
|
|
236
|
-
return converted
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return value
|
|
203
|
+
return getSchemaValue(keyOrDataPath, {
|
|
204
|
+
type,
|
|
205
|
+
schema,
|
|
206
|
+
callback,
|
|
207
|
+
context: this.context,
|
|
208
|
+
default: isFunction(def) ? () => def.call(this) : def
|
|
209
|
+
})
|
|
241
210
|
},
|
|
242
211
|
|
|
243
212
|
getLabel(schema, name) {
|
|
@@ -263,12 +232,8 @@ export default {
|
|
|
263
232
|
}
|
|
264
233
|
},
|
|
265
234
|
|
|
266
|
-
|
|
267
|
-
return
|
|
268
|
-
type: Boolean,
|
|
269
|
-
default: true,
|
|
270
|
-
schema
|
|
271
|
-
})
|
|
235
|
+
shouldRenderSchema(schema = null) {
|
|
236
|
+
return shouldRenderSchema(schema, this.context)
|
|
272
237
|
},
|
|
273
238
|
|
|
274
239
|
shouldShow(schema = null) {
|
|
@@ -314,7 +314,7 @@ export default {
|
|
|
314
314
|
|
|
315
315
|
watch: {
|
|
316
316
|
$route(to, from) {
|
|
317
|
-
if (from.path === to.path && from.hash === to.hash) {
|
|
317
|
+
if (this.providesData && from.path === to.path && from.hash === to.hash) {
|
|
318
318
|
// Paths and hashes remain the same, so only queries have changed.
|
|
319
319
|
// Update filter and reload data without clearing.
|
|
320
320
|
this.query = to.query
|
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 {
|
|
6
|
+
import { asArray, camelize } from '@ditojs/utils'
|
|
7
7
|
|
|
8
8
|
// @vue/component
|
|
9
9
|
export default {
|
|
@@ -17,6 +17,8 @@ export default {
|
|
|
17
17
|
data: { type: [Object, Array], required: true },
|
|
18
18
|
meta: { type: Object, required: true },
|
|
19
19
|
store: { type: Object, required: true },
|
|
20
|
+
width: { type: [Number, String], default: null },
|
|
21
|
+
label: { type: String, default: null },
|
|
20
22
|
single: { type: Boolean, default: false },
|
|
21
23
|
nested: { type: Boolean, default: true },
|
|
22
24
|
disabled: { type: Boolean, default: false }
|
|
@@ -109,21 +111,6 @@ export default {
|
|
|
109
111
|
return this.processedData
|
|
110
112
|
},
|
|
111
113
|
|
|
112
|
-
label: getSchemaAccessor('label', {
|
|
113
|
-
type: [String, Boolean],
|
|
114
|
-
get(label) {
|
|
115
|
-
return isString(label)
|
|
116
|
-
? label
|
|
117
|
-
: label !== false && this.$options.generateLabel
|
|
118
|
-
? this.getLabel(this.schema)
|
|
119
|
-
: null
|
|
120
|
-
}
|
|
121
|
-
}),
|
|
122
|
-
|
|
123
|
-
width: getSchemaAccessor('width', {
|
|
124
|
-
type: [String, Number]
|
|
125
|
-
}),
|
|
126
|
-
|
|
127
114
|
visible: getSchemaAccessor('visible', {
|
|
128
115
|
type: Boolean,
|
|
129
116
|
default() {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.dito-info {
|
|
2
|
+
--size: calc(1em * var(--line-height));
|
|
3
|
+
|
|
4
|
+
display: inline-block;
|
|
5
|
+
position: relative;
|
|
6
|
+
flex: 0 0 var(--size);
|
|
7
|
+
width: var(--size);
|
|
8
|
+
height: var(--size);
|
|
9
|
+
text-align: center;
|
|
10
|
+
vertical-align: top;
|
|
11
|
+
margin-left: 0.35em;
|
|
12
|
+
color: $color-active;
|
|
13
|
+
|
|
14
|
+
&::before {
|
|
15
|
+
@extend %icon-info;
|
|
16
|
+
|
|
17
|
+
width: var(--size);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.tippy-box[data-theme~='info'] {
|
|
22
|
+
background-color: $color-active;
|
|
23
|
+
color: $color-white;
|
|
24
|
+
|
|
25
|
+
> .tippy-arrow::before {
|
|
26
|
+
color: $color-active;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.tippy-content {
|
|
30
|
+
white-space: pre-line;
|
|
31
|
+
}
|
|
32
|
+
}
|