@conduction/nextcloud-vue 2.133.0 → 2.134.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/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +85 -10
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +60 -36
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue.js +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue2.js +10 -0
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnIntegrationWidget/CnIntegrationWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js +202 -6
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js +137 -55
- package/dist/esm/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue3.js.map +1 -1
- package/dist/esm/dialogs/CnPartyAddDialog.vue.js +9 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue.js.map +1 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue2.js +184 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue2.js.map +1 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue3.js +168 -0
- package/dist/esm/dialogs/CnPartyAddDialog.vue3.js.map +1 -0
- package/dist/esm/l10n/en.json.js +11 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +11 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +95 -70
- package/dist/esm/utils/objectParties.js +79 -1
- package/dist/esm/utils/objectParties.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +5683 -4860
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +95 -70
- package/l10n/en.json +11 -1
- package/l10n/nl.json +11 -1
- package/package.json +1 -1
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +105 -12
- package/src/components/CnIntegrationWidget/CnIntegrationWidget.vue +10 -0
- package/src/components/CnObjectPartiesWidget/CnObjectPartiesWidget.vue +264 -3
- package/src/dialogs/CnPartyAddDialog.vue +309 -0
- package/src/utils/objectParties.js +78 -0
|
@@ -2,7 +2,7 @@ import script from './CnFieldListWidget.vue2.js';
|
|
|
2
2
|
import { render } from './CnFieldListWidget.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-91c65ff8";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -74,12 +74,12 @@ var script = {
|
|
|
74
74
|
* - `field` (required) — the object field holding the array.
|
|
75
75
|
* - `key` — the item field that identifies an entry (default: the item itself for strings).
|
|
76
76
|
* - `row` — `{ title, titleFallback?, avatar?, meta?: [paths|{ path, map?, format? }], pill?: { path, map?, variantMap? }, aside?: { path, format?, prefix?, fallback? }, detail?: { template, when?, copy?: [{ path, label }] } }`. `detail.copy` puts a copy button beside the detail line for each named value of the row (an empty value gets none), such as a DNS record's name and value.
|
|
77
|
-
* - `add` — `{ label?, fields: [{ key, label, type?: 'text'|'select', options?, required?, pattern?, patternMessage? }], unique?, defaults? }`.
|
|
77
|
+
* - `add` — `{ label?, fields: [{ key, label, type?: 'text'|'select'|'multiselect'|'checkbox', options?, optionsSource?, required?, pattern?, patternMessage? }], unique?, defaults? }`. A `multiselect` field holds a list of values. `optionsSource` — `{ url, path?, valuePath?, labelPath? }` (default `id` and `name`) — adds options read from an endpoint after the static ones, each value once (tokens `@objectId`, `@object.<field>`), for choices that live in other records such as a case type's statuses.
|
|
78
78
|
* - `remove` — `{ label? }`; omitted = no remove.
|
|
79
79
|
* - `rowActions` — `[{ id, label, ariaLabel?, when?, placement?: 'band'|'inline', request: { method?, url, payload? } }]`, or `{ id, label, dialog, props }` to open a modal registered in the app registry with filled props (shown in `readOnly` too, since it writes nothing, and only when every token in `props` fills); tokens `@object.<field>`, `@objectId`, `@row.<field>`, `@index`. In the table variant `placement: 'inline'` draws the action as a button in the row instead of in the "..." menu; `ariaLabel` is a template filled from the row.
|
|
80
80
|
* - `when` (row actions, `detail`) — `{ field: value }`, every field equal; or per field `{ eq?, neq?, set? }`, where a value `@row.<field>` (or `@<field>`) is another field of the same row: `{ deliveredRef: { set: true, neq: '@originalRef' } }`.
|
|
81
81
|
* - `rowSource` — `{ url, path?, key }`: live per-row state merged by key.
|
|
82
|
-
* - `variant: 'table'` + `columns` — `[{ header, path, map?, format?, strong?, pill?, variantMap? }]
|
|
82
|
+
* - `variant: 'table'` + `columns` — `[{ header, path, map?, format?, strong?, pill?, variantMap?, labelsFrom? }]` (a list value reads as its items joined; `labelsFrom` names an add field whose option labels word the values): rows as a table; a per-row "..." menu holds the row actions and remove; `detail` lines become a warning band under the table, with the row actions that have `placement: 'band'`.
|
|
83
83
|
* - `add.trigger: 'button'`, `add.placement: 'header' | 'title' | 'footer'` — the add form opens from a button; `title` reports the button for the card's title row on the `header` event.
|
|
84
84
|
* - `readOnly`, `hint`, `emptyText`.
|
|
85
85
|
* - `row.href` — the path of a link for the row title; only http(s) and root-relative links, an absolute one opens in a new tab.
|
|
@@ -140,6 +140,8 @@ var script = {
|
|
|
140
140
|
noticeType: 'error',
|
|
141
141
|
// What the last copy button put on the clipboard, said to a screen reader.
|
|
142
142
|
copied: '',
|
|
143
|
+
/** Options read through each add field's `optionsSource`, by field key. */
|
|
144
|
+
sourcedOptions: {},
|
|
143
145
|
}
|
|
144
146
|
},
|
|
145
147
|
|
|
@@ -237,9 +239,12 @@ var script = {
|
|
|
237
239
|
.map((field) => ({
|
|
238
240
|
...field,
|
|
239
241
|
label: this.tr(field.label || field.key),
|
|
240
|
-
options:
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
options: [
|
|
243
|
+
...(Array.isArray(field.options) ? field.options : []).map((option) => (
|
|
244
|
+
typeof option === 'object' ? { value: option.value, label: this.tr(option.label || String(option.value)) } : { value: option, label: this.tr(String(option)) }
|
|
245
|
+
)),
|
|
246
|
+
...(this.sourcedOptions[field.key] || []),
|
|
247
|
+
],
|
|
243
248
|
}))
|
|
244
249
|
},
|
|
245
250
|
|
|
@@ -361,12 +366,14 @@ var script = {
|
|
|
361
366
|
objectData() {
|
|
362
367
|
this.saved = null;
|
|
363
368
|
this.loadLive();
|
|
369
|
+
this.loadOptions();
|
|
364
370
|
},
|
|
365
371
|
},
|
|
366
372
|
|
|
367
373
|
created() {
|
|
368
374
|
this.resetDraft();
|
|
369
375
|
this.loadLive();
|
|
376
|
+
this.loadOptions();
|
|
370
377
|
},
|
|
371
378
|
|
|
372
379
|
methods: {
|
|
@@ -455,12 +462,77 @@ var script = {
|
|
|
455
462
|
}
|
|
456
463
|
return def.format === 'date-long' ? formatBoardDate(date, new Date(date.getFullYear() + 1, 0, 1)) : formatBoardDate(date)
|
|
457
464
|
}
|
|
465
|
+
if (Array.isArray(raw)) {
|
|
466
|
+
return raw.map((item) => this.wordOf(item, def)).filter((word) => word !== '').join(', ')
|
|
467
|
+
}
|
|
468
|
+
return this.wordOf(raw, def)
|
|
469
|
+
},
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* One value in words: through the column's `map`, then the option labels
|
|
473
|
+
* of the add field it names in `labelsFrom`, else the value itself.
|
|
474
|
+
*
|
|
475
|
+
* @param {string|number|boolean|object} raw The value.
|
|
476
|
+
* @param {object} def The column.
|
|
477
|
+
* @return {string}
|
|
478
|
+
*/
|
|
479
|
+
wordOf(raw, def) {
|
|
458
480
|
if (def.map && Object.hasOwn(def.map, String(raw))) {
|
|
459
481
|
return this.tr(def.map[String(raw)])
|
|
460
482
|
}
|
|
483
|
+
if (def.labelsFrom) {
|
|
484
|
+
const field = this.addFields.find((candidate) => candidate.key === def.labelsFrom);
|
|
485
|
+
const option = field && field.options.find((candidate) => String(candidate.value) === String(raw));
|
|
486
|
+
if (option) {
|
|
487
|
+
return option.label
|
|
488
|
+
}
|
|
489
|
+
}
|
|
461
490
|
return typeof raw === 'object' ? '' : String(raw)
|
|
462
491
|
},
|
|
463
492
|
|
|
493
|
+
/**
|
|
494
|
+
* The empty value of an add field: false for a checkbox, a list for a multiselect.
|
|
495
|
+
*
|
|
496
|
+
* @param {object} field The add field.
|
|
497
|
+
* @return {boolean|Array|string}
|
|
498
|
+
*/
|
|
499
|
+
emptyValue(field) {
|
|
500
|
+
if (field.type === 'checkbox') {
|
|
501
|
+
return false
|
|
502
|
+
}
|
|
503
|
+
return field.type === 'multiselect' ? [] : ''
|
|
504
|
+
},
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Read the options of every add field that names an `optionsSource`.
|
|
508
|
+
*
|
|
509
|
+
* A source that cannot be read leaves the static options alone.
|
|
510
|
+
*
|
|
511
|
+
* @return {Promise<void>}
|
|
512
|
+
*/
|
|
513
|
+
async loadOptions() {
|
|
514
|
+
const fields = this.content.add && Array.isArray(this.content.add.fields) ? this.content.add.fields : [];
|
|
515
|
+
for (const field of fields) {
|
|
516
|
+
const source = field && field.optionsSource;
|
|
517
|
+
if (!source || !source.url || !field.key) {
|
|
518
|
+
continue
|
|
519
|
+
}
|
|
520
|
+
try {
|
|
521
|
+
const { axios } = await this.http();
|
|
522
|
+
const response = await axios.get(prefixUrl(this.resolve(source.url, {})));
|
|
523
|
+
const list = source.path ? readPath(response && response.data, source.path) : response && response.data;
|
|
524
|
+
const options = (Array.isArray(list) ? list : [])
|
|
525
|
+
.map((item) => ({ value: readPath(item, source.valuePath || 'id'), label: String(readPath(item, source.labelPath || 'name') ?? '') }))
|
|
526
|
+
.filter((option, index, all) => option.value !== undefined && option.value !== null && option.value !== ''
|
|
527
|
+
&& all.findIndex((other) => String(other.value) === String(option.value)) === index);
|
|
528
|
+
this.sourcedOptions = { ...this.sourcedOptions, [field.key]: options };
|
|
529
|
+
} catch (e) {
|
|
530
|
+
// eslint-disable-next-line no-console
|
|
531
|
+
console.warn('[CnFieldListWidget] optionsSource could not be read:', e?.message || e);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
|
|
464
536
|
pillOf(entry, spec) {
|
|
465
537
|
if (!spec || !spec.path) {
|
|
466
538
|
return null
|
|
@@ -632,7 +704,7 @@ var script = {
|
|
|
632
704
|
resetDraft() {
|
|
633
705
|
const draft = {};
|
|
634
706
|
for (const field of this.addFields) {
|
|
635
|
-
const empty = field
|
|
707
|
+
const empty = this.emptyValue(field);
|
|
636
708
|
const first = field.type === 'select' && field.options.length > 0 ? field.options[0].value : empty;
|
|
637
709
|
draft[field.key] = field.default !== undefined ? field.default : first;
|
|
638
710
|
}
|
|
@@ -787,10 +859,10 @@ var script = {
|
|
|
787
859
|
const errors = {};
|
|
788
860
|
for (const field of this.addFields) {
|
|
789
861
|
const value = this.draft[field.key];
|
|
790
|
-
const empty = value === undefined || value === null || String(value).trim() === '';
|
|
862
|
+
const empty = value === undefined || value === null || (Array.isArray(value) ? value.length === 0 : String(value).trim() === '');
|
|
791
863
|
if (field.required && empty) {
|
|
792
864
|
errors[field.key] = this.tr('Fill this in.');
|
|
793
|
-
} else if (!empty && field.pattern && !new RegExp(field.pattern).test(String(value).trim())) {
|
|
865
|
+
} else if (!empty && field.pattern && !Array.isArray(value) && !new RegExp(field.pattern).test(String(value).trim())) {
|
|
794
866
|
errors[field.key] = this.tr(field.patternMessage || 'This value is not valid.');
|
|
795
867
|
}
|
|
796
868
|
}
|
|
@@ -870,7 +942,7 @@ var script = {
|
|
|
870
942
|
for (const [index, field] of this.addFields.entries()) {
|
|
871
943
|
const scalarValue = this.content.add?.scalar === true && index === 0 ? row.item : undefined;
|
|
872
944
|
const value = row.item && typeof row.item === 'object' ? readPath(row.item, field.key) : scalarValue;
|
|
873
|
-
draft[field.key] = value === undefined || value === null ? (field
|
|
945
|
+
draft[field.key] = value === undefined || value === null ? this.emptyValue(field) : value;
|
|
874
946
|
}
|
|
875
947
|
this.draft = draft;
|
|
876
948
|
this.errors = {};
|
|
@@ -903,7 +975,10 @@ var script = {
|
|
|
903
975
|
const entry = { ...(add.defaults || {}) };
|
|
904
976
|
for (const field of this.addFields) {
|
|
905
977
|
const value = this.draft[field.key];
|
|
906
|
-
if (
|
|
978
|
+
if (Array.isArray(value)) {
|
|
979
|
+
// An emptied list is written as empty, so an edit can clear it.
|
|
980
|
+
entry[field.key] = value;
|
|
981
|
+
} else if (value !== undefined && value !== null && String(value).trim() !== '') {
|
|
907
982
|
entry[field.key] = trimmed(value);
|
|
908
983
|
}
|
|
909
984
|
}
|