@conduction/nextcloud-vue 2.82.0 → 2.84.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/CnActionsBar/CnActionsBar.vue2.js +2 -2
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +24 -0
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +9 -4
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
- package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue.js +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue2.js +22 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue2.js.map +1 -1
- package/dist/esm/components/CnBodySections/CnBodySections.vue3.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +47 -4
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue.js +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +125 -3
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js +3 -3
- package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +14 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue.js +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +203 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +38 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +45 -5
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue.js +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +96 -12
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +95 -50
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js +29 -6
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnMassActionBar/CnMassActionBar.vue2.js +2 -2
- package/dist/esm/components/CnMassActionBar/CnMassActionBar.vue2.js.map +1 -1
- package/dist/esm/components/CnMassImportDialog/CnMassImportDialog.vue2.js +2 -2
- package/dist/esm/components/CnMassImportDialog/CnMassImportDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +31 -2
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +1 -1
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +16 -2
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +3 -3
- package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +37 -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/CnReportsPage/CnReportsPage.vue.js +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js +176 -0
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js +181 -52
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +1 -1
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +70 -5
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +61 -35
- package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue.js +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +72 -5
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +33 -8
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +4 -2
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue.js +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +72 -5
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +88 -71
- package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +1 -1
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +18 -4
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +33 -3
- 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/CnWalkthrough/CnWalkthrough.vue.js +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +16 -0
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
- package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +68 -6
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +133 -105
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +16 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +41 -4
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +900 -537
- package/dist/esm/utils/buildManifest.js +37 -3
- package/dist/esm/utils/buildManifest.js.map +1 -1
- package/dist/esm/utils/detailWidgetVisibility.js +149 -0
- package/dist/esm/utils/detailWidgetVisibility.js.map +1 -0
- package/dist/esm/utils/fetchAggregate.js +25 -2
- package/dist/esm/utils/fetchAggregate.js.map +1 -1
- package/dist/esm/utils/formatMetric.js +39 -3
- package/dist/esm/utils/formatMetric.js.map +1 -1
- package/dist/esm/utils/resolveManifestTokens.js +1 -0
- package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +9 -0
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/switchValues.js +62 -0
- package/dist/esm/utils/switchValues.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +36711 -34909
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +900 -537
- package/l10n/en.json +16 -1
- package/l10n/nl.json +41 -4
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +31 -2
- package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +1 -1
- package/src/components/CnBodySections/CnBodySections.vue +22 -1
- package/src/components/CnCountdownWidget/CnCountdownWidget.vue +47 -4
- package/src/components/CnDashboardGrid/CnDashboardGrid.vue +128 -6
- package/src/components/CnDashboardPage/CnDashboardPage.vue +14 -0
- package/src/components/CnDeltaWidget/CnDeltaWidget.vue +1 -1
- package/src/components/CnDetailPage/CnDetailPage.md +2 -0
- package/src/components/CnDetailPage/CnDetailPage.vue +203 -4
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +63 -1
- package/src/components/CnGaugeWidget/CnGaugeWidget.vue +1 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +125 -15
- package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +29 -6
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.md +1 -1
- package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +31 -2
- package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +54 -3
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +37 -2
- package/src/components/CnReportsPage/CnReportsPage.vue +263 -5
- package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +110 -18
- package/src/components/CnStagesWidget/CnStagesWidget.vue +103 -6
- package/src/components/CnStatWidget/CnStatWidget.vue +4 -2
- package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +125 -7
- package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +18 -4
- package/src/components/CnTabsWidget/CnTabsWidget.vue +33 -3
- package/src/components/CnWalkthrough/CnWalkthrough.vue +16 -0
- package/src/css/form-field.css +14 -0
- package/src/css/form-widget.css +11 -0
- package/src/css/index-page.css +11 -0
- package/src/css/index.css +1 -0
- package/src/css/look-board-reports.css +175 -0
- package/src/css/look-board.css +44 -1
- package/src/dialogs/CnTransitionInputDialog.vue +87 -7
- package/src/schemas/app-manifest-v2.schema.json +24 -3
- package/src/utils/buildManifest.js +36 -2
- package/src/utils/detailWidgetVisibility.js +145 -0
- package/src/utils/fetchAggregate.js +24 -1
- package/src/utils/formatMetric.js +38 -2
- package/src/utils/resolveManifestTokens.js +1 -0
- package/src/utils/sentinelTokens.js +9 -0
- package/src/utils/switchValues.js +59 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -7,7 +7,9 @@ import { fillTemplate } from '../../utils/fillTemplate.js';
|
|
|
7
7
|
import { prefixUrl } from '../../utils/headers.js';
|
|
8
8
|
import { objectUrlOf, changedFields, writeFields } from '../../utils/objectWrite.js';
|
|
9
9
|
import { readPath } from '../../utils/readPath.js';
|
|
10
|
+
import { resolveFilterTokens, hasUnresolvedTokens } from '../../utils/resolveFilterTokens.js';
|
|
10
11
|
import { serverErrorMessage } from '../../utils/serverErrorMessage.js';
|
|
12
|
+
import { switchIsOn, switchStoredValue } from '../../utils/switchValues.js';
|
|
11
13
|
|
|
12
14
|
const TYPES = ['text', 'textarea', 'select', 'switch', 'number', 'file', 'chips', 'reference'];
|
|
13
15
|
|
|
@@ -37,7 +39,7 @@ var script = {
|
|
|
37
39
|
/**
|
|
38
40
|
* The widget configuration.
|
|
39
41
|
*
|
|
40
|
-
* - `fields` (required) — `[{ key, label, type?: 'text'|'textarea'|'select'|'switch'|'number'|'file'|'chips'|'reference', register?, schema?, labelField?, valueTemplate?, filter?, limit?, emptyLabel?, default?, minItems?, required?, minItemsMessage?, lowercase?, addLabel?, confirmLabel?, removeLabel?, picker?: { title?, mimeTypes?, startAt?, valueTemplate? }, chooseLabel?, clearLabel?, hint?, placeholder?, options?: [{ value, label }], required?, pattern?, patternMessage?, min?, max?, rows?, wide?, readOnly? }]`; `key` is a field of the object, a top-level name or a dot-path.
|
|
42
|
+
* - `fields` (required) — `[{ key, label, type?: 'text'|'textarea'|'select'|'switch'|'number'|'file'|'chips'|'reference', register?, schema?, labelField?, valueTemplate?, filter?, limit?, emptyLabel?, free?, freeLabel?, freePlaceholder?, freePattern?, freePatternMessage?, default?, minItems?, required?, minItemsMessage?, values?: { on, off }, lowercase?, addLabel?, confirmLabel?, removeLabel?, picker?: { title?, mimeTypes?, startAt?, valueTemplate? }, chooseLabel?, clearLabel?, hint?, placeholder?, options?: [{ value, label }], required?, pattern?, patternMessage?, min?, max?, rows?, wide?, readOnly? }]`; `key` is a field of the object, a top-level name or a dot-path. A `reference` field's `filter` values may be `@objectId` and `@object.<field>` (the record being edited). A `switch` field's `values: { on, off }` reads and writes those values instead of true/false.
|
|
41
43
|
* - `save` — `{ url, method?, payload? }`, write through an app endpoint (tokens `{value}`, `{field}`, `{changes}`, `{object.<path>}`).
|
|
42
44
|
* - `columns` — 1 or 2 (default 2).
|
|
43
45
|
* - `saveLabel`, `savedText`, `readOnly`.
|
|
@@ -86,6 +88,9 @@ var script = {
|
|
|
86
88
|
// `reference` fields: the objects to choose from and the read's state (`loading`, `ready`, `error`), by field key.
|
|
87
89
|
referenceOptions: {},
|
|
88
90
|
referenceState: {},
|
|
91
|
+
// The query each `reference` field was last read with, by field key, so a
|
|
92
|
+
// new object re-reads only the fields whose filter changes with it.
|
|
93
|
+
referenceQuery: {},
|
|
89
94
|
errors: {},
|
|
90
95
|
saving: false,
|
|
91
96
|
notice: '',
|
|
@@ -110,6 +115,9 @@ var script = {
|
|
|
110
115
|
hint: this.tr(field.hint || ''),
|
|
111
116
|
placeholder: this.tr(field.placeholder || ''),
|
|
112
117
|
chooseLabel: this.tr(field.chooseLabel || 'Choose a file'),
|
|
118
|
+
free: field.type === 'reference' && field.free === true,
|
|
119
|
+
freeLabel: this.tr(field.freeLabel || 'Or type a value'),
|
|
120
|
+
freePlaceholder: this.tr(field.freePlaceholder || ''),
|
|
113
121
|
clearLabel: this.tr(field.clearLabel || 'Remove'),
|
|
114
122
|
rows: field.rows || 3,
|
|
115
123
|
wide: field.wide === true || field.type === 'textarea',
|
|
@@ -143,6 +151,7 @@ var script = {
|
|
|
143
151
|
watch: {
|
|
144
152
|
objectData() {
|
|
145
153
|
this.adopt();
|
|
154
|
+
this.loadReferences();
|
|
146
155
|
},
|
|
147
156
|
},
|
|
148
157
|
|
|
@@ -158,7 +167,14 @@ var script = {
|
|
|
158
167
|
* parameters, at most `limit`, 100 by default). A failed read leaves the
|
|
159
168
|
* field with its stored value only, and says so in the hint's place.
|
|
160
169
|
*
|
|
170
|
+
* `filter` values may be `@objectId` and `@object.<field>`: the record
|
|
171
|
+
* the form edits, so a list can be narrowed to it (the logos of this
|
|
172
|
+
* portal). Until the record has that value the field is not read; it is
|
|
173
|
+
* read again when the record changes the resolved query, never twice
|
|
174
|
+
* for the same query.
|
|
175
|
+
*
|
|
161
176
|
* @spec openspec/changes/screens-settings-form-reference/specs/settings-form/spec.md#requirement-a-settings-form-field-can-pick-an-object
|
|
177
|
+
* @spec openspec/changes/screens-settings-form-reference-object-filter/specs/settings-form/spec.md#requirement-a-reference-fields-filter-can-name-the-record-being-edited
|
|
162
178
|
* @return {Promise<void>}
|
|
163
179
|
*/
|
|
164
180
|
async loadReferences() {
|
|
@@ -166,13 +182,35 @@ var script = {
|
|
|
166
182
|
if (fields.length === 0) {
|
|
167
183
|
return
|
|
168
184
|
}
|
|
185
|
+
const ctx = { objectId: this.objectId || (this.objectData && this.objectData.id) || undefined, object: this.objectData || undefined };
|
|
186
|
+
const pending = [];
|
|
187
|
+
for (const field of fields) {
|
|
188
|
+
const filter = resolveFilterTokens(field.filter && typeof field.filter === 'object' ? field.filter : {}, ctx);
|
|
189
|
+
if (hasUnresolvedTokens(filter)) {
|
|
190
|
+
// The record has no value for the token yet: nothing to read.
|
|
191
|
+
continue
|
|
192
|
+
}
|
|
193
|
+
const params = { ...filter, _limit: Number(field.limit) > 0 ? Number(field.limit) : 100 };
|
|
194
|
+
const query = JSON.stringify(params);
|
|
195
|
+
if (this.referenceQuery[field.key] === query) {
|
|
196
|
+
continue
|
|
197
|
+
}
|
|
198
|
+
this.referenceQuery = { ...this.referenceQuery, [field.key]: query };
|
|
199
|
+
pending.push({ field, params, query });
|
|
200
|
+
}
|
|
201
|
+
if (pending.length === 0) {
|
|
202
|
+
return
|
|
203
|
+
}
|
|
169
204
|
const { default: axios } = await import('@nextcloud/axios');
|
|
170
|
-
await Promise.all(
|
|
205
|
+
await Promise.all(pending.map(async ({ field, params, query }) => {
|
|
171
206
|
this.referenceState = { ...this.referenceState, [field.key]: 'loading' };
|
|
172
207
|
try {
|
|
173
208
|
const url = `/apps/openregister/api/objects/${encodeURIComponent(field.register)}/${encodeURIComponent(field.schema)}`;
|
|
174
|
-
const params = { ...(field.filter && typeof field.filter === 'object' ? field.filter : {}), _limit: Number(field.limit) > 0 ? Number(field.limit) : 100 };
|
|
175
209
|
const { data } = await axios.get(prefixUrl(url), { params });
|
|
210
|
+
if (this.referenceQuery[field.key] !== query) {
|
|
211
|
+
// A newer record asked for another list meanwhile.
|
|
212
|
+
return
|
|
213
|
+
}
|
|
176
214
|
const rows = Array.isArray(data) ? data : (Array.isArray(data?.results) ? data.results : []);
|
|
177
215
|
const options = [];
|
|
178
216
|
for (const row of rows) {
|
|
@@ -214,6 +252,24 @@ var script = {
|
|
|
214
252
|
return [...choices, ...options]
|
|
215
253
|
},
|
|
216
254
|
|
|
255
|
+
/**
|
|
256
|
+
* The typed value of a `reference` field with `free`: the value the form
|
|
257
|
+
* holds when it is not one of the objects to pick, else empty (picking
|
|
258
|
+
* an object clears the typed value).
|
|
259
|
+
*
|
|
260
|
+
* @spec openspec/changes/screens-settings-form-reference-free-value/specs/settings-form/spec.md#requirement-a-reference-field-can-also-take-a-typed-value
|
|
261
|
+
* @param {object} field The field.
|
|
262
|
+
* @return {string}
|
|
263
|
+
*/
|
|
264
|
+
freeValue(field) {
|
|
265
|
+
const current = this.form[field.key];
|
|
266
|
+
if (typeof current !== 'string' || current === '') {
|
|
267
|
+
return ''
|
|
268
|
+
}
|
|
269
|
+
const options = this.referenceOptions[field.key] || [];
|
|
270
|
+
return options.some((option) => option.value === current) ? '' : current
|
|
271
|
+
},
|
|
272
|
+
|
|
217
273
|
tr(text) {
|
|
218
274
|
if (typeof text !== 'string' || text === '') {
|
|
219
275
|
return ''
|
|
@@ -284,7 +340,7 @@ var script = {
|
|
|
284
340
|
stored(field) {
|
|
285
341
|
const value = readPath(this.objectData || {}, field.key);
|
|
286
342
|
if (field.type === 'switch') {
|
|
287
|
-
return value
|
|
343
|
+
return switchIsOn(value, field.values)
|
|
288
344
|
}
|
|
289
345
|
if (field.type === 'chips') {
|
|
290
346
|
return Array.isArray(value) ? value.map((item) => String(item)) : []
|
|
@@ -408,6 +464,9 @@ var script = {
|
|
|
408
464
|
if (Number.isNaN(value) || (field.min !== undefined && value < field.min) || (field.max !== undefined && value > field.max)) {
|
|
409
465
|
errors[field.key] = this.tr('This number is not valid.');
|
|
410
466
|
}
|
|
467
|
+
} else if (field.free && field.freePattern && this.freeValue(field) !== '' && !new RegExp(field.freePattern).test(String(value))) {
|
|
468
|
+
// A typed value (not one of the objects) answers to `freePattern`.
|
|
469
|
+
errors[field.key] = this.tr(field.freePatternMessage || 'This value is not valid.');
|
|
411
470
|
} else if (field.pattern && !new RegExp(field.pattern).test(String(value))) {
|
|
412
471
|
errors[field.key] = this.tr(field.patternMessage || 'This value is not valid.');
|
|
413
472
|
}
|
|
@@ -441,6 +500,12 @@ var script = {
|
|
|
441
500
|
}
|
|
442
501
|
}
|
|
443
502
|
const patch = changedFields(compare, next);
|
|
503
|
+
// A switch with a value map (`values: { on, off }`) writes those values.
|
|
504
|
+
for (const field of this.fields) {
|
|
505
|
+
if (field.type === 'switch' && Object.hasOwn(patch, field.key)) {
|
|
506
|
+
patch[field.key] = switchStoredValue(patch[field.key], field.values);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
444
509
|
this.saving = true;
|
|
445
510
|
try {
|
|
446
511
|
if (Object.keys(patch).length > 0) {
|
|
@@ -452,7 +517,7 @@ var script = {
|
|
|
452
517
|
const field = this.fields.find((candidate) => candidate.key === key);
|
|
453
518
|
const answered = readPath(data, key);
|
|
454
519
|
const written = answered !== undefined ? answered : patch[key];
|
|
455
|
-
baseline[key] = field.type === 'switch' ? written
|
|
520
|
+
baseline[key] = field.type === 'switch' ? switchIsOn(written, field.values) : (written === null ? (field.type === 'chips' ? [] : '') : written);
|
|
456
521
|
form[key] = baseline[key];
|
|
457
522
|
loaded[key] = baseline[key];
|
|
458
523
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnSettingsFormWidget.vue2.js","sources":["../../../../src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<form class=\"cn-settings-form\"\n\t\tdata-testid=\"cn-settings-form\"\n\t\tnovalidate\n\t\t@submit.prevent=\"save\">\n\t\t<div class=\"cn-settings-form__grid\" :class=\"`cn-settings-form__grid--${columns}`\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\tclass=\"cn-settings-form__field\"\n\t\t\t\t:class=\"{ 'cn-settings-form__field--wide': field.wide }\"\n\t\t\t\t:data-testid=\"`cn-settings-form-field-${field.key}`\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'switch'\"\n\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t{{ field.label }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<CnChipsFieldWidget\n\t\t\t\t\tv-else-if=\"field.type === 'chips'\"\n\t\t\t\t\t:modelValue=\"form[field.key]\"\n\t\t\t\t\t:content=\"chipsContent(field)\"\n\t\t\t\t\t@update:modelValue=\"form[field.key] = $event\" />\n\t\t\t\t<template v-else>\n\t\t\t\t\t<label class=\"cn-settings-form__label\" :for=\"inputId(field)\">{{ field.label }}</label>\n\t\t\t\t\t<div v-if=\"field.type === 'file'\" class=\"cn-settings-form__file\" :data-testid=\"`cn-settings-form-file-${field.key}`\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--file\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-settings-form__control--placeholder': !form[field.key] }\">\n\t\t\t\t\t\t\t{{ form[field.key] ? fileName(form[field.key]) : field.placeholder }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly\"\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t:aria-describedby=\"inputId(field)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-choose-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"chooseFile(field)\">\n\t\t\t\t\t\t\t{{ field.chooseLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly && form[field.key]\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-clear-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"form[field.key] = ''\">\n\t\t\t\t\t\t\t{{ field.clearLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t\t<select\n\t\t\t\t\t\tv-else-if=\"field.type === 'reference'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:disabled=\"field.readOnly\"\n\t\t\t\t\t\t:aria-busy=\"referenceState[field.key] === 'loading' ? 'true' : null\"\n\t\t\t\t\t\t:data-testid=\"`cn-settings-form-reference-${field.key}`\">\n\t\t\t\t\t\t<option v-for=\"option in referenceChoices(field)\" :key=\"option.value\" :value=\"option.value\">\n\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t</select>\n\t\t\t\t\t<select\n\t\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t\t<option v-for=\"option in field.options\" :key=\"String(option.value)\" :value=\"option.value\">\n\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t</select>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--area\"\n\t\t\t\t\t\t:rows=\"field.rows\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\" />\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-else\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:type=\"field.type === 'number' ? 'number' : 'text'\"\n\t\t\t\t\t\t:min=\"field.min\"\n\t\t\t\t\t\t:max=\"field.max\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\"\n\t\t\t\t\t\t:aria-invalid=\"errors[field.key] ? 'true' : null\">\n\t\t\t\t</template>\n\t\t\t\t<p v-if=\"errors[field.key]\" class=\"cn-settings-form__error\" role=\"alert\">\n\t\t\t\t\t{{ errors[field.key] }}\n\t\t\t\t</p>\n\t\t\t\t<p v-else-if=\"field.hint\" class=\"cn-settings-form__hint\">\n\t\t\t\t\t{{ field.hint }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<NcNoteCard v-if=\"notice\" :type=\"noticeType\" data-testid=\"cn-settings-form-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\n\t\t<div v-if=\"!readOnly\" class=\"cn-settings-form__actions\">\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\ttype=\"submit\"\n\t\t\t\t:disabled=\"saving\"\n\t\t\t\tdata-testid=\"cn-settings-form-save\">\n\t\t\t\t{{ saveLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</form>\n</template>\n\n<script>\nimport { FilePickerClosed, getFilePickerBuilder } from '@nextcloud/dialogs'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport CnChipsFieldWidget from '../CnChipsFieldWidget/CnChipsFieldWidget.vue'\nimport { pickRefLabel } from '../../composables/useRefLabels.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { changedFields, objectUrlOf, writeFields } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n// The native file-picker modal ships its chrome styles here; without this the\n// spawned picker renders unstyled. Rules are scoped to the picker/dialog classes.\nimport '@nextcloud/dialogs/style.css'\n\nconst TYPES = ['text', 'textarea', 'select', 'switch', 'number', 'file', 'chips', 'reference']\n\nlet uid = 0\n\n/**\n * CnSettingsFormWidget — the `settings-form` widget: fields of the CURRENT\n * object as a one- or two-column grid of framed inputs with light labels and\n * hints, saved by ONE PATCH of the fields that changed since the last save.\n *\n * \"Last save\" is the baseline this widget keeps: a save moves it forward, so\n * editing a field back to the value the page loaded with, after a save, still\n * counts as a change (comparing against the loaded object skipped that PATCH).\n *\n * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md\n */\nexport default {\n\tname: 'CnSettingsFormWidget',\n\n\tcomponents: { CnChipsFieldWidget, NcButton, NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `fields` (required) — `[{ key, label, type?: 'text'|'textarea'|'select'|'switch'|'number'|'file'|'chips'|'reference', register?, schema?, labelField?, valueTemplate?, filter?, limit?, emptyLabel?, default?, minItems?, required?, minItemsMessage?, lowercase?, addLabel?, confirmLabel?, removeLabel?, picker?: { title?, mimeTypes?, startAt?, valueTemplate? }, chooseLabel?, clearLabel?, hint?, placeholder?, options?: [{ value, label }], required?, pattern?, patternMessage?, min?, max?, rows?, wide?, readOnly? }]`; `key` is a field of the object, a top-level name or a dot-path.\n\t\t * - `save` — `{ url, method?, payload? }`, write through an app endpoint (tokens `{value}`, `{field}`, `{changes}`, `{object.<path>}`).\n\t\t * - `columns` — 1 or 2 (default 2).\n\t\t * - `saveLabel`, `savedText`, `readOnly`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\tuid += 1\n\t\treturn {\n\t\t\tuid,\n\t\t\tform: {},\n\t\t\tbaseline: {},\n\t\t\tloaded: {},\n\t\t\t// `reference` fields: the objects to choose from and the read's state (`loading`, `ready`, `error`), by field key.\n\t\t\treferenceOptions: {},\n\t\t\treferenceState: {},\n\t\t\terrors: {},\n\t\t\tsaving: false,\n\t\t\tnotice: '',\n\t\t\tnoticeType: 'success',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured fields, normalised and translated.\n\t\t *\n\t\t * @return {Array<object>}\n\t\t */\n\t\tfields() {\n\t\t\tconst list = Array.isArray(this.content.fields) ? this.content.fields : []\n\t\t\treturn list\n\t\t\t\t.filter((field) => field && field.key)\n\t\t\t\t.map((field) => ({\n\t\t\t\t\t...field,\n\t\t\t\t\ttype: TYPES.includes(field.type) ? field.type : 'text',\n\t\t\t\t\tlabel: this.tr(field.label || field.key),\n\t\t\t\t\thint: this.tr(field.hint || ''),\n\t\t\t\t\tplaceholder: this.tr(field.placeholder || ''),\n\t\t\t\t\tchooseLabel: this.tr(field.chooseLabel || 'Choose a file'),\n\t\t\t\t\tclearLabel: this.tr(field.clearLabel || 'Remove'),\n\t\t\t\t\trows: field.rows || 3,\n\t\t\t\t\twide: field.wide === true || field.type === 'textarea',\n\t\t\t\t\treadOnly: this.readOnly || field.readOnly === true,\n\t\t\t\t\toptions: (Array.isArray(field.options) ? field.options : []).map((option) => (\n\t\t\t\t\t\ttypeof option === 'object' && option !== null\n\t\t\t\t\t\t\t? { value: option.value, label: this.tr(String(option.label ?? option.value)) }\n\t\t\t\t\t\t\t: { value: option, label: this.tr(String(option)) }\n\t\t\t\t\t)),\n\t\t\t\t}))\n\t\t},\n\n\t\tcolumns() {\n\t\t\treturn this.content.columns === 1 ? 1 : 2\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tsaveLabel() {\n\t\t\treturn this.tr(this.content.saveLabel || 'Save')\n\t\t},\n\n\t\t/** The object URL the form is saved to, or '' when it is not known. */\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.adopt()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.adopt(true)\n\t\tthis.loadReferences()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Read the objects each `reference` field chooses from: one list read\n\t\t * per field of its `register` and `schema` (`filter` as query\n\t\t * parameters, at most `limit`, 100 by default). A failed read leaves the\n\t\t * field with its stored value only, and says so in the hint's place.\n\t\t *\n\t\t * @spec openspec/changes/screens-settings-form-reference/specs/settings-form/spec.md#requirement-a-settings-form-field-can-pick-an-object\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadReferences() {\n\t\t\tconst fields = this.fields.filter((field) => field.type === 'reference' && typeof field.register === 'string' && field.register !== '' && typeof field.schema === 'string' && field.schema !== '')\n\t\t\tif (fields.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\tawait Promise.all(fields.map(async (field) => {\n\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'loading' }\n\t\t\t\ttry {\n\t\t\t\t\tconst url = `/apps/openregister/api/objects/${encodeURIComponent(field.register)}/${encodeURIComponent(field.schema)}`\n\t\t\t\t\tconst params = { ...(field.filter && typeof field.filter === 'object' ? field.filter : {}), _limit: Number(field.limit) > 0 ? Number(field.limit) : 100 }\n\t\t\t\t\tconst { data } = await axios.get(prefixUrl(url), { params })\n\t\t\t\t\tconst rows = Array.isArray(data) ? data : (Array.isArray(data?.results) ? data.results : [])\n\t\t\t\t\tconst options = []\n\t\t\t\t\tfor (const row of rows) {\n\t\t\t\t\t\tconst id = row && (row.id ?? row.uuid ?? (row['@self'] && row['@self'].id))\n\t\t\t\t\t\tif (id === undefined || id === null || id === '') {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst scope = { ...row, id, register: field.register, schema: field.schema }\n\t\t\t\t\t\tconst value = fillTemplate(typeof field.valueTemplate === 'string' && field.valueTemplate !== '' ? field.valueTemplate : '{id}', scope)\n\t\t\t\t\t\tif (value !== '') {\n\t\t\t\t\t\t\toptions.push({ value, label: pickRefLabel(row, field.labelField) || String(id) })\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [field.key]: options }\n\t\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'ready' }\n\t\t\t\t} catch {\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [field.key]: [] }\n\t\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'error' }\n\t\t\t\t\tthis.errors = { ...this.errors, [field.key]: this.tr('The list to choose from could not be loaded.') }\n\t\t\t\t}\n\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * The choices of a `reference` field: \"none\" (unless required), the\n\t\t * objects read, and the value the form holds when it is not one of\n\t\t * them (a free string such as a URL stays selectable, as it is stored).\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {Array<{value: string, label: string}>}\n\t\t */\n\t\treferenceChoices(field) {\n\t\t\tconst options = this.referenceOptions[field.key] || []\n\t\t\tconst current = this.form[field.key]\n\t\t\tconst choices = field.required ? [] : [{ value: '', label: this.tr(field.emptyLabel || 'None') }]\n\t\t\tif (typeof current === 'string' && current !== '' && !options.some((option) => option.value === current)) {\n\t\t\t\tchoices.push({ value: current, label: current })\n\t\t\t}\n\t\t\treturn [...choices, ...options]\n\t\t},\n\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\tinputId(field) {\n\t\t\treturn `cn-settings-form-${this.uid}-${field.key}`\n\t\t},\n\n\t\t/**\n\t\t * The name shown for a stored file value: its last path segment.\n\t\t *\n\t\t * @param {string} value The stored value.\n\t\t * @return {string}\n\t\t */\n\t\tfileName(value) {\n\t\t\tconst text = String(value)\n\t\t\treturn text.split('/').filter(Boolean).pop() || text\n\t\t},\n\n\t\t/**\n\t\t * Open the Nextcloud file picker and take the chosen file as the value.\n\t\t * `field.picker` = `{ title?, mimeTypes?, startAt?, valueTemplate? }`; the\n\t\t * template's `{path}`, `{fileid}` and `{name}` are filled from the chosen\n\t\t * node (default `{path}`).\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form-file/specs/settings-form/spec.md#requirement-a-file-field-takes-a-file-from-the-nextcloud-picker\n\t\t */\n\t\tasync chooseFile(field) {\n\t\t\tconst picker = field.picker || {}\n\t\t\tlet builder = getFilePickerBuilder(this.tr(picker.title || field.label))\n\t\t\t\t.setMultiSelect(false)\n\t\t\t\t.allowDirectories(false)\n\t\t\t\t.startAt(picker.startAt || '/')\n\t\t\t\t.addButton({ label: t('nextcloud-vue', 'Choose'), type: 'primary', callback: () => {} })\n\t\t\tif (Array.isArray(picker.mimeTypes) && picker.mimeTypes.length > 0) {\n\t\t\t\tbuilder = builder.setMimeTypeFilter(picker.mimeTypes)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst nodes = await builder.build().pickNodes()\n\t\t\t\tconst node = Array.isArray(nodes) ? nodes[0] : nodes\n\t\t\t\tif (!node) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.form[field.key] = String(picker.valueTemplate || '{path}').replace(/\\{(path|fileid|name)\\}/g, (match, part) => {\n\t\t\t\t\tconst value = part === 'name' ? (node.basename || this.fileName(node.path)) : node[part]\n\t\t\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof FilePickerClosed) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('The file picker could not be opened.')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The stored value of a field as the input holds it.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tstored(field) {\n\t\t\tconst value = readPath(this.objectData || {}, field.key)\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\tif (field.type === 'chips') {\n\t\t\t\treturn Array.isArray(value) ? value.map((item) => String(item)) : []\n\t\t\t}\n\t\t\treturn value === undefined || value === null ? '' : value\n\t\t},\n\n\t\t/**\n\t\t * The value the input shows for a field: the stored one, else the field's\n\t\t * `default` when nothing is stored. The baseline stays the stored value, so\n\t\t * a default that was never saved counts as a change and the next Save writes it.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tshown(field) {\n\t\t\tconst value = this.stored(field)\n\t\t\tconst absent = readPath(this.objectData || {}, field.key) === undefined || readPath(this.objectData || {}, field.key) === null || value === '' || (field.type === 'chips' && value.length === 0)\n\t\t\tif (absent && field.default !== undefined) {\n\t\t\t\treturn field.type === 'chips' && Array.isArray(field.default) ? [...field.default] : field.default\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * Take the object's values as the new baseline; a field the person has\n\t\t * not touched follows it, a touched one keeps the typed value.\n\t\t *\n\t\t * @param {boolean} [first] Whether this is the first read.\n\t\t */\n\t\tadopt(first = false) {\n\t\t\tconst baseline = {}\n\t\t\tconst loaded = {}\n\t\t\tconst form = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tbaseline[field.key] = this.stored(field)\n\t\t\t\tloaded[field.key] = this.shown(field)\n\t\t\t\tconst untouched = first || JSON.stringify(this.form[field.key]) === JSON.stringify(this.loaded[field.key])\n\t\t\t\tform[field.key] = untouched ? loaded[field.key] : this.form[field.key]\n\t\t\t}\n\t\t\tthis.baseline = baseline\n\t\t\tthis.loaded = loaded\n\t\t\tthis.form = form\n\t\t},\n\n\t\t/**\n\t\t * The configuration of the embedded chips widget for a `chips` field.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {object}\n\t\t */\n\t\tchipsContent(field) {\n\t\t\treturn {\n\t\t\t\tlabel: field.label,\n\t\t\t\thint: field.hint,\n\t\t\t\tplaceholder: field.placeholder,\n\t\t\t\taddLabel: field.addLabel,\n\t\t\t\tconfirmLabel: field.confirmLabel,\n\t\t\t\tremoveLabel: field.removeLabel,\n\t\t\t\tpattern: field.pattern,\n\t\t\t\tpatternMessage: field.patternMessage,\n\t\t\t\tlowercase: field.lowercase,\n\t\t\t\toptions: field.options,\n\t\t\t\tminItems: field.minItems,\n\t\t\t\trequired: field.required,\n\t\t\t\tminItemsMessage: field.minItemsMessage,\n\t\t\t\treadOnly: field.readOnly,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The value to send for a field: numbers as numbers, an empty value as null.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\toutgoing(field) {\n\t\t\tconst value = this.form[field.key]\n\t\t\tif (field.type === 'number') {\n\t\t\t\treturn value === '' || value === null || value === undefined ? null : Number(value)\n\t\t\t}\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\tif (field.type === 'chips') {\n\t\t\t\treturn Array.isArray(value) ? [...value] : []\n\t\t\t}\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn value.trim() === '' ? null : value.trim()\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * Check required, number range and pattern before any write.\n\t\t *\n\t\t * @return {object} Error text by field key.\n\t\t */\n\t\tvalidate() {\n\t\t\tconst errors = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.type === 'switch' || field.readOnly) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = this.outgoing(field)\n\t\t\t\tif (field.type === 'chips') {\n\t\t\t\t\tconst least = Number(field.minItems) > 0 ? Number(field.minItems) : (field.required ? 1 : 0)\n\t\t\t\t\tif (value.length < least) {\n\t\t\t\t\t\terrors[field.key] = this.tr(field.minItemsMessage || 'Keep at least {count}.').replace('{count}', String(least))\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst empty = value === null || value === undefined || value === ''\n\t\t\t\tif (empty) {\n\t\t\t\t\tif (field.required) {\n\t\t\t\t\t\terrors[field.key] = this.tr('Fill this in.')\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (field.type === 'number') {\n\t\t\t\t\tif (Number.isNaN(value) || (field.min !== undefined && value < field.min) || (field.max !== undefined && value > field.max)) {\n\t\t\t\t\t\terrors[field.key] = this.tr('This number is not valid.')\n\t\t\t\t\t}\n\t\t\t\t} else if (field.pattern && !new RegExp(field.pattern).test(String(value))) {\n\t\t\t\t\terrors[field.key] = this.tr(field.patternMessage || 'This value is not valid.')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn errors\n\t\t},\n\n\t\t/**\n\t\t * Save: PATCH the fields that differ from the last saved values.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md#requirement-a-settings-form-saves-only-what-changed\n\t\t */\n\t\tasync save() {\n\t\t\tthis.errors = this.validate()\n\t\t\tthis.notice = ''\n\t\t\tif (Object.keys(this.errors).length > 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.objectUrl && !(this.content.save && this.content.save.url)) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('This form cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = {}\n\t\t\tconst compare = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (!field.readOnly) {\n\t\t\t\t\tnext[field.key] = this.outgoing(field)\n\t\t\t\t\tcompare[field.key] = this.baseline[field.key] === '' ? null : this.baseline[field.key]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst patch = changedFields(compare, next)\n\t\t\tthis.saving = true\n\t\t\ttry {\n\t\t\t\tif (Object.keys(patch).length > 0) {\n\t\t\t\t\tconst data = await writeFields(this.objectUrl, patch, { save: this.content.save, object: this.objectData })\n\t\t\t\t\tconst baseline = { ...this.baseline }\n\t\t\t\t\tconst loaded = { ...this.loaded }\n\t\t\t\t\tconst form = { ...this.form }\n\t\t\t\t\tfor (const key of Object.keys(patch)) {\n\t\t\t\t\t\tconst field = this.fields.find((candidate) => candidate.key === key)\n\t\t\t\t\t\tconst answered = readPath(data, key)\n\t\t\t\t\t\tconst written = answered !== undefined ? answered : patch[key]\n\t\t\t\t\t\tbaseline[key] = field.type === 'switch' ? written === true : (written === null ? (field.type === 'chips' ? [] : '') : written)\n\t\t\t\t\t\tform[key] = baseline[key]\n\t\t\t\t\t\tloaded[key] = baseline[key]\n\t\t\t\t\t}\n\t\t\t\t\tthis.baseline = baseline\n\t\t\t\t\tthis.loaded = loaded\n\t\t\t\t\tthis.form = form\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'success'\n\t\t\t\tthis.notice = this.tr(this.content.savedText || 'Saved.')\n\t\t\t\t/**\n\t\t\t\t * @event saved The changed fields were written.\n\t\t\t\t * @type {{patch: object}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { patch })\n\t\t\t} catch (e) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-settings-form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 14px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__grid {\n\tdisplay: grid;\n\tgap: 14px 16px;\n\tgrid-template-columns: minmax(0, 1fr);\n}\n\n.cn-settings-form__grid--2 {\n\tgrid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.cn-settings-form__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__field--wide {\n\tgrid-column: 1 / -1;\n}\n\n.cn-settings-form__label {\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-settings-form__control {\n\twidth: 100%;\n\tbox-sizing: border-box;\n\theight: var(--cn-board-control-height, 40px);\n\tpadding: 0 12px;\n\tborder: 1px solid var(--color-border-maxcontrast);\n\tborder-radius: var(--cn-board-control-radius, 8px);\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\tfont: inherit;\n}\n\n.cn-settings-form__file {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-settings-form__control--file {\n\tdisplay: inline-flex;\n\talign-items: center;\n\twidth: auto;\n\tmin-width: 120px;\n\tflex: 0 1 auto;\n\toverflow-wrap: anywhere;\n}\n\n.cn-settings-form__control--placeholder {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__control--area {\n\theight: auto;\n\tpadding: 10px 12px;\n\tresize: vertical;\n}\n\n.cn-settings-form__control:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-settings-form__hint,\n.cn-settings-form__error {\n\tmargin: 0;\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-settings-form__actions {\n\tdisplay: flex;\n\tjustify-content: flex-start;\n}\n\n@media (max-width: 640px) {\n\t.cn-settings-form__grid--2 {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t}\n}\n</style>\n"],"names":["CnChipsFieldWidget","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnSettingsFormWidget.vue2.js","sources":["../../../../src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<form class=\"cn-settings-form\"\n\t\tdata-testid=\"cn-settings-form\"\n\t\tnovalidate\n\t\t@submit.prevent=\"save\">\n\t\t<div class=\"cn-settings-form__grid\" :class=\"`cn-settings-form__grid--${columns}`\">\n\t\t\t<div\n\t\t\t\tv-for=\"field in fields\"\n\t\t\t\t:key=\"field.key\"\n\t\t\t\tclass=\"cn-settings-form__field\"\n\t\t\t\t:class=\"{ 'cn-settings-form__field--wide': field.wide }\"\n\t\t\t\t:data-testid=\"`cn-settings-form-field-${field.key}`\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\tv-if=\"field.type === 'switch'\"\n\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t{{ field.label }}\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<CnChipsFieldWidget\n\t\t\t\t\tv-else-if=\"field.type === 'chips'\"\n\t\t\t\t\t:modelValue=\"form[field.key]\"\n\t\t\t\t\t:content=\"chipsContent(field)\"\n\t\t\t\t\t@update:modelValue=\"form[field.key] = $event\" />\n\t\t\t\t<template v-else>\n\t\t\t\t\t<label class=\"cn-settings-form__label\" :for=\"inputId(field)\">{{ field.label }}</label>\n\t\t\t\t\t<div v-if=\"field.type === 'file'\" class=\"cn-settings-form__file\" :data-testid=\"`cn-settings-form-file-${field.key}`\">\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--file\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-settings-form__control--placeholder': !form[field.key] }\">\n\t\t\t\t\t\t\t{{ form[field.key] ? fileName(form[field.key]) : field.placeholder }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly\"\n\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t:aria-describedby=\"inputId(field)\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-choose-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"chooseFile(field)\">\n\t\t\t\t\t\t\t{{ field.chooseLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"!field.readOnly && form[field.key]\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-clear-${field.key}`\"\n\t\t\t\t\t\t\t@click=\"form[field.key] = ''\">\n\t\t\t\t\t\t\t{{ field.clearLabel }}\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div v-else-if=\"field.type === 'reference'\" class=\"cn-settings-form__reference\">\n\t\t\t\t\t\t<select\n\t\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t\t:disabled=\"field.readOnly\"\n\t\t\t\t\t\t\t:aria-busy=\"referenceState[field.key] === 'loading' ? 'true' : null\"\n\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-reference-${field.key}`\">\n\t\t\t\t\t\t\t<option v-for=\"option in referenceChoices(field)\" :key=\"option.value\" :value=\"option.value\">\n\t\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t\t</option>\n\t\t\t\t\t\t</select>\n\t\t\t\t\t\t<!-- `free`: a typed value (a URL) besides picking an object. -->\n\t\t\t\t\t\t<template v-if=\"field.free && !field.readOnly\">\n\t\t\t\t\t\t\t<label class=\"cn-settings-form__sublabel\" :for=\"`${inputId(field)}-free`\">{{ field.freeLabel }}</label>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t:id=\"`${inputId(field)}-free`\"\n\t\t\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t\t\ttype=\"text\"\n\t\t\t\t\t\t\t\tinputmode=\"url\"\n\t\t\t\t\t\t\t\t:value=\"freeValue(field)\"\n\t\t\t\t\t\t\t\t:placeholder=\"field.freePlaceholder\"\n\t\t\t\t\t\t\t\t:aria-invalid=\"errors[field.key] ? 'true' : null\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-settings-form-reference-free-${field.key}`\"\n\t\t\t\t\t\t\t\t@input=\"form[field.key] = $event.target.value.trim()\">\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</div>\n\t\t\t\t\t<select\n\t\t\t\t\t\tv-else-if=\"field.type === 'select'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:disabled=\"field.readOnly\">\n\t\t\t\t\t\t<option v-for=\"option in field.options\" :key=\"String(option.value)\" :value=\"option.value\">\n\t\t\t\t\t\t\t{{ option.label }}\n\t\t\t\t\t\t</option>\n\t\t\t\t\t</select>\n\t\t\t\t\t<textarea\n\t\t\t\t\t\tv-else-if=\"field.type === 'textarea'\"\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control cn-settings-form__control--area\"\n\t\t\t\t\t\t:rows=\"field.rows\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\" />\n\t\t\t\t\t<input\n\t\t\t\t\t\tv-else\n\t\t\t\t\t\t:id=\"inputId(field)\"\n\t\t\t\t\t\tv-model=\"form[field.key]\"\n\t\t\t\t\t\tclass=\"cn-settings-form__control\"\n\t\t\t\t\t\t:type=\"field.type === 'number' ? 'number' : 'text'\"\n\t\t\t\t\t\t:min=\"field.min\"\n\t\t\t\t\t\t:max=\"field.max\"\n\t\t\t\t\t\t:placeholder=\"field.placeholder\"\n\t\t\t\t\t\t:readonly=\"field.readOnly\"\n\t\t\t\t\t\t:aria-invalid=\"errors[field.key] ? 'true' : null\">\n\t\t\t\t</template>\n\t\t\t\t<p v-if=\"errors[field.key]\" class=\"cn-settings-form__error\" role=\"alert\">\n\t\t\t\t\t{{ errors[field.key] }}\n\t\t\t\t</p>\n\t\t\t\t<!-- A chips field prints its own hint (it gets it in chipsContent). -->\n\t\t\t\t<p v-else-if=\"field.hint && field.type !== 'chips'\" class=\"cn-settings-form__hint\">\n\t\t\t\t\t{{ field.hint }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<NcNoteCard v-if=\"notice\" :type=\"noticeType\" data-testid=\"cn-settings-form-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\n\t\t<div v-if=\"!readOnly\" class=\"cn-settings-form__actions\">\n\t\t\t<NcButton\n\t\t\t\tvariant=\"primary\"\n\t\t\t\ttype=\"submit\"\n\t\t\t\t:disabled=\"saving\"\n\t\t\t\tdata-testid=\"cn-settings-form-save\">\n\t\t\t\t{{ saveLabel }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</form>\n</template>\n\n<script>\nimport { FilePickerClosed, getFilePickerBuilder } from '@nextcloud/dialogs'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport CnChipsFieldWidget from '../CnChipsFieldWidget/CnChipsFieldWidget.vue'\nimport { pickRefLabel } from '../../composables/useRefLabels.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { changedFields, objectUrlOf, writeFields } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { hasUnresolvedTokens, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\nimport { switchIsOn, switchStoredValue } from '../../utils/switchValues.js'\n\n// The native file-picker modal ships its chrome styles here; without this the\n// spawned picker renders unstyled. Rules are scoped to the picker/dialog classes.\nimport '@nextcloud/dialogs/style.css'\n\nconst TYPES = ['text', 'textarea', 'select', 'switch', 'number', 'file', 'chips', 'reference']\n\nlet uid = 0\n\n/**\n * CnSettingsFormWidget — the `settings-form` widget: fields of the CURRENT\n * object as a one- or two-column grid of framed inputs with light labels and\n * hints, saved by ONE PATCH of the fields that changed since the last save.\n *\n * \"Last save\" is the baseline this widget keeps: a save moves it forward, so\n * editing a field back to the value the page loaded with, after a save, still\n * counts as a change (comparing against the loaded object skipped that PATCH).\n *\n * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md\n */\nexport default {\n\tname: 'CnSettingsFormWidget',\n\n\tcomponents: { CnChipsFieldWidget, NcButton, NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `fields` (required) — `[{ key, label, type?: 'text'|'textarea'|'select'|'switch'|'number'|'file'|'chips'|'reference', register?, schema?, labelField?, valueTemplate?, filter?, limit?, emptyLabel?, free?, freeLabel?, freePlaceholder?, freePattern?, freePatternMessage?, default?, minItems?, required?, minItemsMessage?, values?: { on, off }, lowercase?, addLabel?, confirmLabel?, removeLabel?, picker?: { title?, mimeTypes?, startAt?, valueTemplate? }, chooseLabel?, clearLabel?, hint?, placeholder?, options?: [{ value, label }], required?, pattern?, patternMessage?, min?, max?, rows?, wide?, readOnly? }]`; `key` is a field of the object, a top-level name or a dot-path. A `reference` field's `filter` values may be `@objectId` and `@object.<field>` (the record being edited). A `switch` field's `values: { on, off }` reads and writes those values instead of true/false.\n\t\t * - `save` — `{ url, method?, payload? }`, write through an app endpoint (tokens `{value}`, `{field}`, `{changes}`, `{object.<path>}`).\n\t\t * - `columns` — 1 or 2 (default 2).\n\t\t * - `saveLabel`, `savedText`, `readOnly`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\tuid += 1\n\t\treturn {\n\t\t\tuid,\n\t\t\tform: {},\n\t\t\tbaseline: {},\n\t\t\tloaded: {},\n\t\t\t// `reference` fields: the objects to choose from and the read's state (`loading`, `ready`, `error`), by field key.\n\t\t\treferenceOptions: {},\n\t\t\treferenceState: {},\n\t\t\t// The query each `reference` field was last read with, by field key, so a\n\t\t\t// new object re-reads only the fields whose filter changes with it.\n\t\t\treferenceQuery: {},\n\t\t\terrors: {},\n\t\t\tsaving: false,\n\t\t\tnotice: '',\n\t\t\tnoticeType: 'success',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The configured fields, normalised and translated.\n\t\t *\n\t\t * @return {Array<object>}\n\t\t */\n\t\tfields() {\n\t\t\tconst list = Array.isArray(this.content.fields) ? this.content.fields : []\n\t\t\treturn list\n\t\t\t\t.filter((field) => field && field.key)\n\t\t\t\t.map((field) => ({\n\t\t\t\t\t...field,\n\t\t\t\t\ttype: TYPES.includes(field.type) ? field.type : 'text',\n\t\t\t\t\tlabel: this.tr(field.label || field.key),\n\t\t\t\t\thint: this.tr(field.hint || ''),\n\t\t\t\t\tplaceholder: this.tr(field.placeholder || ''),\n\t\t\t\t\tchooseLabel: this.tr(field.chooseLabel || 'Choose a file'),\n\t\t\t\t\tfree: field.type === 'reference' && field.free === true,\n\t\t\t\t\tfreeLabel: this.tr(field.freeLabel || 'Or type a value'),\n\t\t\t\t\tfreePlaceholder: this.tr(field.freePlaceholder || ''),\n\t\t\t\t\tclearLabel: this.tr(field.clearLabel || 'Remove'),\n\t\t\t\t\trows: field.rows || 3,\n\t\t\t\t\twide: field.wide === true || field.type === 'textarea',\n\t\t\t\t\treadOnly: this.readOnly || field.readOnly === true,\n\t\t\t\t\toptions: (Array.isArray(field.options) ? field.options : []).map((option) => (\n\t\t\t\t\t\ttypeof option === 'object' && option !== null\n\t\t\t\t\t\t\t? { value: option.value, label: this.tr(String(option.label ?? option.value)) }\n\t\t\t\t\t\t\t: { value: option, label: this.tr(String(option)) }\n\t\t\t\t\t)),\n\t\t\t\t}))\n\t\t},\n\n\t\tcolumns() {\n\t\t\treturn this.content.columns === 1 ? 1 : 2\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tsaveLabel() {\n\t\t\treturn this.tr(this.content.saveLabel || 'Save')\n\t\t},\n\n\t\t/** The object URL the form is saved to, or '' when it is not known. */\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.adopt()\n\t\t\tthis.loadReferences()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.adopt(true)\n\t\tthis.loadReferences()\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Read the objects each `reference` field chooses from: one list read\n\t\t * per field of its `register` and `schema` (`filter` as query\n\t\t * parameters, at most `limit`, 100 by default). A failed read leaves the\n\t\t * field with its stored value only, and says so in the hint's place.\n\t\t *\n\t\t * `filter` values may be `@objectId` and `@object.<field>`: the record\n\t\t * the form edits, so a list can be narrowed to it (the logos of this\n\t\t * portal). Until the record has that value the field is not read; it is\n\t\t * read again when the record changes the resolved query, never twice\n\t\t * for the same query.\n\t\t *\n\t\t * @spec openspec/changes/screens-settings-form-reference/specs/settings-form/spec.md#requirement-a-settings-form-field-can-pick-an-object\n\t\t * @spec openspec/changes/screens-settings-form-reference-object-filter/specs/settings-form/spec.md#requirement-a-reference-fields-filter-can-name-the-record-being-edited\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadReferences() {\n\t\t\tconst fields = this.fields.filter((field) => field.type === 'reference' && typeof field.register === 'string' && field.register !== '' && typeof field.schema === 'string' && field.schema !== '')\n\t\t\tif (fields.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst ctx = { objectId: this.objectId || (this.objectData && this.objectData.id) || undefined, object: this.objectData || undefined }\n\t\t\tconst pending = []\n\t\t\tfor (const field of fields) {\n\t\t\t\tconst filter = resolveFilterTokens(field.filter && typeof field.filter === 'object' ? field.filter : {}, ctx)\n\t\t\t\tif (hasUnresolvedTokens(filter)) {\n\t\t\t\t\t// The record has no value for the token yet: nothing to read.\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst params = { ...filter, _limit: Number(field.limit) > 0 ? Number(field.limit) : 100 }\n\t\t\t\tconst query = JSON.stringify(params)\n\t\t\t\tif (this.referenceQuery[field.key] === query) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tthis.referenceQuery = { ...this.referenceQuery, [field.key]: query }\n\t\t\t\tpending.push({ field, params, query })\n\t\t\t}\n\t\t\tif (pending.length === 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\tawait Promise.all(pending.map(async ({ field, params, query }) => {\n\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'loading' }\n\t\t\t\ttry {\n\t\t\t\t\tconst url = `/apps/openregister/api/objects/${encodeURIComponent(field.register)}/${encodeURIComponent(field.schema)}`\n\t\t\t\t\tconst { data } = await axios.get(prefixUrl(url), { params })\n\t\t\t\t\tif (this.referenceQuery[field.key] !== query) {\n\t\t\t\t\t\t// A newer record asked for another list meanwhile.\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tconst rows = Array.isArray(data) ? data : (Array.isArray(data?.results) ? data.results : [])\n\t\t\t\t\tconst options = []\n\t\t\t\t\tfor (const row of rows) {\n\t\t\t\t\t\tconst id = row && (row.id ?? row.uuid ?? (row['@self'] && row['@self'].id))\n\t\t\t\t\t\tif (id === undefined || id === null || id === '') {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst scope = { ...row, id, register: field.register, schema: field.schema }\n\t\t\t\t\t\tconst value = fillTemplate(typeof field.valueTemplate === 'string' && field.valueTemplate !== '' ? field.valueTemplate : '{id}', scope)\n\t\t\t\t\t\tif (value !== '') {\n\t\t\t\t\t\t\toptions.push({ value, label: pickRefLabel(row, field.labelField) || String(id) })\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [field.key]: options }\n\t\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'ready' }\n\t\t\t\t} catch {\n\t\t\t\t\tthis.referenceOptions = { ...this.referenceOptions, [field.key]: [] }\n\t\t\t\t\tthis.referenceState = { ...this.referenceState, [field.key]: 'error' }\n\t\t\t\t\tthis.errors = { ...this.errors, [field.key]: this.tr('The list to choose from could not be loaded.') }\n\t\t\t\t}\n\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * The choices of a `reference` field: \"none\" (unless required), the\n\t\t * objects read, and the value the form holds when it is not one of\n\t\t * them (a free string such as a URL stays selectable, as it is stored).\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {Array<{value: string, label: string}>}\n\t\t */\n\t\treferenceChoices(field) {\n\t\t\tconst options = this.referenceOptions[field.key] || []\n\t\t\tconst current = this.form[field.key]\n\t\t\tconst choices = field.required ? [] : [{ value: '', label: this.tr(field.emptyLabel || 'None') }]\n\t\t\tif (typeof current === 'string' && current !== '' && !options.some((option) => option.value === current)) {\n\t\t\t\tchoices.push({ value: current, label: current })\n\t\t\t}\n\t\t\treturn [...choices, ...options]\n\t\t},\n\n\t\t/**\n\t\t * The typed value of a `reference` field with `free`: the value the form\n\t\t * holds when it is not one of the objects to pick, else empty (picking\n\t\t * an object clears the typed value).\n\t\t *\n\t\t * @spec openspec/changes/screens-settings-form-reference-free-value/specs/settings-form/spec.md#requirement-a-reference-field-can-also-take-a-typed-value\n\t\t * @param {object} field The field.\n\t\t * @return {string}\n\t\t */\n\t\tfreeValue(field) {\n\t\t\tconst current = this.form[field.key]\n\t\t\tif (typeof current !== 'string' || current === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst options = this.referenceOptions[field.key] || []\n\t\t\treturn options.some((option) => option.value === current) ? '' : current\n\t\t},\n\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\tinputId(field) {\n\t\t\treturn `cn-settings-form-${this.uid}-${field.key}`\n\t\t},\n\n\t\t/**\n\t\t * The name shown for a stored file value: its last path segment.\n\t\t *\n\t\t * @param {string} value The stored value.\n\t\t * @return {string}\n\t\t */\n\t\tfileName(value) {\n\t\t\tconst text = String(value)\n\t\t\treturn text.split('/').filter(Boolean).pop() || text\n\t\t},\n\n\t\t/**\n\t\t * Open the Nextcloud file picker and take the chosen file as the value.\n\t\t * `field.picker` = `{ title?, mimeTypes?, startAt?, valueTemplate? }`; the\n\t\t * template's `{path}`, `{fileid}` and `{name}` are filled from the chosen\n\t\t * node (default `{path}`).\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form-file/specs/settings-form/spec.md#requirement-a-file-field-takes-a-file-from-the-nextcloud-picker\n\t\t */\n\t\tasync chooseFile(field) {\n\t\t\tconst picker = field.picker || {}\n\t\t\tlet builder = getFilePickerBuilder(this.tr(picker.title || field.label))\n\t\t\t\t.setMultiSelect(false)\n\t\t\t\t.allowDirectories(false)\n\t\t\t\t.startAt(picker.startAt || '/')\n\t\t\t\t.addButton({ label: t('nextcloud-vue', 'Choose'), type: 'primary', callback: () => {} })\n\t\t\tif (Array.isArray(picker.mimeTypes) && picker.mimeTypes.length > 0) {\n\t\t\t\tbuilder = builder.setMimeTypeFilter(picker.mimeTypes)\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst nodes = await builder.build().pickNodes()\n\t\t\t\tconst node = Array.isArray(nodes) ? nodes[0] : nodes\n\t\t\t\tif (!node) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.form[field.key] = String(picker.valueTemplate || '{path}').replace(/\\{(path|fileid|name)\\}/g, (match, part) => {\n\t\t\t\t\tconst value = part === 'name' ? (node.basename || this.fileName(node.path)) : node[part]\n\t\t\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof FilePickerClosed) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('The file picker could not be opened.')\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The stored value of a field as the input holds it.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tstored(field) {\n\t\t\tconst value = readPath(this.objectData || {}, field.key)\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn switchIsOn(value, field.values)\n\t\t\t}\n\t\t\tif (field.type === 'chips') {\n\t\t\t\treturn Array.isArray(value) ? value.map((item) => String(item)) : []\n\t\t\t}\n\t\t\treturn value === undefined || value === null ? '' : value\n\t\t},\n\n\t\t/**\n\t\t * The value the input shows for a field: the stored one, else the field's\n\t\t * `default` when nothing is stored. The baseline stays the stored value, so\n\t\t * a default that was never saved counts as a change and the next Save writes it.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\tshown(field) {\n\t\t\tconst value = this.stored(field)\n\t\t\tconst absent = readPath(this.objectData || {}, field.key) === undefined || readPath(this.objectData || {}, field.key) === null || value === '' || (field.type === 'chips' && value.length === 0)\n\t\t\tif (absent && field.default !== undefined) {\n\t\t\t\treturn field.type === 'chips' && Array.isArray(field.default) ? [...field.default] : field.default\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * Take the object's values as the new baseline; a field the person has\n\t\t * not touched follows it, a touched one keeps the typed value.\n\t\t *\n\t\t * @param {boolean} [first] Whether this is the first read.\n\t\t */\n\t\tadopt(first = false) {\n\t\t\tconst baseline = {}\n\t\t\tconst loaded = {}\n\t\t\tconst form = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tbaseline[field.key] = this.stored(field)\n\t\t\t\tloaded[field.key] = this.shown(field)\n\t\t\t\tconst untouched = first || JSON.stringify(this.form[field.key]) === JSON.stringify(this.loaded[field.key])\n\t\t\t\tform[field.key] = untouched ? loaded[field.key] : this.form[field.key]\n\t\t\t}\n\t\t\tthis.baseline = baseline\n\t\t\tthis.loaded = loaded\n\t\t\tthis.form = form\n\t\t},\n\n\t\t/**\n\t\t * The configuration of the embedded chips widget for a `chips` field.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {object}\n\t\t */\n\t\tchipsContent(field) {\n\t\t\treturn {\n\t\t\t\tlabel: field.label,\n\t\t\t\thint: field.hint,\n\t\t\t\tplaceholder: field.placeholder,\n\t\t\t\taddLabel: field.addLabel,\n\t\t\t\tconfirmLabel: field.confirmLabel,\n\t\t\t\tremoveLabel: field.removeLabel,\n\t\t\t\tpattern: field.pattern,\n\t\t\t\tpatternMessage: field.patternMessage,\n\t\t\t\tlowercase: field.lowercase,\n\t\t\t\toptions: field.options,\n\t\t\t\tminItems: field.minItems,\n\t\t\t\trequired: field.required,\n\t\t\t\tminItemsMessage: field.minItemsMessage,\n\t\t\t\treadOnly: field.readOnly,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The value to send for a field: numbers as numbers, an empty value as null.\n\t\t *\n\t\t * @param {object} field The field.\n\t\t * @return {unknown}\n\t\t */\n\t\toutgoing(field) {\n\t\t\tconst value = this.form[field.key]\n\t\t\tif (field.type === 'number') {\n\t\t\t\treturn value === '' || value === null || value === undefined ? null : Number(value)\n\t\t\t}\n\t\t\tif (field.type === 'switch') {\n\t\t\t\treturn value === true\n\t\t\t}\n\t\t\tif (field.type === 'chips') {\n\t\t\t\treturn Array.isArray(value) ? [...value] : []\n\t\t\t}\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn value.trim() === '' ? null : value.trim()\n\t\t\t}\n\t\t\treturn value\n\t\t},\n\n\t\t/**\n\t\t * Check required, number range and pattern before any write.\n\t\t *\n\t\t * @return {object} Error text by field key.\n\t\t */\n\t\tvalidate() {\n\t\t\tconst errors = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.type === 'switch' || field.readOnly) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst value = this.outgoing(field)\n\t\t\t\tif (field.type === 'chips') {\n\t\t\t\t\tconst least = Number(field.minItems) > 0 ? Number(field.minItems) : (field.required ? 1 : 0)\n\t\t\t\t\tif (value.length < least) {\n\t\t\t\t\t\terrors[field.key] = this.tr(field.minItemsMessage || 'Keep at least {count}.').replace('{count}', String(least))\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst empty = value === null || value === undefined || value === ''\n\t\t\t\tif (empty) {\n\t\t\t\t\tif (field.required) {\n\t\t\t\t\t\terrors[field.key] = this.tr('Fill this in.')\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (field.type === 'number') {\n\t\t\t\t\tif (Number.isNaN(value) || (field.min !== undefined && value < field.min) || (field.max !== undefined && value > field.max)) {\n\t\t\t\t\t\terrors[field.key] = this.tr('This number is not valid.')\n\t\t\t\t\t}\n\t\t\t\t} else if (field.free && field.freePattern && this.freeValue(field) !== '' && !new RegExp(field.freePattern).test(String(value))) {\n\t\t\t\t\t// A typed value (not one of the objects) answers to `freePattern`.\n\t\t\t\t\terrors[field.key] = this.tr(field.freePatternMessage || 'This value is not valid.')\n\t\t\t\t} else if (field.pattern && !new RegExp(field.pattern).test(String(value))) {\n\t\t\t\t\terrors[field.key] = this.tr(field.patternMessage || 'This value is not valid.')\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn errors\n\t\t},\n\n\t\t/**\n\t\t * Save: PATCH the fields that differ from the last saved values.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-settings-form/specs/settings-form/spec.md#requirement-a-settings-form-saves-only-what-changed\n\t\t */\n\t\tasync save() {\n\t\t\tthis.errors = this.validate()\n\t\t\tthis.notice = ''\n\t\t\tif (Object.keys(this.errors).length > 0) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!this.objectUrl && !(this.content.save && this.content.save.url)) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = this.tr('This form cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst next = {}\n\t\t\tconst compare = {}\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (!field.readOnly) {\n\t\t\t\t\tnext[field.key] = this.outgoing(field)\n\t\t\t\t\tcompare[field.key] = this.baseline[field.key] === '' ? null : this.baseline[field.key]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst patch = changedFields(compare, next)\n\t\t\t// A switch with a value map (`values: { on, off }`) writes those values.\n\t\t\tfor (const field of this.fields) {\n\t\t\t\tif (field.type === 'switch' && Object.hasOwn(patch, field.key)) {\n\t\t\t\t\tpatch[field.key] = switchStoredValue(patch[field.key], field.values)\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.saving = true\n\t\t\ttry {\n\t\t\t\tif (Object.keys(patch).length > 0) {\n\t\t\t\t\tconst data = await writeFields(this.objectUrl, patch, { save: this.content.save, object: this.objectData })\n\t\t\t\t\tconst baseline = { ...this.baseline }\n\t\t\t\t\tconst loaded = { ...this.loaded }\n\t\t\t\t\tconst form = { ...this.form }\n\t\t\t\t\tfor (const key of Object.keys(patch)) {\n\t\t\t\t\t\tconst field = this.fields.find((candidate) => candidate.key === key)\n\t\t\t\t\t\tconst answered = readPath(data, key)\n\t\t\t\t\t\tconst written = answered !== undefined ? answered : patch[key]\n\t\t\t\t\t\tbaseline[key] = field.type === 'switch' ? switchIsOn(written, field.values) : (written === null ? (field.type === 'chips' ? [] : '') : written)\n\t\t\t\t\t\tform[key] = baseline[key]\n\t\t\t\t\t\tloaded[key] = baseline[key]\n\t\t\t\t\t}\n\t\t\t\t\tthis.baseline = baseline\n\t\t\t\t\tthis.loaded = loaded\n\t\t\t\t\tthis.form = form\n\t\t\t\t}\n\t\t\t\tthis.noticeType = 'success'\n\t\t\t\tthis.notice = this.tr(this.content.savedText || 'Saved.')\n\t\t\t\t/**\n\t\t\t\t * @event saved The changed fields were written.\n\t\t\t\t * @type {{patch: object}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { patch })\n\t\t\t} catch (e) {\n\t\t\t\tthis.noticeType = 'error'\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t} finally {\n\t\t\t\tthis.saving = false\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-settings-form {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 14px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__grid {\n\tdisplay: grid;\n\tgap: 14px 16px;\n\tgrid-template-columns: minmax(0, 1fr);\n}\n\n.cn-settings-form__grid--2 {\n\tgrid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.cn-settings-form__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 4px;\n\tmin-width: 0;\n}\n\n.cn-settings-form__field--wide {\n\tgrid-column: 1 / -1;\n}\n\n.cn-settings-form__label {\n\tfont-size: 13px;\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-settings-form__reference {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-settings-form__sublabel {\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__control {\n\twidth: 100%;\n\tbox-sizing: border-box;\n\theight: var(--cn-board-control-height, 40px);\n\tpadding: 0 12px;\n\tborder: 1px solid var(--color-border-maxcontrast);\n\tborder-radius: var(--cn-board-control-radius, 8px);\n\tbackground: var(--color-main-background);\n\tcolor: var(--color-main-text);\n\tfont: inherit;\n}\n\n.cn-settings-form__file {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-settings-form__control--file {\n\tdisplay: inline-flex;\n\talign-items: center;\n\twidth: auto;\n\tmin-width: 120px;\n\tflex: 0 1 auto;\n\toverflow-wrap: anywhere;\n}\n\n.cn-settings-form__control--placeholder {\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__control--area {\n\theight: auto;\n\tpadding: 10px 12px;\n\tresize: vertical;\n}\n\n.cn-settings-form__control:focus-visible {\n\toutline: 2px solid var(--color-primary-element);\n\toutline-offset: 1px;\n}\n\n.cn-settings-form__hint,\n.cn-settings-form__error {\n\tmargin: 0;\n\tfont-size: 12px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-settings-form__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-settings-form__actions {\n\tdisplay: flex;\n\tjustify-content: flex-start;\n}\n\n@media (max-width: 640px) {\n\t.cn-settings-form__grid--2 {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t}\n}\n</style>\n"],"names":["CnChipsFieldWidget","t"],"mappings":"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"}
|
|
@@ -4,22 +4,28 @@ const _hoisted_1 = ["data-testid"];
|
|
|
4
4
|
const _hoisted_2 = ["for"];
|
|
5
5
|
const _hoisted_3 = ["data-testid"];
|
|
6
6
|
const _hoisted_4 = ["id"];
|
|
7
|
-
const _hoisted_5 =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
7
|
+
const _hoisted_5 = {
|
|
8
|
+
key: 1,
|
|
9
|
+
class: "cn-settings-form__reference"
|
|
10
|
+
};
|
|
11
|
+
const _hoisted_6 = ["id", "onUpdate:modelValue", "disabled", "aria-busy", "data-testid"];
|
|
12
|
+
const _hoisted_7 = ["value"];
|
|
13
|
+
const _hoisted_8 = ["for"];
|
|
14
|
+
const _hoisted_9 = ["id", "value", "placeholder", "aria-invalid", "data-testid", "onInput"];
|
|
15
|
+
const _hoisted_10 = ["id", "onUpdate:modelValue", "disabled"];
|
|
16
|
+
const _hoisted_11 = ["value"];
|
|
17
|
+
const _hoisted_12 = ["id", "onUpdate:modelValue", "rows", "placeholder", "readonly"];
|
|
18
|
+
const _hoisted_13 = ["id", "onUpdate:modelValue", "type", "min", "max", "placeholder", "readonly", "aria-invalid"];
|
|
19
|
+
const _hoisted_14 = {
|
|
14
20
|
key: 3,
|
|
15
21
|
class: "cn-settings-form__error",
|
|
16
22
|
role: "alert"
|
|
17
23
|
};
|
|
18
|
-
const
|
|
24
|
+
const _hoisted_15 = {
|
|
19
25
|
key: 4,
|
|
20
26
|
class: "cn-settings-form__hint"
|
|
21
27
|
};
|
|
22
|
-
const
|
|
28
|
+
const _hoisted_16 = {
|
|
23
29
|
key: 1,
|
|
24
30
|
class: "cn-settings-form__actions"
|
|
25
31
|
};
|
|
@@ -109,24 +115,44 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
109
115
|
: createCommentVNode("v-if", true)
|
|
110
116
|
], 8 /* PROPS */, _hoisted_3))
|
|
111
117
|
: (field.type === 'reference')
|
|
112
|
-
?
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
118
|
+
? (openBlock(), createElementBlock("div", _hoisted_5, [
|
|
119
|
+
withDirectives(createElementVNode("select", {
|
|
120
|
+
id: $options.inputId(field),
|
|
121
|
+
"onUpdate:modelValue": $event => (($data.form[field.key]) = $event),
|
|
122
|
+
class: "cn-settings-form__control",
|
|
123
|
+
disabled: field.readOnly,
|
|
124
|
+
"aria-busy": $data.referenceState[field.key] === 'loading' ? 'true' : null,
|
|
125
|
+
"data-testid": `cn-settings-form-reference-${field.key}`
|
|
126
|
+
}, [
|
|
127
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.referenceChoices(field), (option) => {
|
|
128
|
+
return (openBlock(), createElementBlock("option", {
|
|
129
|
+
key: option.value,
|
|
130
|
+
value: option.value
|
|
131
|
+
}, toDisplayString(option.label), 9 /* TEXT, PROPS */, _hoisted_7))
|
|
132
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
133
|
+
], 8 /* PROPS */, _hoisted_6), [
|
|
134
|
+
[vModelSelect, $data.form[field.key]]
|
|
135
|
+
]),
|
|
136
|
+
(field.free && !field.readOnly)
|
|
137
|
+
? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
|
|
138
|
+
createElementVNode("label", {
|
|
139
|
+
class: "cn-settings-form__sublabel",
|
|
140
|
+
for: `${$options.inputId(field)}-free`
|
|
141
|
+
}, toDisplayString(field.freeLabel), 9 /* TEXT, PROPS */, _hoisted_8),
|
|
142
|
+
createElementVNode("input", {
|
|
143
|
+
id: `${$options.inputId(field)}-free`,
|
|
144
|
+
class: "cn-settings-form__control",
|
|
145
|
+
type: "text",
|
|
146
|
+
inputmode: "url",
|
|
147
|
+
value: $options.freeValue(field),
|
|
148
|
+
placeholder: field.freePlaceholder,
|
|
149
|
+
"aria-invalid": $data.errors[field.key] ? 'true' : null,
|
|
150
|
+
"data-testid": `cn-settings-form-reference-free-${field.key}`,
|
|
151
|
+
onInput: $event => ($data.form[field.key] = $event.target.value.trim())
|
|
152
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_9)
|
|
153
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
154
|
+
: createCommentVNode("v-if", true)
|
|
155
|
+
]))
|
|
130
156
|
: (field.type === 'select')
|
|
131
157
|
? withDirectives((openBlock(), createElementBlock("select", {
|
|
132
158
|
key: 2,
|
|
@@ -139,9 +165,9 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
139
165
|
return (openBlock(), createElementBlock("option", {
|
|
140
166
|
key: String(option.value),
|
|
141
167
|
value: option.value
|
|
142
|
-
}, toDisplayString(option.label), 9 /* TEXT, PROPS */,
|
|
168
|
+
}, toDisplayString(option.label), 9 /* TEXT, PROPS */, _hoisted_11))
|
|
143
169
|
}), 128 /* KEYED_FRAGMENT */))
|
|
144
|
-
], 8 /* PROPS */,
|
|
170
|
+
], 8 /* PROPS */, _hoisted_10)), [
|
|
145
171
|
[vModelSelect, $data.form[field.key]]
|
|
146
172
|
])
|
|
147
173
|
: (field.type === 'textarea')
|
|
@@ -153,7 +179,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
153
179
|
rows: field.rows,
|
|
154
180
|
placeholder: field.placeholder,
|
|
155
181
|
readonly: field.readOnly
|
|
156
|
-
}, null, 8 /* PROPS */,
|
|
182
|
+
}, null, 8 /* PROPS */, _hoisted_12)), [
|
|
157
183
|
[vModelText, $data.form[field.key]]
|
|
158
184
|
])
|
|
159
185
|
: withDirectives((openBlock(), createElementBlock("input", {
|
|
@@ -167,14 +193,14 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
167
193
|
placeholder: field.placeholder,
|
|
168
194
|
readonly: field.readOnly,
|
|
169
195
|
"aria-invalid": $data.errors[field.key] ? 'true' : null
|
|
170
|
-
}, null, 8 /* PROPS */,
|
|
196
|
+
}, null, 8 /* PROPS */, _hoisted_13)), [
|
|
171
197
|
[vModelDynamic, $data.form[field.key]]
|
|
172
198
|
])
|
|
173
199
|
], 64 /* STABLE_FRAGMENT */)),
|
|
174
200
|
($data.errors[field.key])
|
|
175
|
-
? (openBlock(), createElementBlock("p",
|
|
176
|
-
: (field.hint)
|
|
177
|
-
? (openBlock(), createElementBlock("p",
|
|
201
|
+
? (openBlock(), createElementBlock("p", _hoisted_14, toDisplayString($data.errors[field.key]), 1 /* TEXT */))
|
|
202
|
+
: (field.hint && field.type !== 'chips')
|
|
203
|
+
? (openBlock(), createElementBlock("p", _hoisted_15, toDisplayString(field.hint), 1 /* TEXT */))
|
|
178
204
|
: createCommentVNode("v-if", true)
|
|
179
205
|
], 10 /* CLASS, PROPS */, _hoisted_1))
|
|
180
206
|
}), 128 /* KEYED_FRAGMENT */))
|
|
@@ -192,7 +218,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
192
218
|
}, 8 /* PROPS */, ["type"]))
|
|
193
219
|
: createCommentVNode("v-if", true),
|
|
194
220
|
(!$options.readOnly)
|
|
195
|
-
? (openBlock(), createElementBlock("div",
|
|
221
|
+
? (openBlock(), createElementBlock("div", _hoisted_16, [
|
|
196
222
|
createVNode(_component_NcButton, {
|
|
197
223
|
variant: "primary",
|
|
198
224
|
type: "submit",
|