@conduction/nextcloud-vue 2.117.0 → 2.118.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/esm/components/CnActionDialog/CnActionDialog.vue2.js +2 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +6 -6
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +2 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +18 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +14 -8
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -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/CnIndexPage/CnIndexPage.vue2.js +9 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue2.js +2 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +71 -0
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +25 -9
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +11 -2
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue.js +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js +161 -5
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js.map +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js +9 -9
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +35 -5
- 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/CnTransitionInputFields/CnTransitionInputFields.vue.js +9 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue.js.map +1 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js +435 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js.map +1 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js +300 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js.map +1 -0
- package/dist/esm/composables/useEndpointSource.js +1 -36
- package/dist/esm/composables/useEndpointSource.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +57 -336
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +18 -155
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +2 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +2 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +308 -229
- package/dist/esm/utils/actionsDispatcher.js +3 -2
- package/dist/esm/utils/actionsDispatcher.js.map +1 -1
- package/dist/esm/utils/interpolateUrlTokens.js +43 -0
- package/dist/esm/utils/interpolateUrlTokens.js.map +1 -0
- package/dist/esm/utils/labelsByField.js +72 -0
- package/dist/esm/utils/labelsByField.js.map +1 -0
- package/dist/esm/utils/listCreateAction.js +91 -0
- package/dist/esm/utils/listCreateAction.js.map +1 -0
- package/dist/esm/utils/transitionInputs.js +493 -0
- package/dist/esm/utils/transitionInputs.js.map +1 -0
- package/dist/esm/utils/visibleWhen.js +9 -2
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +6690 -5404
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +308 -229
- package/l10n/en.json +2 -1
- package/l10n/nl.json +2 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.vue +6 -6
- package/src/components/CnDashboardPage/CnDashboardPage.vue +27 -5
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +11 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +9 -4
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +86 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +11 -2
- package/src/components/CnSearchPage/CnSearchPage.vue +170 -14
- package/src/components/CnTabsWidget/CnTabsWidget.vue +35 -5
- package/src/components/CnTransitionInputFields/CnTransitionInputFields.vue +750 -0
- package/src/components/CnTransitionInputFields/index.js +11 -0
- package/src/components/index.js +1 -0
- package/src/composables/useEndpointSource.js +3 -36
- package/src/dialogs/CnTransitionInputDialog.vue +73 -465
- package/src/index.js +2 -0
- package/src/utils/interpolateUrlTokens.js +40 -0
- package/src/utils/labelsByField.js +69 -0
- package/src/utils/listCreateAction.js +87 -0
- package/src/utils/transitionInputs.js +489 -0
- package/src/utils/visibleWhen.js +9 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { translate } from '@nextcloud/l10n';
|
|
2
|
-
import { NcButton, NcLoadingIcon
|
|
3
|
-
import __sfc_main
|
|
4
|
-
import __sfc_main from '../components/
|
|
2
|
+
import { NcButton, NcLoadingIcon } from '@nextcloud/vue';
|
|
3
|
+
import __sfc_main from '../components/CnDialog/CnDialog.vue.js';
|
|
4
|
+
import __sfc_main$1 from '../components/CnTransitionInputFields/CnTransitionInputFields.vue.js';
|
|
5
5
|
import { dialogBoardMixin } from '../mixins/dialogBoard.js';
|
|
6
|
-
import {
|
|
6
|
+
import { initialInputValues, resolveInputFields, inputFieldsComplete, submittedValue } from '../utils/transitionInputs.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* CnTransitionInputDialog — collects a lifecycle transition's declared
|
|
@@ -12,25 +12,27 @@ import { fieldsFromSchema } from '../utils/schema.js';
|
|
|
12
12
|
* A schema's `x-openregister-lifecycle.transitions.<action>` block may declare
|
|
13
13
|
* `inputs: [{ field, required }]`; the transition endpoint then accepts
|
|
14
14
|
* `{ action, data: { <field>: <value> } }`. This dialog renders one input per
|
|
15
|
-
* declared field, disables the confirm button until every
|
|
16
|
-
* field is filled, and emits the collected values — the
|
|
17
|
-
* (`CnLifecycleActions`) performs the actual POST. Cancel emits `close`
|
|
15
|
+
* declared field, disables the confirm button until every shown
|
|
16
|
+
* `required: true` field is filled, and emits the collected values — the
|
|
17
|
+
* parent (`CnLifecycleActions`) performs the actual POST. Cancel emits `close`
|
|
18
18
|
* without any confirm, so no request is made.
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
20
|
+
* The inputs are drawn by `CnTransitionInputFields`, which a host can also
|
|
21
|
+
* use on its own to open an act's inputs in place. Field rendering resolves
|
|
22
|
+
* each declared field against the object's JSON Schema via
|
|
23
|
+
* `fieldsFromSchema()` when a `schema` is given: the label comes from the
|
|
24
|
+
* property `title`, booleans render as a switch, numbers as a number field,
|
|
25
|
+
* and long text (`maxLength > 255` or a `textarea`/`markdown` format) as a
|
|
26
|
+
* textarea. Anything else — including a field the schema does not declare —
|
|
27
|
+
* falls back to a plain labelled text input.
|
|
26
28
|
*
|
|
27
29
|
* An input may also say how it is asked for, which matters when the choices
|
|
28
30
|
* depend on the record rather than on its schema: `label` names the field,
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* `options: [{ value, label }]` or `optionsSource` (a path into `context`)
|
|
32
|
+
* turn it into a picker, and `widget` names `text`, `textarea`, `number`,
|
|
33
|
+
* `date` or `template` outright. `other`, `helperFrom`, `preview` and
|
|
34
|
+
* `default` are described in `utils/transitionInputs.js`. The transition may
|
|
35
|
+
* carry `columns`, `summary` and `notice` for the layout around the inputs.
|
|
34
36
|
*
|
|
35
37
|
* Lives in its own file under `src/dialogs/` per the modal-isolation rule.
|
|
36
38
|
*
|
|
@@ -47,14 +49,10 @@ var script = {
|
|
|
47
49
|
name: 'CnTransitionInputDialog',
|
|
48
50
|
|
|
49
51
|
components: {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
CnDialog: __sfc_main,
|
|
53
|
+
CnTransitionInputFields: __sfc_main$1,
|
|
52
54
|
NcButton,
|
|
53
55
|
NcLoadingIcon,
|
|
54
|
-
NcTextField,
|
|
55
|
-
NcTextArea,
|
|
56
|
-
NcCheckboxRadioSwitch,
|
|
57
|
-
NcSelect,
|
|
58
56
|
},
|
|
59
57
|
|
|
60
58
|
mixins: [dialogBoardMixin],
|
|
@@ -64,12 +62,14 @@ var script = {
|
|
|
64
62
|
* The transition being applied. `inputs` is the declared input list from
|
|
65
63
|
* `x-openregister-lifecycle.transitions.<action>.inputs` (server-derived
|
|
66
64
|
* or config-declared); `label` doubles as dialog title + confirm label.
|
|
65
|
+
* `columns`, `summary` and `notice` lay out the inputs (see
|
|
66
|
+
* `CnTransitionInputFields`).
|
|
67
67
|
*
|
|
68
68
|
* An input may carry a `label` for its field and `options` to pick
|
|
69
69
|
* from, each `{ value, label }`; the picker shows the label and sends
|
|
70
70
|
* the value.
|
|
71
71
|
*
|
|
72
|
-
* @type {{action?: string, label?: string, inputs?: Array<{field: string, required?: boolean, label?: string, options?: Array<{value: string, label?: string}
|
|
72
|
+
* @type {{action?: string, label?: string, columns?: number, summary?: object, notice?: object, inputs?: Array<{field: string, required?: boolean, label?: string, widget?: string, options?: Array<{value: string, label?: string}>, optionsSource?: string}>}}
|
|
73
73
|
*/
|
|
74
74
|
transition: {
|
|
75
75
|
type: Object,
|
|
@@ -110,6 +110,16 @@ var script = {
|
|
|
110
110
|
default: '',
|
|
111
111
|
},
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* What an input's `optionsSource` and the summary paths read.
|
|
115
|
+
*
|
|
116
|
+
* @type {object}
|
|
117
|
+
*/
|
|
118
|
+
context: {
|
|
119
|
+
type: Object,
|
|
120
|
+
default: () => ({}),
|
|
121
|
+
},
|
|
122
|
+
|
|
113
123
|
/**
|
|
114
124
|
* The sentence a refused transition answered with. Present means the
|
|
115
125
|
* dialog stayed open BECAUSE the attempt was refused, with everything
|
|
@@ -151,66 +161,18 @@ var script = {
|
|
|
151
161
|
data() {
|
|
152
162
|
return {
|
|
153
163
|
/** @type {{[key: string]: unknown}} Collected input values, keyed by declared field name. */
|
|
154
|
-
values: this.
|
|
164
|
+
values: initialInputValues(this.transition?.inputs, this.schema, this.currentObject),
|
|
155
165
|
}
|
|
156
166
|
},
|
|
157
167
|
|
|
158
168
|
computed: {
|
|
159
|
-
/**
|
|
160
|
-
inputs() {
|
|
161
|
-
const declared = Array.isArray(this.transition.inputs) ? this.transition.inputs : [];
|
|
162
|
-
return declared
|
|
163
|
-
.filter((input) => input && typeof input.field === 'string' && input.field !== '')
|
|
164
|
-
.map((input) => ({
|
|
165
|
-
field: input.field,
|
|
166
|
-
required: input.required === true,
|
|
167
|
-
picker: input.picker && typeof input.picker === 'object' ? input.picker : null,
|
|
168
|
-
fields: Array.isArray(input.fields) ? input.fields.filter((f) => typeof f === 'string') : null,
|
|
169
|
-
label: typeof input.label === 'string' && input.label.trim() !== '' ? input.label.trim() : null,
|
|
170
|
-
options: this.declaredOptions(input.options),
|
|
171
|
-
}))
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* One renderable field descriptor per declared input. Schema-declared
|
|
176
|
-
* fields come from `fieldsFromSchema()` (label from the property title,
|
|
177
|
-
* widget from the type/format); the widget is then clamped to the minimal
|
|
178
|
-
* set this dialog renders (text / textarea / number / checkbox). Fields
|
|
179
|
-
* the schema does not declare fall back to a plain text input.
|
|
180
|
-
*
|
|
181
|
-
* An input that declares `options` is a picker whatever the schema
|
|
182
|
-
* says, because its choices are the ones this transition offers on
|
|
183
|
-
* this record. A declared `label` names the field over the schema's.
|
|
184
|
-
*/
|
|
169
|
+
/** One field descriptor per declared input (see `resolveInputFields`). */
|
|
185
170
|
fields() {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
return {
|
|
192
|
-
key: input.field,
|
|
193
|
-
label: input.label || (field && field.label) || input.field,
|
|
194
|
-
description: (field && field.description) || '',
|
|
195
|
-
widget: 'select',
|
|
196
|
-
options: input.options,
|
|
197
|
-
required: input.required,
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const prop = (this.schema && this.schema.properties && this.schema.properties[input.field]) || null;
|
|
201
|
-
if (prop && prop.type === 'object' && prop.properties && typeof prop.properties === 'object') {
|
|
202
|
-
return this.objectField(input, prop)
|
|
203
|
-
}
|
|
204
|
-
if (!field) {
|
|
205
|
-
return { key: input.field, label: input.label || input.field, description: '', widget: 'text', required: input.required }
|
|
206
|
-
}
|
|
207
|
-
if (field.reference && field.reference.multiple !== true) {
|
|
208
|
-
const register = field.reference.register || this.register;
|
|
209
|
-
if (register !== '') {
|
|
210
|
-
return { ...field, label: input.label || field.label, widget: 'reference', referenceRegister: register, picker: input.picker, required: input.required }
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
return { ...field, label: input.label || field.label, widget: this.clampWidget(field.widget), required: input.required }
|
|
171
|
+
return resolveInputFields(this.transition.inputs, {
|
|
172
|
+
schema: this.schema,
|
|
173
|
+
register: this.register,
|
|
174
|
+
context: this.context,
|
|
175
|
+
values: this.values,
|
|
214
176
|
})
|
|
215
177
|
},
|
|
216
178
|
|
|
@@ -224,167 +186,27 @@ var script = {
|
|
|
224
186
|
return this.transition.label || translate('nextcloud-vue', 'Confirm')
|
|
225
187
|
},
|
|
226
188
|
|
|
227
|
-
/** True when every `required: true` input holds a
|
|
189
|
+
/** True when every shown `required: true` input holds a value. */
|
|
228
190
|
canConfirm() {
|
|
229
|
-
|
|
230
|
-
return false
|
|
231
|
-
}
|
|
232
|
-
return this.fields.every((field) => (field.widget === 'object'
|
|
233
|
-
? field.subFields.every((sub) => !sub.required || this.isSubFilled(field.key, sub))
|
|
234
|
-
: (!field.required || this.isFilled(field))))
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
/** The refused keys this dialog offers no field for. */
|
|
238
|
-
unofferedRefusals() {
|
|
239
|
-
const offered = this.fields.map((field) => field.key);
|
|
240
|
-
return this.refusedKeys.filter((key) => !offered.includes(key))
|
|
241
|
-
},
|
|
242
|
-
|
|
243
|
-
/** The refusal's field keys, normalised to strings. */
|
|
244
|
-
refusedKeys() {
|
|
245
|
-
if (!Array.isArray(this.fieldErrors)) {
|
|
246
|
-
return []
|
|
247
|
-
}
|
|
248
|
-
return this.fieldErrors.filter((key) => typeof key === 'string' && key !== '')
|
|
191
|
+
return this.busy !== true && inputFieldsComplete(this.fields, this.values)
|
|
249
192
|
},
|
|
250
193
|
},
|
|
251
194
|
|
|
252
195
|
methods: {
|
|
253
|
-
// Exposed to the template for the static button labels — the same
|
|
254
|
-
// `methods: { t }` pattern the other dialogs in this folder use.
|
|
255
196
|
t: translate,
|
|
256
197
|
|
|
257
198
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* @param {string} key The field key.
|
|
261
|
-
* @return {boolean}
|
|
262
|
-
*/
|
|
263
|
-
isRefused(key) {
|
|
264
|
-
return this.refusedKeys.includes(key)
|
|
265
|
-
},
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* What to say beside a refused field.
|
|
269
|
-
*
|
|
270
|
-
* The KIND is decided here rather than read out of the refusal's
|
|
271
|
-
* sentence. A field this dialog offers and the person left empty is a
|
|
272
|
-
* missing required input; one it offers that carries a value was
|
|
273
|
-
* refused for what is in it. Parsing the server's prose to tell those
|
|
274
|
-
* apart would break the first time the sentence is reworded, and a
|
|
275
|
-
* reworded sentence is not a contract change.
|
|
276
|
-
*
|
|
277
|
-
* @param {string} key The field key.
|
|
278
|
-
* @return {string}
|
|
279
|
-
*/
|
|
280
|
-
refusalFor(key) {
|
|
281
|
-
const field = this.fields.find((candidate) => candidate.key === key);
|
|
282
|
-
if (field && !this.isFilled(field)) {
|
|
283
|
-
return translate('nextcloud-vue', 'This field is required.')
|
|
284
|
-
}
|
|
285
|
-
return translate('nextcloud-vue', 'This value was not accepted.')
|
|
286
|
-
},
|
|
287
|
-
|
|
288
|
-
/**
|
|
289
|
-
* What to say about a refused key this dialog does not offer.
|
|
290
|
-
*
|
|
291
|
-
* @param {string} key The field key.
|
|
292
|
-
* @return {string}
|
|
293
|
-
*/
|
|
294
|
-
undeclaredMessage(key) {
|
|
295
|
-
return translate('nextcloud-vue', 'This action does not accept the field "{field}".', { field: key })
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* The descriptor of an object input: its sub-properties (narrowed to the
|
|
300
|
-
* input's `fields` when it names them), each with its own widget.
|
|
301
|
-
* A sub-field is required when the input names it in `fields` and the
|
|
302
|
-
* sub-schema lists it as required, or when the whole input is required
|
|
303
|
-
* and it is the only one asked.
|
|
304
|
-
*
|
|
305
|
-
* @param {object} input The normalised input.
|
|
306
|
-
* @param {object} prop The object property's schema.
|
|
307
|
-
* @return {object} The field descriptor.
|
|
308
|
-
*/
|
|
309
|
-
objectField(input, prop) {
|
|
310
|
-
const subs = fieldsFromSchema(prop, { includeReadOnly: true, ...(input.fields ? { include: input.fields } : {}) });
|
|
311
|
-
const required = Array.isArray(prop.required) ? prop.required : [];
|
|
312
|
-
const only = subs.length === 1;
|
|
313
|
-
return {
|
|
314
|
-
key: input.field,
|
|
315
|
-
label: prop.title || input.field,
|
|
316
|
-
description: prop.description || '',
|
|
317
|
-
widget: 'object',
|
|
318
|
-
required: input.required,
|
|
319
|
-
subFields: subs.map((sub) => ({
|
|
320
|
-
...sub,
|
|
321
|
-
widget: this.clampWidget(sub.widget),
|
|
322
|
-
required: (input.fields ? required.includes(sub.key) : sub.required === true) || (input.required && only),
|
|
323
|
-
})),
|
|
324
|
-
}
|
|
325
|
-
},
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* The choices an input declares, as `[{ value, label }]`, or null when
|
|
329
|
-
* it declares none. An option without a value is dropped, because it
|
|
330
|
-
* cannot be sent; one without a label shows its value.
|
|
331
|
-
*
|
|
332
|
-
* @param {unknown} options The input's declared `options`.
|
|
333
|
-
* @return {Array<{value: string, label: string}>|null}
|
|
334
|
-
*/
|
|
335
|
-
declaredOptions(options) {
|
|
336
|
-
if (!Array.isArray(options)) {
|
|
337
|
-
return null
|
|
338
|
-
}
|
|
339
|
-
const usable = options
|
|
340
|
-
.filter((option) => option && typeof option === 'object'
|
|
341
|
-
&& (typeof option.value === 'string' || typeof option.value === 'number')
|
|
342
|
-
&& String(option.value).trim() !== '')
|
|
343
|
-
.map((option) => ({
|
|
344
|
-
value: String(option.value),
|
|
345
|
-
label: typeof option.label === 'string' && option.label.trim() !== '' ? option.label.trim() : String(option.value),
|
|
346
|
-
}));
|
|
347
|
-
return usable.length > 0 ? usable : null
|
|
348
|
-
},
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* The option a picker field currently holds, or null.
|
|
352
|
-
*
|
|
353
|
-
* @param {object} field The select field descriptor.
|
|
354
|
-
* @return {{value: string, label: string}|null}
|
|
355
|
-
*/
|
|
356
|
-
selectedOption(field) {
|
|
357
|
-
const value = this.values[field.key];
|
|
358
|
-
return field.options.find((option) => option.value === String(value ?? '')) || null
|
|
359
|
-
},
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Ids a reference picker must not offer: the current record, when the
|
|
363
|
-
* input's `picker.excludeSelf` says so.
|
|
364
|
-
*
|
|
365
|
-
* @param {object} field The reference field descriptor.
|
|
366
|
-
* @return {string[]} The ids to leave out.
|
|
367
|
-
*/
|
|
368
|
-
excludedIds(field) {
|
|
369
|
-
if (!field.picker || field.picker.excludeSelf !== true || !this.currentObject) {
|
|
370
|
-
return []
|
|
371
|
-
}
|
|
372
|
-
const self = this.currentObject;
|
|
373
|
-
return [self.id, self.uuid, self['@self'] && self['@self'].id].filter((id) => id !== undefined && id !== null).map(String)
|
|
374
|
-
},
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Label of a sub-field, with the required marker.
|
|
199
|
+
* Store one input's value.
|
|
378
200
|
*
|
|
379
|
-
* @param {
|
|
380
|
-
* @
|
|
201
|
+
* @param {string} key The declared field name.
|
|
202
|
+
* @param {unknown} value The new value.
|
|
381
203
|
*/
|
|
382
|
-
|
|
383
|
-
|
|
204
|
+
setValue(key, value) {
|
|
205
|
+
this.values = { ...this.values, [key]: value };
|
|
384
206
|
},
|
|
385
207
|
|
|
386
208
|
/**
|
|
387
|
-
* A typed sub-value.
|
|
209
|
+
* A typed sub-value of an object input.
|
|
388
210
|
*
|
|
389
211
|
* @param {string} key The input key.
|
|
390
212
|
* @param {string} sub The sub-field key.
|
|
@@ -407,110 +229,6 @@ var script = {
|
|
|
407
229
|
this.setValue(key, { ...group, [sub]: value });
|
|
408
230
|
},
|
|
409
231
|
|
|
410
|
-
/**
|
|
411
|
-
* Whether a required sub-field holds a value.
|
|
412
|
-
*
|
|
413
|
-
* @param {string} key The input key.
|
|
414
|
-
* @param {object} sub The sub-field descriptor.
|
|
415
|
-
* @return {boolean}
|
|
416
|
-
*/
|
|
417
|
-
isSubFilled(key, sub) {
|
|
418
|
-
const value = this.subValue(key, sub.key);
|
|
419
|
-
return sub.widget === 'checkbox' ? value === true : String(value ?? '').trim() !== ''
|
|
420
|
-
},
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Whether a refusal named `<input>.<sub>`.
|
|
424
|
-
*
|
|
425
|
-
* @param {string} key The input key.
|
|
426
|
-
* @param {string} sub The sub-field key.
|
|
427
|
-
* @return {boolean}
|
|
428
|
-
*/
|
|
429
|
-
isSubRefused(key, sub) {
|
|
430
|
-
return this.refusedKeys.includes(`${key}.${sub}`)
|
|
431
|
-
},
|
|
432
|
-
|
|
433
|
-
/** Seed each declared input from its schema default (booleans start false). */
|
|
434
|
-
initialValues() {
|
|
435
|
-
const values = {};
|
|
436
|
-
const declared = Array.isArray(this.transition?.inputs) ? this.transition.inputs : [];
|
|
437
|
-
const properties = (this.schema && this.schema.properties) || {};
|
|
438
|
-
for (const input of declared) {
|
|
439
|
-
if (!input || typeof input.field !== 'string' || input.field === '') {
|
|
440
|
-
continue
|
|
441
|
-
}
|
|
442
|
-
const prop = properties[input.field] || {};
|
|
443
|
-
if (prop.type === 'object' && prop.properties && typeof prop.properties === 'object') {
|
|
444
|
-
// An object input starts from the record's present value, so
|
|
445
|
-
// the sub-fields it asks for show what is there.
|
|
446
|
-
const present = this.currentObject ? this.currentObject[input.field] : null;
|
|
447
|
-
values[input.field] = present && typeof present === 'object' ? { ...present } : {};
|
|
448
|
-
continue
|
|
449
|
-
}
|
|
450
|
-
values[input.field] = prop.default !== undefined
|
|
451
|
-
? prop.default
|
|
452
|
-
: (prop.type === 'boolean' ? false : '');
|
|
453
|
-
}
|
|
454
|
-
return values
|
|
455
|
-
},
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Clamp a `fieldsFromSchema()` widget to the minimal set this dialog
|
|
459
|
-
* renders. Anything richer (select, date, user picker, …) degrades to a
|
|
460
|
-
* plain text input rather than pulling a form engine into the dialog.
|
|
461
|
-
*
|
|
462
|
-
* @param {string} widget The resolved widget name.
|
|
463
|
-
* @return {'text'|'textarea'|'number'|'checkbox'}
|
|
464
|
-
*/
|
|
465
|
-
clampWidget(widget) {
|
|
466
|
-
if (widget === 'checkbox' || widget === 'switch') {
|
|
467
|
-
return 'checkbox'
|
|
468
|
-
}
|
|
469
|
-
if (widget === 'textarea') {
|
|
470
|
-
return 'textarea'
|
|
471
|
-
}
|
|
472
|
-
if (widget === 'number') {
|
|
473
|
-
return 'number'
|
|
474
|
-
}
|
|
475
|
-
return 'text'
|
|
476
|
-
},
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* The field's visible label, with a `*` marker on required inputs so the
|
|
480
|
-
* confirm-gating is visually explained.
|
|
481
|
-
*
|
|
482
|
-
* @param {object} field The field descriptor.
|
|
483
|
-
* @return {string}
|
|
484
|
-
*/
|
|
485
|
-
requiredLabel(field) {
|
|
486
|
-
return field.required ? `${field.label} *` : field.label
|
|
487
|
-
},
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Store one input's value.
|
|
491
|
-
*
|
|
492
|
-
* @param {string} key The declared field name.
|
|
493
|
-
* @param {unknown} value The new value.
|
|
494
|
-
*/
|
|
495
|
-
setValue(key, value) {
|
|
496
|
-
this.values = { ...this.values, [key]: value };
|
|
497
|
-
},
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Whether a required field counts as filled: a checked switch for
|
|
501
|
-
* booleans, a non-blank string otherwise.
|
|
502
|
-
*
|
|
503
|
-
* @param {object} field The field descriptor.
|
|
504
|
-
* @return {boolean}
|
|
505
|
-
*/
|
|
506
|
-
isFilled(field) {
|
|
507
|
-
const value = this.values[field.key];
|
|
508
|
-
if (field.widget === 'checkbox') {
|
|
509
|
-
return value === true
|
|
510
|
-
}
|
|
511
|
-
return String(value ?? '').trim() !== ''
|
|
512
|
-
},
|
|
513
|
-
|
|
514
232
|
/**
|
|
515
233
|
* The object an object input sends: the record's current value with the
|
|
516
234
|
* asked sub-fields merged over it, so a sub-field that was not asked for
|
|
@@ -538,18 +256,21 @@ var script = {
|
|
|
538
256
|
return base
|
|
539
257
|
},
|
|
540
258
|
|
|
541
|
-
/** Confirm: emit
|
|
259
|
+
/** Confirm: emit the asked keys (numbers cast, "Other" as '') and let the parent POST. */
|
|
542
260
|
onConfirm() {
|
|
543
261
|
if (!this.canConfirm) {
|
|
544
262
|
return
|
|
545
263
|
}
|
|
546
264
|
const data = {};
|
|
547
265
|
for (const field of this.fields) {
|
|
266
|
+
if (field.hidden || field.widget === 'template') {
|
|
267
|
+
continue
|
|
268
|
+
}
|
|
548
269
|
if (field.widget === 'object') {
|
|
549
270
|
data[field.key] = this.mergedObject(field);
|
|
550
271
|
continue
|
|
551
272
|
}
|
|
552
|
-
let value = this.values[field.key];
|
|
273
|
+
let value = submittedValue(this.values[field.key]);
|
|
553
274
|
if (field.widget === 'number' && String(value ?? '').trim() !== '') {
|
|
554
275
|
const parsed = Number(value);
|
|
555
276
|
if (!Number.isNaN(parsed)) {
|
|
@@ -560,8 +281,8 @@ var script = {
|
|
|
560
281
|
}
|
|
561
282
|
/**
|
|
562
283
|
* @event confirm Emitted when the user confirms with all required
|
|
563
|
-
* inputs filled. Payload holds
|
|
564
|
-
* parent POSTs `{ action, data }`.
|
|
284
|
+
* inputs filled. Payload holds the declared input keys that were
|
|
285
|
+
* asked; the parent POSTs `{ action, data }`.
|
|
565
286
|
* @type {{[key: string]: unknown}}
|
|
566
287
|
*/
|
|
567
288
|
this.$emit('confirm', data);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnTransitionInputDialog.vue2.js","sources":["../../../src/dialogs/CnTransitionInputDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:look=\"look\"\n\t\t:width=\"width\"\n\t\tdefaultWidth=\"form\"\n\t\t:eyebrow=\"eyebrow\"\n\t\t:subtitle=\"subtitle\"\n\t\t:name=\"dialogTitle\"\n\t\tsize=\"normal\"\n\t\t@closing=\"$emit('close')\">\n\t\t<div\n\t\t\tclass=\"cn-transition-input\"\n\t\t\t:aria-busy=\"busy ? 'true' : null\"\n\t\t\tdata-testid=\"cn-modal\"\n\t\t\tdata-testid-modal=\"cn-transition-input-dialog\">\n\t\t\t<!-- A refusal keeps this dialog open with what was typed still in\n\t\t\t it. Closing first and reporting behind it loses the work and\n\t\t\t asks the person to retype it from memory. -->\n\t\t\t<p v-if=\"error\"\n\t\t\t\tclass=\"cn-transition-input__error\"\n\t\t\t\tdata-testid=\"cn-transition-input-error\">\n\t\t\t\t{{ error }}\n\t\t\t</p>\n\t\t\t<div v-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\tclass=\"cn-transition-input__field\"\n\t\t\t\t:class=\"{ 'cn-transition-input__field--refused': isRefused(field.key) }\"\n\t\t\t\t:data-testid=\"`cn-transition-input-${field.key}`\">\n\t\t\t\t<!-- An input that declares its choices is picked from them. -->\n\t\t\t\t<NcSelect v-if=\"field.widget === 'select'\"\n\t\t\t\t\t:modelValue=\"selectedOption(field)\"\n\t\t\t\t\t:options=\"field.options\"\n\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t:inputLabel=\"requiredLabel(field)\"\n\t\t\t\t\t:clearable=\"!field.required\"\n\t\t\t\t\t:data-testid=\"`cn-transition-input-select-${field.key}`\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event && $event.value !== undefined ? $event.value : '')\" />\n\n\t\t\t\t<!-- An input that points at another record is picked, never typed. -->\n\t\t\t\t<div v-else-if=\"field.widget === 'reference'\" class=\"cn-transition-input__reference\">\n\t\t\t\t\t<label class=\"cn-transition-input__label\">{{ requiredLabel(field) }}</label>\n\t\t\t\t\t<CnResourceSelect\n\t\t\t\t\t\t:register=\"field.referenceRegister\"\n\t\t\t\t\t\t:schema=\"String(field.reference.schema)\"\n\t\t\t\t\t\t:labelField=\"(field.picker && field.picker.labelField) || field.reference.labelField || 'name'\"\n\t\t\t\t\t\t:filter=\"(field.picker && field.picker.filter) || {}\"\n\t\t\t\t\t\t:exclude=\"excludedIds(field)\"\n\t\t\t\t\t\t:allowCreate=\"false\"\n\t\t\t\t\t\t:preload=\"true\"\n\t\t\t\t\t\t:inputLabel=\"requiredLabel(field)\"\n\t\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t\t:data-testid=\"`cn-transition-input-picker-${field.key}`\"\n\t\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\t\t\t\t</div>\n\n\t\t\t\t<!-- An object input: its sub-properties, one field at a time. -->\n\t\t\t\t<fieldset v-else-if=\"field.widget === 'object'\" class=\"cn-transition-input__object\">\n\t\t\t\t\t<legend>{{ requiredLabel(field) }}</legend>\n\t\t\t\t\t<div v-for=\"sub in field.subFields\"\n\t\t\t\t\t\t:key=\"sub.key\"\n\t\t\t\t\t\tclass=\"cn-transition-input__subfield\"\n\t\t\t\t\t\t:data-testid=\"`cn-transition-input-${field.key}-${sub.key}`\">\n\t\t\t\t\t\t<NcTextArea v-if=\"sub.widget === 'textarea'\"\n\t\t\t\t\t\t\t:modelValue=\"String(subValue(field.key, sub.key) ?? '')\"\n\t\t\t\t\t\t\t:label=\"subLabel(sub)\"\n\t\t\t\t\t\t\trows=\"3\"\n\t\t\t\t\t\t\t@update:modelValue=\"setSubValue(field.key, sub.key, $event)\" />\n\t\t\t\t\t\t<NcCheckboxRadioSwitch v-else-if=\"sub.widget === 'checkbox'\"\n\t\t\t\t\t\t\t:modelValue=\"subValue(field.key, sub.key) === true\"\n\t\t\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t\t\t@update:modelValue=\"setSubValue(field.key, sub.key, $event === true)\">\n\t\t\t\t\t\t\t{{ subLabel(sub) }}\n\t\t\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t\t\t<NcTextField v-else\n\t\t\t\t\t\t\t:modelValue=\"String(subValue(field.key, sub.key) ?? '')\"\n\t\t\t\t\t\t\t:type=\"sub.widget === 'number' ? 'number' : 'text'\"\n\t\t\t\t\t\t\t:label=\"subLabel(sub)\"\n\t\t\t\t\t\t\t@update:modelValue=\"setSubValue(field.key, sub.key, $event)\" />\n\t\t\t\t\t\t<p v-if=\"isSubRefused(field.key, sub.key)\"\n\t\t\t\t\t\t\tclass=\"cn-transition-input__field-error\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-transition-input-error-${field.key}.${sub.key}`\">\n\t\t\t\t\t\t\t{{ t('nextcloud-vue', 'This value was not accepted.') }}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t</fieldset>\n\n\t\t\t\t<NcCheckboxRadioSwitch v-else-if=\"field.widget === 'checkbox'\"\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 === true)\">\n\t\t\t\t\t{{ requiredLabel(field) }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t\t<NcTextArea v-else-if=\"field.widget === 'textarea'\"\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"requiredLabel(field)\"\n\t\t\t\t\t:helperText=\"field.description || ''\"\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 v-else-if=\"field.widget === '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=\"requiredLabel(field)\"\n\t\t\t\t\t:helperText=\"field.description || ''\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<NcTextField v-else\n\t\t\t\t\t:modelValue=\"String(values[field.key] ?? '')\"\n\t\t\t\t\t:label=\"requiredLabel(field)\"\n\t\t\t\t\t:helperText=\"field.description || ''\"\n\t\t\t\t\t@update:modelValue=\"setValue(field.key, $event)\" />\n\n\t\t\t\t<p v-if=\"isRefused(field.key)\"\n\t\t\t\t\tclass=\"cn-transition-input__field-error\"\n\t\t\t\t\t:data-testid=\"`cn-transition-input-error-${field.key}`\">\n\t\t\t\t\t{{ refusalFor(field.key) }}\n\t\t\t\t</p>\n\t\t\t</div>\n\n\t\t\t<!-- A key the refusal names that this dialog never offered is not a\n\t\t\t field anybody can correct here. Saying so beats saying nothing:\n\t\t\t the request sent something the transition does not accept. -->\n\t\t\t<p v-for=\"key in unofferedRefusals\"\n\t\t\t\t:key=\"key\"\n\t\t\t\tclass=\"cn-transition-input__field-error\"\n\t\t\t\t:data-testid=\"`cn-transition-input-error-${key}`\">\n\t\t\t\t{{ undeclaredMessage(key) }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton\n\t\t\t\tdata-testid=\"cn-transition-input-cancel\"\n\t\t\t\t@click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<!-- Busy while the parent's POST runs: a transition can take\n\t\t\t seconds, and a confirm button that only greys out reads as one\n\t\t\t that did nothing. -->\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\t:aria-busy=\"busy ? 'true' : null\"\n\t\t\t\tdata-testid=\"cn-transition-input-confirm\"\n\t\t\t\t@click=\"onConfirm\">\n\t\t\t\t<template v-if=\"busy\" #icon>\n\t\t\t\t\t<NcLoadingIcon :size=\"20\" data-testid=\"cn-transition-input-busy\" />\n\t\t\t\t</template>\n\t\t\t\t{{ confirmLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, NcSelect, NcTextArea, NcTextField } from '@nextcloud/vue'\nimport CnDialog from '../components/CnDialog/CnDialog.vue'\nimport CnResourceSelect from '../components/CnResourceSelect/CnResourceSelect.vue'\nimport { dialogBoardMixin } from '../mixins/dialogBoard.js'\nimport { fieldsFromSchema } from '../utils/schema.js'\n\n/**\n * CnTransitionInputDialog — collects a lifecycle transition's declared\n * `inputs` before the transition is applied.\n *\n * A schema's `x-openregister-lifecycle.transitions.<action>` block may declare\n * `inputs: [{ field, required }]`; the transition endpoint then accepts\n * `{ action, data: { <field>: <value> } }`. This dialog renders one input per\n * declared field, disables the confirm button until every `required: true`\n * field is filled, and emits the collected values — the parent\n * (`CnLifecycleActions`) performs the actual POST. Cancel emits `close`\n * without any confirm, so no request is made.\n *\n * Field rendering resolves each declared field against the object's JSON\n * Schema via `fieldsFromSchema()` when a `schema` is given: the label comes\n * from the property `title`, booleans render as a switch, numbers as a number\n * field, and long text (`maxLength > 255` or a `textarea`/`markdown` format)\n * as a textarea. Anything else — including a field the schema does not\n * declare — falls back to a plain labelled text input.\n *\n * An input may also say how it is asked for, which matters when the choices\n * depend on the record rather than on its schema: `label` names the field,\n * and `options: [{ value, label }]` turns it into a picker that shows each\n * `label` and sends the chosen `value`. An input that declares neither is\n * rendered from the schema as before. Deliberately minimal:\n * text, textarea, number and checkbox cover transition inputs; this is not a\n * form engine (use `CnFormDialog` for full object forms).\n *\n * Lives in its own file under `src/dialogs/` per the modal-isolation rule.\n *\n * ```vue\n * <CnTransitionInputDialog\n * v-if=\"inputTransition\"\n * :transition=\"inputTransition\"\n * :schema=\"schema\"\n * @confirm=\"onInputConfirm\"\n * @close=\"inputTransition = null\" />\n * ```\n */\nexport default {\n\tname: 'CnTransitionInputDialog',\n\n\tcomponents: {\n\t\tCnResourceSelect,\n\t\tCnDialog,\n\t\tNcButton,\n\t\tNcLoadingIcon,\n\t\tNcTextField,\n\t\tNcTextArea,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcSelect,\n\t},\n\n\tmixins: [dialogBoardMixin],\n\n\tprops: {\n\t\t/**\n\t\t * The transition being applied. `inputs` is the declared input list from\n\t\t * `x-openregister-lifecycle.transitions.<action>.inputs` (server-derived\n\t\t * or config-declared); `label` doubles as dialog title + confirm label.\n\t\t *\n\t\t * An input may carry a `label` for its field and `options` to pick\n\t\t * from, each `{ value, label }`; the picker shows the label and sends\n\t\t * the value.\n\t\t *\n\t\t * @type {{action?: string, label?: string, inputs?: Array<{field: string, required?: boolean, label?: string, options?: Array<{value: string, label?: string}>}>}}\n\t\t */\n\t\ttransition: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/**\n\t\t * The object's JSON Schema (with `properties`), used to resolve each\n\t\t * input's label, widget and helper text. Optional — undeclared fields\n\t\t * render as plain text inputs labelled by their field name.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The record the transition runs on. Gives `picker.excludeSelf` its id\n\t\t * to leave out, and the current value an object input is merged over.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcurrentObject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Register slug the reference pickers look in when the schema property\n\t\t * names none of its own.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The sentence a refused transition answered with. Present means the\n\t\t * dialog stayed open BECAUSE the attempt was refused, with everything\n\t\t * typed still in it.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\terror: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The input keys the refusal named (`fields` in the 400 body). Each one\n\t\t * that this dialog offers is marked on its own field; each one it does\n\t\t * not is reported as a key the transition does not accept.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\tfieldErrors: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Whether the parent is mid-POST. Keeps the confirm button from firing\n\t\t * a second attempt while the first is in flight.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tbusy: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['confirm', 'close'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {{[key: string]: unknown}} Collected input values, keyed by declared field name. */\n\t\t\tvalues: this.initialValues(),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** The declared inputs, normalised to `{ field, required }`. */\n\t\tinputs() {\n\t\t\tconst declared = Array.isArray(this.transition.inputs) ? this.transition.inputs : []\n\t\t\treturn declared\n\t\t\t\t.filter((input) => input && typeof input.field === 'string' && input.field !== '')\n\t\t\t\t.map((input) => ({\n\t\t\t\t\tfield: input.field,\n\t\t\t\t\trequired: input.required === true,\n\t\t\t\t\tpicker: input.picker && typeof input.picker === 'object' ? input.picker : null,\n\t\t\t\t\tfields: Array.isArray(input.fields) ? input.fields.filter((f) => typeof f === 'string') : null,\n\t\t\t\t\tlabel: typeof input.label === 'string' && input.label.trim() !== '' ? input.label.trim() : null,\n\t\t\t\t\toptions: this.declaredOptions(input.options),\n\t\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * One renderable field descriptor per declared input. Schema-declared\n\t\t * fields come from `fieldsFromSchema()` (label from the property title,\n\t\t * widget from the type/format); the widget is then clamped to the minimal\n\t\t * set this dialog renders (text / textarea / number / checkbox). Fields\n\t\t * the schema does not declare fall back to a plain text input.\n\t\t *\n\t\t * An input that declares `options` is a picker whatever the schema\n\t\t * says, because its choices are the ones this transition offers on\n\t\t * this record. A declared `label` names the field over the schema's.\n\t\t */\n\t\tfields() {\n\t\t\tconst keys = this.inputs.map((input) => input.field)\n\t\t\tconst resolved = fieldsFromSchema(this.schema, { include: keys, includeReadOnly: true })\n\t\t\treturn this.inputs.map((input) => {\n\t\t\t\tconst field = resolved.find((f) => f.key === input.field)\n\t\t\t\tif (input.options) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkey: input.field,\n\t\t\t\t\t\tlabel: input.label || (field && field.label) || input.field,\n\t\t\t\t\t\tdescription: (field && field.description) || '',\n\t\t\t\t\t\twidget: 'select',\n\t\t\t\t\t\toptions: input.options,\n\t\t\t\t\t\trequired: input.required,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst prop = (this.schema && this.schema.properties && this.schema.properties[input.field]) || null\n\t\t\t\tif (prop && prop.type === 'object' && prop.properties && typeof prop.properties === 'object') {\n\t\t\t\t\treturn this.objectField(input, prop)\n\t\t\t\t}\n\t\t\t\tif (!field) {\n\t\t\t\t\treturn { key: input.field, label: input.label || input.field, description: '', widget: 'text', required: input.required }\n\t\t\t\t}\n\t\t\t\tif (field.reference && field.reference.multiple !== true) {\n\t\t\t\t\tconst register = field.reference.register || this.register\n\t\t\t\t\tif (register !== '') {\n\t\t\t\t\t\treturn { ...field, label: input.label || field.label, widget: 'reference', referenceRegister: register, picker: input.picker, required: input.required }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { ...field, label: input.label || field.label, widget: this.clampWidget(field.widget), required: input.required }\n\t\t\t})\n\t\t},\n\n\t\t/** Dialog title — the transition's label, with a generic fallback. */\n\t\tdialogTitle() {\n\t\t\treturn this.transition.label || t('nextcloud-vue', 'Provide details')\n\t\t},\n\n\t\t/** Confirm button label — the transition's label per the contract. */\n\t\tconfirmLabel() {\n\t\t\treturn this.transition.label || t('nextcloud-vue', 'Confirm')\n\t\t},\n\n\t\t/** True when every `required: true` input holds a non-empty value. */\n\t\tcanConfirm() {\n\t\t\tif (this.busy === true) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.fields.every((field) => (field.widget === 'object'\n\t\t\t\t? field.subFields.every((sub) => !sub.required || this.isSubFilled(field.key, sub))\n\t\t\t\t: (!field.required || this.isFilled(field))))\n\t\t},\n\n\t\t/** The refused keys this dialog offers no field for. */\n\t\tunofferedRefusals() {\n\t\t\tconst offered = this.fields.map((field) => field.key)\n\t\t\treturn this.refusedKeys.filter((key) => !offered.includes(key))\n\t\t},\n\n\t\t/** The refusal's field keys, normalised to strings. */\n\t\trefusedKeys() {\n\t\t\tif (!Array.isArray(this.fieldErrors)) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn this.fieldErrors.filter((key) => typeof key === 'string' && key !== '')\n\t\t},\n\t},\n\n\tmethods: {\n\t\t// Exposed to the template for the static button labels — the same\n\t\t// `methods: { t }` pattern the other dialogs in this folder use.\n\t\tt,\n\n\t\t/**\n\t\t * Whether the refusal named this field.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @return {boolean}\n\t\t */\n\t\tisRefused(key) {\n\t\t\treturn this.refusedKeys.includes(key)\n\t\t},\n\n\t\t/**\n\t\t * What to say beside a refused field.\n\t\t *\n\t\t * The KIND is decided here rather than read out of the refusal's\n\t\t * sentence. A field this dialog offers and the person left empty is a\n\t\t * missing required input; one it offers that carries a value was\n\t\t * refused for what is in it. Parsing the server's prose to tell those\n\t\t * apart would break the first time the sentence is reworded, and a\n\t\t * reworded sentence is not a contract change.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @return {string}\n\t\t */\n\t\trefusalFor(key) {\n\t\t\tconst field = this.fields.find((candidate) => candidate.key === key)\n\t\t\tif (field && !this.isFilled(field)) {\n\t\t\t\treturn t('nextcloud-vue', 'This field is required.')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'This value was not accepted.')\n\t\t},\n\n\t\t/**\n\t\t * What to say about a refused key this dialog does not offer.\n\t\t *\n\t\t * @param {string} key The field key.\n\t\t * @return {string}\n\t\t */\n\t\tundeclaredMessage(key) {\n\t\t\treturn t('nextcloud-vue', 'This action does not accept the field \"{field}\".', { field: key })\n\t\t},\n\n\t\t/**\n\t\t * The descriptor of an object input: its sub-properties (narrowed to the\n\t\t * input's `fields` when it names them), each with its own widget.\n\t\t * A sub-field is required when the input names it in `fields` and the\n\t\t * sub-schema lists it as required, or when the whole input is required\n\t\t * and it is the only one asked.\n\t\t *\n\t\t * @param {object} input The normalised input.\n\t\t * @param {object} prop The object property's schema.\n\t\t * @return {object} The field descriptor.\n\t\t */\n\t\tobjectField(input, prop) {\n\t\t\tconst subs = fieldsFromSchema(prop, { includeReadOnly: true, ...(input.fields ? { include: input.fields } : {}) })\n\t\t\tconst required = Array.isArray(prop.required) ? prop.required : []\n\t\t\tconst only = subs.length === 1\n\t\t\treturn {\n\t\t\t\tkey: input.field,\n\t\t\t\tlabel: prop.title || input.field,\n\t\t\t\tdescription: prop.description || '',\n\t\t\t\twidget: 'object',\n\t\t\t\trequired: input.required,\n\t\t\t\tsubFields: subs.map((sub) => ({\n\t\t\t\t\t...sub,\n\t\t\t\t\twidget: this.clampWidget(sub.widget),\n\t\t\t\t\trequired: (input.fields ? required.includes(sub.key) : sub.required === true) || (input.required && only),\n\t\t\t\t})),\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The choices an input declares, as `[{ value, label }]`, or null when\n\t\t * it declares none. An option without a value is dropped, because it\n\t\t * cannot be sent; one without a label shows its value.\n\t\t *\n\t\t * @param {unknown} options The input's declared `options`.\n\t\t * @return {Array<{value: string, label: string}>|null}\n\t\t */\n\t\tdeclaredOptions(options) {\n\t\t\tif (!Array.isArray(options)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst usable = options\n\t\t\t\t.filter((option) => option && typeof option === 'object'\n\t\t\t\t\t&& (typeof option.value === 'string' || typeof option.value === 'number')\n\t\t\t\t\t&& String(option.value).trim() !== '')\n\t\t\t\t.map((option) => ({\n\t\t\t\t\tvalue: String(option.value),\n\t\t\t\t\tlabel: typeof option.label === 'string' && option.label.trim() !== '' ? option.label.trim() : String(option.value),\n\t\t\t\t}))\n\t\t\treturn usable.length > 0 ? usable : null\n\t\t},\n\n\t\t/**\n\t\t * The option a picker field currently holds, or null.\n\t\t *\n\t\t * @param {object} field The select field descriptor.\n\t\t * @return {{value: string, label: string}|null}\n\t\t */\n\t\tselectedOption(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\treturn field.options.find((option) => option.value === String(value ?? '')) || null\n\t\t},\n\n\t\t/**\n\t\t * Ids a reference picker must not offer: the current record, when the\n\t\t * input's `picker.excludeSelf` says so.\n\t\t *\n\t\t * @param {object} field The reference field descriptor.\n\t\t * @return {string[]} The ids to leave out.\n\t\t */\n\t\texcludedIds(field) {\n\t\t\tif (!field.picker || field.picker.excludeSelf !== true || !this.currentObject) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\tconst self = this.currentObject\n\t\t\treturn [self.id, self.uuid, self['@self'] && self['@self'].id].filter((id) => id !== undefined && id !== null).map(String)\n\t\t},\n\n\t\t/**\n\t\t * Label of a sub-field, with the required marker.\n\t\t *\n\t\t * @param {object} sub The sub-field descriptor.\n\t\t * @return {string}\n\t\t */\n\t\tsubLabel(sub) {\n\t\t\treturn sub.required ? `${sub.label} *` : sub.label\n\t\t},\n\n\t\t/**\n\t\t * A typed sub-value.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {string} sub The sub-field key.\n\t\t * @return {unknown}\n\t\t */\n\t\tsubValue(key, sub) {\n\t\t\tconst group = this.values[key]\n\t\t\treturn group && typeof group === 'object' ? group[sub] : undefined\n\t\t},\n\n\t\t/**\n\t\t * Store one sub-value, keeping the rest of the object input's values.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {string} sub The sub-field key.\n\t\t * @param {unknown} value The new value.\n\t\t */\n\t\tsetSubValue(key, sub, value) {\n\t\t\tconst group = this.values[key] && typeof this.values[key] === 'object' ? this.values[key] : {}\n\t\t\tthis.setValue(key, { ...group, [sub]: value })\n\t\t},\n\n\t\t/**\n\t\t * Whether a required sub-field holds a value.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {object} sub The sub-field descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisSubFilled(key, sub) {\n\t\t\tconst value = this.subValue(key, sub.key)\n\t\t\treturn sub.widget === 'checkbox' ? value === true : String(value ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * Whether a refusal named `<input>.<sub>`.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {string} sub The sub-field key.\n\t\t * @return {boolean}\n\t\t */\n\t\tisSubRefused(key, sub) {\n\t\t\treturn this.refusedKeys.includes(`${key}.${sub}`)\n\t\t},\n\n\t\t/** Seed each declared input from its schema default (booleans start false). */\n\t\tinitialValues() {\n\t\t\tconst values = {}\n\t\t\tconst declared = Array.isArray(this.transition?.inputs) ? this.transition.inputs : []\n\t\t\tconst properties = (this.schema && this.schema.properties) || {}\n\t\t\tfor (const input of declared) {\n\t\t\t\tif (!input || typeof input.field !== 'string' || input.field === '') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst prop = properties[input.field] || {}\n\t\t\t\tif (prop.type === 'object' && prop.properties && typeof prop.properties === 'object') {\n\t\t\t\t\t// An object input starts from the record's present value, so\n\t\t\t\t\t// the sub-fields it asks for show what is there.\n\t\t\t\t\tconst present = this.currentObject ? this.currentObject[input.field] : null\n\t\t\t\t\tvalues[input.field] = present && typeof present === 'object' ? { ...present } : {}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvalues[input.field] = prop.default !== undefined\n\t\t\t\t\t? prop.default\n\t\t\t\t\t: (prop.type === 'boolean' ? false : '')\n\t\t\t}\n\t\t\treturn values\n\t\t},\n\n\t\t/**\n\t\t * Clamp a `fieldsFromSchema()` widget to the minimal set this dialog\n\t\t * renders. Anything richer (select, date, user picker, …) degrades to a\n\t\t * plain text input rather than pulling a form engine into the dialog.\n\t\t *\n\t\t * @param {string} widget The resolved widget name.\n\t\t * @return {'text'|'textarea'|'number'|'checkbox'}\n\t\t */\n\t\tclampWidget(widget) {\n\t\t\tif (widget === 'checkbox' || widget === 'switch') {\n\t\t\t\treturn 'checkbox'\n\t\t\t}\n\t\t\tif (widget === 'textarea') {\n\t\t\t\treturn 'textarea'\n\t\t\t}\n\t\t\tif (widget === 'number') {\n\t\t\t\treturn 'number'\n\t\t\t}\n\t\t\treturn 'text'\n\t\t},\n\n\t\t/**\n\t\t * The field's visible label, with a `*` marker on required inputs so the\n\t\t * confirm-gating is visually explained.\n\t\t *\n\t\t * @param {object} field The field descriptor.\n\t\t * @return {string}\n\t\t */\n\t\trequiredLabel(field) {\n\t\t\treturn field.required ? `${field.label} *` : field.label\n\t\t},\n\n\t\t/**\n\t\t * Store one input's value.\n\t\t *\n\t\t * @param {string} key The declared field name.\n\t\t * @param {unknown} value The new value.\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 * Whether a required field counts as filled: a checked switch for\n\t\t * booleans, a non-blank string otherwise.\n\t\t *\n\t\t * @param {object} field The field descriptor.\n\t\t * @return {boolean}\n\t\t */\n\t\tisFilled(field) {\n\t\t\tconst value = this.values[field.key]\n\t\t\tif (field.widget === 'checkbox') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\treturn String(value ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * The object an object input sends: the record's current value with the\n\t\t * asked sub-fields merged over it, so a sub-field that was not asked for\n\t\t * keeps its value. A shown field left empty over an empty current value\n\t\t * is not written. Never a dotted key.\n\t\t *\n\t\t * @param {object} field The object field descriptor.\n\t\t * @return {object}\n\t\t */\n\t\tmergedObject(field) {\n\t\t\tconst present = this.currentObject ? this.currentObject[field.key] : null\n\t\t\tconst base = present && typeof present === 'object' ? { ...present } : {}\n\t\t\tfor (const sub of field.subFields) {\n\t\t\t\tlet value = this.subValue(field.key, sub.key)\n\t\t\t\tconst empty = sub.widget === 'checkbox' ? value === undefined : String(value ?? '').trim() === ''\n\t\t\t\tconst had = base[sub.key]\n\t\t\t\tif (empty && (had === undefined || had === null || had === '')) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (sub.widget === 'number' && !empty && !Number.isNaN(Number(value))) {\n\t\t\t\t\tvalue = Number(value)\n\t\t\t\t}\n\t\t\t\tbase[sub.key] = value\n\t\t\t}\n\t\t\treturn base\n\t\t},\n\n\t\t/** Confirm: emit exactly the declared keys (numbers cast) and let the parent POST. */\n\t\tonConfirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.widget === 'object') {\n\t\t\t\t\tdata[field.key] = this.mergedObject(field)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tlet value = this.values[field.key]\n\t\t\t\tif (field.widget === 'number' && String(value ?? '').trim() !== '') {\n\t\t\t\t\tconst parsed = Number(value)\n\t\t\t\t\tif (!Number.isNaN(parsed)) {\n\t\t\t\t\t\tvalue = parsed\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdata[field.key] = value\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event confirm Emitted when the user confirms with all required\n\t\t\t * inputs filled. Payload holds exactly the declared input keys; the\n\t\t\t * parent POSTs `{ action, data }`.\n\t\t\t * @type {{[key: string]: unknown}}\n\t\t\t */\n\t\t\tthis.$emit('confirm', data)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-transition-input {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tpadding: 4px 0;\n}\n\n.cn-transition-input__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n\n.cn-transition-input__field-error {\n\tmargin: 4px 0 0;\n\tfont-size: 0.9em;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n\n.cn-transition-input__object {\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius);\n\tpadding: 8px 12px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n}\n\n.cn-transition-input__label {\n\tdisplay: block;\n\tmargin-bottom: 4px;\n}\n\n.cn-transition-input__field--refused {\n\tborder-inline-start: 2px solid var(--color-error);\n\tpadding-inline-start: 8px;\n}\n</style>\n"],"names":["CnResourceSelect","CnDialog","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnTransitionInputDialog.vue2.js","sources":["../../../src/dialogs/CnTransitionInputDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:look=\"look\"\n\t\t:width=\"width\"\n\t\tdefaultWidth=\"form\"\n\t\t:eyebrow=\"eyebrow\"\n\t\t:subtitle=\"subtitle\"\n\t\t:name=\"dialogTitle\"\n\t\tsize=\"normal\"\n\t\t@closing=\"$emit('close')\">\n\t\t<div\n\t\t\tclass=\"cn-transition-input\"\n\t\t\t:aria-busy=\"busy ? 'true' : null\"\n\t\t\tdata-testid=\"cn-modal\"\n\t\t\tdata-testid-modal=\"cn-transition-input-dialog\">\n\t\t\t<!-- A refusal keeps this dialog open with what was typed still in\n\t\t\t it. Closing first and reporting behind it loses the work and\n\t\t\t asks the person to retype it from memory. -->\n\t\t\t<p v-if=\"error\"\n\t\t\t\tclass=\"cn-transition-input__error\"\n\t\t\t\tdata-testid=\"cn-transition-input-error\">\n\t\t\t\t{{ error }}\n\t\t\t</p>\n\t\t\t<CnTransitionInputFields\n\t\t\t\t:inputs=\"transition.inputs || []\"\n\t\t\t\t:modelValue=\"values\"\n\t\t\t\t:schema=\"schema\"\n\t\t\t\t:currentObject=\"currentObject\"\n\t\t\t\t:register=\"register\"\n\t\t\t\t:context=\"context\"\n\t\t\t\t:fieldErrors=\"fieldErrors\"\n\t\t\t\t:disabled=\"busy\"\n\t\t\t\t:columns=\"transition.columns === 2 ? 2 : 1\"\n\t\t\t\t:summary=\"transition.summary || null\"\n\t\t\t\t:notice=\"transition.notice || null\"\n\t\t\t\t@update:modelValue=\"values = $event\" />\n\t\t</div>\n\n\t\t<template #actions>\n\t\t\t<NcButton\n\t\t\t\tdata-testid=\"cn-transition-input-cancel\"\n\t\t\t\t@click=\"$emit('close')\">\n\t\t\t\t{{ t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<!-- Busy while the parent's POST runs: a transition can take\n\t\t\t seconds, and a confirm button that only greys out reads as one\n\t\t\t that did nothing. -->\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\t:aria-busy=\"busy ? 'true' : null\"\n\t\t\t\tdata-testid=\"cn-transition-input-confirm\"\n\t\t\t\t@click=\"onConfirm\">\n\t\t\t\t<template v-if=\"busy\" #icon>\n\t\t\t\t\t<NcLoadingIcon :size=\"20\" data-testid=\"cn-transition-input-busy\" />\n\t\t\t\t</template>\n\t\t\t\t{{ confirmLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcLoadingIcon } from '@nextcloud/vue'\nimport CnDialog from '../components/CnDialog/CnDialog.vue'\nimport CnTransitionInputFields from '../components/CnTransitionInputFields/CnTransitionInputFields.vue'\nimport { dialogBoardMixin } from '../mixins/dialogBoard.js'\nimport {\n\tinitialInputValues,\n\tinputFieldsComplete,\n\tresolveInputFields,\n\tsubmittedValue,\n} from '../utils/transitionInputs.js'\n\n/**\n * CnTransitionInputDialog — collects a lifecycle transition's declared\n * `inputs` before the transition is applied.\n *\n * A schema's `x-openregister-lifecycle.transitions.<action>` block may declare\n * `inputs: [{ field, required }]`; the transition endpoint then accepts\n * `{ action, data: { <field>: <value> } }`. This dialog renders one input per\n * declared field, disables the confirm button until every shown\n * `required: true` field is filled, and emits the collected values — the\n * parent (`CnLifecycleActions`) performs the actual POST. Cancel emits `close`\n * without any confirm, so no request is made.\n *\n * The inputs are drawn by `CnTransitionInputFields`, which a host can also\n * use on its own to open an act's inputs in place. Field rendering resolves\n * each declared field against the object's JSON Schema via\n * `fieldsFromSchema()` when a `schema` is given: the label comes from the\n * property `title`, booleans render as a switch, numbers as a number field,\n * and long text (`maxLength > 255` or a `textarea`/`markdown` format) as a\n * textarea. Anything else — including a field the schema does not declare —\n * falls back to a plain labelled text input.\n *\n * An input may also say how it is asked for, which matters when the choices\n * depend on the record rather than on its schema: `label` names the field,\n * `options: [{ value, label }]` or `optionsSource` (a path into `context`)\n * turn it into a picker, and `widget` names `text`, `textarea`, `number`,\n * `date` or `template` outright. `other`, `helperFrom`, `preview` and\n * `default` are described in `utils/transitionInputs.js`. The transition may\n * carry `columns`, `summary` and `notice` for the layout around the inputs.\n *\n * Lives in its own file under `src/dialogs/` per the modal-isolation rule.\n *\n * ```vue\n * <CnTransitionInputDialog\n * v-if=\"inputTransition\"\n * :transition=\"inputTransition\"\n * :schema=\"schema\"\n * @confirm=\"onInputConfirm\"\n * @close=\"inputTransition = null\" />\n * ```\n */\nexport default {\n\tname: 'CnTransitionInputDialog',\n\n\tcomponents: {\n\t\tCnDialog,\n\t\tCnTransitionInputFields,\n\t\tNcButton,\n\t\tNcLoadingIcon,\n\t},\n\n\tmixins: [dialogBoardMixin],\n\n\tprops: {\n\t\t/**\n\t\t * The transition being applied. `inputs` is the declared input list from\n\t\t * `x-openregister-lifecycle.transitions.<action>.inputs` (server-derived\n\t\t * or config-declared); `label` doubles as dialog title + confirm label.\n\t\t * `columns`, `summary` and `notice` lay out the inputs (see\n\t\t * `CnTransitionInputFields`).\n\t\t *\n\t\t * An input may carry a `label` for its field and `options` to pick\n\t\t * from, each `{ value, label }`; the picker shows the label and sends\n\t\t * the value.\n\t\t *\n\t\t * @type {{action?: string, label?: string, columns?: number, summary?: object, notice?: object, inputs?: Array<{field: string, required?: boolean, label?: string, widget?: string, options?: Array<{value: string, label?: string}>, optionsSource?: string}>}}\n\t\t */\n\t\ttransition: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/**\n\t\t * The object's JSON Schema (with `properties`), used to resolve each\n\t\t * input's label, widget and helper text. Optional — undeclared fields\n\t\t * render as plain text inputs labelled by their field name.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The record the transition runs on. Gives `picker.excludeSelf` its id\n\t\t * to leave out, and the current value an object input is merged over.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcurrentObject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Register slug the reference pickers look in when the schema property\n\t\t * names none of its own.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * What an input's `optionsSource` and the summary paths read.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontext: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * The sentence a refused transition answered with. Present means the\n\t\t * dialog stayed open BECAUSE the attempt was refused, with everything\n\t\t * typed still in it.\n\t\t *\n\t\t * @type {string}\n\t\t */\n\t\terror: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The input keys the refusal named (`fields` in the 400 body). Each one\n\t\t * that this dialog offers is marked on its own field; each one it does\n\t\t * not is reported as a key the transition does not accept.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\tfieldErrors: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Whether the parent is mid-POST. Keeps the confirm button from firing\n\t\t * a second attempt while the first is in flight.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tbusy: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\temits: ['confirm', 'close'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** @type {{[key: string]: unknown}} Collected input values, keyed by declared field name. */\n\t\t\tvalues: initialInputValues(this.transition?.inputs, this.schema, this.currentObject),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** One field descriptor per declared input (see `resolveInputFields`). */\n\t\tfields() {\n\t\t\treturn resolveInputFields(this.transition.inputs, {\n\t\t\t\tschema: this.schema,\n\t\t\t\tregister: this.register,\n\t\t\t\tcontext: this.context,\n\t\t\t\tvalues: this.values,\n\t\t\t})\n\t\t},\n\n\t\t/** Dialog title — the transition's label, with a generic fallback. */\n\t\tdialogTitle() {\n\t\t\treturn this.transition.label || t('nextcloud-vue', 'Provide details')\n\t\t},\n\n\t\t/** Confirm button label — the transition's label per the contract. */\n\t\tconfirmLabel() {\n\t\t\treturn this.transition.label || t('nextcloud-vue', 'Confirm')\n\t\t},\n\n\t\t/** True when every shown `required: true` input holds a value. */\n\t\tcanConfirm() {\n\t\t\treturn this.busy !== true && inputFieldsComplete(this.fields, this.values)\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Store one input's value.\n\t\t *\n\t\t * @param {string} key The declared field name.\n\t\t * @param {unknown} value The new value.\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 * A typed sub-value of an object input.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {string} sub The sub-field key.\n\t\t * @return {unknown}\n\t\t */\n\t\tsubValue(key, sub) {\n\t\t\tconst group = this.values[key]\n\t\t\treturn group && typeof group === 'object' ? group[sub] : undefined\n\t\t},\n\n\t\t/**\n\t\t * Store one sub-value, keeping the rest of the object input's values.\n\t\t *\n\t\t * @param {string} key The input key.\n\t\t * @param {string} sub The sub-field key.\n\t\t * @param {unknown} value The new value.\n\t\t */\n\t\tsetSubValue(key, sub, value) {\n\t\t\tconst group = this.values[key] && typeof this.values[key] === 'object' ? this.values[key] : {}\n\t\t\tthis.setValue(key, { ...group, [sub]: value })\n\t\t},\n\n\t\t/**\n\t\t * The object an object input sends: the record's current value with the\n\t\t * asked sub-fields merged over it, so a sub-field that was not asked for\n\t\t * keeps its value. A shown field left empty over an empty current value\n\t\t * is not written. Never a dotted key.\n\t\t *\n\t\t * @param {object} field The object field descriptor.\n\t\t * @return {object}\n\t\t */\n\t\tmergedObject(field) {\n\t\t\tconst present = this.currentObject ? this.currentObject[field.key] : null\n\t\t\tconst base = present && typeof present === 'object' ? { ...present } : {}\n\t\t\tfor (const sub of field.subFields) {\n\t\t\t\tlet value = this.subValue(field.key, sub.key)\n\t\t\t\tconst empty = sub.widget === 'checkbox' ? value === undefined : String(value ?? '').trim() === ''\n\t\t\t\tconst had = base[sub.key]\n\t\t\t\tif (empty && (had === undefined || had === null || had === '')) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (sub.widget === 'number' && !empty && !Number.isNaN(Number(value))) {\n\t\t\t\t\tvalue = Number(value)\n\t\t\t\t}\n\t\t\t\tbase[sub.key] = value\n\t\t\t}\n\t\t\treturn base\n\t\t},\n\n\t\t/** Confirm: emit the asked keys (numbers cast, \"Other\" as '') and let the parent POST. */\n\t\tonConfirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.hidden || field.widget === 'template') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (field.widget === 'object') {\n\t\t\t\t\tdata[field.key] = this.mergedObject(field)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tlet value = submittedValue(this.values[field.key])\n\t\t\t\tif (field.widget === 'number' && String(value ?? '').trim() !== '') {\n\t\t\t\t\tconst parsed = Number(value)\n\t\t\t\t\tif (!Number.isNaN(parsed)) {\n\t\t\t\t\t\tvalue = parsed\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdata[field.key] = value\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event confirm Emitted when the user confirms with all required\n\t\t\t * inputs filled. Payload holds the declared input keys that were\n\t\t\t * asked; the parent POSTs `{ action, data }`.\n\t\t\t * @type {{[key: string]: unknown}}\n\t\t\t */\n\t\t\tthis.$emit('confirm', data)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-transition-input {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 12px;\n\tpadding: 4px 0;\n}\n\n.cn-transition-input__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["CnDialog","CnTransitionInputFields","t"],"mappings":"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"}
|