@ditojs/admin 2.1.2 → 2.2.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.
Files changed (38) hide show
  1. package/dist/dito-admin.es.js +1875 -1763
  2. package/dist/dito-admin.umd.js +4 -4
  3. package/dist/style.css +1 -1
  4. package/package.json +5 -5
  5. package/src/DitoContext.js +10 -10
  6. package/src/DitoTypeComponent.js +1 -0
  7. package/src/components/DitoContainer.vue +21 -10
  8. package/src/components/DitoCreateButton.vue +11 -8
  9. package/src/components/DitoDraggable.vue +45 -0
  10. package/src/components/DitoPane.vue +1 -1
  11. package/src/components/DitoPanel.vue +1 -1
  12. package/src/components/DitoSchema.vue +11 -6
  13. package/src/components/DitoSchemaInlined.vue +1 -0
  14. package/src/components/DitoTreeItem.vue +3 -2
  15. package/src/components/index.js +1 -0
  16. package/src/mixins/DataMixin.js +3 -3
  17. package/src/mixins/DitoMixin.js +23 -10
  18. package/src/mixins/RouteMixin.js +1 -1
  19. package/src/mixins/SortableMixin.js +2 -5
  20. package/src/mixins/SourceMixin.js +0 -5
  21. package/src/mixins/TypeMixin.js +22 -13
  22. package/src/styles/_pulldown.scss +9 -12
  23. package/src/types/DitoTypeButton.vue +7 -4
  24. package/src/types/DitoTypeCode.vue +1 -0
  25. package/src/types/DitoTypeComponent.vue +1 -0
  26. package/src/types/DitoTypeLabel.vue +2 -1
  27. package/src/types/DitoTypeList.vue +4 -2
  28. package/src/types/DitoTypeMarkup.vue +2 -0
  29. package/src/types/DitoTypeObject.vue +2 -0
  30. package/src/types/DitoTypePanel.vue +1 -0
  31. package/src/types/DitoTypeSection.vue +1 -1
  32. package/src/types/DitoTypeTextarea.vue +1 -0
  33. package/src/types/DitoTypeTreeList.vue +2 -0
  34. package/src/types/DitoTypeUpload.vue +5 -2
  35. package/src/utils/accessor.js +1 -1
  36. package/src/utils/options.js +1 -0
  37. package/src/utils/schema.js +97 -79
  38. package/types/index.d.ts +3 -24
@@ -38,10 +38,11 @@
38
38
  :columns="columns"
39
39
  :hasEditButtons="hasEditButtons"
40
40
  )
