@conduction/nextcloud-vue 2.56.0-beta.20 → 2.56.0-beta.21
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/CnFlowDetail/CnRunDetailSidebar.vue2.js +2 -0
- package/dist/esm/components/CnFlowDetail/CnRunDetailSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowDetail/CnRunDetailSidebar.vue3.js +7 -0
- package/dist/esm/components/CnFlowDetail/CnRunDetailSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue.js +10 -0
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue.js.map +1 -0
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue2.js +150 -0
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue2.js.map +1 -0
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue3.js +54 -0
- package/dist/esm/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue3.js.map +1 -0
- package/dist/esm/dialogs/CnFlowNodeEditModal.vue2.js +7 -10
- package/dist/esm/dialogs/CnFlowNodeEditModal.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnFlowNodeEditModal.vue3.js +23 -13
- package/dist/esm/dialogs/CnFlowNodeEditModal.vue3.js.map +1 -1
- package/dist/esm/dialogs/CnRunNodeDialog.vue2.js +8 -6
- package/dist/esm/dialogs/CnRunNodeDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnRunNodeDialog.vue3.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 +15 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +15 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +64 -0
- package/dist/esm/utils/selectOptions.js +57 -0
- package/dist/esm/utils/selectOptions.js.map +1 -0
- package/dist/nextcloud-vue.cjs.js +5945 -5645
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +64 -0
- package/l10n/en.json +15 -1
- package/l10n/nl.json +15 -1
- package/package.json +1 -1
- package/src/components/CnFlowDetail/CnRunDetailSidebar.vue +6 -0
- package/src/components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue +250 -0
- package/src/components/CnFlowStepOutcomes/index.js +8 -0
- package/src/components/index.js +1 -0
- package/src/dialogs/CnFlowNodeEditModal.vue +41 -20
- package/src/dialogs/CnRunNodeDialog.vue +8 -6
- package/src/index.js +1 -0
- package/src/utils/selectOptions.js +54 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnRunNodeDialog.vue2.js","sources":["../../../src/dialogs/CnRunNodeDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n -->\n\n<template>\n\t<NcDialog\n\t\t:name=\"tr(title)\"\n\t\tsize=\"normal\"\n\t\t:noClose=\"loading\"\n\t\tdata-testid=\"cn-run-node-dialog\"\n\t\t@closing=\"$emit('close')\">\n\t\t<NcNoteCard v-if=\"loadError\" type=\"error\" data-testid=\"cn-run-node-dialog-error\">\n\t\t\t{{ loadError }}\n\t\t</NcNoteCard>\n\n\t\t<div v-else class=\"cn-run-node-dialog__form\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\t:data-cn-field=\"field.key\"\n\t\t\t\tclass=\"cn-run-node-dialog__field\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'boolean'\"\n\t\t\t\t\t:modelValue=\"values[field.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\">\n\t\t\t\t\t{{ tr(field.label) }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t:modelValue=\"selectedOption(field)\"\n\t\t\t\t\t:options=\"optionsFor(field)\"\n\t\t\t\t\t:inputLabel=\"tr(field.label)\"\n\t\t\t\t\t:loading=\"optionsLoading[field.key] === true\"\n\t\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Pick one…')\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event ? $event.id : '')\" />\n\n\t\t\t\t<NcTextArea\n\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\trows=\"4\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else-if=\"field.type === 'number'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setNumberValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\t\t\t</div>\n\n\t\t\t<p v-if=\"!fields.length\" class=\"cn-run-node-dialog__hint\">\n\t\t\t\t{{ t('nextcloud-vue', 'This step has no options.') }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"loading\" @click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"!loadError\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"loading || !requiredFieldsFilled\"\n\t\t\t\t@click=\"$emit('confirm', values)\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"loading\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { prefixUrl } from '../utils/headers.js'\n\n/**\n * The dialog `run-node` opens to collect a directly-invoked flow node's own\n * declared config, before POSTing to OpenRegister's\n * `/api/flows/{flowId}/nodes/{nodeId}/run` (manifest-run-node-action / RN-4).\n *\n * WHY THIS IS A NEW, SMALL RENDERER AND NOT `CnFlowNodeEditModal`'S ONE\n * ----------------------------------------------------------------------\n * design.md says \"render it with the SAME field renderer CnFlowSidebar\n * [reads: CnFlowNodeEditModal] uses\" as the INTENT — no new form-rendering\n * VOCABULARY — and this component honours that: the type-to-widget mapping\n * (switch/select/textarea/number/text) and the `optionsFrom` fetch-and-\n * normalise behaviour below are the SAME rules that modal applies. What it\n * does NOT reuse is that modal's component/methods directly, because that\n * renderer solves a materially different problem: it guesses a widget for\n * ANY engine config key via `widgetFor()` heuristics (including keys no\n * `configForm()` ever declared — cron expressions, HTTP methods, principal\n * pickers, a `runAs` identity field, a raw-JSON fallback), because the flow\n * EDITOR must let an author set every key the engine reads whether or not\n * its type ever described one. A run-node CALLER dialog has no such need —\n * it renders ONLY the fields `configForm()` explicitly declares (this\n * interface's whole contract, per its own docblock: \"a field over a key the\n * node ignores looks like it works and changes nothing\") — text / textarea /\n * number / boolean / select, nothing else. Extracting a shared component\n * from the editor's modal is a reasonable follow-up; it was not done here to\n * avoid an invasive refactor of an unrelated, already-shipped surface for a\n * dialog whose actual field vocabulary is a fifth its size.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-the-nodes-own-config-form-drives-the-dialog-not-a-new-token\n */\nexport default {\n\tname: 'CnRunNodeDialog',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/** Pre-translated dialog title. */\n\t\ttitle: { type: String, default: '' },\n\t\t/**\n\t\t * The node's declared config form — `IFlowNodeConfigForm::configForm()`'s\n\t\t * shape, unchanged: `[{key, label, type, help?, required?, optionsFrom?}]`.\n\t\t *\n\t\t * @type {Array<object>}\n\t\t */\n\t\tfields: { type: Array, default: () => [] },\n\t\t/** Whether a run is in flight — disables Cancel/Run and shows a spinner. */\n\t\tloading: { type: Boolean, default: false },\n\t\t/** Set when the node's form could not be resolved; replaces the form with an error and hides Run. */\n\t\tloadError: { type: String, default: '' },\n\t\t/** The consumer's bound `t()`, matching CnActionButtons' own `cnTranslate` inject. */\n\t\ttranslate: { type: Function, default: null },\n\t},\n\n\temits: ['close', 'confirm'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Live field values, keyed by field.key. */\n\t\t\tvalues: {},\n\t\t\t/** Fetched `{id, label}` options per select field.key. */\n\t\t\toptions: {},\n\t\t\t/** In-flight flag per select field.key. */\n\t\t\toptionsLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Every `required: true` field carries a non-empty value. */\n\t\trequiredFieldsFilled() {\n\t\t\treturn this.fields.every((field) => {\n\t\t\t\tif (field.required !== true) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tconst value = this.values[field.key]\n\t\t\t\treturn value !== undefined && value !== null && value !== ''\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tfields: {\n\t\t\timmediate: true,\n\t\t\thandler(fields) {\n\t\t\t\tconst seed = {}\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tseed[field.key] = field.type === 'boolean' ? false : ''\n\t\t\t\t}\n\t\t\t\tthis.values = seed\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tif (field.type === 'select' && field.optionsFrom) {\n\t\t\t\t\t\tthis.loadOptions(field)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve a manifest/node-authored UI string through the host translate\n\t\t * function, matching CnActionButtons' own `tr()`.\n\t\t *\n\t\t * @param {string} [value] The English source string.\n\t\t * @return {string|undefined} The translated (or source) string.\n\t\t */\n\t\ttr(value) {\n\t\t\tif (!value) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn typeof this.translate === 'function' ? this.translate(value) : value\n\t\t},\n\n\t\t/**\n\t\t * Write one field's value.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {unknown} value The new value.\n\t\t * @return {void}\n\t\t */\n\t\tsetValue(key, value) {\n\t\t\tthis.values = { ...this.values, [key]: value }\n\t\t},\n\n\t\t/**\n\t\t * Write a number field, coercing an empty string to '' (not 0 — an\n\t\t * empty required-number field must still fail `requiredFieldsFilled`)\n\t\t * and anything else to a JS number.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {string} raw The NcTextField string value.\n\t\t * @return {void}\n\t\t */\n\t\tsetNumberValue(key, raw) {\n\t\t\tthis.setValue(key, raw === '' ? '' : Number(raw))\n\t\t},\n\n\t\t/**\n\t\t * The NcSelect-shaped `{id, label}` currently selected for a field, or\n\t\t * null. Falls back to `{id: value, label: String(value)}` when the\n\t\t * stored value is not (yet, or no longer) among the loaded options —\n\t\t * the same graceful-degrade `CnFlowNodeEditModal` applies.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\tif (value === undefined || value === null || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst opts = this.options[field.key] || []\n\t\t\treturn opts.find((o) => o.id === value) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/**\n\t\t * The loaded `{id, label}` options for a select field.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {Array<object>}\n\t\t */\n\t\toptionsFor(field) {\n\t\t\treturn this.options[field.key] || []\n\t\t},\n\n\t\t/**\n\t\t * Fetch and normalise a select field's `optionsFrom` catalogue —\n\t\t * SAME acceptance shape as `CnFlowNodeEditModal`'s own picker (design.md's\n\t\t * point: reuse the FORM CONTRACT, not necessarily the component): a bare\n\t\t * array or `{results: [...]}`; each row read as `{id, label}`,\n\t\t * `{value, label}`, or an OpenRegister object (`@self.uuid`/`uuid`,\n\t\t * `name`/`title`). A row this dialog cannot make sense of is dropped\n\t\t * rather than shown as a blank option.\n\t\t *\n\t\t * @param {object} field The field declaration carrying `optionsFrom`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions(field) {\n\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: true }\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }] = await Promise.all([import('@nextcloud/axios')])\n\t\t\t\tconst raw = String(field.optionsFrom)\n\t\t\t\tconst url = prefixUrl(raw)\n\t\t\t\tconst response = await axios.get(url)\n\t\t\t\tconst rows = Array.isArray(response.data) ? response.data : (response.data?.results || [])\n\t\t\t\tconst opts = rows.map((row) => {\n\t\t\t\t\tconst id = row.id ?? row.value ?? row['@self']?.uuid ?? row.uuid\n\t\t\t\t\treturn { id, label: row.label || row.name || row.title || String(id) }\n\t\t\t\t}).filter((o) => o.id !== undefined && o.id !== null && o.id !== '')\n\t\t\t\tthis.options = { ...this.options, [field.key]: opts }\n\t\t\t} catch (error) {\n\t\t\t\t// A picker that fails to load degrades to an empty list rather\n\t\t\t\t// than blocking the whole dialog — the field just shows no\n\t\t\t\t// choices, which is honest about what happened.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-run-node-dialog: could not load options for \"${field.key}\"`, error)\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: false }\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-run-node-dialog__form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-run-node-dialog__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnRunNodeDialog.vue2.js","sources":["../../../src/dialogs/CnRunNodeDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n -->\n\n<template>\n\t<NcDialog\n\t\t:name=\"tr(title)\"\n\t\tsize=\"normal\"\n\t\t:noClose=\"loading\"\n\t\tdata-testid=\"cn-run-node-dialog\"\n\t\t@closing=\"$emit('close')\">\n\t\t<NcNoteCard v-if=\"loadError\" type=\"error\" data-testid=\"cn-run-node-dialog-error\">\n\t\t\t{{ loadError }}\n\t\t</NcNoteCard>\n\n\t\t<div v-else class=\"cn-run-node-dialog__form\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\t:data-cn-field=\"field.key\"\n\t\t\t\tclass=\"cn-run-node-dialog__field\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'boolean'\"\n\t\t\t\t\t:modelValue=\"values[field.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\">\n\t\t\t\t\t{{ tr(field.label) }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t:modelValue=\"selectedOption(field)\"\n\t\t\t\t\t:options=\"optionsFor(field)\"\n\t\t\t\t\t:inputLabel=\"tr(field.label)\"\n\t\t\t\t\t:loading=\"optionsLoading[field.key] === true\"\n\t\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Pick one…')\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event ? $event.id : '')\" />\n\n\t\t\t\t<NcTextArea\n\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\trows=\"4\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else-if=\"field.type === 'number'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setNumberValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\t\t\t</div>\n\n\t\t\t<p v-if=\"!fields.length\" class=\"cn-run-node-dialog__hint\">\n\t\t\t\t{{ t('nextcloud-vue', 'This step has no options.') }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"loading\" @click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"!loadError\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"loading || !requiredFieldsFilled\"\n\t\t\t\t@click=\"$emit('confirm', values)\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"loading\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { prefixUrl } from '../utils/headers.js'\nimport { hasStaticOptions, normaliseSelectOptions } from '../utils/selectOptions.js'\n\n/**\n * The dialog `run-node` opens to collect a directly-invoked flow node's own\n * declared config, before POSTing to OpenRegister's\n * `/api/flows/{flowId}/nodes/{nodeId}/run` (manifest-run-node-action / RN-4).\n *\n * WHY THIS IS A NEW, SMALL RENDERER AND NOT `CnFlowNodeEditModal`'S ONE\n * ----------------------------------------------------------------------\n * design.md says \"render it with the SAME field renderer CnFlowSidebar\n * [reads: CnFlowNodeEditModal] uses\" as the INTENT — no new form-rendering\n * VOCABULARY — and this component honours that: the type-to-widget mapping\n * (switch/select/textarea/number/text) and the `optionsFrom` fetch-and-\n * normalise behaviour below are the SAME rules that modal applies. What it\n * does NOT reuse is that modal's component/methods directly, because that\n * renderer solves a materially different problem: it guesses a widget for\n * ANY engine config key via `widgetFor()` heuristics (including keys no\n * `configForm()` ever declared — cron expressions, HTTP methods, principal\n * pickers, a `runAs` identity field, a raw-JSON fallback), because the flow\n * EDITOR must let an author set every key the engine reads whether or not\n * its type ever described one. A run-node CALLER dialog has no such need —\n * it renders ONLY the fields `configForm()` explicitly declares (this\n * interface's whole contract, per its own docblock: \"a field over a key the\n * node ignores looks like it works and changes nothing\") — text / textarea /\n * number / boolean / select, nothing else. Extracting a shared component\n * from the editor's modal is a reasonable follow-up; it was not done here to\n * avoid an invasive refactor of an unrelated, already-shipped surface for a\n * dialog whose actual field vocabulary is a fifth its size.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-the-nodes-own-config-form-drives-the-dialog-not-a-new-token\n */\nexport default {\n\tname: 'CnRunNodeDialog',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/** Pre-translated dialog title. */\n\t\ttitle: { type: String, default: '' },\n\t\t/**\n\t\t * The node's declared config form — `IFlowNodeConfigForm::configForm()`'s\n\t\t * shape, unchanged: `[{key, label, type, help?, required?, optionsFrom?, options?}]`.\n\t\t * A `select` takes its choices from `optionsFrom` (a url) or `options`\n\t\t * (strings, or `{value, label}` pairs declared in the form itself).\n\t\t *\n\t\t * @type {Array<object>}\n\t\t */\n\t\tfields: { type: Array, default: () => [] },\n\t\t/** Whether a run is in flight — disables Cancel/Run and shows a spinner. */\n\t\tloading: { type: Boolean, default: false },\n\t\t/** Set when the node's form could not be resolved; replaces the form with an error and hides Run. */\n\t\tloadError: { type: String, default: '' },\n\t\t/** The consumer's bound `t()`, matching CnActionButtons' own `cnTranslate` inject. */\n\t\ttranslate: { type: Function, default: null },\n\t},\n\n\temits: ['close', 'confirm'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Live field values, keyed by field.key. */\n\t\t\tvalues: {},\n\t\t\t/** Fetched `{id, label}` options per select field.key. */\n\t\t\toptions: {},\n\t\t\t/** In-flight flag per select field.key. */\n\t\t\toptionsLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Every `required: true` field carries a non-empty value. */\n\t\trequiredFieldsFilled() {\n\t\t\treturn this.fields.every((field) => {\n\t\t\t\tif (field.required !== true) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tconst value = this.values[field.key]\n\t\t\t\treturn value !== undefined && value !== null && value !== ''\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tfields: {\n\t\t\timmediate: true,\n\t\t\thandler(fields) {\n\t\t\t\tconst seed = {}\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tseed[field.key] = field.type === 'boolean' ? false : ''\n\t\t\t\t}\n\t\t\t\tthis.values = seed\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tif (hasStaticOptions(field)) {\n\t\t\t\t\t\tthis.options = { ...this.options, [field.key]: normaliseSelectOptions(field.options, (s) => this.tr(s)) }\n\t\t\t\t\t} else if (field.type === 'select' && field.optionsFrom) {\n\t\t\t\t\t\tthis.loadOptions(field)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve a manifest/node-authored UI string through the host translate\n\t\t * function, matching CnActionButtons' own `tr()`.\n\t\t *\n\t\t * @param {string} [value] The English source string.\n\t\t * @return {string|undefined} The translated (or source) string.\n\t\t */\n\t\ttr(value) {\n\t\t\tif (!value) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn typeof this.translate === 'function' ? this.translate(value) : value\n\t\t},\n\n\t\t/**\n\t\t * Write one field's value.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {unknown} value The new value.\n\t\t * @return {void}\n\t\t */\n\t\tsetValue(key, value) {\n\t\t\tthis.values = { ...this.values, [key]: value }\n\t\t},\n\n\t\t/**\n\t\t * Write a number field, coercing an empty string to '' (not 0 — an\n\t\t * empty required-number field must still fail `requiredFieldsFilled`)\n\t\t * and anything else to a JS number.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {string} raw The NcTextField string value.\n\t\t * @return {void}\n\t\t */\n\t\tsetNumberValue(key, raw) {\n\t\t\tthis.setValue(key, raw === '' ? '' : Number(raw))\n\t\t},\n\n\t\t/**\n\t\t * The NcSelect-shaped `{id, label}` currently selected for a field, or\n\t\t * null. Falls back to `{id: value, label: String(value)}` when the\n\t\t * stored value is not (yet, or no longer) among the loaded options —\n\t\t * the same graceful-degrade `CnFlowNodeEditModal` applies.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\tif (value === undefined || value === null || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst opts = this.options[field.key] || []\n\t\t\treturn opts.find((o) => o.id === value) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/**\n\t\t * The loaded `{id, label}` options for a select field.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {Array<object>}\n\t\t */\n\t\toptionsFor(field) {\n\t\t\treturn this.options[field.key] || []\n\t\t},\n\n\t\t/**\n\t\t * Fetch and normalise a select field's `optionsFrom` catalogue —\n\t\t * SAME acceptance shape as `CnFlowNodeEditModal`'s own picker (design.md's\n\t\t * point: reuse the FORM CONTRACT, not necessarily the component): a bare\n\t\t * array or `{results: [...]}`; each row read as `{id, label}`,\n\t\t * `{value, label}`, or an OpenRegister object (`@self.uuid`/`uuid`,\n\t\t * `name`/`title`). A row this dialog cannot make sense of is dropped\n\t\t * rather than shown as a blank option.\n\t\t *\n\t\t * @param {object} field The field declaration carrying `optionsFrom`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions(field) {\n\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: true }\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }] = await Promise.all([import('@nextcloud/axios')])\n\t\t\t\tconst raw = String(field.optionsFrom)\n\t\t\t\tconst url = prefixUrl(raw)\n\t\t\t\tconst response = await axios.get(url)\n\t\t\t\tconst rows = Array.isArray(response.data) ? response.data : (response.data?.results || [])\n\t\t\t\tconst opts = normaliseSelectOptions(rows)\n\t\t\t\tthis.options = { ...this.options, [field.key]: opts }\n\t\t\t} catch (error) {\n\t\t\t\t// A picker that fails to load degrades to an empty list rather\n\t\t\t\t// than blocking the whole dialog — the field just shows no\n\t\t\t\t// choices, which is honest about what happened.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-run-node-dialog: could not load options for \"${field.key}\"`, error)\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: false }\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-run-node-dialog__form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-run-node-dialog__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["t"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnRunNodeDialog.vue3.js","sources":["../../../src/dialogs/CnRunNodeDialog.vue?vue&type=template&id=3eb7c55d&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n -->\n\n<template>\n\t<NcDialog\n\t\t:name=\"tr(title)\"\n\t\tsize=\"normal\"\n\t\t:noClose=\"loading\"\n\t\tdata-testid=\"cn-run-node-dialog\"\n\t\t@closing=\"$emit('close')\">\n\t\t<NcNoteCard v-if=\"loadError\" type=\"error\" data-testid=\"cn-run-node-dialog-error\">\n\t\t\t{{ loadError }}\n\t\t</NcNoteCard>\n\n\t\t<div v-else class=\"cn-run-node-dialog__form\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\t:data-cn-field=\"field.key\"\n\t\t\t\tclass=\"cn-run-node-dialog__field\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'boolean'\"\n\t\t\t\t\t:modelValue=\"values[field.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\">\n\t\t\t\t\t{{ tr(field.label) }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t:modelValue=\"selectedOption(field)\"\n\t\t\t\t\t:options=\"optionsFor(field)\"\n\t\t\t\t\t:inputLabel=\"tr(field.label)\"\n\t\t\t\t\t:loading=\"optionsLoading[field.key] === true\"\n\t\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Pick one…')\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event ? $event.id : '')\" />\n\n\t\t\t\t<NcTextArea\n\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\trows=\"4\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else-if=\"field.type === 'number'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setNumberValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\t\t\t</div>\n\n\t\t\t<p v-if=\"!fields.length\" class=\"cn-run-node-dialog__hint\">\n\t\t\t\t{{ t('nextcloud-vue', 'This step has no options.') }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"loading\" @click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"!loadError\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"loading || !requiredFieldsFilled\"\n\t\t\t\t@click=\"$emit('confirm', values)\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"loading\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { prefixUrl } from '../utils/headers.js'\n\n/**\n * The dialog `run-node` opens to collect a directly-invoked flow node's own\n * declared config, before POSTing to OpenRegister's\n * `/api/flows/{flowId}/nodes/{nodeId}/run` (manifest-run-node-action / RN-4).\n *\n * WHY THIS IS A NEW, SMALL RENDERER AND NOT `CnFlowNodeEditModal`'S ONE\n * ----------------------------------------------------------------------\n * design.md says \"render it with the SAME field renderer CnFlowSidebar\n * [reads: CnFlowNodeEditModal] uses\" as the INTENT — no new form-rendering\n * VOCABULARY — and this component honours that: the type-to-widget mapping\n * (switch/select/textarea/number/text) and the `optionsFrom` fetch-and-\n * normalise behaviour below are the SAME rules that modal applies. What it\n * does NOT reuse is that modal's component/methods directly, because that\n * renderer solves a materially different problem: it guesses a widget for\n * ANY engine config key via `widgetFor()` heuristics (including keys no\n * `configForm()` ever declared — cron expressions, HTTP methods, principal\n * pickers, a `runAs` identity field, a raw-JSON fallback), because the flow\n * EDITOR must let an author set every key the engine reads whether or not\n * its type ever described one. A run-node CALLER dialog has no such need —\n * it renders ONLY the fields `configForm()` explicitly declares (this\n * interface's whole contract, per its own docblock: \"a field over a key the\n * node ignores looks like it works and changes nothing\") — text / textarea /\n * number / boolean / select, nothing else. Extracting a shared component\n * from the editor's modal is a reasonable follow-up; it was not done here to\n * avoid an invasive refactor of an unrelated, already-shipped surface for a\n * dialog whose actual field vocabulary is a fifth its size.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-the-nodes-own-config-form-drives-the-dialog-not-a-new-token\n */\nexport default {\n\tname: 'CnRunNodeDialog',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/** Pre-translated dialog title. */\n\t\ttitle: { type: String, default: '' },\n\t\t/**\n\t\t * The node's declared config form — `IFlowNodeConfigForm::configForm()`'s\n\t\t * shape, unchanged: `[{key, label, type, help?, required?, optionsFrom?}]`.\n\t\t *\n\t\t * @type {Array<object>}\n\t\t */\n\t\tfields: { type: Array, default: () => [] },\n\t\t/** Whether a run is in flight — disables Cancel/Run and shows a spinner. */\n\t\tloading: { type: Boolean, default: false },\n\t\t/** Set when the node's form could not be resolved; replaces the form with an error and hides Run. */\n\t\tloadError: { type: String, default: '' },\n\t\t/** The consumer's bound `t()`, matching CnActionButtons' own `cnTranslate` inject. */\n\t\ttranslate: { type: Function, default: null },\n\t},\n\n\temits: ['close', 'confirm'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Live field values, keyed by field.key. */\n\t\t\tvalues: {},\n\t\t\t/** Fetched `{id, label}` options per select field.key. */\n\t\t\toptions: {},\n\t\t\t/** In-flight flag per select field.key. */\n\t\t\toptionsLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Every `required: true` field carries a non-empty value. */\n\t\trequiredFieldsFilled() {\n\t\t\treturn this.fields.every((field) => {\n\t\t\t\tif (field.required !== true) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tconst value = this.values[field.key]\n\t\t\t\treturn value !== undefined && value !== null && value !== ''\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tfields: {\n\t\t\timmediate: true,\n\t\t\thandler(fields) {\n\t\t\t\tconst seed = {}\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tseed[field.key] = field.type === 'boolean' ? false : ''\n\t\t\t\t}\n\t\t\t\tthis.values = seed\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tif (field.type === 'select' && field.optionsFrom) {\n\t\t\t\t\t\tthis.loadOptions(field)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve a manifest/node-authored UI string through the host translate\n\t\t * function, matching CnActionButtons' own `tr()`.\n\t\t *\n\t\t * @param {string} [value] The English source string.\n\t\t * @return {string|undefined} The translated (or source) string.\n\t\t */\n\t\ttr(value) {\n\t\t\tif (!value) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn typeof this.translate === 'function' ? this.translate(value) : value\n\t\t},\n\n\t\t/**\n\t\t * Write one field's value.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {unknown} value The new value.\n\t\t * @return {void}\n\t\t */\n\t\tsetValue(key, value) {\n\t\t\tthis.values = { ...this.values, [key]: value }\n\t\t},\n\n\t\t/**\n\t\t * Write a number field, coercing an empty string to '' (not 0 — an\n\t\t * empty required-number field must still fail `requiredFieldsFilled`)\n\t\t * and anything else to a JS number.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {string} raw The NcTextField string value.\n\t\t * @return {void}\n\t\t */\n\t\tsetNumberValue(key, raw) {\n\t\t\tthis.setValue(key, raw === '' ? '' : Number(raw))\n\t\t},\n\n\t\t/**\n\t\t * The NcSelect-shaped `{id, label}` currently selected for a field, or\n\t\t * null. Falls back to `{id: value, label: String(value)}` when the\n\t\t * stored value is not (yet, or no longer) among the loaded options —\n\t\t * the same graceful-degrade `CnFlowNodeEditModal` applies.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\tif (value === undefined || value === null || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst opts = this.options[field.key] || []\n\t\t\treturn opts.find((o) => o.id === value) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/**\n\t\t * The loaded `{id, label}` options for a select field.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {Array<object>}\n\t\t */\n\t\toptionsFor(field) {\n\t\t\treturn this.options[field.key] || []\n\t\t},\n\n\t\t/**\n\t\t * Fetch and normalise a select field's `optionsFrom` catalogue —\n\t\t * SAME acceptance shape as `CnFlowNodeEditModal`'s own picker (design.md's\n\t\t * point: reuse the FORM CONTRACT, not necessarily the component): a bare\n\t\t * array or `{results: [...]}`; each row read as `{id, label}`,\n\t\t * `{value, label}`, or an OpenRegister object (`@self.uuid`/`uuid`,\n\t\t * `name`/`title`). A row this dialog cannot make sense of is dropped\n\t\t * rather than shown as a blank option.\n\t\t *\n\t\t * @param {object} field The field declaration carrying `optionsFrom`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions(field) {\n\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: true }\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }] = await Promise.all([import('@nextcloud/axios')])\n\t\t\t\tconst raw = String(field.optionsFrom)\n\t\t\t\tconst url = prefixUrl(raw)\n\t\t\t\tconst response = await axios.get(url)\n\t\t\t\tconst rows = Array.isArray(response.data) ? response.data : (response.data?.results || [])\n\t\t\t\tconst opts = rows.map((row) => {\n\t\t\t\t\tconst id = row.id ?? row.value ?? row['@self']?.uuid ?? row.uuid\n\t\t\t\t\treturn { id, label: row.label || row.name || row.title || String(id) }\n\t\t\t\t}).filter((o) => o.id !== undefined && o.id !== null && o.id !== '')\n\t\t\t\tthis.options = { ...this.options, [field.key]: opts }\n\t\t\t} catch (error) {\n\t\t\t\t// A picker that fails to load degrades to an empty list rather\n\t\t\t\t// than blocking the whole dialog — the field just shows no\n\t\t\t\t// choices, which is honest about what happened.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-run-node-dialog: could not load options for \"${field.key}\"`, error)\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: false }\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-run-node-dialog__form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-run-node-dialog__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_createVNode","_createBlock","_openBlock","_createElementBlock","_Fragment","_renderList","_toDisplayString"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnRunNodeDialog.vue3.js","sources":["../../../src/dialogs/CnRunNodeDialog.vue?vue&type=template&id=3eb7c55d&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n -->\n\n<template>\n\t<NcDialog\n\t\t:name=\"tr(title)\"\n\t\tsize=\"normal\"\n\t\t:noClose=\"loading\"\n\t\tdata-testid=\"cn-run-node-dialog\"\n\t\t@closing=\"$emit('close')\">\n\t\t<NcNoteCard v-if=\"loadError\" type=\"error\" data-testid=\"cn-run-node-dialog-error\">\n\t\t\t{{ loadError }}\n\t\t</NcNoteCard>\n\n\t\t<div v-else class=\"cn-run-node-dialog__form\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\t:data-cn-field=\"field.key\"\n\t\t\t\tclass=\"cn-run-node-dialog__field\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'boolean'\"\n\t\t\t\t\t:modelValue=\"values[field.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\">\n\t\t\t\t\t{{ tr(field.label) }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t:modelValue=\"selectedOption(field)\"\n\t\t\t\t\t:options=\"optionsFor(field)\"\n\t\t\t\t\t:inputLabel=\"tr(field.label)\"\n\t\t\t\t\t:loading=\"optionsLoading[field.key] === true\"\n\t\t\t\t\t:placeholder=\"t('nextcloud-vue', 'Pick one…')\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event ? $event.id : '')\" />\n\n\t\t\t\t<NcTextArea\n\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\trows=\"4\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else-if=\"field.type === 'number'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\ttype=\"number\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setNumberValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField\n\t\t\t\t\tv-else\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"tr(field.label)\"\n\t\t\t\t\t:helperText=\"tr(field.help)\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\t\t\t</div>\n\n\t\t\t<p v-if=\"!fields.length\" class=\"cn-run-node-dialog__hint\">\n\t\t\t\t{{ t('nextcloud-vue', 'This step has no options.') }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"loading\" @click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"!loadError\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"loading || !requiredFieldsFilled\"\n\t\t\t\t@click=\"$emit('confirm', values)\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<NcLoadingIcon v-if=\"loading\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ t('nextcloud-vue', 'Run') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport { prefixUrl } from '../utils/headers.js'\nimport { hasStaticOptions, normaliseSelectOptions } from '../utils/selectOptions.js'\n\n/**\n * The dialog `run-node` opens to collect a directly-invoked flow node's own\n * declared config, before POSTing to OpenRegister's\n * `/api/flows/{flowId}/nodes/{nodeId}/run` (manifest-run-node-action / RN-4).\n *\n * WHY THIS IS A NEW, SMALL RENDERER AND NOT `CnFlowNodeEditModal`'S ONE\n * ----------------------------------------------------------------------\n * design.md says \"render it with the SAME field renderer CnFlowSidebar\n * [reads: CnFlowNodeEditModal] uses\" as the INTENT — no new form-rendering\n * VOCABULARY — and this component honours that: the type-to-widget mapping\n * (switch/select/textarea/number/text) and the `optionsFrom` fetch-and-\n * normalise behaviour below are the SAME rules that modal applies. What it\n * does NOT reuse is that modal's component/methods directly, because that\n * renderer solves a materially different problem: it guesses a widget for\n * ANY engine config key via `widgetFor()` heuristics (including keys no\n * `configForm()` ever declared — cron expressions, HTTP methods, principal\n * pickers, a `runAs` identity field, a raw-JSON fallback), because the flow\n * EDITOR must let an author set every key the engine reads whether or not\n * its type ever described one. A run-node CALLER dialog has no such need —\n * it renders ONLY the fields `configForm()` explicitly declares (this\n * interface's whole contract, per its own docblock: \"a field over a key the\n * node ignores looks like it works and changes nothing\") — text / textarea /\n * number / boolean / select, nothing else. Extracting a shared component\n * from the editor's modal is a reasonable follow-up; it was not done here to\n * avoid an invasive refactor of an unrelated, already-shipped surface for a\n * dialog whose actual field vocabulary is a fifth its size.\n *\n * @spec openspec/changes/manifest-run-node-action/specs/manifest-run-node-action/spec.md#requirement-the-nodes-own-config-form-drives-the-dialog-not-a-new-token\n */\nexport default {\n\tname: 'CnRunNodeDialog',\n\n\tcomponents: { NcButton, NcCheckboxRadioSwitch, NcDialog, NcLoadingIcon, NcNoteCard, NcSelect, NcTextArea, NcTextField },\n\n\tprops: {\n\t\t/** Pre-translated dialog title. */\n\t\ttitle: { type: String, default: '' },\n\t\t/**\n\t\t * The node's declared config form — `IFlowNodeConfigForm::configForm()`'s\n\t\t * shape, unchanged: `[{key, label, type, help?, required?, optionsFrom?, options?}]`.\n\t\t * A `select` takes its choices from `optionsFrom` (a url) or `options`\n\t\t * (strings, or `{value, label}` pairs declared in the form itself).\n\t\t *\n\t\t * @type {Array<object>}\n\t\t */\n\t\tfields: { type: Array, default: () => [] },\n\t\t/** Whether a run is in flight — disables Cancel/Run and shows a spinner. */\n\t\tloading: { type: Boolean, default: false },\n\t\t/** Set when the node's form could not be resolved; replaces the form with an error and hides Run. */\n\t\tloadError: { type: String, default: '' },\n\t\t/** The consumer's bound `t()`, matching CnActionButtons' own `cnTranslate` inject. */\n\t\ttranslate: { type: Function, default: null },\n\t},\n\n\temits: ['close', 'confirm'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** Live field values, keyed by field.key. */\n\t\t\tvalues: {},\n\t\t\t/** Fetched `{id, label}` options per select field.key. */\n\t\t\toptions: {},\n\t\t\t/** In-flight flag per select field.key. */\n\t\t\toptionsLoading: {},\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** Every `required: true` field carries a non-empty value. */\n\t\trequiredFieldsFilled() {\n\t\t\treturn this.fields.every((field) => {\n\t\t\t\tif (field.required !== true) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tconst value = this.values[field.key]\n\t\t\t\treturn value !== undefined && value !== null && value !== ''\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tfields: {\n\t\t\timmediate: true,\n\t\t\thandler(fields) {\n\t\t\t\tconst seed = {}\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tseed[field.key] = field.type === 'boolean' ? false : ''\n\t\t\t\t}\n\t\t\t\tthis.values = seed\n\t\t\t\tfor (const field of (fields || [])) {\n\t\t\t\t\tif (hasStaticOptions(field)) {\n\t\t\t\t\t\tthis.options = { ...this.options, [field.key]: normaliseSelectOptions(field.options, (s) => this.tr(s)) }\n\t\t\t\t\t} else if (field.type === 'select' && field.optionsFrom) {\n\t\t\t\t\t\tthis.loadOptions(field)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Resolve a manifest/node-authored UI string through the host translate\n\t\t * function, matching CnActionButtons' own `tr()`.\n\t\t *\n\t\t * @param {string} [value] The English source string.\n\t\t * @return {string|undefined} The translated (or source) string.\n\t\t */\n\t\ttr(value) {\n\t\t\tif (!value) {\n\t\t\t\treturn value\n\t\t\t}\n\t\t\treturn typeof this.translate === 'function' ? this.translate(value) : value\n\t\t},\n\n\t\t/**\n\t\t * Write one field's value.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {unknown} value The new value.\n\t\t * @return {void}\n\t\t */\n\t\tsetValue(key, value) {\n\t\t\tthis.values = { ...this.values, [key]: value }\n\t\t},\n\n\t\t/**\n\t\t * Write a number field, coercing an empty string to '' (not 0 — an\n\t\t * empty required-number field must still fail `requiredFieldsFilled`)\n\t\t * and anything else to a JS number.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @param {string} raw The NcTextField string value.\n\t\t * @return {void}\n\t\t */\n\t\tsetNumberValue(key, raw) {\n\t\t\tthis.setValue(key, raw === '' ? '' : Number(raw))\n\t\t},\n\n\t\t/**\n\t\t * The NcSelect-shaped `{id, label}` currently selected for a field, or\n\t\t * null. Falls back to `{id: value, label: String(value)}` when the\n\t\t * stored value is not (yet, or no longer) among the loaded options —\n\t\t * the same graceful-degrade `CnFlowNodeEditModal` applies.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedOption(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\tif (value === undefined || value === null || value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst opts = this.options[field.key] || []\n\t\t\treturn opts.find((o) => o.id === value) || { id: value, label: String(value) }\n\t\t},\n\n\t\t/**\n\t\t * The loaded `{id, label}` options for a select field.\n\t\t *\n\t\t * @param {object} field The field declaration.\n\t\t * @return {Array<object>}\n\t\t */\n\t\toptionsFor(field) {\n\t\t\treturn this.options[field.key] || []\n\t\t},\n\n\t\t/**\n\t\t * Fetch and normalise a select field's `optionsFrom` catalogue —\n\t\t * SAME acceptance shape as `CnFlowNodeEditModal`'s own picker (design.md's\n\t\t * point: reuse the FORM CONTRACT, not necessarily the component): a bare\n\t\t * array or `{results: [...]}`; each row read as `{id, label}`,\n\t\t * `{value, label}`, or an OpenRegister object (`@self.uuid`/`uuid`,\n\t\t * `name`/`title`). A row this dialog cannot make sense of is dropped\n\t\t * rather than shown as a blank option.\n\t\t *\n\t\t * @param {object} field The field declaration carrying `optionsFrom`.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadOptions(field) {\n\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: true }\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }] = await Promise.all([import('@nextcloud/axios')])\n\t\t\t\tconst raw = String(field.optionsFrom)\n\t\t\t\tconst url = prefixUrl(raw)\n\t\t\t\tconst response = await axios.get(url)\n\t\t\t\tconst rows = Array.isArray(response.data) ? response.data : (response.data?.results || [])\n\t\t\t\tconst opts = normaliseSelectOptions(rows)\n\t\t\t\tthis.options = { ...this.options, [field.key]: opts }\n\t\t\t} catch (error) {\n\t\t\t\t// A picker that fails to load degrades to an empty list rather\n\t\t\t\t// than blocking the whole dialog — the field just shows no\n\t\t\t\t// choices, which is honest about what happened.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error(`cn-run-node-dialog: could not load options for \"${field.key}\"`, error)\n\t\t\t} finally {\n\t\t\t\tthis.optionsLoading = { ...this.optionsLoading, [field.key]: false }\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-run-node-dialog__form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n}\n\n.cn-run-node-dialog__hint {\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_createVNode","_createBlock","_openBlock","_createElementBlock","_Fragment","_renderList","_toDisplayString"],"mappings":"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"}
|
package/dist/esm/index.js
CHANGED
|
@@ -142,6 +142,7 @@ export { default as CnFlowRunsWidget } from './components/CnFlowRunsWidget/CnFlo
|
|
|
142
142
|
export { default as CnFlowRunsWidgetForm } from './components/CnFlowRunsWidgetForm/CnFlowRunsWidgetForm.vue.js';
|
|
143
143
|
export { default as CnFlowSidebar } from './components/CnFlowDetail/CnFlowSidebar.vue.js';
|
|
144
144
|
export { default as CnFlowsPage } from './components/CnFlowsPage/CnFlowsPage.vue.js';
|
|
145
|
+
export { default as CnFlowStepOutcomes } from './components/CnFlowStepOutcomes/CnFlowStepOutcomes.vue.js';
|
|
145
146
|
export { default as CnFolderSidebar } from './components/CnFolderSidebar/CnFolderSidebar.vue.js';
|
|
146
147
|
export { default as CnFolderTree } from './components/CnFolderTree/CnFolderTree.vue.js';
|
|
147
148
|
export { default as CnFormBuilder } from './components/CnFormBuilder/CnFormBuilder.vue.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/l10n/en.json.js
CHANGED
|
@@ -1090,7 +1090,21 @@ var translations = {
|
|
|
1090
1090
|
"Loading…": "Loading…",
|
|
1091
1091
|
"A register and schema are required": "A register and schema are required",
|
|
1092
1092
|
"Change the search or try again.": "Change the search or try again.",
|
|
1093
|
-
"Try again later.": "Try again later."
|
|
1093
|
+
"Try again later.": "Try again later.",
|
|
1094
|
+
"Who this step reached": "Who this step reached",
|
|
1095
|
+
"Each list shows its first entries only.": "Each list shows its first entries only.",
|
|
1096
|
+
Delivered: "Delivered",
|
|
1097
|
+
"Opted out": "Opted out",
|
|
1098
|
+
"Not sent, the opt-out check did not answer": "Not sent, the opt-out check did not answer",
|
|
1099
|
+
"Skipped by their notification settings": "Skipped by their notification settings",
|
|
1100
|
+
"Skipped, sending is switched off": "Skipped, sending is switched off",
|
|
1101
|
+
"Held back by the send limit": "Held back by the send limit",
|
|
1102
|
+
"Refused by the step’s address rule": "Refused by the step’s address rule",
|
|
1103
|
+
"Not a known user or group": "Not a known user or group",
|
|
1104
|
+
Failed: "Failed",
|
|
1105
|
+
"external recipients are off": "external recipients are off",
|
|
1106
|
+
"not on the item": "not on the item",
|
|
1107
|
+
"not a valid address": "not a valid address"
|
|
1094
1108
|
};
|
|
1095
1109
|
var plurals = {
|
|
1096
1110
|
"%n year": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/l10n/nl.json.js
CHANGED
|
@@ -1142,7 +1142,21 @@ var translations = {
|
|
|
1142
1142
|
"Loading…": "Laden…",
|
|
1143
1143
|
"A register and schema are required": "Een register en schema zijn verplicht",
|
|
1144
1144
|
"Change the search or try again.": "Pas de zoekopdracht aan of probeer het opnieuw.",
|
|
1145
|
-
"Try again later.": "Probeer het later opnieuw."
|
|
1145
|
+
"Try again later.": "Probeer het later opnieuw.",
|
|
1146
|
+
"Who this step reached": "Wie deze stap bereikte",
|
|
1147
|
+
"Each list shows its first entries only.": "Elke lijst toont alleen de eerste vermeldingen.",
|
|
1148
|
+
Delivered: "Bezorgd",
|
|
1149
|
+
"Opted out": "Afgemeld",
|
|
1150
|
+
"Not sent, the opt-out check did not answer": "Niet verstuurd, de afmeldcontrole gaf geen antwoord",
|
|
1151
|
+
"Skipped by their notification settings": "Overgeslagen door hun meldingsinstellingen",
|
|
1152
|
+
"Skipped, sending is switched off": "Overgeslagen, verzenden staat uit",
|
|
1153
|
+
"Held back by the send limit": "Tegengehouden door de verzendlimiet",
|
|
1154
|
+
"Refused by the step’s address rule": "Geweigerd door de adresregel van de stap",
|
|
1155
|
+
"Not a known user or group": "Geen bekende gebruiker of groep",
|
|
1156
|
+
Failed: "Mislukt",
|
|
1157
|
+
"external recipients are off": "externe ontvangers staan uit",
|
|
1158
|
+
"not on the item": "staat niet op het item",
|
|
1159
|
+
"not a valid address": "geen geldig adres"
|
|
1146
1160
|
};
|
|
1147
1161
|
var plurals = {
|
|
1148
1162
|
"%n year": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -26582,6 +26582,18 @@ a.cn-flow-runs-widget__row-content:hover .cn-flow-runs-widget__name[data-v-75628
|
|
|
26582
26582
|
font-size: 0.85em;
|
|
26583
26583
|
color: var(--color-text-maxcontrast);
|
|
26584
26584
|
}
|
|
26585
|
+
|
|
26586
|
+
/* Full width, like the text fields around it: at its natural width the
|
|
26587
|
+
picker cut every option label in half. */
|
|
26588
|
+
.cn-flow-node-edit__select[data-v-e107484a] {
|
|
26589
|
+
width: 100%;
|
|
26590
|
+
}
|
|
26591
|
+
.cn-flow-node-edit__field-help[data-v-e107484a] {
|
|
26592
|
+
margin: 4px 0 0;
|
|
26593
|
+
padding-inline-start: 8px;
|
|
26594
|
+
font-size: 0.85em;
|
|
26595
|
+
color: var(--color-text-maxcontrast);
|
|
26596
|
+
}
|
|
26585
26597
|
.cn-flow-node-edit__advanced summary[data-v-e107484a] {
|
|
26586
26598
|
cursor: pointer;
|
|
26587
26599
|
color: var(--color-text-maxcontrast);
|
|
@@ -28036,6 +28048,58 @@ to {
|
|
|
28036
28048
|
}
|
|
28037
28049
|
|
|
28038
28050
|
|
|
28051
|
+
.cn-flow-step-outcomes[data-v-5ac5ad4f] {
|
|
28052
|
+
margin: 4px 0 0;
|
|
28053
|
+
font-size: 0.9em;
|
|
28054
|
+
}
|
|
28055
|
+
.cn-flow-step-outcomes__list[data-v-5ac5ad4f] {
|
|
28056
|
+
margin: 0;
|
|
28057
|
+
padding: 0;
|
|
28058
|
+
}
|
|
28059
|
+
|
|
28060
|
+
/* Stacked, name over value: the run sidebar is narrow, and a side-by-side
|
|
28061
|
+
row wrapped mid-list. The host's dt/dd margins and alignment are reset. */
|
|
28062
|
+
.cn-flow-step-outcomes__row[data-v-5ac5ad4f] {
|
|
28063
|
+
display: block;
|
|
28064
|
+
margin-block: 4px;
|
|
28065
|
+
padding-block: 2px;
|
|
28066
|
+
padding-inline-start: 8px;
|
|
28067
|
+
border-inline-start: 3px solid var(--color-border);
|
|
28068
|
+
text-align: start;
|
|
28069
|
+
}
|
|
28070
|
+
.cn-flow-step-outcomes__row--success[data-v-5ac5ad4f] {
|
|
28071
|
+
border-inline-start-color: var(--color-success);
|
|
28072
|
+
}
|
|
28073
|
+
.cn-flow-step-outcomes__row--warning[data-v-5ac5ad4f] {
|
|
28074
|
+
border-inline-start-color: var(--color-warning);
|
|
28075
|
+
}
|
|
28076
|
+
.cn-flow-step-outcomes__row--error[data-v-5ac5ad4f] {
|
|
28077
|
+
border-inline-start-color: var(--color-error);
|
|
28078
|
+
}
|
|
28079
|
+
.cn-flow-step-outcomes__name[data-v-5ac5ad4f] {
|
|
28080
|
+
display: block;
|
|
28081
|
+
white-space: normal;
|
|
28082
|
+
overflow-wrap: anywhere;
|
|
28083
|
+
margin: 0;
|
|
28084
|
+
padding: 0;
|
|
28085
|
+
font-weight: bold;
|
|
28086
|
+
text-align: start;
|
|
28087
|
+
}
|
|
28088
|
+
.cn-flow-step-outcomes__value[data-v-5ac5ad4f] {
|
|
28089
|
+
display: block;
|
|
28090
|
+
white-space: normal;
|
|
28091
|
+
margin: 0;
|
|
28092
|
+
padding: 0;
|
|
28093
|
+
text-align: start;
|
|
28094
|
+
color: var(--color-main-text);
|
|
28095
|
+
overflow-wrap: anywhere;
|
|
28096
|
+
}
|
|
28097
|
+
.cn-flow-step-outcomes__truncated[data-v-5ac5ad4f] {
|
|
28098
|
+
margin: 4px 0 0;
|
|
28099
|
+
color: var(--color-text-maxcontrast);
|
|
28100
|
+
}
|
|
28101
|
+
|
|
28102
|
+
|
|
28039
28103
|
.cn-run-sidebar[data-v-48e781f0] {
|
|
28040
28104
|
display: flex;
|
|
28041
28105
|
flex-direction: column;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>
|
|
3
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
4
|
+
*
|
|
5
|
+
* The choices a node's `select` field offers, in the `{id, label}` shape
|
|
6
|
+
* NcSelect takes.
|
|
7
|
+
*
|
|
8
|
+
* A field gets its choices one of two ways. `optionsFrom` names a url the
|
|
9
|
+
* owning app answers. `options` lists them in the form itself, for a short
|
|
10
|
+
* fixed vocabulary that has no endpoint of its own. Both dialogs that render a
|
|
11
|
+
* node's configForm read the same shapes through this module, so the two
|
|
12
|
+
* cannot come to accept different ones.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Normalise rows into `{id, label}` options.
|
|
17
|
+
*
|
|
18
|
+
* Accepts plain strings and numbers, `{id, label}`, `{value, label}`, and
|
|
19
|
+
* OpenRegister objects (uuid from `@self`, label from name or title). A row
|
|
20
|
+
* without an id is dropped rather than shown as a blank option.
|
|
21
|
+
*
|
|
22
|
+
* @param {Array<unknown>} rows The raw rows.
|
|
23
|
+
* @param {(label: string) => string} [translate] Applied to each declared label.
|
|
24
|
+
* @return {Array<{id: string|number, label: string}>} The options.
|
|
25
|
+
*/
|
|
26
|
+
function normaliseSelectOptions(rows, translate = (s) => s) {
|
|
27
|
+
if (!Array.isArray(rows)) {
|
|
28
|
+
return []
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return rows.map((row) => {
|
|
32
|
+
if (typeof row === 'string' || typeof row === 'number') {
|
|
33
|
+
return { id: row, label: String(row) }
|
|
34
|
+
}
|
|
35
|
+
if (!row || typeof row !== 'object') {
|
|
36
|
+
return { id: undefined, label: '' }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const id = row.id ?? row.value ?? row['@self']?.uuid ?? row.uuid;
|
|
40
|
+
const declared = row.label || row.name || row.title;
|
|
41
|
+
|
|
42
|
+
return { id, label: declared ? String(translate(declared)) : String(id) }
|
|
43
|
+
}).filter((option) => option.id !== undefined && option.id !== null && option.id !== '')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Whether a field declares its choices in the form itself.
|
|
48
|
+
*
|
|
49
|
+
* @param {object} field The field declaration.
|
|
50
|
+
* @return {boolean} True for a `select` with an `options` list.
|
|
51
|
+
*/
|
|
52
|
+
function hasStaticOptions(field) {
|
|
53
|
+
return field?.type === 'select' && Array.isArray(field?.options)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { hasStaticOptions, normaliseSelectOptions };
|
|
57
|
+
//# sourceMappingURL=selectOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectOptions.js","sources":["../../../src/utils/selectOptions.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V. <info@conduction.nl>\n * SPDX-License-Identifier: EUPL-1.2\n *\n * The choices a node's `select` field offers, in the `{id, label}` shape\n * NcSelect takes.\n *\n * A field gets its choices one of two ways. `optionsFrom` names a url the\n * owning app answers. `options` lists them in the form itself, for a short\n * fixed vocabulary that has no endpoint of its own. Both dialogs that render a\n * node's configForm read the same shapes through this module, so the two\n * cannot come to accept different ones.\n */\n\n/**\n * Normalise rows into `{id, label}` options.\n *\n * Accepts plain strings and numbers, `{id, label}`, `{value, label}`, and\n * OpenRegister objects (uuid from `@self`, label from name or title). A row\n * without an id is dropped rather than shown as a blank option.\n *\n * @param {Array<unknown>} rows The raw rows.\n * @param {(label: string) => string} [translate] Applied to each declared label.\n * @return {Array<{id: string|number, label: string}>} The options.\n */\nexport function normaliseSelectOptions(rows, translate = (s) => s) {\n\tif (!Array.isArray(rows)) {\n\t\treturn []\n\t}\n\n\treturn rows.map((row) => {\n\t\tif (typeof row === 'string' || typeof row === 'number') {\n\t\t\treturn { id: row, label: String(row) }\n\t\t}\n\t\tif (!row || typeof row !== 'object') {\n\t\t\treturn { id: undefined, label: '' }\n\t\t}\n\n\t\tconst id = row.id ?? row.value ?? row['@self']?.uuid ?? row.uuid\n\t\tconst declared = row.label || row.name || row.title\n\n\t\treturn { id, label: declared ? String(translate(declared)) : String(id) }\n\t}).filter((option) => option.id !== undefined && option.id !== null && option.id !== '')\n}\n\n/**\n * Whether a field declares its choices in the form itself.\n *\n * @param {object} field The field declaration.\n * @return {boolean} True for a `select` with an `options` list.\n */\nexport function hasStaticOptions(field) {\n\treturn field?.type === 'select' && Array.isArray(field?.options)\n}\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE;AACnE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC3B,EAAE,OAAO,EAAE;AACX,EAAE;AACF;AACA,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK;AAC1B,EAAE,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AAC1D,GAAG,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;AACzC,GAAG;AACH,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;AACvC,GAAG,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;AACtC,GAAG;AACH;AACA,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,GAAG,CAAC,KAAI;AAClE,EAAE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAK;AACrD;AACA,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE;AAC3E,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,MAAM,CAAC,EAAE,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;AACzF,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,KAAK,EAAE;AACxC,CAAC,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC;AACjE;;;;"}
|