@conduction/nextcloud-vue 2.78.0 → 2.79.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.
- package/dist/bundled-packages.json +0 -2
- package/dist/esm/bundled-packages.json +0 -2
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +113 -104
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +12 -2
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +80 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +115 -91
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +139 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +140 -92
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +77 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +61 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +173 -5
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +181 -99
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js +29 -11
- package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js +252 -0
- package/dist/esm/components/CnFilesBrowser/openRegisterSource.js.map +1 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +25 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +3 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +100 -3
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -2
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +3 -2
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
- package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +30 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/useAppManifest.js +8 -3
- package/dist/esm/composables/useAppManifest.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +61 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +106 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +314 -15
- package/dist/esm/utils/boardDate.js +193 -0
- package/dist/esm/utils/boardDate.js.map +1 -0
- package/dist/esm/utils/dynamicProperties.js +5 -1
- package/dist/esm/utils/dynamicProperties.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +57 -6
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2039 -581
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +314 -15
- package/l10n/en.json +61 -1
- package/l10n/nl.json +106 -2
- package/package.json +1 -1
- package/scripts/build-validators.js +26 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +48 -39
- package/src/components/CnAppRoot/CnAppRoot.vue +12 -2
- package/src/components/CnCellRenderer/CnCellRenderer.vue +119 -2
- package/src/components/CnDashboardPage/CnDashboardPage.vue +219 -4
- package/src/components/CnDataTable/CnDataTable.md +2 -0
- package/src/components/CnDataTable/CnDataTable.vue +81 -2
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +61 -1
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +232 -11
- package/src/components/CnFilesBrowser/filesBrowser.js +43 -2
- package/src/components/CnFilesBrowser/index.js +1 -0
- package/src/components/CnFilesBrowser/openRegisterSource.js +248 -0
- package/src/components/CnFormDialog/CnFormDialog.vue +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +27 -3
- package/src/components/CnObjectSidebar/CnFilesTab.vue +103 -4
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +3 -2
- package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +1 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +30 -1
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
- package/src/components/index.js +1 -1
- package/src/composables/useAppManifest.js +8 -3
- package/src/css/look-board-detail.css +10 -0
- package/src/css/look-board-index.css +92 -14
- package/src/css/look-board.css +77 -0
- package/src/css/table.css +37 -0
- package/src/index.js +4 -0
- package/src/schemas/app-manifest-v2.schema.json +46 -1
- package/src/utils/boardDate.js +189 -0
- package/src/utils/dynamicProperties.js +5 -1
- package/src/utils/validateManifestV2.compiled.js +57 -2
- package/dist/esm/_virtual/equal.js +0 -4
- package/dist/esm/_virtual/equal.js.map +0 -1
- package/dist/esm/_virtual/ucs2length.js +0 -4
- package/dist/esm/_virtual/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js +0 -9
- package/dist/esm/node_modules/ajv/dist/runtime/equal.js.map +0 -1
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js +0 -25
- package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js.map +0 -1
- package/dist/esm/node_modules/fast-deep-equal/index.js +0 -47
- package/dist/esm/node_modules/fast-deep-equal/index.js.map +0 -1
|
@@ -76,6 +76,7 @@ const DEFAULT_MAP = {
|
|
|
76
76
|
enum: 'enumValues',
|
|
77
77
|
required: 'isRequired',
|
|
78
78
|
default: 'defaultValue',
|
|
79
|
+
hideOnCreate: 'hideOnCreate',
|
|
79
80
|
};
|
|
80
81
|
|
|
81
82
|
/**
|
|
@@ -287,6 +288,8 @@ function definitionQueryParams(config, value, formData = {}) {
|
|
|
287
288
|
* @param {object} [config] The `x-openregister-extends-form` block (`map`, `typeMap`).
|
|
288
289
|
* @param {object} [options] Extra options.
|
|
289
290
|
* @param {number} [options.orderFrom] Order assigned to the first field; each subsequent field takes the next integer. Dynamic fields sort after the schema's own, so pass a number above every declared `order`.
|
|
291
|
+
* @param {boolean} [options.create] The form creates a new object: a definition whose `hideOnCreate` (or the field `config.map.hideOnCreate` names) is `true` gets no field, because the app fills that answer itself at creation. Edit forms still show it.
|
|
292
|
+
* @spec openspec/changes/dynamic-question-hide-on-create/specs/dynamic-question-hide-on-create/spec.md#requirement-a-question-can-stay-off-the-create-form
|
|
290
293
|
* @return {{properties: object, required: string[]}} Properties keyed by prefixed id, plus the required key list.
|
|
291
294
|
*/
|
|
292
295
|
function propertiesFromDefinitions(definitions, config = {}, options = {}) {
|
|
@@ -296,7 +299,8 @@ function propertiesFromDefinitions(definitions, config = {}, options = {}) {
|
|
|
296
299
|
|
|
297
300
|
const properties = {};
|
|
298
301
|
const required = [];
|
|
299
|
-
const list = Array.isArray(definitions) ? definitions : []
|
|
302
|
+
const list = (Array.isArray(definitions) ? definitions : [])
|
|
303
|
+
.filter((record) => !(options.create === true && record && mapped(record, map, 'hideOnCreate') === true));
|
|
300
304
|
|
|
301
305
|
list.forEach((record, index) => {
|
|
302
306
|
if (!record || !record.id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamicProperties.js","sources":["../../../src/utils/dynamicProperties.js"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 Conduction B.V.\n// SPDX-License-Identifier: EUPL-1.2\n\n/**\n * Form fields that a record's own data decides, rather than its schema.\n *\n * Some domains keep half of an object's shape in the database instead of the\n * schema. A municipal case type declares which extra questions its cases must\n * answer; a product line declares which attributes its orders carry. The\n * schema cannot enumerate those, because a functional admin adds them at\n * runtime without a release.\n *\n * The pattern is always the same three parts, so this module names them once:\n *\n * - a **driving property** on the schema — a reference the user picks first\n * (`case.caseType`), carrying an `x-openregister-extends-form` block;\n * - a **definitions schema** whose records describe the extra fields\n * (`propertyDefinition`), filtered by the driving property's value;\n * - a **values schema** that stores one answer per definition per object\n * (`caseProperty`), written after the parent object exists.\n *\n * Definitions are mapped into ordinary JSON Schema properties and handed to\n * `fieldsFromSchema`, so widget resolution, enum labels, validation and\n * description splitting all come from the one engine. A dynamic field is not\n * a second kind of field; it is a normal field whose declaration arrived late.\n *\n * @module utils/dynamicProperties\n */\n\nimport { resolveFilterTokens } from './resolveFilterTokens.js'\n\n/**\n * The vendor extension a driving property carries.\n *\n * @type {string}\n */\nexport const EXTENDS_FORM_KEY = 'x-openregister-extends-form'\n\n/**\n * The vendor extension a driving property carries to prefill its siblings.\n *\n * Where `x-openregister-extends-form` adds NEW fields, this one fills fields\n * the schema already declares. A case type knows the status a case of its\n * kind starts in and who normally handles it, so a person should not have to\n * retype what the chosen type already answers.\n *\n * @type {string}\n */\nexport const PREFILL_KEY = 'x-openregister-prefill'\n\n/**\n * Prefix that namespaces a dynamic field's key inside form data.\n *\n * Definition records are named by a functional admin, so a definition called\n * `title` or `status` is not merely possible but likely. Without a namespace\n * it would overwrite the real schema property of that name — silently, since\n * a form has no way to tell the two apart once they share a key.\n *\n * @type {string}\n */\nexport const DYNAMIC_KEY_PREFIX = 'x-prop:'\n\n/**\n * How a definition record's declared type becomes a JSON Schema property.\n *\n * Covers the JSON Schema type names themselves plus the shorthands a\n * definitions schema tends to use, because an admin picking a type from a\n * dropdown picks `date`, not `string`/`format: date`.\n *\n * @type {Record<string, object>}\n */\nconst TYPE_MAP = {\n\tstring: { type: 'string' },\n\ttext: { type: 'string' },\n\ttextarea: { type: 'string', format: 'textarea' },\n\tmarkdown: { type: 'string', format: 'markdown' },\n\tnumber: { type: 'number' },\n\tinteger: { type: 'integer' },\n\tboolean: { type: 'boolean' },\n\tdate: { type: 'string', format: 'date' },\n\tdatetime: { type: 'string', format: 'date-time' },\n\t'date-time': { type: 'string', format: 'date-time' },\n\turl: { type: 'string', format: 'uri' },\n\turi: { type: 'string', format: 'uri' },\n\temail: { type: 'string', format: 'email' },\n\tenum: { type: 'string' },\n\tjson: { type: 'object', widget: 'json' },\n\tarray: { type: 'array' },\n\tobject: { type: 'object', widget: 'json' },\n}\n\n/**\n * Field names read off a definition record when the declaration omits `map`.\n *\n * @type {Record<string, string>}\n */\nconst DEFAULT_MAP = {\n\ttitle: 'name',\n\tdescription: 'description',\n\ttype: 'propertyType',\n\tenum: 'enumValues',\n\trequired: 'isRequired',\n\tdefault: 'defaultValue',\n}\n\n/**\n * Read a value off a record by mapped field name.\n *\n * @param {object} record The definition record.\n * @param {object} map The resolved field-name map.\n * @param {string} role The map role (`title`, `type`, …).\n * @return {unknown} The value, or undefined when the role is unmapped or absent.\n */\nfunction mapped(record, map, role) {\n\tconst field = map[role]\n\tif (!field) {\n\t\treturn undefined\n\t}\n\treturn record[field]\n}\n\n/**\n * The `x-openregister-extends-form` declarations on a schema, one per driving\n * property. Pure: reads the schema and nothing else.\n *\n * A schema may carry more than one — an order extended by both its product\n * line and its customer segment — so this always returns a list.\n *\n * @param {object} schema The schema object with a `properties` field.\n * @return {Array<{key: string, config: object}>} The declarations, in property order.\n */\nexport function extendsFormDeclarations(schema) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\tconst out = []\n\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\tconst config = prop && prop[EXTENDS_FORM_KEY]\n\t\tif (config && typeof config === 'object' && config.definitions) {\n\t\t\tout.push({ key, config })\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * A definition's name as a person should read it.\n *\n * Definition names are typed by a functional admin, and in practice a good\n * many arrive as identifiers rather than labels: real seeded data in dossiq\n * carries `auditorsStatementThreshold` and `interimReportTermWeeks`, which\n * render verbatim on a form a case handler is supposed to find friendly.\n *\n * Only an identifier-shaped name is touched. Anything containing a space is\n * already a label someone wrote deliberately, and reformatting it would be\n * this function deciding it knows better than the person who typed it.\n *\n * @param {string} name The definition's name.\n * @return {string} The name, made readable when it was an identifier.\n */\nfunction humaniseName(name) {\n\tconst value = String(name || '')\n\tif (!value || value.includes(' ')) {\n\t\treturn value\n\t}\n\n\tconst words = value\n\t\t// `camelCase` and `snake_case` / `kebab-case` both become words. The\n\t\t// lookahead pair keeps an acronym whole: `defaultBSNPolicy` splits to\n\t\t// `default BSN Policy`, not `default B S N Policy`.\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.trim()\n\t\t.split(/\\s+/)\n\t\t.filter(Boolean)\n\tif (words.length === 0) {\n\t\treturn value\n\t}\n\n\t// Sentence case, not Title Case: splitting `auditorsStatementThreshold`\n\t// leaves each word capitalised, and shipping that would put a Title Case\n\t// label on every form. An all-caps word is an acronym and keeps its shape.\n\tconst cased = words.map((word, index) => {\n\t\tif (word.length > 1 && word === word.toUpperCase()) {\n\t\t\treturn word\n\t\t}\n\t\tconst lower = word.toLowerCase()\n\t\treturn index === 0 ? lower.charAt(0).toUpperCase() + lower.slice(1) : lower\n\t})\n\n\treturn cased.join(' ')\n}\n\n/**\n * The schema's `x-openregister-prefill` declarations, in property order.\n *\n * A declaration needs a `fields` map to be worth acting on: without it there\n * is nothing to copy, and returning it anyway would cost a fetch per change\n * for no effect.\n *\n * @param {object} schema The schema object with a `properties` field.\n * @return {Array<{key: string, config: object}>} The declarations, in property order.\n */\nexport function prefillDeclarations(schema) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\tconst out = []\n\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\tconst config = prop && prop[PREFILL_KEY]\n\t\tif (config && typeof config === 'object' && config.fields\n\t\t\t&& Object.keys(config.fields).length > 0) {\n\t\t\tout.push({ key, config })\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * The values one chosen record offers its siblings.\n *\n * Reads `config.fields` as `{ targetProperty: sourceProperty }` and returns\n * only the pairs the record can actually answer. A source field the record\n * leaves empty yields nothing, so a case type with no default assignee\n * prefills the status it does know and leaves the assignee alone, rather\n * than blanking a value.\n *\n * @param {object} record The chosen record, as the API returned it.\n * @param {object} config The `x-openregister-prefill` block (needs `fields`).\n * @return {object} Target property keys mapped to the values to apply.\n */\nexport function prefillValues(record, config) {\n\tconst fields = (config && config.fields) || null\n\tif (!record || !fields) {\n\t\treturn {}\n\t}\n\n\tconst out = {}\n\tfor (const [target, source] of Object.entries(fields)) {\n\t\tif (typeof source !== 'string' || !source) {\n\t\t\tcontinue\n\t\t}\n\t\tconst value = record[source]\n\t\tif (value === undefined || value === null || value === '') {\n\t\t\tcontinue\n\t\t}\n\t\tif (Array.isArray(value) && value.length === 0) {\n\t\t\tcontinue\n\t\t}\n\t\tout[target] = value\n\t}\n\treturn out\n}\n\n/**\n * The query parameters that fetch the definitions for one driving value.\n *\n * `config.definitions.filter` is token-resolved the way `x-relation-filter`\n * is, with the driving property's value available as `$value` and the whole\n * form as `@object.<field>`. A filter entry whose token stays unresolved is\n * dropped rather than sent, because a literal `@object.foo` reaching the API\n * filters on nonsense and returns zero rows — which reads exactly like a\n * case type that has no extra properties.\n *\n * @param {object} config The `x-openregister-extends-form` block.\n * @param {unknown} value The driving property's current value.\n * @param {object} [formData] The full form data, for `@object.<field>` tokens.\n * @return {object} Query parameters for `fetchCollection`.\n */\nexport function definitionQueryParams(config, value, formData = {}) {\n\tconst params = { _limit: 100 }\n\tconst raw = (config && config.definitions && config.definitions.filter) || null\n\tif (!raw || typeof raw !== 'object') {\n\t\treturn params\n\t}\n\n\t// `$value` is the driving property itself; substitute it before token\n\t// resolution so the generic resolver never sees a token it cannot answer.\n\tconst seeded = {}\n\tfor (const [key, entry] of Object.entries(raw)) {\n\t\tseeded[key] = entry === '$value' ? value : entry\n\t}\n\tconst resolved = resolveFilterTokens(seeded, { object: { ...formData }, objectId: formData.id })\n\tfor (const [key, entry] of Object.entries(resolved)) {\n\t\tif (typeof entry === 'string' && entry.charAt(0) === '@') {\n\t\t\tcontinue\n\t\t}\n\t\tif (entry && typeof entry === 'object' && !Array.isArray(entry)) {\n\t\t\tfor (const [op, operand] of Object.entries(entry)) {\n\t\t\t\tparams[`${key}[${op}]`] = operand\n\t\t\t}\n\t\t} else if (entry !== '' && entry !== null && entry !== undefined) {\n\t\t\tparams[key] = entry\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * Turn definition records into JSON Schema properties.\n *\n * The result is an ordinary `properties` map — the same shape a schema\n * carries — so the caller can hand it straight to `fieldsFromSchema` and get\n * widgets, enum labels, validation and required-marking for free.\n *\n * Each key is `DYNAMIC_KEY_PREFIX` + the record's id, never the admin-authored\n * name, so a definition can be renamed without orphaning the answers already\n * stored against it.\n *\n * @param {Array<object>} definitions The definition records.\n * @param {object} [config] The `x-openregister-extends-form` block (`map`, `typeMap`).\n * @param {object} [options] Extra options.\n * @param {number} [options.orderFrom] Order assigned to the first field; each subsequent field takes the next integer. Dynamic fields sort after the schema's own, so pass a number above every declared `order`.\n * @return {{properties: object, required: string[]}} Properties keyed by prefixed id, plus the required key list.\n */\nexport function propertiesFromDefinitions(definitions, config = {}, options = {}) {\n\tconst map = { ...DEFAULT_MAP, ...(config.map || {}) }\n\tconst typeMap = { ...TYPE_MAP, ...(config.typeMap || {}) }\n\tconst orderFrom = typeof options.orderFrom === 'number' ? options.orderFrom : 1000\n\n\tconst properties = {}\n\tconst required = []\n\tconst list = Array.isArray(definitions) ? definitions : []\n\n\tlist.forEach((record, index) => {\n\t\tif (!record || !record.id) {\n\t\t\treturn\n\t\t}\n\t\tconst key = DYNAMIC_KEY_PREFIX + record.id\n\t\tconst declaredType = mapped(record, map, 'type')\n\t\tconst base = typeMap[declaredType] || typeMap.string\n\n\t\tconst title = mapped(record, map, 'title')\n\t\tconst description = mapped(record, map, 'description')\n\t\tconst enumValues = mapped(record, map, 'enum')\n\t\tconst defaultValue = mapped(record, map, 'default')\n\t\tconst maxLength = mapped(record, map, 'maxLength')\n\t\tconst format = mapped(record, map, 'format')\n\n\t\tconst prop = {\n\t\t\t...base,\n\t\t\ttitle: humaniseName(title) || key,\n\t\t\t// A definition record separates its short `definition` from its\n\t\t\t// longer `description`; either may be absent, and an empty string\n\t\t\t// must not become the helper text \"undefined\".\n\t\t\tdescription: description || mapped(record, map, 'definition') || '',\n\t\t}\n\t\t// An explicitly mapped format wins over the one the type shorthand\n\t\t// implied, so a definition can say `string` + `date` and still get a\n\t\t// date picker.\n\t\tif (format) {\n\t\t\tprop.format = format\n\t\t}\n\t\tif (typeof maxLength === 'number' && maxLength > 0) {\n\t\t\tprop.maxLength = maxLength\n\t\t}\n\t\tif (Array.isArray(enumValues) && enumValues.length > 0) {\n\t\t\tprop.enum = [...enumValues]\n\t\t}\n\t\tif (defaultValue !== undefined && defaultValue !== null && defaultValue !== '') {\n\t\t\tprop.default = defaultValue\n\t\t}\n\t\tprop.order = orderFrom + index\n\n\t\tproperties[key] = prop\n\t\tif (mapped(record, map, 'required') === true) {\n\t\t\trequired.push(key)\n\t\t}\n\t})\n\n\treturn { properties, required }\n}\n\n/**\n * Whether a form-data key holds a dynamic field's answer.\n *\n * @param {string} key The form-data key.\n * @return {boolean} True for a dynamic key.\n */\nexport function isDynamicKey(key) {\n\treturn typeof key === 'string' && key.startsWith(DYNAMIC_KEY_PREFIX)\n}\n\n/**\n * The definition id a dynamic key refers to.\n *\n * @param {string} key The dynamic form-data key.\n * @return {string} The definition id, or '' when the key is not dynamic.\n */\nexport function definitionIdFromKey(key) {\n\treturn isDynamicKey(key) ? key.slice(DYNAMIC_KEY_PREFIX.length) : ''\n}\n\n/**\n * Split a submitted form payload into the object's own fields and the answers\n * that belong in the values schema.\n *\n * The parent object must be saved first — a value row references it — so the\n * two halves cannot go out in one call, and mixing them would post keys the\n * parent schema does not declare. OpenRegister drops undeclared properties\n * silently, so an unsplit payload loses every answer with a 200 and no error.\n *\n * @param {object} formData The dialog's confirmed payload.\n * @return {{base: object, answers: Array<{definitionId: string, value: unknown}>}} The parent's fields, and one answer per dynamic field.\n */\nexport function splitDynamicFormData(formData) {\n\tconst base = {}\n\tconst answers = []\n\tfor (const [key, value] of Object.entries(formData || {})) {\n\t\tif (isDynamicKey(key)) {\n\t\t\tanswers.push({ definitionId: definitionIdFromKey(key), value })\n\t\t} else {\n\t\t\tbase[key] = value\n\t\t}\n\t}\n\treturn { base, answers }\n}\n\n/**\n * Whether a declaration stores its answers as an array on the parent.\n *\n * Two shapes are supported. The default writes one child record per answer\n * (`values.schema` + `objectRef` + `definitionRef`), which is normalised and\n * queryable. Setting `values.mode: 'array'` instead folds the answers into an\n * array property on the parent object itself, which reads in one request and\n * saves in one write, at the cost of not being queryable per answer.\n *\n * @param {object} config One `x-openregister-extends-form` declaration.\n * @return {boolean} True when the declaration stores an array on the parent.\n */\nexport function usesArrayValues(config) {\n\tconst values = (config && config.values) || null\n\treturn !!(values && values.mode === 'array' && values.arrayKey)\n}\n\n/**\n * Build the array a declaration stores on its parent object.\n *\n * Each entry carries the definition it answers as well as its name, so a\n * reader can render the answers without resolving every definition first.\n * That denormalisation is the point of the array shape: one read, no joins.\n *\n * @param {Array<object>} answers `{ definitionId, value }` entries.\n * @param {object} config One `x-openregister-extends-form` declaration.\n * @param {Array<object>} definitions The definition records, for their names.\n * @return {Array<object>} Entries for the parent's array property.\n */\nexport function valueArrayFor(answers, config, definitions = []) {\n\tif (!usesArrayValues(config)) {\n\t\treturn []\n\t}\n\tconst values = config.values\n\tconst definitionRef = values.definitionRef || 'definition'\n\tconst valueKey = values.valueKey || 'value'\n\tconst nameKey = values.nameKey || 'name'\n\tconst nameFrom = (config.map && config.map.title) || 'name'\n\tconst byId = new Map((definitions || []).map((d) => [String(d.id ?? d.uuid ?? ''), d]))\n\n\treturn (answers || [])\n\t\t.filter(({ value }) => value !== undefined && value !== null && value !== '')\n\t\t.map(({ definitionId, value }) => {\n\t\t\tconst def = byId.get(String(definitionId))\n\t\t\treturn {\n\t\t\t\t[definitionRef]: definitionId,\n\t\t\t\t[nameKey]: def ? String(def[nameFrom] ?? '') : '',\n\t\t\t\t// Same rule as the record shape: a non-scalar answer is\n\t\t\t\t// serialised rather than dropped.\n\t\t\t\t[valueKey]: (typeof value === 'object') ? JSON.stringify(value) : String(value),\n\t\t\t}\n\t\t})\n}\n\n/**\n * The value-schema records to write for one saved parent object.\n *\n * An answer left empty writes no row: an absent row and a row holding `''`\n * mean the same thing to every reader, and not writing it keeps the value\n * schema free of rows that only record that someone opened the form.\n *\n * @param {Array<{definitionId: string, value: unknown}>} answers The answers from `splitDynamicFormData`.\n * @param {object} config The `x-openregister-extends-form` block (needs `values`).\n * @param {string} objectId The saved parent object's id.\n * @return {Array<object>} One payload per row to create; empty when nothing is to be written.\n */\nexport function valueRecordsFor(answers, config, objectId) {\n\tconst values = (config && config.values) || null\n\tif (!values || !values.schema || !objectId) {\n\t\treturn []\n\t}\n\tconst objectRef = values.objectRef || 'object'\n\tconst definitionRef = values.definitionRef || 'definition'\n\tconst valueKey = values.valueKey || 'value'\n\n\treturn (answers || [])\n\t\t.filter(({ value }) => value !== undefined && value !== null && value !== '')\n\t\t.map(({ definitionId, value }) => ({\n\t\t\t[objectRef]: objectId,\n\t\t\t[definitionRef]: definitionId,\n\t\t\t// A value schema stores one column for every type it carries, so a\n\t\t\t// non-scalar answer is serialised rather than dropped.\n\t\t\t[valueKey]: (typeof value === 'object') ? JSON.stringify(value) : String(value),\n\t\t}))\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dynamicProperties.js","sources":["../../../src/utils/dynamicProperties.js"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 Conduction B.V.\n// SPDX-License-Identifier: EUPL-1.2\n\n/**\n * Form fields that a record's own data decides, rather than its schema.\n *\n * Some domains keep half of an object's shape in the database instead of the\n * schema. A municipal case type declares which extra questions its cases must\n * answer; a product line declares which attributes its orders carry. The\n * schema cannot enumerate those, because a functional admin adds them at\n * runtime without a release.\n *\n * The pattern is always the same three parts, so this module names them once:\n *\n * - a **driving property** on the schema — a reference the user picks first\n * (`case.caseType`), carrying an `x-openregister-extends-form` block;\n * - a **definitions schema** whose records describe the extra fields\n * (`propertyDefinition`), filtered by the driving property's value;\n * - a **values schema** that stores one answer per definition per object\n * (`caseProperty`), written after the parent object exists.\n *\n * Definitions are mapped into ordinary JSON Schema properties and handed to\n * `fieldsFromSchema`, so widget resolution, enum labels, validation and\n * description splitting all come from the one engine. A dynamic field is not\n * a second kind of field; it is a normal field whose declaration arrived late.\n *\n * @module utils/dynamicProperties\n */\n\nimport { resolveFilterTokens } from './resolveFilterTokens.js'\n\n/**\n * The vendor extension a driving property carries.\n *\n * @type {string}\n */\nexport const EXTENDS_FORM_KEY = 'x-openregister-extends-form'\n\n/**\n * The vendor extension a driving property carries to prefill its siblings.\n *\n * Where `x-openregister-extends-form` adds NEW fields, this one fills fields\n * the schema already declares. A case type knows the status a case of its\n * kind starts in and who normally handles it, so a person should not have to\n * retype what the chosen type already answers.\n *\n * @type {string}\n */\nexport const PREFILL_KEY = 'x-openregister-prefill'\n\n/**\n * Prefix that namespaces a dynamic field's key inside form data.\n *\n * Definition records are named by a functional admin, so a definition called\n * `title` or `status` is not merely possible but likely. Without a namespace\n * it would overwrite the real schema property of that name — silently, since\n * a form has no way to tell the two apart once they share a key.\n *\n * @type {string}\n */\nexport const DYNAMIC_KEY_PREFIX = 'x-prop:'\n\n/**\n * How a definition record's declared type becomes a JSON Schema property.\n *\n * Covers the JSON Schema type names themselves plus the shorthands a\n * definitions schema tends to use, because an admin picking a type from a\n * dropdown picks `date`, not `string`/`format: date`.\n *\n * @type {Record<string, object>}\n */\nconst TYPE_MAP = {\n\tstring: { type: 'string' },\n\ttext: { type: 'string' },\n\ttextarea: { type: 'string', format: 'textarea' },\n\tmarkdown: { type: 'string', format: 'markdown' },\n\tnumber: { type: 'number' },\n\tinteger: { type: 'integer' },\n\tboolean: { type: 'boolean' },\n\tdate: { type: 'string', format: 'date' },\n\tdatetime: { type: 'string', format: 'date-time' },\n\t'date-time': { type: 'string', format: 'date-time' },\n\turl: { type: 'string', format: 'uri' },\n\turi: { type: 'string', format: 'uri' },\n\temail: { type: 'string', format: 'email' },\n\tenum: { type: 'string' },\n\tjson: { type: 'object', widget: 'json' },\n\tarray: { type: 'array' },\n\tobject: { type: 'object', widget: 'json' },\n}\n\n/**\n * Field names read off a definition record when the declaration omits `map`.\n *\n * @type {Record<string, string>}\n */\nconst DEFAULT_MAP = {\n\ttitle: 'name',\n\tdescription: 'description',\n\ttype: 'propertyType',\n\tenum: 'enumValues',\n\trequired: 'isRequired',\n\tdefault: 'defaultValue',\n\thideOnCreate: 'hideOnCreate',\n}\n\n/**\n * Read a value off a record by mapped field name.\n *\n * @param {object} record The definition record.\n * @param {object} map The resolved field-name map.\n * @param {string} role The map role (`title`, `type`, …).\n * @return {unknown} The value, or undefined when the role is unmapped or absent.\n */\nfunction mapped(record, map, role) {\n\tconst field = map[role]\n\tif (!field) {\n\t\treturn undefined\n\t}\n\treturn record[field]\n}\n\n/**\n * The `x-openregister-extends-form` declarations on a schema, one per driving\n * property. Pure: reads the schema and nothing else.\n *\n * A schema may carry more than one — an order extended by both its product\n * line and its customer segment — so this always returns a list.\n *\n * @param {object} schema The schema object with a `properties` field.\n * @return {Array<{key: string, config: object}>} The declarations, in property order.\n */\nexport function extendsFormDeclarations(schema) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\tconst out = []\n\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\tconst config = prop && prop[EXTENDS_FORM_KEY]\n\t\tif (config && typeof config === 'object' && config.definitions) {\n\t\t\tout.push({ key, config })\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * A definition's name as a person should read it.\n *\n * Definition names are typed by a functional admin, and in practice a good\n * many arrive as identifiers rather than labels: real seeded data in dossiq\n * carries `auditorsStatementThreshold` and `interimReportTermWeeks`, which\n * render verbatim on a form a case handler is supposed to find friendly.\n *\n * Only an identifier-shaped name is touched. Anything containing a space is\n * already a label someone wrote deliberately, and reformatting it would be\n * this function deciding it knows better than the person who typed it.\n *\n * @param {string} name The definition's name.\n * @return {string} The name, made readable when it was an identifier.\n */\nfunction humaniseName(name) {\n\tconst value = String(name || '')\n\tif (!value || value.includes(' ')) {\n\t\treturn value\n\t}\n\n\tconst words = value\n\t\t// `camelCase` and `snake_case` / `kebab-case` both become words. The\n\t\t// lookahead pair keeps an acronym whole: `defaultBSNPolicy` splits to\n\t\t// `default BSN Policy`, not `default B S N Policy`.\n\t\t.replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n\t\t.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n\t\t.replace(/[_-]+/g, ' ')\n\t\t.trim()\n\t\t.split(/\\s+/)\n\t\t.filter(Boolean)\n\tif (words.length === 0) {\n\t\treturn value\n\t}\n\n\t// Sentence case, not Title Case: splitting `auditorsStatementThreshold`\n\t// leaves each word capitalised, and shipping that would put a Title Case\n\t// label on every form. An all-caps word is an acronym and keeps its shape.\n\tconst cased = words.map((word, index) => {\n\t\tif (word.length > 1 && word === word.toUpperCase()) {\n\t\t\treturn word\n\t\t}\n\t\tconst lower = word.toLowerCase()\n\t\treturn index === 0 ? lower.charAt(0).toUpperCase() + lower.slice(1) : lower\n\t})\n\n\treturn cased.join(' ')\n}\n\n/**\n * The schema's `x-openregister-prefill` declarations, in property order.\n *\n * A declaration needs a `fields` map to be worth acting on: without it there\n * is nothing to copy, and returning it anyway would cost a fetch per change\n * for no effect.\n *\n * @param {object} schema The schema object with a `properties` field.\n * @return {Array<{key: string, config: object}>} The declarations, in property order.\n */\nexport function prefillDeclarations(schema) {\n\tif (!schema || !schema.properties) {\n\t\treturn []\n\t}\n\tconst out = []\n\tfor (const [key, prop] of Object.entries(schema.properties)) {\n\t\tconst config = prop && prop[PREFILL_KEY]\n\t\tif (config && typeof config === 'object' && config.fields\n\t\t\t&& Object.keys(config.fields).length > 0) {\n\t\t\tout.push({ key, config })\n\t\t}\n\t}\n\treturn out\n}\n\n/**\n * The values one chosen record offers its siblings.\n *\n * Reads `config.fields` as `{ targetProperty: sourceProperty }` and returns\n * only the pairs the record can actually answer. A source field the record\n * leaves empty yields nothing, so a case type with no default assignee\n * prefills the status it does know and leaves the assignee alone, rather\n * than blanking a value.\n *\n * @param {object} record The chosen record, as the API returned it.\n * @param {object} config The `x-openregister-prefill` block (needs `fields`).\n * @return {object} Target property keys mapped to the values to apply.\n */\nexport function prefillValues(record, config) {\n\tconst fields = (config && config.fields) || null\n\tif (!record || !fields) {\n\t\treturn {}\n\t}\n\n\tconst out = {}\n\tfor (const [target, source] of Object.entries(fields)) {\n\t\tif (typeof source !== 'string' || !source) {\n\t\t\tcontinue\n\t\t}\n\t\tconst value = record[source]\n\t\tif (value === undefined || value === null || value === '') {\n\t\t\tcontinue\n\t\t}\n\t\tif (Array.isArray(value) && value.length === 0) {\n\t\t\tcontinue\n\t\t}\n\t\tout[target] = value\n\t}\n\treturn out\n}\n\n/**\n * The query parameters that fetch the definitions for one driving value.\n *\n * `config.definitions.filter` is token-resolved the way `x-relation-filter`\n * is, with the driving property's value available as `$value` and the whole\n * form as `@object.<field>`. A filter entry whose token stays unresolved is\n * dropped rather than sent, because a literal `@object.foo` reaching the API\n * filters on nonsense and returns zero rows — which reads exactly like a\n * case type that has no extra properties.\n *\n * @param {object} config The `x-openregister-extends-form` block.\n * @param {unknown} value The driving property's current value.\n * @param {object} [formData] The full form data, for `@object.<field>` tokens.\n * @return {object} Query parameters for `fetchCollection`.\n */\nexport function definitionQueryParams(config, value, formData = {}) {\n\tconst params = { _limit: 100 }\n\tconst raw = (config && config.definitions && config.definitions.filter) || null\n\tif (!raw || typeof raw !== 'object') {\n\t\treturn params\n\t}\n\n\t// `$value` is the driving property itself; substitute it before token\n\t// resolution so the generic resolver never sees a token it cannot answer.\n\tconst seeded = {}\n\tfor (const [key, entry] of Object.entries(raw)) {\n\t\tseeded[key] = entry === '$value' ? value : entry\n\t}\n\tconst resolved = resolveFilterTokens(seeded, { object: { ...formData }, objectId: formData.id })\n\tfor (const [key, entry] of Object.entries(resolved)) {\n\t\tif (typeof entry === 'string' && entry.charAt(0) === '@') {\n\t\t\tcontinue\n\t\t}\n\t\tif (entry && typeof entry === 'object' && !Array.isArray(entry)) {\n\t\t\tfor (const [op, operand] of Object.entries(entry)) {\n\t\t\t\tparams[`${key}[${op}]`] = operand\n\t\t\t}\n\t\t} else if (entry !== '' && entry !== null && entry !== undefined) {\n\t\t\tparams[key] = entry\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * Turn definition records into JSON Schema properties.\n *\n * The result is an ordinary `properties` map — the same shape a schema\n * carries — so the caller can hand it straight to `fieldsFromSchema` and get\n * widgets, enum labels, validation and required-marking for free.\n *\n * Each key is `DYNAMIC_KEY_PREFIX` + the record's id, never the admin-authored\n * name, so a definition can be renamed without orphaning the answers already\n * stored against it.\n *\n * @param {Array<object>} definitions The definition records.\n * @param {object} [config] The `x-openregister-extends-form` block (`map`, `typeMap`).\n * @param {object} [options] Extra options.\n * @param {number} [options.orderFrom] Order assigned to the first field; each subsequent field takes the next integer. Dynamic fields sort after the schema's own, so pass a number above every declared `order`.\n * @param {boolean} [options.create] The form creates a new object: a definition whose `hideOnCreate` (or the field `config.map.hideOnCreate` names) is `true` gets no field, because the app fills that answer itself at creation. Edit forms still show it.\n * @spec openspec/changes/dynamic-question-hide-on-create/specs/dynamic-question-hide-on-create/spec.md#requirement-a-question-can-stay-off-the-create-form\n * @return {{properties: object, required: string[]}} Properties keyed by prefixed id, plus the required key list.\n */\nexport function propertiesFromDefinitions(definitions, config = {}, options = {}) {\n\tconst map = { ...DEFAULT_MAP, ...(config.map || {}) }\n\tconst typeMap = { ...TYPE_MAP, ...(config.typeMap || {}) }\n\tconst orderFrom = typeof options.orderFrom === 'number' ? options.orderFrom : 1000\n\n\tconst properties = {}\n\tconst required = []\n\tconst list = (Array.isArray(definitions) ? definitions : [])\n\t\t.filter((record) => !(options.create === true && record && mapped(record, map, 'hideOnCreate') === true))\n\n\tlist.forEach((record, index) => {\n\t\tif (!record || !record.id) {\n\t\t\treturn\n\t\t}\n\t\tconst key = DYNAMIC_KEY_PREFIX + record.id\n\t\tconst declaredType = mapped(record, map, 'type')\n\t\tconst base = typeMap[declaredType] || typeMap.string\n\n\t\tconst title = mapped(record, map, 'title')\n\t\tconst description = mapped(record, map, 'description')\n\t\tconst enumValues = mapped(record, map, 'enum')\n\t\tconst defaultValue = mapped(record, map, 'default')\n\t\tconst maxLength = mapped(record, map, 'maxLength')\n\t\tconst format = mapped(record, map, 'format')\n\n\t\tconst prop = {\n\t\t\t...base,\n\t\t\ttitle: humaniseName(title) || key,\n\t\t\t// A definition record separates its short `definition` from its\n\t\t\t// longer `description`; either may be absent, and an empty string\n\t\t\t// must not become the helper text \"undefined\".\n\t\t\tdescription: description || mapped(record, map, 'definition') || '',\n\t\t}\n\t\t// An explicitly mapped format wins over the one the type shorthand\n\t\t// implied, so a definition can say `string` + `date` and still get a\n\t\t// date picker.\n\t\tif (format) {\n\t\t\tprop.format = format\n\t\t}\n\t\tif (typeof maxLength === 'number' && maxLength > 0) {\n\t\t\tprop.maxLength = maxLength\n\t\t}\n\t\tif (Array.isArray(enumValues) && enumValues.length > 0) {\n\t\t\tprop.enum = [...enumValues]\n\t\t}\n\t\tif (defaultValue !== undefined && defaultValue !== null && defaultValue !== '') {\n\t\t\tprop.default = defaultValue\n\t\t}\n\t\tprop.order = orderFrom + index\n\n\t\tproperties[key] = prop\n\t\tif (mapped(record, map, 'required') === true) {\n\t\t\trequired.push(key)\n\t\t}\n\t})\n\n\treturn { properties, required }\n}\n\n/**\n * Whether a form-data key holds a dynamic field's answer.\n *\n * @param {string} key The form-data key.\n * @return {boolean} True for a dynamic key.\n */\nexport function isDynamicKey(key) {\n\treturn typeof key === 'string' && key.startsWith(DYNAMIC_KEY_PREFIX)\n}\n\n/**\n * The definition id a dynamic key refers to.\n *\n * @param {string} key The dynamic form-data key.\n * @return {string} The definition id, or '' when the key is not dynamic.\n */\nexport function definitionIdFromKey(key) {\n\treturn isDynamicKey(key) ? key.slice(DYNAMIC_KEY_PREFIX.length) : ''\n}\n\n/**\n * Split a submitted form payload into the object's own fields and the answers\n * that belong in the values schema.\n *\n * The parent object must be saved first — a value row references it — so the\n * two halves cannot go out in one call, and mixing them would post keys the\n * parent schema does not declare. OpenRegister drops undeclared properties\n * silently, so an unsplit payload loses every answer with a 200 and no error.\n *\n * @param {object} formData The dialog's confirmed payload.\n * @return {{base: object, answers: Array<{definitionId: string, value: unknown}>}} The parent's fields, and one answer per dynamic field.\n */\nexport function splitDynamicFormData(formData) {\n\tconst base = {}\n\tconst answers = []\n\tfor (const [key, value] of Object.entries(formData || {})) {\n\t\tif (isDynamicKey(key)) {\n\t\t\tanswers.push({ definitionId: definitionIdFromKey(key), value })\n\t\t} else {\n\t\t\tbase[key] = value\n\t\t}\n\t}\n\treturn { base, answers }\n}\n\n/**\n * Whether a declaration stores its answers as an array on the parent.\n *\n * Two shapes are supported. The default writes one child record per answer\n * (`values.schema` + `objectRef` + `definitionRef`), which is normalised and\n * queryable. Setting `values.mode: 'array'` instead folds the answers into an\n * array property on the parent object itself, which reads in one request and\n * saves in one write, at the cost of not being queryable per answer.\n *\n * @param {object} config One `x-openregister-extends-form` declaration.\n * @return {boolean} True when the declaration stores an array on the parent.\n */\nexport function usesArrayValues(config) {\n\tconst values = (config && config.values) || null\n\treturn !!(values && values.mode === 'array' && values.arrayKey)\n}\n\n/**\n * Build the array a declaration stores on its parent object.\n *\n * Each entry carries the definition it answers as well as its name, so a\n * reader can render the answers without resolving every definition first.\n * That denormalisation is the point of the array shape: one read, no joins.\n *\n * @param {Array<object>} answers `{ definitionId, value }` entries.\n * @param {object} config One `x-openregister-extends-form` declaration.\n * @param {Array<object>} definitions The definition records, for their names.\n * @return {Array<object>} Entries for the parent's array property.\n */\nexport function valueArrayFor(answers, config, definitions = []) {\n\tif (!usesArrayValues(config)) {\n\t\treturn []\n\t}\n\tconst values = config.values\n\tconst definitionRef = values.definitionRef || 'definition'\n\tconst valueKey = values.valueKey || 'value'\n\tconst nameKey = values.nameKey || 'name'\n\tconst nameFrom = (config.map && config.map.title) || 'name'\n\tconst byId = new Map((definitions || []).map((d) => [String(d.id ?? d.uuid ?? ''), d]))\n\n\treturn (answers || [])\n\t\t.filter(({ value }) => value !== undefined && value !== null && value !== '')\n\t\t.map(({ definitionId, value }) => {\n\t\t\tconst def = byId.get(String(definitionId))\n\t\t\treturn {\n\t\t\t\t[definitionRef]: definitionId,\n\t\t\t\t[nameKey]: def ? String(def[nameFrom] ?? '') : '',\n\t\t\t\t// Same rule as the record shape: a non-scalar answer is\n\t\t\t\t// serialised rather than dropped.\n\t\t\t\t[valueKey]: (typeof value === 'object') ? JSON.stringify(value) : String(value),\n\t\t\t}\n\t\t})\n}\n\n/**\n * The value-schema records to write for one saved parent object.\n *\n * An answer left empty writes no row: an absent row and a row holding `''`\n * mean the same thing to every reader, and not writing it keeps the value\n * schema free of rows that only record that someone opened the form.\n *\n * @param {Array<{definitionId: string, value: unknown}>} answers The answers from `splitDynamicFormData`.\n * @param {object} config The `x-openregister-extends-form` block (needs `values`).\n * @param {string} objectId The saved parent object's id.\n * @return {Array<object>} One payload per row to create; empty when nothing is to be written.\n */\nexport function valueRecordsFor(answers, config, objectId) {\n\tconst values = (config && config.values) || null\n\tif (!values || !values.schema || !objectId) {\n\t\treturn []\n\t}\n\tconst objectRef = values.objectRef || 'object'\n\tconst definitionRef = values.definitionRef || 'definition'\n\tconst valueKey = values.valueKey || 'value'\n\n\treturn (answers || [])\n\t\t.filter(({ value }) => value !== undefined && value !== null && value !== '')\n\t\t.map(({ definitionId, value }) => ({\n\t\t\t[objectRef]: objectId,\n\t\t\t[definitionRef]: definitionId,\n\t\t\t// A value schema stores one column for every type it carries, so a\n\t\t\t// non-scalar answer is serialised rather than dropped.\n\t\t\t[valueKey]: (typeof value === 'object') ? JSON.stringify(value) : String(value),\n\t\t}))\n}\n"],"names":[],"mappings":"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"}
|