@conduction/nextcloud-vue 2.56.0-beta.15 → 2.56.0-beta.17
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/esm/components/CnFormDialog/CnFormDialog.vue2.js +87 -18
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +6 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +8 -2
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/utils/rowActionItem.js +8 -3
- package/dist/esm/utils/rowActionItem.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +109 -24
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/package.json +1 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +92 -18
- package/src/components/CnSetupWizard/CnSetupWizard.vue +8 -2
- package/src/utils/rowActionItem.js +7 -2
|
@@ -462,6 +462,11 @@
|
|
|
462
462
|
:register="nestedCreate.register"
|
|
463
463
|
:item="null"
|
|
464
464
|
:initialData="nestedCreate.initialData"
|
|
465
|
+
:excludeFields="nestedCreate.form.excludeFields"
|
|
466
|
+
:includeFields="nestedCreate.form.includeFields"
|
|
467
|
+
:fieldOverrides="nestedCreate.form.fieldOverrides"
|
|
468
|
+
:size="nestedCreate.form.size"
|
|
469
|
+
:columns="nestedCreate.form.columns"
|
|
465
470
|
:recoverDraft="false"
|
|
466
471
|
data-testid="cn-form-dialog-nested-create"
|
|
467
472
|
@confirm="onNestedCreateConfirm"
|
|
@@ -2645,7 +2650,12 @@ export default {
|
|
|
2645
2650
|
* the new object. When the referenced schema cannot be loaded, the
|
|
2646
2651
|
* term alone is saved as before, so the field never dead-ends.
|
|
2647
2652
|
*
|
|
2653
|
+
* The form is the one the schema's index page shows for its own Add
|
|
2654
|
+
* button: that page's `createOverride` saves it and its form settings
|
|
2655
|
+
* shape it, with the typed term in the name.
|
|
2656
|
+
*
|
|
2648
2657
|
* @spec openspec/changes/form-pickers-from-schema/specs/schema-utilities/spec.md
|
|
2658
|
+
* @spec openspec/changes/nested-create-uses-page-config/specs/schema-utilities/spec.md
|
|
2649
2659
|
* @param {object} field The reference field descriptor.
|
|
2650
2660
|
* @param {string} term The typed search term.
|
|
2651
2661
|
* @return {Promise<object|null>} The created object, or null.
|
|
@@ -2662,21 +2672,37 @@ export default {
|
|
|
2662
2672
|
store.registerObjectType(slug, schemaRef, register)
|
|
2663
2673
|
}
|
|
2664
2674
|
const labelField = this.referenceLabelField(field)
|
|
2675
|
+
const loadSchema = async () => {
|
|
2676
|
+
try {
|
|
2677
|
+
return await store.fetchSchema(slug)
|
|
2678
|
+
} catch {
|
|
2679
|
+
return null
|
|
2680
|
+
}
|
|
2681
|
+
}
|
|
2665
2682
|
// The app may own how this schema is created (pipelinq's client and
|
|
2666
2683
|
// contact need a contact-first endpoint; a plain save 400s). A
|
|
2667
2684
|
// create override keeps this form and saves through the app's
|
|
2668
2685
|
// handler; a create modal (only when no override exists) opens the
|
|
2669
2686
|
// app's own dialog instead of the generic form.
|
|
2670
|
-
|
|
2687
|
+
//
|
|
2688
|
+
// A stored schema usually names its reference by id (`$ref: 28`)
|
|
2689
|
+
// while the manifest page names it by slug (`schema: 'client'`), so
|
|
2690
|
+
// when the reference itself matches no page, the referenced schema
|
|
2691
|
+
// is loaded and its slug, id and uuid are tried too.
|
|
2692
|
+
let schema
|
|
2693
|
+
let appCreate = this.appCreateFor(register, [schemaRef])
|
|
2694
|
+
if (!appCreate.page) {
|
|
2695
|
+
schema = await loadSchema()
|
|
2696
|
+
if (schema) {
|
|
2697
|
+
appCreate = this.appCreateFor(register, [schemaRef, schema.slug, schema.id, schema.uuid])
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2671
2700
|
if (!appCreate.override && appCreate.modal) {
|
|
2672
2701
|
return this.openAppCreateModal(appCreate.modal, store, slug, labelField, term)
|
|
2673
2702
|
}
|
|
2674
2703
|
const override = appCreate.override
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
schema = await store.fetchSchema(slug)
|
|
2678
|
-
} catch {
|
|
2679
|
-
schema = null
|
|
2704
|
+
if (schema === undefined) {
|
|
2705
|
+
schema = await loadSchema()
|
|
2680
2706
|
}
|
|
2681
2707
|
if (!schema || !schema.properties) {
|
|
2682
2708
|
const payload = { [labelField]: term }
|
|
@@ -2685,36 +2711,84 @@ export default {
|
|
|
2685
2711
|
: store.saveObject(slug, payload)
|
|
2686
2712
|
}
|
|
2687
2713
|
const initialData = {}
|
|
2688
|
-
|
|
2689
|
-
|
|
2714
|
+
const prefillKey = this.nestedPrefillKey(schema, labelField)
|
|
2715
|
+
if (term && prefillKey) {
|
|
2716
|
+
initialData[prefillKey] = term
|
|
2690
2717
|
}
|
|
2718
|
+
const form = appCreate.form || this.nestedFormConfig(null)
|
|
2691
2719
|
return new Promise((resolve) => {
|
|
2692
|
-
this.nestedCreate = { field, schema, register, slug, schemaRef, initialData, override, resolve }
|
|
2720
|
+
this.nestedCreate = { field, schema, register, slug, schemaRef, initialData, override, form, resolve }
|
|
2693
2721
|
})
|
|
2694
2722
|
},
|
|
2695
2723
|
|
|
2724
|
+
/**
|
|
2725
|
+
* The property of the referenced schema the typed term belongs in: the
|
|
2726
|
+
* reference's label field when the schema has it, else its name, title
|
|
2727
|
+
* or label. Visibility is decided by the form (a page `fieldOverrides`
|
|
2728
|
+
* entry can make a read-only name editable), not here.
|
|
2729
|
+
*
|
|
2730
|
+
* @spec openspec/changes/nested-create-uses-page-config/specs/schema-utilities/spec.md
|
|
2731
|
+
* @param {object} schema The referenced schema.
|
|
2732
|
+
* @param {string} labelField The reference's label field.
|
|
2733
|
+
* @return {string|null} The property key, or null when none fits.
|
|
2734
|
+
*/
|
|
2735
|
+
nestedPrefillKey(schema, labelField) {
|
|
2736
|
+
const properties = (schema && schema.properties) || {}
|
|
2737
|
+
return [labelField, 'name', 'title', 'label'].find((key) => properties[key]) || null
|
|
2738
|
+
},
|
|
2739
|
+
|
|
2740
|
+
/**
|
|
2741
|
+
* The create-form settings of the index page that lists a schema, in
|
|
2742
|
+
* the shape the nested CnFormDialog binds: the same `excludeFields`,
|
|
2743
|
+
* `includeFields`, `fieldOverrides`, `formSize` and `formColumns`
|
|
2744
|
+
* CnIndexPage hands its own Add form, so creating from a picker shows
|
|
2745
|
+
* the form the page shows. Without a page, the form's defaults.
|
|
2746
|
+
*
|
|
2747
|
+
* @spec openspec/changes/nested-create-uses-page-config/specs/schema-utilities/spec.md
|
|
2748
|
+
* @param {object|null} config The page's `config`, or null.
|
|
2749
|
+
* @return {{excludeFields: string[], includeFields: (string[]|null), fieldOverrides: object, size: string, columns: number}} The form settings.
|
|
2750
|
+
*/
|
|
2751
|
+
nestedFormConfig(config) {
|
|
2752
|
+
const c = config || {}
|
|
2753
|
+
const isMap = (v) => v !== null && typeof v === 'object' && !Array.isArray(v)
|
|
2754
|
+
return {
|
|
2755
|
+
excludeFields: Array.isArray(c.excludeFields) ? c.excludeFields : [],
|
|
2756
|
+
includeFields: Array.isArray(c.includeFields) ? c.includeFields : null,
|
|
2757
|
+
fieldOverrides: isMap(c.fieldOverrides) ? c.fieldOverrides : {},
|
|
2758
|
+
size: typeof c.formSize === 'string' && c.formSize !== '' ? c.formSize : 'normal',
|
|
2759
|
+
columns: c.formColumns === 2 ? 2 : 1,
|
|
2760
|
+
}
|
|
2761
|
+
},
|
|
2762
|
+
|
|
2696
2763
|
/**
|
|
2697
2764
|
* How the app creates objects of a schema, read off the manifest page
|
|
2698
2765
|
* that lists them: the index page whose `config.schema` (and, when it
|
|
2699
2766
|
* names one, `config.register`) matches. Its `config.createOverride` is
|
|
2700
2767
|
* resolved to the registered handler; its `config.createModal` is the
|
|
2701
|
-
* registry key of a `kind: 'modal'` dialog
|
|
2768
|
+
* registry key of a `kind: 'modal'` dialog; its form settings
|
|
2769
|
+
* (`fieldOverrides` and friends) shape the nested form.
|
|
2702
2770
|
*
|
|
2703
|
-
*
|
|
2771
|
+
* The schema is matched on any of the given references, so a caller
|
|
2772
|
+
* holding the referenced schema can pass its slug, id and uuid: the
|
|
2773
|
+
* manifest names a schema by slug, a stored `$ref` often by id.
|
|
2774
|
+
*
|
|
2775
|
+
* @spec openspec/changes/nested-create-uses-page-config/specs/schema-utilities/spec.md
|
|
2704
2776
|
* @param {string} register The reference's register.
|
|
2705
|
-
* @param {string}
|
|
2706
|
-
* @return {{override: (((formData: object, ctx: object) => Promise<object>)|null), modal: (string|null)}} What the app declared.
|
|
2777
|
+
* @param {string|Array<string|number>} schemaRefs The schema's slug, id or uuid, one or several.
|
|
2778
|
+
* @return {{page: (object|null), override: (((formData: object, ctx: object) => Promise<object>)|null), modal: (string|null), form: (object|null)}} What the app declared.
|
|
2707
2779
|
*/
|
|
2708
|
-
appCreateFor(register,
|
|
2709
|
-
const none = { override: null, modal: null }
|
|
2780
|
+
appCreateFor(register, schemaRefs) {
|
|
2781
|
+
const none = { page: null, override: null, modal: null, form: null }
|
|
2710
2782
|
const pages = this.cnManifest && Array.isArray(this.cnManifest.pages) ? this.cnManifest.pages : []
|
|
2711
|
-
const wanted =
|
|
2783
|
+
const wanted = (Array.isArray(schemaRefs) ? schemaRefs : [schemaRefs])
|
|
2784
|
+
.filter((ref) => ref !== undefined && ref !== null && ref !== '')
|
|
2785
|
+
.map((ref) => String(ref).toLowerCase())
|
|
2712
2786
|
const page = pages.find((p) => {
|
|
2713
2787
|
const config = p && p.config
|
|
2714
2788
|
if (!config || config.schema === undefined || config.schema === null) {
|
|
2715
2789
|
return false
|
|
2716
2790
|
}
|
|
2717
|
-
if (String(config.schema).toLowerCase()
|
|
2791
|
+
if (!wanted.includes(String(config.schema).toLowerCase())) {
|
|
2718
2792
|
return false
|
|
2719
2793
|
}
|
|
2720
2794
|
return !config.register || String(config.register) === String(register)
|
|
@@ -2732,7 +2806,7 @@ export default {
|
|
|
2732
2806
|
const modal = modalEntry && modalEntry.kind === 'modal' && typeof this.cnOpenModal === 'function'
|
|
2733
2807
|
? config.createModal
|
|
2734
2808
|
: null
|
|
2735
|
-
return { override: override || null, modal }
|
|
2809
|
+
return { page, override: override || null, modal, form: this.nestedFormConfig(config) }
|
|
2736
2810
|
},
|
|
2737
2811
|
|
|
2738
2812
|
/**
|
|
@@ -641,9 +641,15 @@ export default {
|
|
|
641
641
|
value = this.choiceLabel(step, raw)
|
|
642
642
|
}
|
|
643
643
|
} else if (step.type === 'config-fields') {
|
|
644
|
+
// Only the fields the reader filled in: a row of empty
|
|
645
|
+
// "Name: , KvK: ," reads as broken, not as "not set".
|
|
644
646
|
value = this.fieldsFor(step)
|
|
645
|
-
.
|
|
646
|
-
|
|
647
|
+
.filter((f) => {
|
|
648
|
+
const v = this.configModel[f.key]
|
|
649
|
+
return v !== null && v !== undefined && String(v).trim() !== ''
|
|
650
|
+
})
|
|
651
|
+
.map((f) => `${f.label}: ${this.configModel[f.key]}`)
|
|
652
|
+
.join(', ') || t('nextcloud-vue', 'Not set')
|
|
647
653
|
}
|
|
648
654
|
if (this.isOnDemand(step)) {
|
|
649
655
|
const ran = this.ranThisSession(step.id)
|
|
@@ -49,10 +49,15 @@ export function isRowActionVisible(action, item) {
|
|
|
49
49
|
* @return {string} The slug.
|
|
50
50
|
*/
|
|
51
51
|
export function slugifyActionLabel(label) {
|
|
52
|
-
|
|
52
|
+
// One pass collapses every run of other characters to a single '-', so at
|
|
53
|
+
// most one '-' can sit at either end; trimming it by index keeps this
|
|
54
|
+
// linear. `/^-+|-+$/g` here was a ReDoS on long runs of '-' (CodeQL).
|
|
55
|
+
const slug = String(label || '')
|
|
53
56
|
.toLowerCase()
|
|
54
57
|
.replace(/[^a-z0-9]+/g, '-')
|
|
55
|
-
|
|
58
|
+
const start = slug.startsWith('-') ? 1 : 0
|
|
59
|
+
const end = slug.length > start && slug.endsWith('-') ? slug.length - 1 : slug.length
|
|
60
|
+
return slug.slice(start, end)
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
/**
|