41
- UseSortable(
41
+ DitoDraggable(
42
42
  tag="tbody"
43
43
  :modelValue="updateOrder(sourceSchema, listData, paginationRange)"
44
- :options="getSortableOptions(draggable)"
44
+ :options="getSortableOptions(false)"
45
+ :draggable="draggable"
45
46
  @update:modelValue="value => (listData = value)"
46
47
  )
47
48
  tr(
@@ -167,6 +168,7 @@ import { pickBy, equals, hyphenate } from '@ditojs/utils'
167
168
  // @vue/component
168
169
  export default DitoTypeComponent.register('list', {
169
170
  mixins: [SourceMixin, SortableMixin],
171
+ alignBottom: false,
170
172
 
171
173
  getSourceType(type) {
172
174
  // No need for transformation here. See TypeTreeList for details.
@@ -83,6 +83,8 @@ export default DitoTypeComponent.register('markup', {
83
83
  Icon
84
84
  },
85
85
 
86
+ alignBottom: false,
87
+
86
88
  data() {
87
89
  return {
88
90
  editor: null,
@@ -63,6 +63,8 @@ import { resolveSchemaComponent } from '../utils/schema.js'
63
63
  export default DitoTypeComponent.register('object', {
64
64
  mixins: [SourceMixin],
65
65
 
66
+ alignBottom: false,
67
+
66
68
  getSourceType(type) {
67
69
  // No need for transformation here. See TypeTreeList for details.
68
70
  return type
@@ -6,6 +6,7 @@ export default DitoTypeComponent.register('panel', {
6
6
  defaultValue: () => undefined, // Callback to override `defaultValue: null`
7
7
  excludeValue: true,
8
8
  generateLabel: false,
9
+ alignBottom: false,
9
10
  omitPadding: true,
10
11
 
11
12
  getPanelSchema(schema) {
@@ -20,7 +20,7 @@ export default DitoTypeComponent.register('section', {
20
20
  ignoreMissingValue: schema => !schema.nested && !('default' in schema),
21
21
  defaultNested: false,
22
22
  generateLabel: false,
23
- omitFlexGrow: true,
23
+ alignBottom: false,
24
24
 
25
25
  computed: {
26
26
  item() {
@@ -17,6 +17,7 @@ import { getSchemaAccessor } from '../utils/accessor.js'
17
17
  export default DitoTypeComponent.register('textarea', {
18
18
  nativeField: true,
19
19
  textField: true,
20
+ alignBottom: false,
20
21
 
21
22
  computed: {
22
23
  lines() {
@@ -35,6 +35,8 @@ export default DitoTypeComponent.register(
35
35
  {
36
36
  mixins: [SourceMixin],
37
37
 
38
+ alignBottom: false,
39
+
38
40
  provide() {
39
41
  return { container: this }
40
42
  },
@@ -12,10 +12,11 @@
12
12
  span Status
13
13
  th
14
14
  span
15
- UseSortable(
15
+ DitoDraggable(
16
16
  v-model="files"
17
17
  tag="tbody"
18
- :options="getSortableOptions(draggable)"
18
+ :options="getSortableOptions(false)"
19
+ :draggable="draggable"
19
20
  )
20
21
  tr(
21
22
  v-for="(file, index) in files"
@@ -111,6 +112,8 @@ export default DitoTypeComponent.register('upload', {
111
112
  mixins: [SortableMixin],
112
113
  components: { VueUpload },
113
114
 
115
+ alignBottom: false,
116
+
114
117
  data() {
115
118
  return {
116
119
  uploads: []
@@ -53,7 +53,7 @@ export function getStoreAccessor(name, { default: def, get, set } = {}) {
53
53
  let value = this.getStore(name)
54
54
  if (value === undefined && def !== undefined) {
55
55
  // Support `default()` functions:
56
- value = isFunction(def) ? def.call(this, this.context) : def
56
+ value = isFunction(def) ? def.call(this) : def
57
57
  // Trigger setter by setting value and accessor to default:
58
58
  this[name] = value
59
59
  // Now access store again, for reactivity tracking
@@ -36,6 +36,7 @@ const ditoOptionKeys = [
36
36
  'generateLabel',
37
37
  'excludeValue',
38
38
  'ignoreMissingValue',
39
+ 'alignBottom',
39
40
  'omitPadding',
40
41
  'processValue',
41
42
  'processSchema',
@@ -98,6 +98,14 @@ export function isView(schema) {
98
98
  return isSchema(schema) && schema.type === 'view'
99
99
  }
100
100
 
101
+ export function isTab(schema) {
102
+ return isSchema(schema) && schema.type === 'tab'
103
+ }
104
+
105
+ export function isPanel(schema) {
106
+ return isSchema(schema) && schema.type === 'panel'
107
+ }
108
+
101
109
  export function getSchemaIdentifier(schema) {
102
110
  return schema.name || schema.label || schema.type
103
111
  }
@@ -161,16 +169,6 @@ export async function resolveSchemas(
161
169
  return schemas
162
170
  }
163
171
 
164
- export async function resolveNestedSchemas(schema) {
165
- const { tabs, panels } = schema
166
- if (tabs) {
167
- schema.tabs = await resolveSchemas(tabs)
168
- }
169
- if (panels) {
170
- schema.panels = await resolveSchemas(panels)
171
- }
172
- }
173
-
174
172
  export async function resolveSchemaComponent(schema) {
175
173
  // Resolves async schema components and adds DitoMixin and TypeMixin to them.
176
174
  let { component } = schema
@@ -193,51 +191,6 @@ export async function resolveSchemaComponents(schemas) {
193
191
  await mapConcurrently(Object.values(schemas || {}), resolveSchemaComponent)
194
192
  }
195
193
 
196
- export async function processView(component, api, schema, name) {
197
- processRouteSchema(api, schema, name)
198
- processDefaults(api, schema)
199
- await resolveNestedSchemas(schema)
200
- const children = []
201
- if (isView(schema)) {
202
- await processSchemaComponents(api, schema, children, 0)
203
- } else {
204
- throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
205
- }
206
- return {
207
- path: `/${schema.path}`,
208
- children,
209
- component,
210
- meta: {
211
- api,
212
- schema
213
- }
214
- }
215
- }
216
-
217
- export function processDefaults(api, schema) {
218
- let defaults = api.defaults[schema.type]
219
- if (defaults) {
220
- if (isFunction(defaults)) {
221
- defaults = defaults(schema)
222
- }
223
- if (isObject(defaults)) {
224
- for (const [key, value] of Object.entries(defaults)) {
225
- if (schema[key] === undefined) {
226
- schema[key] = value
227
- } else {
228
- schema[key] = merge(value, schema[key])
229
- }
230
- }
231
- }
232
- }
233
- }
234
-
235
- export function processRouteSchema(api, schema, name) {
236
- // Used for view and source schemas, see SourceMixin.
237
- schema.name = name
238
- schema.path ||= api.normalizePath(name)
239
- }
240
-
241
194
  export async function processSchemaComponents(api, schema, routes, level) {
242
195
  const promises = []
243
196
  const process = (component, name, relativeLevel) => {
@@ -277,19 +230,59 @@ export async function processSchemaComponent(api, schema, name, routes, level) {
277
230
  ])
278
231
  }
279
232
 
280
- export async function processForms(api, schema, level) {
281
- const processForm = async form => {
282
- form = await resolveForm(form)
283
- processDefaults(api, schema)
284
- return form
233
+ export async function processView(component, api, schema, name) {
234
+ if (!isView(schema)) {
235
+ throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
236
+ }
237
+ processRouteSchema(api, schema, name)
238
+ processDefaults(api, schema)
239
+ await resolveNestedSchemas(api, schema)
240
+ const children = []
241
+ await processSchemaComponents(api, schema, children, 0)
242
+ return {
243
+ path: `/${schema.path}`,
244
+ children,
245
+ component,
246
+ meta: {
247
+ api,
248
+ schema
249
+ }
250
+ }
251
+ }
252
+
253
+ export function processDefaults(api, schema) {
254
+ let defaults = api.defaults[schema.type]
255
+ if (defaults) {
256
+ if (isFunction(defaults)) {
257
+ defaults = defaults(schema)
258
+ }
259
+ if (isObject(defaults)) {
260
+ for (const [key, value] of Object.entries(defaults)) {
261
+ if (schema[key] === undefined) {
262
+ schema[key] = value
263
+ } else {
264
+ schema[key] = merge(value, schema[key])
265
+ }
266
+ }
267
+ }
285
268
  }
269
+ }
286
270
 
271
+ export function processRouteSchema(api, schema, name) {
272
+ // Used for view and source schemas, see SourceMixin.
273
+ schema.name = name
274
+ schema.path ||= api.normalizePath(name)
275
+ }
276
+
277
+ export async function processForms(api, schema, level) {
287
278
  // First resolve the forms and store the results back on the schema.
288
279
  let { form, forms, components } = schema
289
280
  if (forms) {
290
- forms = schema.forms = await resolveSchemas(forms, processForm)
281
+ forms = schema.forms = await resolveSchemas(forms, form =>
282
+ processForm(api, form)
283
+ )
291
284
  } else if (form) {
292
- form = schema.form = await processForm(form)
285
+ form = schema.form = await processForm(api, form)
293
286
  } else if (components) {
294
287
  // NOTE: Processing forms in computed components is not supported, since it
295
288
  // only can be computed in conjunction with actual data.
@@ -306,15 +299,50 @@ export async function processForms(api, schema, level) {
306
299
  return children
307
300
  }
308
301
 
309
- export async function resolveForm(schema) {
302
+ export async function processForm(api, schema) {
310
303
  schema = await resolveSchema(schema, true)
311
304
  if (!isForm(schema)) {
312
305
  throw new Error(`Invalid form schema: '${getSchemaIdentifier(schema)}'`)
313
306
  }
314
- await resolveNestedSchemas(schema)
307
+ processDefaults(api, schema)
308
+ await resolveNestedSchemas(api, schema)
309
+ return schema
310
+ }
311
+
312
+ export async function processTab(api, schema) {
313
+ schema = await resolveSchema(schema, true)
314
+ if (!isTab(schema)) {
315
+ throw new Error(`Invalid tab schema: '${getSchemaIdentifier(schema)}'`)
316
+ }
317
+ processDefaults(api, schema)
318
+ return schema
319
+ }
320
+
321
+ export async function processPanel(api, schema) {
322
+ schema = await resolveSchema(schema, true)
323
+ if (!isPanel(schema)) {
324
+ throw new Error(`Invalid panel schema: '${getSchemaIdentifier(schema)}'`)
325
+ }
326
+ processDefaults(api, schema)
315
327
  return schema
316
328
  }
317
329
 
330
+ export async function resolveNestedSchemas(api, schema) {
331
+ const { tabs, panels } = schema
332
+ if (tabs) {
333
+ schema.tabs = await resolveSchemas(
334
+ tabs,
335
+ tab => processTab(api, tab)
336
+ )
337
+ }
338
+ if (panels) {
339
+ schema.panels = await resolveSchemas(
340
+ panels,
341
+ panel => processPanel(api, panel)
342
+ )
343
+ }
344
+ }
345
+
318
346
  export function hasFormSchema(schema) {
319
347
  // Support both single form and multiple forms notation, as well as inlined
320
348
  // components.
@@ -404,10 +432,6 @@ export function getItemFormSchema(schema, item, context) {
404
432
  return getItemFormSchemaFromForms(getFormSchemas(schema, context), item)
405
433
  }
406
434
 
407
- export function hasLabel(schema) {
408
- return schema.label !== false
409
- }
410
-
411
435
  export function isCompact(schema) {
412
436
  return !!schema.compact
413
437
  }
@@ -420,10 +444,14 @@ export function isNested(schema) {
420
444
  return !!(schema.nested || getTypeOptions(schema)?.defaultNested === true)
421
445
  }
422
446
 
423
- export function shouldOmitPadding(schema) {
447
+ export function omitPadding(schema) {
424
448
  return !!getTypeOptions(schema)?.omitPadding
425
449
  }
426
450
 
451
+ export function alignBottom(schema) {
452
+ return !!getTypeOptions(schema)?.alignBottom
453
+ }
454
+
427
455
  export function getDefaultValue(schema) {
428
456
  // Support default values both on schema and on component level.
429
457
  // NOTE: At the time of creation, components may not be instantiated, (e.g. if
@@ -447,16 +475,6 @@ export function ignoreMissingValue(schema) {
447
475
  )
448
476
  }
449
477
 
450
- export function hasLabels(schema) {
451
- const checkComponents = components =>
452
- Object.values(components || {}).some(hasLabel)
453
-
454
- return (
455
- checkComponents(schema.components) ||
456
- Object.values(schema.tabs || {}).some(checkComponents)
457
- )
458
- }
459
-
460
478
  export function setDefaultValues(schema, data = {}, component) {
461
479
  const options = { component, rootData: data }
462
480
 
package/types/index.d.ts CHANGED
@@ -319,40 +319,19 @@ export interface SchemaSourceMixin<$Item> {
319
319
  *
320
320
  * @defaultValue `false`
321
321
  */
322
- creatable?: OrItemAccessor<
323
- $Item,
324
- {},
325
- | boolean
326
- | {
327
- label: string
328
- }
329
- >
322
+ creatable?: OrItemAccessor<$Item, {}, boolean | { label: string }>
330
323
  /**
331
324
  * Whether to add edit buttons next to the list items.
332
325
  *
333
326
  * @defaultValue `false`
334
327
  */
335
- editable?: OrItemAccessor<
336
- $Item,
337
- {},
338
- | boolean
339
- | {
340
- label: string
341
- }
342
- >
328
+ editable?: OrItemAccessor<$Item, {}, boolean | { label: string }>
343
329
  /**
344
330
  * Whether to add delete buttons next to the list items.
345
331
  *
346
332
  * @defaultValue `false`
347
333
  */
348
- deletable?: OrItemAccessor<
349
- $Item,
350
- {},
351
- | boolean
352
- | {
353
- label: string
354
- }
355
- >
334
+ deletable?: OrItemAccessor<$Item, {}, boolean | { label: string }>
356
335
  /**
357
336
  * The column used for the order resulting from dragging around list entries
358
337
  * when the `draggable` property of the list schema is set to `true`.