@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.
Files changed (97) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +2 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +6 -6
  5. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +2 -1
  7. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  8. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  9. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +18 -0
  10. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  11. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +14 -8
  12. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  13. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  14. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -1
  15. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  17. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +9 -4
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  19. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  20. package/dist/esm/components/CnMailTab/CnMailTab.vue2.js +2 -1
  21. package/dist/esm/components/CnMailTab/CnMailTab.vue2.js.map +1 -1
  22. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  23. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +71 -0
  24. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  25. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +25 -9
  26. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  27. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  28. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +11 -2
  29. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  30. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  31. package/dist/esm/components/CnSearchPage/CnSearchPage.vue.js +1 -1
  32. package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js +161 -5
  33. package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js.map +1 -1
  34. package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js +9 -9
  35. package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js.map +1 -1
  36. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  37. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +35 -5
  38. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  39. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  40. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue.js +9 -0
  41. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue.js.map +1 -0
  42. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js +435 -0
  43. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js.map +1 -0
  44. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js +300 -0
  45. package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js.map +1 -0
  46. package/dist/esm/composables/useEndpointSource.js +1 -36
  47. package/dist/esm/composables/useEndpointSource.js.map +1 -1
  48. package/dist/esm/dialogs/CnTransitionInputDialog.vue.js +1 -1
  49. package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +57 -336
  50. package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
  51. package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +18 -155
  52. package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
  53. package/dist/esm/index.js +2 -0
  54. package/dist/esm/index.js.map +1 -1
  55. package/dist/esm/l10n/en.json.js +2 -1
  56. package/dist/esm/l10n/en.json.js.map +1 -1
  57. package/dist/esm/l10n/nl.json.js +2 -1
  58. package/dist/esm/l10n/nl.json.js.map +1 -1
  59. package/dist/esm/library-style.js +1 -1
  60. package/dist/esm/nextcloud-vue.css +308 -229
  61. package/dist/esm/utils/actionsDispatcher.js +3 -2
  62. package/dist/esm/utils/actionsDispatcher.js.map +1 -1
  63. package/dist/esm/utils/interpolateUrlTokens.js +43 -0
  64. package/dist/esm/utils/interpolateUrlTokens.js.map +1 -0
  65. package/dist/esm/utils/labelsByField.js +72 -0
  66. package/dist/esm/utils/labelsByField.js.map +1 -0
  67. package/dist/esm/utils/listCreateAction.js +91 -0
  68. package/dist/esm/utils/listCreateAction.js.map +1 -0
  69. package/dist/esm/utils/transitionInputs.js +493 -0
  70. package/dist/esm/utils/transitionInputs.js.map +1 -0
  71. package/dist/esm/utils/visibleWhen.js +9 -2
  72. package/dist/esm/utils/visibleWhen.js.map +1 -1
  73. package/dist/nextcloud-vue.cjs.js +6690 -5404
  74. package/dist/nextcloud-vue.cjs.js.map +2 -2
  75. package/dist/nextcloud-vue.css +308 -229
  76. package/l10n/en.json +2 -1
  77. package/l10n/nl.json +2 -1
  78. package/package.json +1 -1
  79. package/src/components/CnActionsBar/CnActionsBar.vue +6 -6
  80. package/src/components/CnDashboardPage/CnDashboardPage.vue +27 -5
  81. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +11 -1
  82. package/src/components/CnIndexPage/CnIndexPage.vue +9 -4
  83. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +86 -0
  84. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +11 -2
  85. package/src/components/CnSearchPage/CnSearchPage.vue +170 -14
  86. package/src/components/CnTabsWidget/CnTabsWidget.vue +35 -5
  87. package/src/components/CnTransitionInputFields/CnTransitionInputFields.vue +750 -0
  88. package/src/components/CnTransitionInputFields/index.js +11 -0
  89. package/src/components/index.js +1 -0
  90. package/src/composables/useEndpointSource.js +3 -36
  91. package/src/dialogs/CnTransitionInputDialog.vue +73 -465
  92. package/src/index.js +2 -0
  93. package/src/utils/interpolateUrlTokens.js +40 -0
  94. package/src/utils/labelsByField.js +69 -0
  95. package/src/utils/listCreateAction.js +87 -0
  96. package/src/utils/transitionInputs.js +489 -0
  97. package/src/utils/visibleWhen.js +9 -2
@@ -1,9 +1,9 @@
1
1
  import { translate } from '@nextcloud/l10n';
2
- import { NcButton, NcLoadingIcon, NcTextField, NcTextArea, NcCheckboxRadioSwitch, NcSelect } from '@nextcloud/vue';
3
- import __sfc_main$1 from '../components/CnDialog/CnDialog.vue.js';
4
- import __sfc_main from '../components/CnResourceSelect/CnResourceSelect.vue.js';
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 { fieldsFromSchema } from '../utils/schema.js';
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 `required: true`
16
- * field is filled, and emits the collected values — the parent
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
- * Field rendering resolves each declared field against the object's JSON
21
- * Schema via `fieldsFromSchema()` when a `schema` is given: the label comes
22
- * from the property `title`, booleans render as a switch, numbers as a number
23
- * field, and long text (`maxLength > 255` or a `textarea`/`markdown` format)
24
- * as a textarea. Anything else — including a field the schema does not
25
- * declare — falls back to a plain labelled text input.
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
- * and `options: [{ value, label }]` turns it into a picker that shows each
30
- * `label` and sends the chosen `value`. An input that declares neither is
31
- * rendered from the schema as before. Deliberately minimal:
32
- * text, textarea, number and checkbox cover transition inputs; this is not a
33
- * form engine (use `CnFormDialog` for full object forms).
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
- CnResourceSelect: __sfc_main,
51
- CnDialog: __sfc_main$1,
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.initialValues(),
164
+ values: initialInputValues(this.transition?.inputs, this.schema, this.currentObject),
155
165
  }
156
166
  },
157
167
 
158
168
  computed: {
159
- /** The declared inputs, normalised to `{ field, required }`. */
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
- const keys = this.inputs.map((input) => input.field);
187
- const resolved = fieldsFromSchema(this.schema, { include: keys, includeReadOnly: true });
188
- return this.inputs.map((input) => {
189
- const field = resolved.find((f) => f.key === input.field);
190
- if (input.options) {
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 non-empty value. */
189
+ /** True when every shown `required: true` input holds a value. */
228
190
  canConfirm() {
229
- if (this.busy === true) {
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
- * Whether the refusal named this field.
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 {object} sub The sub-field descriptor.
380
- * @return {string}
201
+ * @param {string} key The declared field name.
202
+ * @param {unknown} value The new value.
381
203
  */
382
- subLabel(sub) {
383
- return sub.required ? `${sub.label} *` : sub.label
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 exactly the declared keys (numbers cast) and let the parent POST. */
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 exactly the declared input keys; the
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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"}