@ditojs/admin 2.3.0 → 2.3.2

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.
@@ -5,37 +5,48 @@
5
5
  'dito-multiselect-multiple': multiple
6
6
  }`
7
7
  )
8
- VueMultiselect(
9
- ref="element"
10
- v-model="selectedOptions"
11
- :class="{ 'multiselect--show-highlight': showHighlight }"
12
- :showLabels="false"
13
- :placeholder="placeholder"
14
- tagPlaceholder="Press enter to add new tag"
15
- :options="populate && activeOptions || []"
16
- :customLabel="getLabelForOption"
17
- :trackBy="optionValue"
18
- :groupLabel="groupByLabel"
19
- :groupValues="groupByOptions"
20
- :multiple="multiple"
21
- :taggable="taggable"
22
- :searchable="searchable"
23
- :internalSearch="!searchFilter"
24
- :preserveSearch="!!searchFilter"
25
- :clearOnSelect="!searchFilter"
26
- :closeOnSelect="!stayOpen"
27
- :loading="isLoading"
28
- v-bind="attributes"
29
- @open="onOpen"
30
- @close="onClose"
31
- @tag="onAddTag"
32
- @search-change="onSearchChange"
33
- )
34
- button.dito-button-clear.dito-button-overlay(
35
- v-if="showClearButton"
36
- type="button"
37
- :disabled="disabled"
38
- @click="clear"
8
+ .dito-multiselect__inner
9
+ VueMultiselect(
10
+ ref="element"
11
+ v-model="selectedOptions"
12
+ :class="{ 'multiselect--show-highlight': showHighlight }"
13
+ :showLabels="false"
14
+ :placeholder="placeholder"
15
+ tagPlaceholder="Press enter to add new tag"
16
+ :options="populate && activeOptions || []"
17
+ :customLabel="getLabelForOption"
18
+ :trackBy="optionValue"
19
+ :groupLabel="groupByLabel"
20
+ :groupValues="groupByOptions"
21
+ :multiple="multiple"
22
+ :taggable="taggable"
23
+ :searchable="searchable"
24
+ :internalSearch="!searchFilter"
25
+ :preserveSearch="!!searchFilter"
26
+ :clearOnSelect="!searchFilter"
27
+ :closeOnSelect="!stayOpen"
28
+ :loading="isLoading"
29
+ v-bind="attributes"
30
+ @open="onOpen"
31
+ @close="onClose"
32
+ @tag="onAddTag"
33
+ @search-change="onSearchChange"
34
+ )
35
+ button.dito-button-clear.dito-button-overlay(
36
+ v-if="showClearButton"
37
+ type="button"
38
+ :disabled="disabled"
39
+ @click="clear"
40
+ )
41
+ DitoEditButtons(
42
+ v-if="editable"
43
+ :editable="editable"
44
+ :editPath="editPath"
45
+ :schema="schema"
46
+ :dataPath="dataPath"
47
+ :data="data"
48
+ :meta="meta"
49
+ :store="store"
39
50
  )
40
51
  </template>
41
52
 
@@ -218,12 +229,20 @@ $tag-padding: 3px;
218
229
  $tag-line-height: 1em;
219
230
 
220
231
  .dito-multiselect {
232
+ display: inline-flex;
221
233
  position: relative;
222
234
 
235
+ &__inner {
236
+ flex: 1;
237
+ position: relative;
238
+ }
239
+
240
+ // TODO: BEM
223
241
  &.dito-multiselect-single {
224
242
  --input-width: 100%;
225
243
  }
226
244
 
245
+ // TODO: BEM
227
246
  &.dito-multiselect-multiple {
228
247
  --input-width: auto;
229
248
  }
@@ -234,6 +253,10 @@ $tag-line-height: 1em;
234
253
  }
235
254
  }
236
255
 
256
+ .dito-edit-buttons {
257
+ margin-left: $form-spacing-half;
258
+ }
259
+
237
260
  .dito-button-clear {
238
261
  width: $spinner-width;
239
262
  }
@@ -1,40 +1,51 @@
1
1
  <template lang="pug">
2
2
  //- Nesting is needed to make an arrow appear over the select item:
3
3
  .dito-select
4
- select(
5
- :id="dataPath"
6
- ref="element"
7
- v-model="selectedValue"
8
- v-bind="attributes"
9
- @mousedown="populate = true"
10
- @focus="populate = true"
11
- )
12
- template(
13
- v-if="populate"
4
+ .dito-select__inner
5
+ select(
6
+ :id="dataPath"
7
+ ref="element"
8
+ v-model="selectedValue"
9
+ v-bind="attributes"
10
+ @mousedown="populate = true"
11
+ @focus="populate = true"
14
12
  )
15
13
  template(
16
- v-for="option in options"
14
+ v-if="populate"
17
15
  )
18
- optgroup(
19
- v-if="groupBy"
20
- :label="option[groupByLabel]"
16
+ template(
17
+ v-for="option in options"
21
18
  )
19
+ optgroup(
20
+ v-if="groupBy"
21
+ :label="option[groupByLabel]"
22
+ )
23
+ option(
24
+ v-for="opt in option[groupByOptions]"
25
+ :value="getValueForOption(opt)"
26
+ ) {{ getLabelForOption(opt) }}
22
27
  option(
23
- v-for="opt in option[groupByOptions]"
24
- :value="getValueForOption(opt)"
25
- ) {{ getLabelForOption(opt) }}
26
- option(
27
- v-else
28
- :value="getValueForOption(option)"
29
- ) {{ getLabelForOption(option) }}
30
- template(
31
- v-else-if="selectedOption"
28
+ v-else
29
+ :value="getValueForOption(option)"
30
+ ) {{ getLabelForOption(option) }}
31
+ template(
32
+ v-else-if="selectedOption"
33
+ )
34
+ option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
35
+ button.dito-button-clear.dito-button-overlay(
36
+ v-if="showClearButton"
37
+ :disabled="disabled"
38
+ @click="clear"
32
39
  )
33
- option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
34
- button.dito-button-clear.dito-button-overlay(
35
- v-if="showClearButton"
36
- :disabled="disabled"
37
- @click="clear"
40
+ DitoEditButtons(
41
+ v-if="editable"
42
+ :editable="editable"
43
+ :editPath="editPath"
44
+ :schema="schema"
45
+ :dataPath="dataPath"
46
+ :data="data"
47
+ :meta="meta"
48
+ :store="store"
38
49
  )
39
50
  </template>
40
51
 
@@ -65,12 +76,30 @@ export default DitoTypeComponent.register('select', {
65
76
  $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
66
77
 
67
78
  .dito-select {
68
- display: inline-block;
79
+ display: inline-flex;
69
80
  position: relative;
70
81
 
71
82
  select {
72
83
  padding-right: $select-arrow-width;
73
84
  }
85
+
86
+ &__inner {
87
+ flex: 1;
88
+ position: relative;
89
+
90
+ &::after {
91
+ position: absolute;
92
+ @include arrow($select-arrow-size);
93
+
94
+ bottom: $select-arrow-bottom;
95
+ right: calc(#{$select-arrow-right} + #{$border-width});
96
+ }
97
+ }
98
+
99
+ .dito-edit-buttons {
100
+ margin-left: $form-spacing-half;
101
+ }
102
+
74
103
  // Handle .dito-width-fill separately due to required nesting of select:
75
104
  &.dito-width-fill {
76
105
  select {
@@ -78,14 +107,6 @@ $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
78
107
  }
79
108
  }
80
109
 
81
- &::after {
82
- position: absolute;
83
- @include arrow($select-arrow-size);
84
-
85
- bottom: $select-arrow-bottom;
86
- right: calc(#{$select-arrow-right} + #{$border-width});
87
- }
88
-
89
110
  &.dito-disabled::after {
90
111
  border-color: $border-color;
91
112
  }
@@ -113,6 +113,10 @@ export function isPanel(schema) {
113
113
  return isSchema(schema) && schema.type === 'panel'
114
114
  }
115
115
 
116
+ export function isMenu(schema) {
117
+ return isSchema(schema) && schema.type === 'menu'
118
+ }
119
+
116
120
  export function getSchemaIdentifier(schema) {
117
121
  return JSON.stringify(schema)
118
122
  }
@@ -176,6 +180,19 @@ export async function resolveSchemas(
176
180
  return schemas
177
181
  }
178
182
 
183
+ export async function resolveViews(unresolvedViews) {
184
+ return resolveSchemas(unresolvedViews, async (schema, unwrapModule) => {
185
+ schema = await resolveSchema(schema, unwrapModule)
186
+ if (!schema.name && isMenu(schema)) {
187
+ // Generate a name for sub-menus from their label if it's missing.
188
+ // NOTE: This is never actually referenced from anywhere, but they need
189
+ // a name by which they're stored in the parent object.
190
+ schema.name = camelize(schema.label)
191
+ }
192
+ return schema
193
+ })
194
+ }
195
+
179
196
  export async function resolveSchemaComponent(schema) {
180
197
  // Resolves async schema components and adds DitoMixin and TypeMixin to them.
181
198
  let { component } = schema
@@ -250,22 +267,31 @@ export async function processSchemaComponent(
250
267
  }
251
268
 
252
269
  export async function processView(component, api, schema, name) {
253
- if (!isView(schema)) {
254
- throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
255
- }
256
- processRouteSchema(api, schema, name)
257
270
  processSchemaDefaults(api, schema)
258
- await processNestedSchemas(api, schema)
259
- const children = []
260
- await processSchemaComponents(api, schema, children, 0)
261
- return {
262
- path: `/${schema.path}`,
263
- children,
264
- component,
265
- meta: {
266
- api,
267
- schema
271
+ if (isView(schema)) {
272
+ processRouteSchema(api, schema, name)
273
+ await processNestedSchemas(api, schema)
274
+ const children = []
275
+ await processSchemaComponents(api, schema, children, 0)
276
+ return {
277
+ path: `/${schema.path}`,
278
+ children,
279
+ component,
280
+ meta: {
281
+ api,
282
+ schema
283
+ }
268
284
  }
285
+ } else if (isMenu(schema)) {
286
+ schema.items = await resolveSchemas(schema.items)
287
+ return Promise.all(
288
+ Object.entries(schema.items).map(async ([name, item]) =>
289
+ processView(component, api, item, name)
290
+ )
291
+ )
292
+ //
293
+ } else {
294
+ throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
269
295
  }
270
296
  }
271
297
 
@@ -303,8 +329,8 @@ export function processNestedSchemaDefaults(api, schema) {
303
329
 
304
330
  export function processRouteSchema(api, schema, name) {
305
331
  // Used for view and source schemas, see SourceMixin.
306
- schema.name = name
307
- schema.path ||= api.normalizePath(name)
332
+ schema.name ??= name
333
+ schema.path ??= api.normalizePath(name)
308
334
  }
309
335
 
310
336
  export async function processForms(api, schema, level) {
@@ -416,13 +442,19 @@ export function getViewSchema(schema, context) {
416
442
  : null
417
443
  }
418
444
 
419
- export function getViewEditPath(schema, context) {
445
+ export function hasViewSchema(schema, context) {
446
+ return !!getViewSchema(schema, context)
447
+ }
448
+
449
+ export function getViewEditPath(schema, id, context) {
420
450
  const view = getViewSchema(schema, context)
421
- return view
422
- ? isSingleComponentView(view)
451
+ if (view) {
452
+ const path = isSingleComponentView(view)
423
453
  ? `/${view.path}`
424
454
  : `/${view.path}/${view.path}`
425
- : null
455
+ return `${path}/${id}`
456
+ }
457
+ return null
426
458
  }
427
459
 
428
460
  export function getFormSchemas(schema, context, modifyForm) {
@@ -595,7 +627,7 @@ export function computeValue(schema, data, name, dataPath, {
595
627
  const { compute } = schema
596
628
  if (compute) {
597
629
  const value = compute(
598
- DitoContext.get(component, {
630
+ new DitoContext(component, {
599
631
  schema,
600
632
  // Override value to prevent endless recursion through calling the
601
633
  // getter for `this.value` in `DitoContext`:
@@ -691,7 +723,7 @@ export function processData(schema, sourceSchema, data, dataPath, {
691
723
 
692
724
  // NOTE: We don't cache this context, since `value` is changing.
693
725
  const getContext = () =>
694
- DitoContext.get(component, {
726
+ new DitoContext(component, {
695
727
  schema,
696
728
  value,
697
729
  name,
@@ -782,7 +814,7 @@ export function processSchemaData(
782
814
  index !== null
783
815
  ? getDataPath(componentDataPath, index)
784
816
  : componentDataPath
785
- const context = DitoContext.get(options.component, {
817
+ const context = new DitoContext(options.component, {
786
818
  schema: componentSchema,
787
819
  data,
788
820
  value: item,