@ditojs/admin 2.26.2 → 2.27.1

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.
@@ -23,7 +23,7 @@ import { getItemFormSchema, processSchemaComponents } from '../utils/schema.js'
23
23
  // @vue/component
24
24
  export default DitoTypeComponent.register('section', {
25
25
  defaultValue: () => undefined, // Callback to override `defaultValue: null`
26
- ignoreMissingValue: schema => !schema.nested && !('default' in schema),
26
+ ignoreMissingValue: ({ schema }) => !schema.nested && !('default' in schema),
27
27
  defaultNested: false,
28
28
  generateLabel: false,
29
29
 
@@ -38,7 +38,7 @@ export default DitoTypeComponent.register(
38
38
  components: { InputField },
39
39
  nativeField: true,
40
40
  textField: true,
41
- ignoreMissingValue: schema => schema.type === 'password',
41
+ ignoreMissingValue: ({ schema }) => schema.type === 'password',
42
42
 
43
43
  computed: {
44
44
  inputType() {
@@ -452,7 +452,7 @@ export default DitoTypeComponent.register('upload', {
452
452
  }
453
453
  },
454
454
 
455
- processValue(schema, value) {
455
+ processValue({ schema, value }) {
456
456
  // Filter out all newly added files that weren't actually uploaded.
457
457
  const files = asFiles(value)
458
458
  .map(({ upload, ...file }) => (!upload || upload.success ? file : null))
@@ -1,4 +1,4 @@
1
- import { isObject, isString, pickBy } from '@ditojs/utils'
1
+ import { isFunction, isObject, isString, pickBy } from '@ditojs/utils'
2
2
 
3
3
  export function hasResource(schema) {
4
4
  return !!getResource(schema.resource)
@@ -6,6 +6,9 @@ export function hasResource(schema) {
6
6
 
7
7
  export function getResource(resource, defaults = {}) {
8
8
  const { parent, ...defs } = defaults
9
+ if (isFunction(resource)) {
10
+ resource = resource(defaults)
11
+ }
9
12
  resource = isObject(resource)
10
13
  ? { ...defs, ...resource }
11
14
  : isString(resource)
@@ -242,33 +242,36 @@ export async function resolveSchemaComponents(schemas) {
242
242
  await mapConcurrently(Object.values(schemas || {}), resolveSchemaComponent)
243
243
  }
244
244
 
245
- const processedSchemas = new WeakSet()
245
+ const processedSchemaDepths = new WeakMap()
246
246
  export async function processSchemaComponents(
247
247
  api,
248
248
  schema,
249
249
  routes = null,
250
- level = 0
250
+ level = 0,
251
+ maxDepth = 1
251
252
  ) {
252
- if (schema && !processedSchemas.has(schema)) {
253
- processedSchemas.add(schema)
254
-
255
- const promises = []
256
- const process = (component, name, relativeLevel) => {
257
- promises.push(
258
- processSchemaComponent(
259
- api,
260
- component,
261
- name,
262
- routes,
263
- level + relativeLevel
253
+ if (schema) {
254
+ const depth = processedSchemaDepths.get(schema) ?? 0
255
+ if (depth < maxDepth) {
256
+ processedSchemaDepths.set(schema, depth + 1)
257
+ const promises = []
258
+ const process = (component, name, relativeLevel) => {
259
+ promises.push(
260
+ processSchemaComponent(
261
+ api,
262
+ component,
263
+ name,
264
+ routes,
265
+ level + relativeLevel
266
+ )
264
267
  )
265
- )
266
- }
268
+ }
267
269
 
268
- iterateNestedSchemaComponents(schema, process)
269
- iterateSchemaComponents(getPanelSchemas(schema), process)
270
+ iterateNestedSchemaComponents(schema, process)
271
+ iterateSchemaComponents(getPanelSchemas(schema), process)
270
272
 
271
- await Promise.all(promises)
273
+ await Promise.all(promises)
274
+ }
272
275
  }
273
276
  }
274
277
 
@@ -368,7 +371,7 @@ export function processRouteSchema(api, schema, name, fullPath = null) {
368
371
 
369
372
  export async function processForms(api, schema, level) {
370
373
  // First resolve the forms and store the results back on the schema.
371
- let { form, forms, components } = schema
374
+ let { form, forms, components, maxDepth = 1 } = schema
372
375
  if (forms) {
373
376
  forms = schema.forms = await resolveSchemas(forms, form =>
374
377
  processForm(api, form)
@@ -387,7 +390,7 @@ export async function processForms(api, schema, level) {
387
390
  forms ||= { default: form } // Only used for process loop below.
388
391
  const children = []
389
392
  for (const form of Object.values(forms)) {
390
- await processSchemaComponents(api, form, children, level)
393
+ await processSchemaComponents(api, form, children, level, maxDepth)
391
394
  }
392
395
  return children
393
396
  }
@@ -624,37 +627,53 @@ export function shouldRenderSchema(schema, context) {
624
627
  )
625
628
  }
626
629
 
627
- export function getDefaultValue(schema) {
630
+ function getContext(context) {
631
+ return isFunction(context) ? context() : context
632
+ }
633
+
634
+ export function getDefaultValue(schema, context) {
628
635
  // Support default values both on schema and on component level.
629
636
  // NOTE: At the time of creation, components may not be instantiated, (e.g. if
630
637
  // entries are created through nested forms, the parent form isn't mounted) so
631
638
  // we can't use `dataPath` to get to components, and the `defaultValue` from
632
639
  // there. That's why `defaultValue` is defined statically in the components:
633
- const defaultValue = schema.default
634
- const value =
635
- defaultValue !== undefined
636
- ? defaultValue
640
+ const defaultValue =
641
+ schema.default !== undefined
642
+ ? schema.default
637
643
  : getTypeOptions(schema)?.defaultValue
638
- return isFunction(value)
639
- ? // TODO: Pass `DitoContext` here too, with the (incomplete) item and al
640
- // the other bits!
641
- value(schema)
642
- : clone(value)
644
+ return isFunction(defaultValue)
645
+ ? defaultValue(getContext(context))
646
+ : clone(defaultValue)
643
647
  }
644
648
 
645
- export function ignoreMissingValue(schema) {
646
- const typeOptions = getTypeOptions(schema)
647
- return !!(
648
- typeOptions?.excludeValue || typeOptions?.ignoreMissingValue?.(schema)
649
- )
649
+ export function shouldExcludeValue(schema, context) {
650
+ const excludeValue =
651
+ schema.exclude !== undefined
652
+ ? schema.exclude
653
+ : getTypeOptions(schema)?.excludeValue
654
+ return isFunction(excludeValue)
655
+ ? excludeValue(getContext(context))
656
+ : !!excludeValue
657
+ }
658
+
659
+ export function shouldIgnoreMissingValue(schema, context) {
660
+ return !!getTypeOptions(schema)?.ignoreMissingValue?.(getContext(context))
650
661
  }
651
662
 
652
663
  export function setDefaultValues(schema, data = {}, component) {
653
664
  const options = { component, rootData: data }
654
665
 
655
- const processBefore = (schema, data, name) => {
656
- if (!(name in data) && !ignoreMissingValue(schema)) {
657
- data[name] = getDefaultValue(schema)
666
+ const processBefore = (schema, data, name, dataPath) => {
667
+ const context = () =>
668
+ new DitoContext(component, {
669
+ schema,
670
+ name,
671
+ data,
672
+ dataPath,
673
+ rootData: options.rootData
674
+ })
675
+ if (!(name in data) && !shouldIgnoreMissingValue(schema, context)) {
676
+ data[name] = getDefaultValue(schema, context)
658
677
  }
659
678
  }
660
679
 
@@ -675,20 +694,20 @@ export function computeValue(schema, data, name, dataPath, {
675
694
  component = null,
676
695
  rootData = component?.rootData
677
696
  } = {}) {
697
+ const context = () =>
698
+ new DitoContext(component, {
699
+ schema,
700
+ // Override value to prevent endless recursion through calling the
701
+ // getter for `this.value` in `DitoContext`:
702
+ value: data[name],
703
+ name,
704
+ data,
705
+ dataPath,
706
+ rootData
707
+ })
678
708
  const { compute } = schema
679
709
  if (compute) {
680
- const value = compute(
681
- new DitoContext(component, {
682
- schema,
683
- // Override value to prevent endless recursion through calling the
684
- // getter for `this.value` in `DitoContext`:
685
- value: data[name],
686
- name,
687
- data,
688
- dataPath,
689
- rootData
690
- })
691
- )
710
+ const value = compute(getContext(context))
692
711
  if (value !== undefined) {
693
712
  // Access `data[name]` directly to update the value without calling
694
713
  // parse():
@@ -698,10 +717,10 @@ export function computeValue(schema, data, name, dataPath, {
698
717
  }
699
718
  }
700
719
  // If the value is still missing after compute, set the default for it:
701
- if (!(name in data) && !ignoreMissingValue(schema)) {
720
+ if (!(name in data) && !shouldIgnoreMissingValue(schema, context)) {
702
721
  // TODO: Fix side-effects
703
722
  // eslint-disable-next-line vue/no-side-effects-in-computed-properties
704
- data[name] = getDefaultValue(schema)
723
+ data[name] = getDefaultValue(schema, context)
705
724
  }
706
725
  // Now access the value. This is important for reactivity and needs to
707
726
  // happen after all prior manipulation of `data[name]`, see above:
@@ -772,13 +791,11 @@ export function processData(schema, sourceSchema, data, dataPath, {
772
791
  }
773
792
 
774
793
  const processAfter = (schema, data, name, dataPath, processedData) => {
775
- const { wrapPrimitives, exclude, process } = schema
794
+ const { wrapPrimitives, process } = schema
776
795
  let value = processedData[name]
777
796
 
778
- const typeOptions = getTypeOptions(schema)
779
-
780
797
  // NOTE: We don't cache this context, since `value` is changing.
781
- const getContext = () =>
798
+ const context = () =>
782
799
  new DitoContext(component, {
783
800
  schema,
784
801
  value,
@@ -799,23 +816,18 @@ export function processData(schema, sourceSchema, data, dataPath, {
799
816
 
800
817
  // Each component type can provide its own static `processValue()` method
801
818
  // to convert the data for storage.
802
- const processValue = typeOptions?.processValue
819
+ const processValue = getTypeOptions(schema)?.processValue
803
820
  if (processValue) {
804
- value = processValue(schema, value, dataPath, graph)
821
+ value = processValue(getContext(context), graph)
805
822
  }
806
823
 
807
824
  // Handle the user's `process()` callback next, if one is provided, so that
808
825
  // it can modify data in `processedData` even if it provides `exclude: true`
809
826
  if (process) {
810
- value = process(getContext())
827
+ value = process(getContext(context))
811
828
  }
812
829
 
813
- if (
814
- typeOptions?.excludeValue ||
815
- // Support functions next to booleans for `schema.exclude`:
816
- exclude === true ||
817
- isFunction(exclude) && exclude(getContext())
818
- ) {
830
+ if (shouldExcludeValue(schema, context)) {
819
831
  delete processedData[name]
820
832
  } else {
821
833
  processedData[name] = value