@conduction/nextcloud-vue 2.124.0 → 2.125.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +120 -11
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +78 -32
  5. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +8 -7
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
  10. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +2 -1
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -2
  13. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDialog/CnDialog.vue2.js +5 -0
  15. package/dist/esm/components/CnDialog/CnDialog.vue2.js.map +1 -1
  16. package/dist/esm/components/CnDialog/CnDialog.vue3.js +1 -1
  17. package/dist/esm/components/CnDialog/CnDialog.vue3.js.map +1 -1
  18. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +13 -0
  19. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  20. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -1
  21. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  22. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
  23. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +7 -2
  24. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  25. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  26. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  27. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +159 -10
  28. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  29. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +151 -90
  30. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  31. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js +12 -0
  32. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
  33. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
  34. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
  35. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue.js +1 -1
  36. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js +39 -68
  37. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue2.js.map +1 -1
  38. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js +70 -116
  39. package/dist/esm/components/CnUserSettingsDialog/CnUserSettingsDialog.vue3.js.map +1 -1
  40. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  41. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +19 -3
  42. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  43. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  44. package/dist/esm/l10n/en.json.js +8 -8
  45. package/dist/esm/l10n/nl.json.js +8 -8
  46. package/dist/esm/library-style.js +1 -1
  47. package/dist/esm/nextcloud-vue.css +316 -185
  48. package/dist/nextcloud-vue.cjs.js +1149 -808
  49. package/dist/nextcloud-vue.cjs.js.map +2 -2
  50. package/dist/nextcloud-vue.css +316 -185
  51. package/l10n/en.json +8 -8
  52. package/l10n/nl.json +8 -8
  53. package/package.json +1 -1
  54. package/src/components/CnActionDialog/CnActionDialog.vue +173 -14
  55. package/src/components/CnAppRoot/CnAppRoot.vue +8 -7
  56. package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -3
  57. package/src/components/CnDialog/CnDialog.vue +6 -1
  58. package/src/components/CnIndexPage/CnIndexPage.vue +14 -0
  59. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +7 -2
  60. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +237 -23
  61. package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +13 -1
  62. package/src/components/CnUserSettingsDialog/CnUserSettingsDialog.vue +147 -145
  63. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +19 -3
  64. package/src/css/dialog.css +23 -0
  65. package/src/css/look-board-index.css +5 -1
  66. package/src/css/look-board.css +19 -0
@@ -3,7 +3,7 @@ export { withTypedAssignee } from './CnAssignDialog.vue2.js';
3
3
  import { render } from './CnAssignDialog.vue3.js';
4
4
 
5
5
  script.render = render;
6
- script.__scopeId = "data-v-45153be8";
6
+ script.__scopeId = "data-v-d3dfbd20";
7
7
  const __sfc_main = script;
8
8
 
9
9
  export { __sfc_main as default };
@@ -61,7 +61,8 @@ function withTypedAssignee(found, typed, label) {
61
61
  * sent as `field` (default `note`); `false` drops it. `rows` is the text
62
62
  * area's height in lines (default 3, as board DqOverdragen draws it).
63
63
  * - `toggles`: `[{ field, label, note? }]`: switches that start off and are
64
- * sent as booleans.
64
+ * sent as booleans; `label` and `note` are templates filled from the record
65
+ * ("{initiatorDisplayName} then gets a message").
65
66
  * - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.
66
67
  * `request` sends the choice itself (`body` templates filled from the
67
68
  * record); `action` dispatches a manifest action with the choice as its
@@ -1 +1 @@
1
- {"version":3,"file":"CnAssignDialog.vue2.js","sources":["../../../../src/components/CnAssignDialog/CnAssignDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:name=\"text(config.title) || t('nextcloud-vue', 'Assign')\"\n\t\t:eyebrow=\"fill(config.eyebrow)\"\n\t\t:subtitle=\"text(config.subtitle)\"\n\t\twidth=\"form\"\n\t\t:noClose=\"busy\"\n\t\tdata-testid=\"cn-assign-dialog\"\n\t\t@closing=\"close\">\n\t\t<div v-if=\"!done\" class=\"cn-assign-dialog\">\n\t\t\t<div class=\"cn-assign-dialog__field\">\n\t\t\t\t<CnSearchSelect\n\t\t\t\t\t:modelValue=\"picked ? picked.id : null\"\n\t\t\t\t\t:inputId=\"assigneeId\"\n\t\t\t\t\t:inputLabel=\"assigneeLabel\"\n\t\t\t\t\t:labelOutside=\"true\"\n\t\t\t\t\t:options=\"shownOptions\"\n\t\t\t\t\t:loading=\"searching\"\n\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t:placeholder=\"text(assigneeConfig.placeholder)\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-assignee\"\n\t\t\t\t\t@search=\"onSearch\"\n\t\t\t\t\t@update:modelValue=\"onPick\" />\n\t\t\t\t<span v-if=\"assigneeHint\" class=\"cn-assign-dialog__hint\">{{ assigneeHint }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-if=\"config.note !== false\" class=\"cn-assign-dialog__field\">\n\t\t\t\t<NcTextArea\n\t\t\t\t\t:id=\"noteId\"\n\t\t\t\t\tv-model=\"note\"\n\t\t\t\t\t:label=\"noteLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:rows=\"noteConfig.rows || 3\"\n\t\t\t\t\tresize=\"vertical\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-note\" />\n\t\t\t\t<span v-if=\"noteConfig.hint\" class=\"cn-assign-dialog__hint\">{{ text(noteConfig.hint) }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-for=\"toggle in toggles\"\n\t\t\t\t:key=\"toggle.field\"\n\t\t\t\tclass=\"cn-assign-dialog__toggle\"\n\t\t\t\t:class=\"{ 'cn-assign-dialog__toggle--on': flags[toggle.field] }\"\n\t\t\t\t:data-testid=\"`cn-assign-dialog-toggle-${toggle.field}`\">\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"flags[toggle.field] === true\" @update:modelValue=\"flags[toggle.field] = $event\">\n\t\t\t\t\t<span class=\"cn-assign-dialog__toggle-title\">{{ text(toggle.label) }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<span v-if=\"toggle.note\" class=\"cn-assign-dialog__hint cn-assign-dialog__toggle-note\">{{ text(toggle.note) }}</span>\n\t\t\t</div>\n\n\t\t\t<p v-if=\"refusal\"\n\t\t\t\tclass=\"cn-assign-dialog__error\"\n\t\t\t\trole=\"alert\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-refusal\">\n\t\t\t\t{{ refusal }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<p v-else role=\"status\" data-testid=\"cn-assign-dialog-done\">\n\t\t\t{{ text(config.doneText) || t('nextcloud-vue', 'Done') }}\n\t\t</p>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"busy\" data-testid=\"cn-assign-dialog-cancel\" @click=\"close\">\n\t\t\t\t{{ done ? t('nextcloud-vue', 'Close') : t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton v-if=\"!done\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-confirm\"\n\t\t\t\t@click=\"confirm\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon :name=\"confirmConfig.icon || 'SwapHorizontal'\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ text(confirmConfig.label) || t('nextcloud-vue', 'Assign') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcTextArea } from '@nextcloud/vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { searchNextcloudGroups, searchNextcloudUsers } from '../../utils/userAutocomplete.js'\nimport { CnDialog } from '../CnDialog/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnSearchSelect } from '../CnSearchSelect/index.js'\n\n/** The page refresh channel the built-in widgets listen on. */\nconst PAGE_REFRESH = 'cn:page:refresh'\n\n/** How long typing rests before a search runs, in ms. */\nconst SEARCH_DELAY = 250\n\n/** Gives each dialog's fields their own ids. */\nlet fieldSeq = 0\n\n/**\n * The found rows, with what was typed offered as an assignee of its own when\n * no row carries that id or name: where sharing is restricted the search\n * answers nothing, and an endpoint may still take the name.\n *\n * @param {Array<object>} found The rows found.\n * @param {string} typed What was typed.\n * @param {string} label The typed row's label.\n * @return {Array<object>} The rows.\n */\nexport function withTypedAssignee(found, typed, label) {\n\tconst lower = typed.toLowerCase()\n\tif (typed === '' || found.some((row) => String(row.id) === typed || String(row.label).toLowerCase() === lower)) {\n\t\treturn found\n\t}\n\treturn [...found, { id: typed, label, icon: 'AccountGroupOutline', kind: 'typed' }]\n}\n\n/**\n * CnAssignDialog — hand a record to another user or team, with a note and\n * optional switches, configured from the manifest (an `open-modal` action's\n * props). dossiq's case handover (board DqOverdragen: new team, why it moves,\n * \"this is a doorzending (Awb 2:3)\") is the first; pipelinq tickets and bulk\n * reassignment use the same dialog.\n *\n * `config`:\n * - `title`, `subtitle`, `doneText`: texts, through the host translate;\n * `eyebrow` a template filled from the record.\n * - `source`: an endpointSource to read the record from, else `object`.\n * - `assignee`: `{ kinds?, label?, placeholder?, hint?, currentPath?,\n * currentHint?, currentAs?, allowTyped?, field?, kindField? }`. `kinds` is `[\"group\"]`\n * (default), `[\"user\"]` or both; `currentPath` reads who has it now from the\n * record and `currentHint` (\"Now with {current}.\", the placeholder named\n * by `currentAs`) says so, in place of `hint`; `allowTyped`\n * offers what was typed as a choice; the id is sent as `field` (default\n * `assignee`) and its kind as `kindField` when set.\n * - `note`: `{ label?, hint?, required?, field?, rows? }`, required by default and\n * sent as `field` (default `note`); `false` drops it. `rows` is the text\n * area's height in lines (default 3, as board DqOverdragen draws it).\n * - `toggles`: `[{ field, label, note? }]`: switches that start off and are\n * sent as booleans.\n * - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.\n * `request` sends the choice itself (`body` templates filled from the\n * record); `action` dispatches a manifest action with the choice as its\n * last argument.\n *\n * Tokens (`@objectId`, `@object.<field>`) resolve in every url. A refusal is\n * shown in the server's own words and the dialog stays open.\n */\nexport default {\n\tname: 'CnAssignDialog',\n\n\tcomponents: { CnDialog, CnIcon, CnSearchSelect, NcButton, NcCheckboxRadioSwitch, NcTextArea },\n\n\tinject: {\n\t\t/** The host app's translate (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The page's pre-bound action dispatcher (CnPageRenderer), for `confirm.action`. */\n\t\tcnDispatchAction: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The dialog's configuration (see the component docs).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The record's id, for the `@objectId` token. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The record, when the host has it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['close', 'done'],\n\n\tdata() {\n\t\tconst seq = ++fieldSeq\n\t\tconst flags = {}\n\t\tfor (const toggle of Array.isArray(this.config.toggles) ? this.config.toggles : []) {\n\t\t\tif (toggle && toggle.field) {\n\t\t\t\tflags[toggle.field] = false\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\trecord: this.object,\n\t\t\toptions: [],\n\t\t\tpicked: null,\n\t\t\tsearching: false,\n\t\t\ttimer: null,\n\t\t\tsearchSeq: 0,\n\t\t\tnote: '',\n\t\t\tflags,\n\t\t\tbusy: false,\n\t\t\trefusal: '',\n\t\t\tdone: false,\n\t\t\tassigneeId: `cn-assign-dialog-assignee-${seq}`,\n\t\t\tnoteId: `cn-assign-dialog-note-${seq}`,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The token context. */\n\t\ttokenCtx() {\n\t\t\treturn { objectId: this.recordId, object: this.record || {} }\n\t\t},\n\n\t\t/**\n\t\t * The record's id: `objectId`, or the route's `id` when the prop is\n\t\t * empty or a token the opener could not resolve.\n\t\t *\n\t\t * @return {string|number}\n\t\t */\n\t\trecordId() {\n\t\t\tconst given = this.objectId\n\t\t\tif (given !== '' && given !== null && given !== undefined && !String(given).startsWith('@')) {\n\t\t\t\treturn given\n\t\t\t}\n\t\t\treturn (this.$route && this.$route.params && this.$route.params.id) || ''\n\t\t},\n\n\t\t/** @return {object} The assignee config. */\n\t\tassigneeConfig() {\n\t\t\treturn this.config.assignee && typeof this.config.assignee === 'object' ? this.config.assignee : {}\n\t\t},\n\n\t\t/** @return {object} The note config. */\n\t\tnoteConfig() {\n\t\t\treturn this.config.note && typeof this.config.note === 'object' ? this.config.note : {}\n\t\t},\n\n\t\t/** @return {object} The confirm config. */\n\t\tconfirmConfig() {\n\t\t\treturn this.config.confirm && typeof this.config.confirm === 'object' ? this.config.confirm : {}\n\t\t},\n\n\t\t/** @return {Array<object>} The switches with a field. */\n\t\ttoggles() {\n\t\t\treturn (Array.isArray(this.config.toggles) ? this.config.toggles : []).filter((toggle) => toggle && toggle.field)\n\t\t},\n\n\t\t/** @return {string[]} The kinds searched: `group`, `user`. */\n\t\tkinds() {\n\t\t\tconst kinds = Array.isArray(this.assigneeConfig.kinds) ? this.assigneeConfig.kinds.filter((k) => k === 'group' || k === 'user') : []\n\t\t\treturn kinds.length ? kinds : ['group']\n\t\t},\n\n\t\t/** @return {string} The assignee field's label. */\n\t\tassigneeLabel() {\n\t\t\tif (this.assigneeConfig.label) {\n\t\t\t\treturn this.text(this.assigneeConfig.label)\n\t\t\t}\n\t\t\treturn this.kinds.length === 1 && this.kinds[0] === 'user' ? t('nextcloud-vue', 'New handler') : t('nextcloud-vue', 'New team')\n\t\t},\n\n\t\t/** @return {string} Who has the record now, read from it. */\n\t\tcurrent() {\n\t\t\tconst path = this.assigneeConfig.currentPath\n\t\t\tconst value = path && this.record ? readPath(this.record, path) : ''\n\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * The hint under the assignee field: who has it now, else the configured hint.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {string}\n\t\t */\n\t\tassigneeHint() {\n\t\t\tconst name = this.assigneeConfig.currentAs || 'current'\n\t\t\tconst now = this.current && this.assigneeConfig.currentHint ? fillTemplate(this.cnTranslate(this.assigneeConfig.currentHint), { [name]: this.current }) : ''\n\t\t\treturn now || this.text(this.assigneeConfig.hint)\n\t\t},\n\n\t\t/** @return {Array<object>} The rows, keeping the picked one listed. */\n\t\tshownOptions() {\n\t\t\tif (this.picked && !this.options.some((o) => String(o.id) === String(this.picked.id))) {\n\t\t\t\treturn [this.picked, ...this.options]\n\t\t\t}\n\t\t\treturn this.options\n\t\t},\n\n\t\t/** @return {boolean} Whether a note is asked and needed. */\n\t\tnoteNeeded() {\n\t\t\treturn this.config.note !== false && this.noteConfig.required !== false\n\t\t},\n\n\t\t/** @return {string} The note field's label. */\n\t\tnoteLabel() {\n\t\t\treturn this.text(this.noteConfig.label) || t('nextcloud-vue', 'Why it is moving')\n\t\t},\n\n\t\t/**\n\t\t * Whether the assignment may run: an assignee, a note when needed, nothing in flight.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {boolean}\n\t\t */\n\t\tcanConfirm() {\n\t\t\treturn !this.busy && this.picked !== null && (!this.noteNeeded || this.note.trim() !== '')\n\t\t},\n\t},\n\n\tasync mounted() {\n\t\tconst source = this.config.source\n\t\tif (source && source.url) {\n\t\t\ttry {\n\t\t\t\tconst data = await fetchEndpointSource(source, this.tokenCtx, { fresh: true })\n\t\t\t\tthis.record = data && typeof data === 'object' ? data : this.record\n\t\t\t} catch {\n\t\t\t\t// The hint stays without the current assignee; the dialog still works.\n\t\t\t}\n\t\t}\n\t},\n\n\tbeforeUnmount() {\n\t\tclearTimeout(this.timer)\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A config text through the host translate, '' for anything else.\n\t\t *\n\t\t * @param {unknown} value The text.\n\t\t * @return {string}\n\t\t */\n\t\ttext(value) {\n\t\t\treturn typeof value === 'string' && value !== '' ? this.cnTranslate(value) : ''\n\t\t},\n\n\t\t/**\n\t\t * A template filled from the record, translated first.\n\t\t *\n\t\t * @param {unknown} template The template.\n\t\t * @return {string}\n\t\t */\n\t\tfill(template) {\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn fillTemplate(this.cnTranslate(template), this.record || {}).trim()\n\t\t},\n\n\t\t/**\n\t\t * Search after typing rests.\n\t\t *\n\t\t * @param {string} query What was typed.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tclearTimeout(this.timer)\n\t\t\tconst typed = String(query ?? '').trim()\n\t\t\tif (typed === '') {\n\t\t\t\tthis.options = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.timer = setTimeout(() => this.search(typed), SEARCH_DELAY)\n\t\t},\n\n\t\t/**\n\t\t * Search the configured kinds; offer what was typed when allowed.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @param {string} typed What was typed.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync search(typed) {\n\t\t\tconst seq = ++this.searchSeq\n\t\t\tthis.searching = true\n\t\t\tconst [groups, users] = await Promise.all([\n\t\t\t\tthis.kinds.includes('group') ? searchNextcloudGroups(typed, { limit: 20 }) : [],\n\t\t\t\tthis.kinds.includes('user') ? searchNextcloudUsers(typed, { limit: 20 }) : [],\n\t\t\t])\n\t\t\tif (seq !== this.searchSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst found = [\n\t\t\t\t...groups.map((g) => ({ id: g.id, label: g.label, secondary: g.subline || '', icon: 'AccountGroupOutline', kind: 'group' })),\n\t\t\t\t...users.map((u) => ({ id: u.id, label: u.label, secondary: u.subline || '', avatar: true, kind: 'user' })),\n\t\t\t]\n\t\t\tthis.options = this.assigneeConfig.allowTyped ? withTypedAssignee(found, typed, t('nextcloud-vue', 'Use \"{name}\"', { name: typed })) : found\n\t\t\tthis.searching = false\n\t\t},\n\n\t\t/**\n\t\t * Take the picked row.\n\t\t *\n\t\t * @param {string|null} id The picked id.\n\t\t */\n\t\tonPick(id) {\n\t\t\tthis.picked = id === null ? null : (this.shownOptions.find((o) => String(o.id) === String(id)) || null)\n\t\t},\n\n\t\t/**\n\t\t * The choice as sent: assignee, its kind, the note and the switches.\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tchoice() {\n\t\t\tconst out = { [this.assigneeConfig.field || 'assignee']: String(this.picked.id) }\n\t\t\tif (this.assigneeConfig.kindField) {\n\t\t\t\tout[this.assigneeConfig.kindField] = this.picked.kind === 'typed' ? this.kinds[0] : this.picked.kind\n\t\t\t}\n\t\t\tif (this.config.note !== false) {\n\t\t\t\tout[this.noteConfig.field || 'note'] = this.note.trim()\n\t\t\t}\n\t\t\treturn { ...out, ...this.flags }\n\t\t},\n\n\t\t/**\n\t\t * Assign once: send `confirm.request`, or dispatch `confirm.action`,\n\t\t * then show the done text and refresh the page.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync confirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.refusal = ''\n\t\t\tconst choice = this.choice()\n\t\t\ttry {\n\t\t\t\tconst request = this.confirmConfig.request\n\t\t\t\tif (request && request.url) {\n\t\t\t\t\tconst url = interpolateUrlTokens(request.url, this.tokenCtx)\n\t\t\t\t\tconst body = {}\n\t\t\t\t\tfor (const [key, value] of Object.entries(request.body || {})) {\n\t\t\t\t\t\tbody[key] = typeof value === 'string' ? fillTemplate(value, this.record || {}) : value\n\t\t\t\t\t}\n\t\t\t\t\tconst method = String(request.method || 'POST').toLowerCase()\n\t\t\t\t\tawait axios[['post', 'put', 'patch'].includes(method) ? method : 'post'](/^https?:\\/\\//i.test(url) ? url : generateUrl(url), { ...body, ...choice })\n\t\t\t\t} else if (this.confirmConfig.action && typeof this.cnDispatchAction === 'function') {\n\t\t\t\t\tawait this.cnDispatchAction({ ...this.confirmConfig.action, args: [...(this.confirmConfig.action.args || []), choice] })\n\t\t\t\t}\n\t\t\t\tthis.done = true\n\t\t\t\temit(PAGE_REFRESH, {})\n\t\t\t\t/** @event done The assignment ran. Payload: the choice as sent. */\n\t\t\t\tthis.$emit('done', choice)\n\t\t\t} catch (failure) {\n\t\t\t\tconst data = failure && failure.response && failure.response.data\n\t\t\t\tthis.refusal = String((data && (data.message || data.error)) || t('nextcloud-vue', 'It was not handed over.'))\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog, unless the assignment is running. */\n\t\tclose() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/** @event close The dialog was closed. */\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-assign-dialog {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 18px;\n}\n\n.cn-assign-dialog__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-assign-dialog__hint {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-assign-dialog__toggle {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tpadding: 12px 14px;\n\tborder: 1px solid var(--color-border-dark);\n\tborder-radius: var(--border-radius-large, 8px);\n}\n\n.cn-assign-dialog__toggle--on {\n\tborder: 2px solid var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-assign-dialog__toggle-title {\n\tfont-weight: 600;\n}\n\n.cn-assign-dialog__toggle-note {\n\tpadding-inline-start: 44px;\n}\n\n.cn-assign-dialog__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["CnDialog","CnIcon","CnSearchSelect","t","axios"],"mappings":"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"}
1
+ {"version":3,"file":"CnAssignDialog.vue2.js","sources":["../../../../src/components/CnAssignDialog/CnAssignDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:name=\"text(config.title) || t('nextcloud-vue', 'Assign')\"\n\t\t:eyebrow=\"fill(config.eyebrow)\"\n\t\t:subtitle=\"text(config.subtitle)\"\n\t\twidth=\"form\"\n\t\t:noClose=\"busy\"\n\t\tdata-testid=\"cn-assign-dialog\"\n\t\t@closing=\"close\">\n\t\t<div v-if=\"!done\" class=\"cn-assign-dialog\">\n\t\t\t<div class=\"cn-assign-dialog__field\">\n\t\t\t\t<CnSearchSelect\n\t\t\t\t\t:modelValue=\"picked ? picked.id : null\"\n\t\t\t\t\t:inputId=\"assigneeId\"\n\t\t\t\t\t:inputLabel=\"assigneeLabel\"\n\t\t\t\t\t:labelOutside=\"true\"\n\t\t\t\t\t:options=\"shownOptions\"\n\t\t\t\t\t:loading=\"searching\"\n\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t:placeholder=\"text(assigneeConfig.placeholder)\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-assignee\"\n\t\t\t\t\t@search=\"onSearch\"\n\t\t\t\t\t@update:modelValue=\"onPick\" />\n\t\t\t\t<span v-if=\"assigneeHint\" class=\"cn-assign-dialog__hint\">{{ assigneeHint }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-if=\"config.note !== false\" class=\"cn-assign-dialog__field\">\n\t\t\t\t<NcTextArea\n\t\t\t\t\t:id=\"noteId\"\n\t\t\t\t\tv-model=\"note\"\n\t\t\t\t\t:label=\"noteLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:rows=\"noteConfig.rows || 3\"\n\t\t\t\t\tresize=\"vertical\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-note\" />\n\t\t\t\t<span v-if=\"noteConfig.hint\" class=\"cn-assign-dialog__hint\">{{ text(noteConfig.hint) }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-for=\"toggle in toggles\"\n\t\t\t\t:key=\"toggle.field\"\n\t\t\t\tclass=\"cn-assign-dialog__toggle\"\n\t\t\t\t:class=\"{ 'cn-assign-dialog__toggle--on': flags[toggle.field] }\"\n\t\t\t\t:data-testid=\"`cn-assign-dialog-toggle-${toggle.field}`\">\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"flags[toggle.field] === true\" @update:modelValue=\"flags[toggle.field] = $event\">\n\t\t\t\t\t<span class=\"cn-assign-dialog__toggle-title\">{{ fill(toggle.label) }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<span v-if=\"toggle.note\" class=\"cn-assign-dialog__hint cn-assign-dialog__toggle-note\">{{ fill(toggle.note) }}</span>\n\t\t\t</div>\n\n\t\t\t<p v-if=\"refusal\"\n\t\t\t\tclass=\"cn-assign-dialog__error\"\n\t\t\t\trole=\"alert\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-refusal\">\n\t\t\t\t{{ refusal }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<p v-else role=\"status\" data-testid=\"cn-assign-dialog-done\">\n\t\t\t{{ text(config.doneText) || t('nextcloud-vue', 'Done') }}\n\t\t</p>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"busy\" data-testid=\"cn-assign-dialog-cancel\" @click=\"close\">\n\t\t\t\t{{ done ? t('nextcloud-vue', 'Close') : t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton v-if=\"!done\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-confirm\"\n\t\t\t\t@click=\"confirm\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon :name=\"confirmConfig.icon || 'SwapHorizontal'\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ text(confirmConfig.label) || t('nextcloud-vue', 'Assign') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcTextArea } from '@nextcloud/vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { searchNextcloudGroups, searchNextcloudUsers } from '../../utils/userAutocomplete.js'\nimport { CnDialog } from '../CnDialog/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnSearchSelect } from '../CnSearchSelect/index.js'\n\n/** The page refresh channel the built-in widgets listen on. */\nconst PAGE_REFRESH = 'cn:page:refresh'\n\n/** How long typing rests before a search runs, in ms. */\nconst SEARCH_DELAY = 250\n\n/** Gives each dialog's fields their own ids. */\nlet fieldSeq = 0\n\n/**\n * The found rows, with what was typed offered as an assignee of its own when\n * no row carries that id or name: where sharing is restricted the search\n * answers nothing, and an endpoint may still take the name.\n *\n * @param {Array<object>} found The rows found.\n * @param {string} typed What was typed.\n * @param {string} label The typed row's label.\n * @return {Array<object>} The rows.\n */\nexport function withTypedAssignee(found, typed, label) {\n\tconst lower = typed.toLowerCase()\n\tif (typed === '' || found.some((row) => String(row.id) === typed || String(row.label).toLowerCase() === lower)) {\n\t\treturn found\n\t}\n\treturn [...found, { id: typed, label, icon: 'AccountGroupOutline', kind: 'typed' }]\n}\n\n/**\n * CnAssignDialog — hand a record to another user or team, with a note and\n * optional switches, configured from the manifest (an `open-modal` action's\n * props). dossiq's case handover (board DqOverdragen: new team, why it moves,\n * \"this is a doorzending (Awb 2:3)\") is the first; pipelinq tickets and bulk\n * reassignment use the same dialog.\n *\n * `config`:\n * - `title`, `subtitle`, `doneText`: texts, through the host translate;\n * `eyebrow` a template filled from the record.\n * - `source`: an endpointSource to read the record from, else `object`.\n * - `assignee`: `{ kinds?, label?, placeholder?, hint?, currentPath?,\n * currentHint?, currentAs?, allowTyped?, field?, kindField? }`. `kinds` is `[\"group\"]`\n * (default), `[\"user\"]` or both; `currentPath` reads who has it now from the\n * record and `currentHint` (\"Now with {current}.\", the placeholder named\n * by `currentAs`) says so, in place of `hint`; `allowTyped`\n * offers what was typed as a choice; the id is sent as `field` (default\n * `assignee`) and its kind as `kindField` when set.\n * - `note`: `{ label?, hint?, required?, field?, rows? }`, required by default and\n * sent as `field` (default `note`); `false` drops it. `rows` is the text\n * area's height in lines (default 3, as board DqOverdragen draws it).\n * - `toggles`: `[{ field, label, note? }]`: switches that start off and are\n * sent as booleans; `label` and `note` are templates filled from the record\n * (\"{initiatorDisplayName} then gets a message\").\n * - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.\n * `request` sends the choice itself (`body` templates filled from the\n * record); `action` dispatches a manifest action with the choice as its\n * last argument.\n *\n * Tokens (`@objectId`, `@object.<field>`) resolve in every url. A refusal is\n * shown in the server's own words and the dialog stays open.\n */\nexport default {\n\tname: 'CnAssignDialog',\n\n\tcomponents: { CnDialog, CnIcon, CnSearchSelect, NcButton, NcCheckboxRadioSwitch, NcTextArea },\n\n\tinject: {\n\t\t/** The host app's translate (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The page's pre-bound action dispatcher (CnPageRenderer), for `confirm.action`. */\n\t\tcnDispatchAction: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The dialog's configuration (see the component docs).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The record's id, for the `@objectId` token. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The record, when the host has it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['close', 'done'],\n\n\tdata() {\n\t\tconst seq = ++fieldSeq\n\t\tconst flags = {}\n\t\tfor (const toggle of Array.isArray(this.config.toggles) ? this.config.toggles : []) {\n\t\t\tif (toggle && toggle.field) {\n\t\t\t\tflags[toggle.field] = false\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\trecord: this.object,\n\t\t\toptions: [],\n\t\t\tpicked: null,\n\t\t\tsearching: false,\n\t\t\ttimer: null,\n\t\t\tsearchSeq: 0,\n\t\t\tnote: '',\n\t\t\tflags,\n\t\t\tbusy: false,\n\t\t\trefusal: '',\n\t\t\tdone: false,\n\t\t\tassigneeId: `cn-assign-dialog-assignee-${seq}`,\n\t\t\tnoteId: `cn-assign-dialog-note-${seq}`,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The token context. */\n\t\ttokenCtx() {\n\t\t\treturn { objectId: this.recordId, object: this.record || {} }\n\t\t},\n\n\t\t/**\n\t\t * The record's id: `objectId`, or the route's `id` when the prop is\n\t\t * empty or a token the opener could not resolve.\n\t\t *\n\t\t * @return {string|number}\n\t\t */\n\t\trecordId() {\n\t\t\tconst given = this.objectId\n\t\t\tif (given !== '' && given !== null && given !== undefined && !String(given).startsWith('@')) {\n\t\t\t\treturn given\n\t\t\t}\n\t\t\treturn (this.$route && this.$route.params && this.$route.params.id) || ''\n\t\t},\n\n\t\t/** @return {object} The assignee config. */\n\t\tassigneeConfig() {\n\t\t\treturn this.config.assignee && typeof this.config.assignee === 'object' ? this.config.assignee : {}\n\t\t},\n\n\t\t/** @return {object} The note config. */\n\t\tnoteConfig() {\n\t\t\treturn this.config.note && typeof this.config.note === 'object' ? this.config.note : {}\n\t\t},\n\n\t\t/** @return {object} The confirm config. */\n\t\tconfirmConfig() {\n\t\t\treturn this.config.confirm && typeof this.config.confirm === 'object' ? this.config.confirm : {}\n\t\t},\n\n\t\t/** @return {Array<object>} The switches with a field. */\n\t\ttoggles() {\n\t\t\treturn (Array.isArray(this.config.toggles) ? this.config.toggles : []).filter((toggle) => toggle && toggle.field)\n\t\t},\n\n\t\t/** @return {string[]} The kinds searched: `group`, `user`. */\n\t\tkinds() {\n\t\t\tconst kinds = Array.isArray(this.assigneeConfig.kinds) ? this.assigneeConfig.kinds.filter((k) => k === 'group' || k === 'user') : []\n\t\t\treturn kinds.length ? kinds : ['group']\n\t\t},\n\n\t\t/** @return {string} The assignee field's label. */\n\t\tassigneeLabel() {\n\t\t\tif (this.assigneeConfig.label) {\n\t\t\t\treturn this.text(this.assigneeConfig.label)\n\t\t\t}\n\t\t\treturn this.kinds.length === 1 && this.kinds[0] === 'user' ? t('nextcloud-vue', 'New handler') : t('nextcloud-vue', 'New team')\n\t\t},\n\n\t\t/** @return {string} Who has the record now, read from it. */\n\t\tcurrent() {\n\t\t\tconst path = this.assigneeConfig.currentPath\n\t\t\tconst value = path && this.record ? readPath(this.record, path) : ''\n\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * The hint under the assignee field: who has it now, else the configured hint.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {string}\n\t\t */\n\t\tassigneeHint() {\n\t\t\tconst name = this.assigneeConfig.currentAs || 'current'\n\t\t\tconst now = this.current && this.assigneeConfig.currentHint ? fillTemplate(this.cnTranslate(this.assigneeConfig.currentHint), { [name]: this.current }) : ''\n\t\t\treturn now || this.text(this.assigneeConfig.hint)\n\t\t},\n\n\t\t/** @return {Array<object>} The rows, keeping the picked one listed. */\n\t\tshownOptions() {\n\t\t\tif (this.picked && !this.options.some((o) => String(o.id) === String(this.picked.id))) {\n\t\t\t\treturn [this.picked, ...this.options]\n\t\t\t}\n\t\t\treturn this.options\n\t\t},\n\n\t\t/** @return {boolean} Whether a note is asked and needed. */\n\t\tnoteNeeded() {\n\t\t\treturn this.config.note !== false && this.noteConfig.required !== false\n\t\t},\n\n\t\t/** @return {string} The note field's label. */\n\t\tnoteLabel() {\n\t\t\treturn this.text(this.noteConfig.label) || t('nextcloud-vue', 'Why it is moving')\n\t\t},\n\n\t\t/**\n\t\t * Whether the assignment may run: an assignee, a note when needed, nothing in flight.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {boolean}\n\t\t */\n\t\tcanConfirm() {\n\t\t\treturn !this.busy && this.picked !== null && (!this.noteNeeded || this.note.trim() !== '')\n\t\t},\n\t},\n\n\tasync mounted() {\n\t\tconst source = this.config.source\n\t\tif (source && source.url) {\n\t\t\ttry {\n\t\t\t\tconst data = await fetchEndpointSource(source, this.tokenCtx, { fresh: true })\n\t\t\t\tthis.record = data && typeof data === 'object' ? data : this.record\n\t\t\t} catch {\n\t\t\t\t// The hint stays without the current assignee; the dialog still works.\n\t\t\t}\n\t\t}\n\t},\n\n\tbeforeUnmount() {\n\t\tclearTimeout(this.timer)\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A config text through the host translate, '' for anything else.\n\t\t *\n\t\t * @param {unknown} value The text.\n\t\t * @return {string}\n\t\t */\n\t\ttext(value) {\n\t\t\treturn typeof value === 'string' && value !== '' ? this.cnTranslate(value) : ''\n\t\t},\n\n\t\t/**\n\t\t * A template filled from the record, translated first.\n\t\t *\n\t\t * @param {unknown} template The template.\n\t\t * @return {string}\n\t\t */\n\t\tfill(template) {\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn fillTemplate(this.cnTranslate(template), this.record || {}).trim()\n\t\t},\n\n\t\t/**\n\t\t * Search after typing rests.\n\t\t *\n\t\t * @param {string} query What was typed.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tclearTimeout(this.timer)\n\t\t\tconst typed = String(query ?? '').trim()\n\t\t\tif (typed === '') {\n\t\t\t\tthis.options = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.timer = setTimeout(() => this.search(typed), SEARCH_DELAY)\n\t\t},\n\n\t\t/**\n\t\t * Search the configured kinds; offer what was typed when allowed.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @param {string} typed What was typed.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync search(typed) {\n\t\t\tconst seq = ++this.searchSeq\n\t\t\tthis.searching = true\n\t\t\tconst [groups, users] = await Promise.all([\n\t\t\t\tthis.kinds.includes('group') ? searchNextcloudGroups(typed, { limit: 20 }) : [],\n\t\t\t\tthis.kinds.includes('user') ? searchNextcloudUsers(typed, { limit: 20 }) : [],\n\t\t\t])\n\t\t\tif (seq !== this.searchSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst found = [\n\t\t\t\t...groups.map((g) => ({ id: g.id, label: g.label, secondary: g.subline || '', icon: 'AccountGroupOutline', kind: 'group' })),\n\t\t\t\t...users.map((u) => ({ id: u.id, label: u.label, secondary: u.subline || '', avatar: true, kind: 'user' })),\n\t\t\t]\n\t\t\tthis.options = this.assigneeConfig.allowTyped ? withTypedAssignee(found, typed, t('nextcloud-vue', 'Use \"{name}\"', { name: typed })) : found\n\t\t\tthis.searching = false\n\t\t},\n\n\t\t/**\n\t\t * Take the picked row.\n\t\t *\n\t\t * @param {string|null} id The picked id.\n\t\t */\n\t\tonPick(id) {\n\t\t\tthis.picked = id === null ? null : (this.shownOptions.find((o) => String(o.id) === String(id)) || null)\n\t\t},\n\n\t\t/**\n\t\t * The choice as sent: assignee, its kind, the note and the switches.\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tchoice() {\n\t\t\tconst out = { [this.assigneeConfig.field || 'assignee']: String(this.picked.id) }\n\t\t\tif (this.assigneeConfig.kindField) {\n\t\t\t\tout[this.assigneeConfig.kindField] = this.picked.kind === 'typed' ? this.kinds[0] : this.picked.kind\n\t\t\t}\n\t\t\tif (this.config.note !== false) {\n\t\t\t\tout[this.noteConfig.field || 'note'] = this.note.trim()\n\t\t\t}\n\t\t\treturn { ...out, ...this.flags }\n\t\t},\n\n\t\t/**\n\t\t * Assign once: send `confirm.request`, or dispatch `confirm.action`,\n\t\t * then show the done text and refresh the page.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync confirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.refusal = ''\n\t\t\tconst choice = this.choice()\n\t\t\ttry {\n\t\t\t\tconst request = this.confirmConfig.request\n\t\t\t\tif (request && request.url) {\n\t\t\t\t\tconst url = interpolateUrlTokens(request.url, this.tokenCtx)\n\t\t\t\t\tconst body = {}\n\t\t\t\t\tfor (const [key, value] of Object.entries(request.body || {})) {\n\t\t\t\t\t\tbody[key] = typeof value === 'string' ? fillTemplate(value, this.record || {}) : value\n\t\t\t\t\t}\n\t\t\t\t\tconst method = String(request.method || 'POST').toLowerCase()\n\t\t\t\t\tawait axios[['post', 'put', 'patch'].includes(method) ? method : 'post'](/^https?:\\/\\//i.test(url) ? url : generateUrl(url), { ...body, ...choice })\n\t\t\t\t} else if (this.confirmConfig.action && typeof this.cnDispatchAction === 'function') {\n\t\t\t\t\tawait this.cnDispatchAction({ ...this.confirmConfig.action, args: [...(this.confirmConfig.action.args || []), choice] })\n\t\t\t\t}\n\t\t\t\tthis.done = true\n\t\t\t\temit(PAGE_REFRESH, {})\n\t\t\t\t/** @event done The assignment ran. Payload: the choice as sent. */\n\t\t\t\tthis.$emit('done', choice)\n\t\t\t} catch (failure) {\n\t\t\t\tconst data = failure && failure.response && failure.response.data\n\t\t\t\tthis.refusal = String((data && (data.message || data.error)) || t('nextcloud-vue', 'It was not handed over.'))\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog, unless the assignment is running. */\n\t\tclose() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/** @event close The dialog was closed. */\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-assign-dialog {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 18px;\n}\n\n.cn-assign-dialog__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-assign-dialog__hint {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-assign-dialog__toggle {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tpadding: 12px 14px;\n\tborder: 1px solid var(--color-border-dark);\n\tborder-radius: var(--border-radius-large, 8px);\n}\n\n.cn-assign-dialog__toggle--on {\n\tborder: 2px solid var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-assign-dialog__toggle-title {\n\tfont-weight: 600;\n}\n\n.cn-assign-dialog__toggle-note {\n\tpadding-inline-start: 44px;\n}\n\n.cn-assign-dialog__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["CnDialog","CnIcon","CnSearchSelect","t","axios"],"mappings":"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"}
@@ -133,12 +133,12 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
133
133
  "onUpdate:modelValue": $event => ($data.flags[toggle.field] = $event)
134
134
  }, {
135
135
  default: withCtx(() => [
136
- createElementVNode("span", _hoisted_7, toDisplayString($options.text(toggle.label)), 1 /* TEXT */)
136
+ createElementVNode("span", _hoisted_7, toDisplayString($options.fill(toggle.label)), 1 /* TEXT */)
137
137
  ]),
138
138
  _: 2 /* DYNAMIC */
139
139
  }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["modelValue", "onUpdate:modelValue"]),
140
140
  (toggle.note)
141
- ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString($options.text(toggle.note)), 1 /* TEXT */))
141
+ ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString($options.fill(toggle.note)), 1 /* TEXT */))
142
142
  : createCommentVNode("v-if", true)
143
143
  ], 10 /* CLASS, PROPS */, _hoisted_6))
144
144
  }), 128 /* KEYED_FRAGMENT */)),
@@ -1 +1 @@
1
- {"version":3,"file":"CnAssignDialog.vue3.js","sources":["../../../../src/components/CnAssignDialog/CnAssignDialog.vue?vue&type=template&id=45153be8&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:name=\"text(config.title) || t('nextcloud-vue', 'Assign')\"\n\t\t:eyebrow=\"fill(config.eyebrow)\"\n\t\t:subtitle=\"text(config.subtitle)\"\n\t\twidth=\"form\"\n\t\t:noClose=\"busy\"\n\t\tdata-testid=\"cn-assign-dialog\"\n\t\t@closing=\"close\">\n\t\t<div v-if=\"!done\" class=\"cn-assign-dialog\">\n\t\t\t<div class=\"cn-assign-dialog__field\">\n\t\t\t\t<CnSearchSelect\n\t\t\t\t\t:modelValue=\"picked ? picked.id : null\"\n\t\t\t\t\t:inputId=\"assigneeId\"\n\t\t\t\t\t:inputLabel=\"assigneeLabel\"\n\t\t\t\t\t:labelOutside=\"true\"\n\t\t\t\t\t:options=\"shownOptions\"\n\t\t\t\t\t:loading=\"searching\"\n\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t:placeholder=\"text(assigneeConfig.placeholder)\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-assignee\"\n\t\t\t\t\t@search=\"onSearch\"\n\t\t\t\t\t@update:modelValue=\"onPick\" />\n\t\t\t\t<span v-if=\"assigneeHint\" class=\"cn-assign-dialog__hint\">{{ assigneeHint }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-if=\"config.note !== false\" class=\"cn-assign-dialog__field\">\n\t\t\t\t<NcTextArea\n\t\t\t\t\t:id=\"noteId\"\n\t\t\t\t\tv-model=\"note\"\n\t\t\t\t\t:label=\"noteLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:rows=\"noteConfig.rows || 3\"\n\t\t\t\t\tresize=\"vertical\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-note\" />\n\t\t\t\t<span v-if=\"noteConfig.hint\" class=\"cn-assign-dialog__hint\">{{ text(noteConfig.hint) }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-for=\"toggle in toggles\"\n\t\t\t\t:key=\"toggle.field\"\n\t\t\t\tclass=\"cn-assign-dialog__toggle\"\n\t\t\t\t:class=\"{ 'cn-assign-dialog__toggle--on': flags[toggle.field] }\"\n\t\t\t\t:data-testid=\"`cn-assign-dialog-toggle-${toggle.field}`\">\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"flags[toggle.field] === true\" @update:modelValue=\"flags[toggle.field] = $event\">\n\t\t\t\t\t<span class=\"cn-assign-dialog__toggle-title\">{{ text(toggle.label) }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<span v-if=\"toggle.note\" class=\"cn-assign-dialog__hint cn-assign-dialog__toggle-note\">{{ text(toggle.note) }}</span>\n\t\t\t</div>\n\n\t\t\t<p v-if=\"refusal\"\n\t\t\t\tclass=\"cn-assign-dialog__error\"\n\t\t\t\trole=\"alert\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-refusal\">\n\t\t\t\t{{ refusal }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<p v-else role=\"status\" data-testid=\"cn-assign-dialog-done\">\n\t\t\t{{ text(config.doneText) || t('nextcloud-vue', 'Done') }}\n\t\t</p>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"busy\" data-testid=\"cn-assign-dialog-cancel\" @click=\"close\">\n\t\t\t\t{{ done ? t('nextcloud-vue', 'Close') : t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton v-if=\"!done\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-confirm\"\n\t\t\t\t@click=\"confirm\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon :name=\"confirmConfig.icon || 'SwapHorizontal'\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ text(confirmConfig.label) || t('nextcloud-vue', 'Assign') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcTextArea } from '@nextcloud/vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { searchNextcloudGroups, searchNextcloudUsers } from '../../utils/userAutocomplete.js'\nimport { CnDialog } from '../CnDialog/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnSearchSelect } from '../CnSearchSelect/index.js'\n\n/** The page refresh channel the built-in widgets listen on. */\nconst PAGE_REFRESH = 'cn:page:refresh'\n\n/** How long typing rests before a search runs, in ms. */\nconst SEARCH_DELAY = 250\n\n/** Gives each dialog's fields their own ids. */\nlet fieldSeq = 0\n\n/**\n * The found rows, with what was typed offered as an assignee of its own when\n * no row carries that id or name: where sharing is restricted the search\n * answers nothing, and an endpoint may still take the name.\n *\n * @param {Array<object>} found The rows found.\n * @param {string} typed What was typed.\n * @param {string} label The typed row's label.\n * @return {Array<object>} The rows.\n */\nexport function withTypedAssignee(found, typed, label) {\n\tconst lower = typed.toLowerCase()\n\tif (typed === '' || found.some((row) => String(row.id) === typed || String(row.label).toLowerCase() === lower)) {\n\t\treturn found\n\t}\n\treturn [...found, { id: typed, label, icon: 'AccountGroupOutline', kind: 'typed' }]\n}\n\n/**\n * CnAssignDialog — hand a record to another user or team, with a note and\n * optional switches, configured from the manifest (an `open-modal` action's\n * props). dossiq's case handover (board DqOverdragen: new team, why it moves,\n * \"this is a doorzending (Awb 2:3)\") is the first; pipelinq tickets and bulk\n * reassignment use the same dialog.\n *\n * `config`:\n * - `title`, `subtitle`, `doneText`: texts, through the host translate;\n * `eyebrow` a template filled from the record.\n * - `source`: an endpointSource to read the record from, else `object`.\n * - `assignee`: `{ kinds?, label?, placeholder?, hint?, currentPath?,\n * currentHint?, currentAs?, allowTyped?, field?, kindField? }`. `kinds` is `[\"group\"]`\n * (default), `[\"user\"]` or both; `currentPath` reads who has it now from the\n * record and `currentHint` (\"Now with {current}.\", the placeholder named\n * by `currentAs`) says so, in place of `hint`; `allowTyped`\n * offers what was typed as a choice; the id is sent as `field` (default\n * `assignee`) and its kind as `kindField` when set.\n * - `note`: `{ label?, hint?, required?, field?, rows? }`, required by default and\n * sent as `field` (default `note`); `false` drops it. `rows` is the text\n * area's height in lines (default 3, as board DqOverdragen draws it).\n * - `toggles`: `[{ field, label, note? }]`: switches that start off and are\n * sent as booleans.\n * - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.\n * `request` sends the choice itself (`body` templates filled from the\n * record); `action` dispatches a manifest action with the choice as its\n * last argument.\n *\n * Tokens (`@objectId`, `@object.<field>`) resolve in every url. A refusal is\n * shown in the server's own words and the dialog stays open.\n */\nexport default {\n\tname: 'CnAssignDialog',\n\n\tcomponents: { CnDialog, CnIcon, CnSearchSelect, NcButton, NcCheckboxRadioSwitch, NcTextArea },\n\n\tinject: {\n\t\t/** The host app's translate (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The page's pre-bound action dispatcher (CnPageRenderer), for `confirm.action`. */\n\t\tcnDispatchAction: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The dialog's configuration (see the component docs).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The record's id, for the `@objectId` token. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The record, when the host has it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['close', 'done'],\n\n\tdata() {\n\t\tconst seq = ++fieldSeq\n\t\tconst flags = {}\n\t\tfor (const toggle of Array.isArray(this.config.toggles) ? this.config.toggles : []) {\n\t\t\tif (toggle && toggle.field) {\n\t\t\t\tflags[toggle.field] = false\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\trecord: this.object,\n\t\t\toptions: [],\n\t\t\tpicked: null,\n\t\t\tsearching: false,\n\t\t\ttimer: null,\n\t\t\tsearchSeq: 0,\n\t\t\tnote: '',\n\t\t\tflags,\n\t\t\tbusy: false,\n\t\t\trefusal: '',\n\t\t\tdone: false,\n\t\t\tassigneeId: `cn-assign-dialog-assignee-${seq}`,\n\t\t\tnoteId: `cn-assign-dialog-note-${seq}`,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The token context. */\n\t\ttokenCtx() {\n\t\t\treturn { objectId: this.recordId, object: this.record || {} }\n\t\t},\n\n\t\t/**\n\t\t * The record's id: `objectId`, or the route's `id` when the prop is\n\t\t * empty or a token the opener could not resolve.\n\t\t *\n\t\t * @return {string|number}\n\t\t */\n\t\trecordId() {\n\t\t\tconst given = this.objectId\n\t\t\tif (given !== '' && given !== null && given !== undefined && !String(given).startsWith('@')) {\n\t\t\t\treturn given\n\t\t\t}\n\t\t\treturn (this.$route && this.$route.params && this.$route.params.id) || ''\n\t\t},\n\n\t\t/** @return {object} The assignee config. */\n\t\tassigneeConfig() {\n\t\t\treturn this.config.assignee && typeof this.config.assignee === 'object' ? this.config.assignee : {}\n\t\t},\n\n\t\t/** @return {object} The note config. */\n\t\tnoteConfig() {\n\t\t\treturn this.config.note && typeof this.config.note === 'object' ? this.config.note : {}\n\t\t},\n\n\t\t/** @return {object} The confirm config. */\n\t\tconfirmConfig() {\n\t\t\treturn this.config.confirm && typeof this.config.confirm === 'object' ? this.config.confirm : {}\n\t\t},\n\n\t\t/** @return {Array<object>} The switches with a field. */\n\t\ttoggles() {\n\t\t\treturn (Array.isArray(this.config.toggles) ? this.config.toggles : []).filter((toggle) => toggle && toggle.field)\n\t\t},\n\n\t\t/** @return {string[]} The kinds searched: `group`, `user`. */\n\t\tkinds() {\n\t\t\tconst kinds = Array.isArray(this.assigneeConfig.kinds) ? this.assigneeConfig.kinds.filter((k) => k === 'group' || k === 'user') : []\n\t\t\treturn kinds.length ? kinds : ['group']\n\t\t},\n\n\t\t/** @return {string} The assignee field's label. */\n\t\tassigneeLabel() {\n\t\t\tif (this.assigneeConfig.label) {\n\t\t\t\treturn this.text(this.assigneeConfig.label)\n\t\t\t}\n\t\t\treturn this.kinds.length === 1 && this.kinds[0] === 'user' ? t('nextcloud-vue', 'New handler') : t('nextcloud-vue', 'New team')\n\t\t},\n\n\t\t/** @return {string} Who has the record now, read from it. */\n\t\tcurrent() {\n\t\t\tconst path = this.assigneeConfig.currentPath\n\t\t\tconst value = path && this.record ? readPath(this.record, path) : ''\n\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * The hint under the assignee field: who has it now, else the configured hint.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {string}\n\t\t */\n\t\tassigneeHint() {\n\t\t\tconst name = this.assigneeConfig.currentAs || 'current'\n\t\t\tconst now = this.current && this.assigneeConfig.currentHint ? fillTemplate(this.cnTranslate(this.assigneeConfig.currentHint), { [name]: this.current }) : ''\n\t\t\treturn now || this.text(this.assigneeConfig.hint)\n\t\t},\n\n\t\t/** @return {Array<object>} The rows, keeping the picked one listed. */\n\t\tshownOptions() {\n\t\t\tif (this.picked && !this.options.some((o) => String(o.id) === String(this.picked.id))) {\n\t\t\t\treturn [this.picked, ...this.options]\n\t\t\t}\n\t\t\treturn this.options\n\t\t},\n\n\t\t/** @return {boolean} Whether a note is asked and needed. */\n\t\tnoteNeeded() {\n\t\t\treturn this.config.note !== false && this.noteConfig.required !== false\n\t\t},\n\n\t\t/** @return {string} The note field's label. */\n\t\tnoteLabel() {\n\t\t\treturn this.text(this.noteConfig.label) || t('nextcloud-vue', 'Why it is moving')\n\t\t},\n\n\t\t/**\n\t\t * Whether the assignment may run: an assignee, a note when needed, nothing in flight.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {boolean}\n\t\t */\n\t\tcanConfirm() {\n\t\t\treturn !this.busy && this.picked !== null && (!this.noteNeeded || this.note.trim() !== '')\n\t\t},\n\t},\n\n\tasync mounted() {\n\t\tconst source = this.config.source\n\t\tif (source && source.url) {\n\t\t\ttry {\n\t\t\t\tconst data = await fetchEndpointSource(source, this.tokenCtx, { fresh: true })\n\t\t\t\tthis.record = data && typeof data === 'object' ? data : this.record\n\t\t\t} catch {\n\t\t\t\t// The hint stays without the current assignee; the dialog still works.\n\t\t\t}\n\t\t}\n\t},\n\n\tbeforeUnmount() {\n\t\tclearTimeout(this.timer)\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A config text through the host translate, '' for anything else.\n\t\t *\n\t\t * @param {unknown} value The text.\n\t\t * @return {string}\n\t\t */\n\t\ttext(value) {\n\t\t\treturn typeof value === 'string' && value !== '' ? this.cnTranslate(value) : ''\n\t\t},\n\n\t\t/**\n\t\t * A template filled from the record, translated first.\n\t\t *\n\t\t * @param {unknown} template The template.\n\t\t * @return {string}\n\t\t */\n\t\tfill(template) {\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn fillTemplate(this.cnTranslate(template), this.record || {}).trim()\n\t\t},\n\n\t\t/**\n\t\t * Search after typing rests.\n\t\t *\n\t\t * @param {string} query What was typed.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tclearTimeout(this.timer)\n\t\t\tconst typed = String(query ?? '').trim()\n\t\t\tif (typed === '') {\n\t\t\t\tthis.options = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.timer = setTimeout(() => this.search(typed), SEARCH_DELAY)\n\t\t},\n\n\t\t/**\n\t\t * Search the configured kinds; offer what was typed when allowed.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @param {string} typed What was typed.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync search(typed) {\n\t\t\tconst seq = ++this.searchSeq\n\t\t\tthis.searching = true\n\t\t\tconst [groups, users] = await Promise.all([\n\t\t\t\tthis.kinds.includes('group') ? searchNextcloudGroups(typed, { limit: 20 }) : [],\n\t\t\t\tthis.kinds.includes('user') ? searchNextcloudUsers(typed, { limit: 20 }) : [],\n\t\t\t])\n\t\t\tif (seq !== this.searchSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst found = [\n\t\t\t\t...groups.map((g) => ({ id: g.id, label: g.label, secondary: g.subline || '', icon: 'AccountGroupOutline', kind: 'group' })),\n\t\t\t\t...users.map((u) => ({ id: u.id, label: u.label, secondary: u.subline || '', avatar: true, kind: 'user' })),\n\t\t\t]\n\t\t\tthis.options = this.assigneeConfig.allowTyped ? withTypedAssignee(found, typed, t('nextcloud-vue', 'Use \"{name}\"', { name: typed })) : found\n\t\t\tthis.searching = false\n\t\t},\n\n\t\t/**\n\t\t * Take the picked row.\n\t\t *\n\t\t * @param {string|null} id The picked id.\n\t\t */\n\t\tonPick(id) {\n\t\t\tthis.picked = id === null ? null : (this.shownOptions.find((o) => String(o.id) === String(id)) || null)\n\t\t},\n\n\t\t/**\n\t\t * The choice as sent: assignee, its kind, the note and the switches.\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tchoice() {\n\t\t\tconst out = { [this.assigneeConfig.field || 'assignee']: String(this.picked.id) }\n\t\t\tif (this.assigneeConfig.kindField) {\n\t\t\t\tout[this.assigneeConfig.kindField] = this.picked.kind === 'typed' ? this.kinds[0] : this.picked.kind\n\t\t\t}\n\t\t\tif (this.config.note !== false) {\n\t\t\t\tout[this.noteConfig.field || 'note'] = this.note.trim()\n\t\t\t}\n\t\t\treturn { ...out, ...this.flags }\n\t\t},\n\n\t\t/**\n\t\t * Assign once: send `confirm.request`, or dispatch `confirm.action`,\n\t\t * then show the done text and refresh the page.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync confirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.refusal = ''\n\t\t\tconst choice = this.choice()\n\t\t\ttry {\n\t\t\t\tconst request = this.confirmConfig.request\n\t\t\t\tif (request && request.url) {\n\t\t\t\t\tconst url = interpolateUrlTokens(request.url, this.tokenCtx)\n\t\t\t\t\tconst body = {}\n\t\t\t\t\tfor (const [key, value] of Object.entries(request.body || {})) {\n\t\t\t\t\t\tbody[key] = typeof value === 'string' ? fillTemplate(value, this.record || {}) : value\n\t\t\t\t\t}\n\t\t\t\t\tconst method = String(request.method || 'POST').toLowerCase()\n\t\t\t\t\tawait axios[['post', 'put', 'patch'].includes(method) ? method : 'post'](/^https?:\\/\\//i.test(url) ? url : generateUrl(url), { ...body, ...choice })\n\t\t\t\t} else if (this.confirmConfig.action && typeof this.cnDispatchAction === 'function') {\n\t\t\t\t\tawait this.cnDispatchAction({ ...this.confirmConfig.action, args: [...(this.confirmConfig.action.args || []), choice] })\n\t\t\t\t}\n\t\t\t\tthis.done = true\n\t\t\t\temit(PAGE_REFRESH, {})\n\t\t\t\t/** @event done The assignment ran. Payload: the choice as sent. */\n\t\t\t\tthis.$emit('done', choice)\n\t\t\t} catch (failure) {\n\t\t\t\tconst data = failure && failure.response && failure.response.data\n\t\t\t\tthis.refusal = String((data && (data.message || data.error)) || t('nextcloud-vue', 'It was not handed over.'))\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog, unless the assignment is running. */\n\t\tclose() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/** @event close The dialog was closed. */\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-assign-dialog {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 18px;\n}\n\n.cn-assign-dialog__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-assign-dialog__hint {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-assign-dialog__toggle {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tpadding: 12px 14px;\n\tborder: 1px solid var(--color-border-dark);\n\tborder-radius: var(--border-radius-large, 8px);\n}\n\n.cn-assign-dialog__toggle--on {\n\tborder: 2px solid var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-assign-dialog__toggle-title {\n\tfont-weight: 600;\n}\n\n.cn-assign-dialog__toggle-note {\n\tpadding-inline-start: 44px;\n}\n\n.cn-assign-dialog__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["_createVNode","_createBlock","_createTextVNode","_openBlock","_createElementBlock","_toDisplayString","_Fragment","_renderList"],"mappings":"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"}
1
+ {"version":3,"file":"CnAssignDialog.vue3.js","sources":["../../../../src/components/CnAssignDialog/CnAssignDialog.vue?vue&type=template&id=d3dfbd20&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<CnDialog\n\t\t:name=\"text(config.title) || t('nextcloud-vue', 'Assign')\"\n\t\t:eyebrow=\"fill(config.eyebrow)\"\n\t\t:subtitle=\"text(config.subtitle)\"\n\t\twidth=\"form\"\n\t\t:noClose=\"busy\"\n\t\tdata-testid=\"cn-assign-dialog\"\n\t\t@closing=\"close\">\n\t\t<div v-if=\"!done\" class=\"cn-assign-dialog\">\n\t\t\t<div class=\"cn-assign-dialog__field\">\n\t\t\t\t<CnSearchSelect\n\t\t\t\t\t:modelValue=\"picked ? picked.id : null\"\n\t\t\t\t\t:inputId=\"assigneeId\"\n\t\t\t\t\t:inputLabel=\"assigneeLabel\"\n\t\t\t\t\t:labelOutside=\"true\"\n\t\t\t\t\t:options=\"shownOptions\"\n\t\t\t\t\t:loading=\"searching\"\n\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t:placeholder=\"text(assigneeConfig.placeholder)\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-assignee\"\n\t\t\t\t\t@search=\"onSearch\"\n\t\t\t\t\t@update:modelValue=\"onPick\" />\n\t\t\t\t<span v-if=\"assigneeHint\" class=\"cn-assign-dialog__hint\">{{ assigneeHint }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-if=\"config.note !== false\" class=\"cn-assign-dialog__field\">\n\t\t\t\t<NcTextArea\n\t\t\t\t\t:id=\"noteId\"\n\t\t\t\t\tv-model=\"note\"\n\t\t\t\t\t:label=\"noteLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:rows=\"noteConfig.rows || 3\"\n\t\t\t\t\tresize=\"vertical\"\n\t\t\t\t\tdata-testid=\"cn-assign-dialog-note\" />\n\t\t\t\t<span v-if=\"noteConfig.hint\" class=\"cn-assign-dialog__hint\">{{ text(noteConfig.hint) }}</span>\n\t\t\t</div>\n\n\t\t\t<div v-for=\"toggle in toggles\"\n\t\t\t\t:key=\"toggle.field\"\n\t\t\t\tclass=\"cn-assign-dialog__toggle\"\n\t\t\t\t:class=\"{ 'cn-assign-dialog__toggle--on': flags[toggle.field] }\"\n\t\t\t\t:data-testid=\"`cn-assign-dialog-toggle-${toggle.field}`\">\n\t\t\t\t<NcCheckboxRadioSwitch :modelValue=\"flags[toggle.field] === true\" @update:modelValue=\"flags[toggle.field] = $event\">\n\t\t\t\t\t<span class=\"cn-assign-dialog__toggle-title\">{{ fill(toggle.label) }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t\t<span v-if=\"toggle.note\" class=\"cn-assign-dialog__hint cn-assign-dialog__toggle-note\">{{ fill(toggle.note) }}</span>\n\t\t\t</div>\n\n\t\t\t<p v-if=\"refusal\"\n\t\t\t\tclass=\"cn-assign-dialog__error\"\n\t\t\t\trole=\"alert\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-refusal\">\n\t\t\t\t{{ refusal }}\n\t\t\t</p>\n\t\t</div>\n\n\t\t<p v-else role=\"status\" data-testid=\"cn-assign-dialog-done\">\n\t\t\t{{ text(config.doneText) || t('nextcloud-vue', 'Done') }}\n\t\t</p>\n\n\t\t<template #actions>\n\t\t\t<NcButton :disabled=\"busy\" data-testid=\"cn-assign-dialog-cancel\" @click=\"close\">\n\t\t\t\t{{ done ? t('nextcloud-vue', 'Close') : t('nextcloud-vue', 'Cancel') }}\n\t\t\t</NcButton>\n\t\t\t<NcButton v-if=\"!done\"\n\t\t\t\tvariant=\"primary\"\n\t\t\t\t:disabled=\"!canConfirm\"\n\t\t\t\tdata-testid=\"cn-assign-dialog-confirm\"\n\t\t\t\t@click=\"confirm\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon :name=\"confirmConfig.icon || 'SwapHorizontal'\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ text(confirmConfig.label) || t('nextcloud-vue', 'Assign') }}\n\t\t\t</NcButton>\n\t\t</template>\n\t</CnDialog>\n</template>\n\n<script>\nimport axios from '@nextcloud/axios'\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcButton, NcCheckboxRadioSwitch, NcTextArea } from '@nextcloud/vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { fillTemplate } from '../../utils/fillTemplate.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { searchNextcloudGroups, searchNextcloudUsers } from '../../utils/userAutocomplete.js'\nimport { CnDialog } from '../CnDialog/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnSearchSelect } from '../CnSearchSelect/index.js'\n\n/** The page refresh channel the built-in widgets listen on. */\nconst PAGE_REFRESH = 'cn:page:refresh'\n\n/** How long typing rests before a search runs, in ms. */\nconst SEARCH_DELAY = 250\n\n/** Gives each dialog's fields their own ids. */\nlet fieldSeq = 0\n\n/**\n * The found rows, with what was typed offered as an assignee of its own when\n * no row carries that id or name: where sharing is restricted the search\n * answers nothing, and an endpoint may still take the name.\n *\n * @param {Array<object>} found The rows found.\n * @param {string} typed What was typed.\n * @param {string} label The typed row's label.\n * @return {Array<object>} The rows.\n */\nexport function withTypedAssignee(found, typed, label) {\n\tconst lower = typed.toLowerCase()\n\tif (typed === '' || found.some((row) => String(row.id) === typed || String(row.label).toLowerCase() === lower)) {\n\t\treturn found\n\t}\n\treturn [...found, { id: typed, label, icon: 'AccountGroupOutline', kind: 'typed' }]\n}\n\n/**\n * CnAssignDialog — hand a record to another user or team, with a note and\n * optional switches, configured from the manifest (an `open-modal` action's\n * props). dossiq's case handover (board DqOverdragen: new team, why it moves,\n * \"this is a doorzending (Awb 2:3)\") is the first; pipelinq tickets and bulk\n * reassignment use the same dialog.\n *\n * `config`:\n * - `title`, `subtitle`, `doneText`: texts, through the host translate;\n * `eyebrow` a template filled from the record.\n * - `source`: an endpointSource to read the record from, else `object`.\n * - `assignee`: `{ kinds?, label?, placeholder?, hint?, currentPath?,\n * currentHint?, currentAs?, allowTyped?, field?, kindField? }`. `kinds` is `[\"group\"]`\n * (default), `[\"user\"]` or both; `currentPath` reads who has it now from the\n * record and `currentHint` (\"Now with {current}.\", the placeholder named\n * by `currentAs`) says so, in place of `hint`; `allowTyped`\n * offers what was typed as a choice; the id is sent as `field` (default\n * `assignee`) and its kind as `kindField` when set.\n * - `note`: `{ label?, hint?, required?, field?, rows? }`, required by default and\n * sent as `field` (default `note`); `false` drops it. `rows` is the text\n * area's height in lines (default 3, as board DqOverdragen draws it).\n * - `toggles`: `[{ field, label, note? }]`: switches that start off and are\n * sent as booleans; `label` and `note` are templates filled from the record\n * (\"{initiatorDisplayName} then gets a message\").\n * - `confirm`: `{ label?, icon?, request?: { method?, url, body? }, action? }`.\n * `request` sends the choice itself (`body` templates filled from the\n * record); `action` dispatches a manifest action with the choice as its\n * last argument.\n *\n * Tokens (`@objectId`, `@object.<field>`) resolve in every url. A refusal is\n * shown in the server's own words and the dialog stays open.\n */\nexport default {\n\tname: 'CnAssignDialog',\n\n\tcomponents: { CnDialog, CnIcon, CnSearchSelect, NcButton, NcCheckboxRadioSwitch, NcTextArea },\n\n\tinject: {\n\t\t/** The host app's translate (CnAppRoot `cnTranslate`). */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The page's pre-bound action dispatcher (CnPageRenderer), for `confirm.action`. */\n\t\tcnDispatchAction: { default: null },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The dialog's configuration (see the component docs).\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tconfig: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The record's id, for the `@objectId` token. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The record, when the host has it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['close', 'done'],\n\n\tdata() {\n\t\tconst seq = ++fieldSeq\n\t\tconst flags = {}\n\t\tfor (const toggle of Array.isArray(this.config.toggles) ? this.config.toggles : []) {\n\t\t\tif (toggle && toggle.field) {\n\t\t\t\tflags[toggle.field] = false\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\trecord: this.object,\n\t\t\toptions: [],\n\t\t\tpicked: null,\n\t\t\tsearching: false,\n\t\t\ttimer: null,\n\t\t\tsearchSeq: 0,\n\t\t\tnote: '',\n\t\t\tflags,\n\t\t\tbusy: false,\n\t\t\trefusal: '',\n\t\t\tdone: false,\n\t\t\tassigneeId: `cn-assign-dialog-assignee-${seq}`,\n\t\t\tnoteId: `cn-assign-dialog-note-${seq}`,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The token context. */\n\t\ttokenCtx() {\n\t\t\treturn { objectId: this.recordId, object: this.record || {} }\n\t\t},\n\n\t\t/**\n\t\t * The record's id: `objectId`, or the route's `id` when the prop is\n\t\t * empty or a token the opener could not resolve.\n\t\t *\n\t\t * @return {string|number}\n\t\t */\n\t\trecordId() {\n\t\t\tconst given = this.objectId\n\t\t\tif (given !== '' && given !== null && given !== undefined && !String(given).startsWith('@')) {\n\t\t\t\treturn given\n\t\t\t}\n\t\t\treturn (this.$route && this.$route.params && this.$route.params.id) || ''\n\t\t},\n\n\t\t/** @return {object} The assignee config. */\n\t\tassigneeConfig() {\n\t\t\treturn this.config.assignee && typeof this.config.assignee === 'object' ? this.config.assignee : {}\n\t\t},\n\n\t\t/** @return {object} The note config. */\n\t\tnoteConfig() {\n\t\t\treturn this.config.note && typeof this.config.note === 'object' ? this.config.note : {}\n\t\t},\n\n\t\t/** @return {object} The confirm config. */\n\t\tconfirmConfig() {\n\t\t\treturn this.config.confirm && typeof this.config.confirm === 'object' ? this.config.confirm : {}\n\t\t},\n\n\t\t/** @return {Array<object>} The switches with a field. */\n\t\ttoggles() {\n\t\t\treturn (Array.isArray(this.config.toggles) ? this.config.toggles : []).filter((toggle) => toggle && toggle.field)\n\t\t},\n\n\t\t/** @return {string[]} The kinds searched: `group`, `user`. */\n\t\tkinds() {\n\t\t\tconst kinds = Array.isArray(this.assigneeConfig.kinds) ? this.assigneeConfig.kinds.filter((k) => k === 'group' || k === 'user') : []\n\t\t\treturn kinds.length ? kinds : ['group']\n\t\t},\n\n\t\t/** @return {string} The assignee field's label. */\n\t\tassigneeLabel() {\n\t\t\tif (this.assigneeConfig.label) {\n\t\t\t\treturn this.text(this.assigneeConfig.label)\n\t\t\t}\n\t\t\treturn this.kinds.length === 1 && this.kinds[0] === 'user' ? t('nextcloud-vue', 'New handler') : t('nextcloud-vue', 'New team')\n\t\t},\n\n\t\t/** @return {string} Who has the record now, read from it. */\n\t\tcurrent() {\n\t\t\tconst path = this.assigneeConfig.currentPath\n\t\t\tconst value = path && this.record ? readPath(this.record, path) : ''\n\t\t\treturn value === undefined || value === null ? '' : String(value)\n\t\t},\n\n\t\t/**\n\t\t * The hint under the assignee field: who has it now, else the configured hint.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {string}\n\t\t */\n\t\tassigneeHint() {\n\t\t\tconst name = this.assigneeConfig.currentAs || 'current'\n\t\t\tconst now = this.current && this.assigneeConfig.currentHint ? fillTemplate(this.cnTranslate(this.assigneeConfig.currentHint), { [name]: this.current }) : ''\n\t\t\treturn now || this.text(this.assigneeConfig.hint)\n\t\t},\n\n\t\t/** @return {Array<object>} The rows, keeping the picked one listed. */\n\t\tshownOptions() {\n\t\t\tif (this.picked && !this.options.some((o) => String(o.id) === String(this.picked.id))) {\n\t\t\t\treturn [this.picked, ...this.options]\n\t\t\t}\n\t\t\treturn this.options\n\t\t},\n\n\t\t/** @return {boolean} Whether a note is asked and needed. */\n\t\tnoteNeeded() {\n\t\t\treturn this.config.note !== false && this.noteConfig.required !== false\n\t\t},\n\n\t\t/** @return {string} The note field's label. */\n\t\tnoteLabel() {\n\t\t\treturn this.text(this.noteConfig.label) || t('nextcloud-vue', 'Why it is moving')\n\t\t},\n\n\t\t/**\n\t\t * Whether the assignment may run: an assignee, a note when needed, nothing in flight.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {boolean}\n\t\t */\n\t\tcanConfirm() {\n\t\t\treturn !this.busy && this.picked !== null && (!this.noteNeeded || this.note.trim() !== '')\n\t\t},\n\t},\n\n\tasync mounted() {\n\t\tconst source = this.config.source\n\t\tif (source && source.url) {\n\t\t\ttry {\n\t\t\t\tconst data = await fetchEndpointSource(source, this.tokenCtx, { fresh: true })\n\t\t\t\tthis.record = data && typeof data === 'object' ? data : this.record\n\t\t\t} catch {\n\t\t\t\t// The hint stays without the current assignee; the dialog still works.\n\t\t\t}\n\t\t}\n\t},\n\n\tbeforeUnmount() {\n\t\tclearTimeout(this.timer)\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * A config text through the host translate, '' for anything else.\n\t\t *\n\t\t * @param {unknown} value The text.\n\t\t * @return {string}\n\t\t */\n\t\ttext(value) {\n\t\t\treturn typeof value === 'string' && value !== '' ? this.cnTranslate(value) : ''\n\t\t},\n\n\t\t/**\n\t\t * A template filled from the record, translated first.\n\t\t *\n\t\t * @param {unknown} template The template.\n\t\t * @return {string}\n\t\t */\n\t\tfill(template) {\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn fillTemplate(this.cnTranslate(template), this.record || {}).trim()\n\t\t},\n\n\t\t/**\n\t\t * Search after typing rests.\n\t\t *\n\t\t * @param {string} query What was typed.\n\t\t */\n\t\tonSearch(query) {\n\t\t\tclearTimeout(this.timer)\n\t\t\tconst typed = String(query ?? '').trim()\n\t\t\tif (typed === '') {\n\t\t\t\tthis.options = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.timer = setTimeout(() => this.search(typed), SEARCH_DELAY)\n\t\t},\n\n\t\t/**\n\t\t * Search the configured kinds; offer what was typed when allowed.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @param {string} typed What was typed.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync search(typed) {\n\t\t\tconst seq = ++this.searchSeq\n\t\t\tthis.searching = true\n\t\t\tconst [groups, users] = await Promise.all([\n\t\t\t\tthis.kinds.includes('group') ? searchNextcloudGroups(typed, { limit: 20 }) : [],\n\t\t\t\tthis.kinds.includes('user') ? searchNextcloudUsers(typed, { limit: 20 }) : [],\n\t\t\t])\n\t\t\tif (seq !== this.searchSeq) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst found = [\n\t\t\t\t...groups.map((g) => ({ id: g.id, label: g.label, secondary: g.subline || '', icon: 'AccountGroupOutline', kind: 'group' })),\n\t\t\t\t...users.map((u) => ({ id: u.id, label: u.label, secondary: u.subline || '', avatar: true, kind: 'user' })),\n\t\t\t]\n\t\t\tthis.options = this.assigneeConfig.allowTyped ? withTypedAssignee(found, typed, t('nextcloud-vue', 'Use \"{name}\"', { name: typed })) : found\n\t\t\tthis.searching = false\n\t\t},\n\n\t\t/**\n\t\t * Take the picked row.\n\t\t *\n\t\t * @param {string|null} id The picked id.\n\t\t */\n\t\tonPick(id) {\n\t\t\tthis.picked = id === null ? null : (this.shownOptions.find((o) => String(o.id) === String(id)) || null)\n\t\t},\n\n\t\t/**\n\t\t * The choice as sent: assignee, its kind, the note and the switches.\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tchoice() {\n\t\t\tconst out = { [this.assigneeConfig.field || 'assignee']: String(this.picked.id) }\n\t\t\tif (this.assigneeConfig.kindField) {\n\t\t\t\tout[this.assigneeConfig.kindField] = this.picked.kind === 'typed' ? this.kinds[0] : this.picked.kind\n\t\t\t}\n\t\t\tif (this.config.note !== false) {\n\t\t\t\tout[this.noteConfig.field || 'note'] = this.note.trim()\n\t\t\t}\n\t\t\treturn { ...out, ...this.flags }\n\t\t},\n\n\t\t/**\n\t\t * Assign once: send `confirm.request`, or dispatch `confirm.action`,\n\t\t * then show the done text and refresh the page.\n\t\t *\n\t\t * @spec openspec/changes/assign-dialog/specs/assign-dialog/spec.md#requirement-a-manifest-configures-an-assign-dialog\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync confirm() {\n\t\t\tif (!this.canConfirm) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.refusal = ''\n\t\t\tconst choice = this.choice()\n\t\t\ttry {\n\t\t\t\tconst request = this.confirmConfig.request\n\t\t\t\tif (request && request.url) {\n\t\t\t\t\tconst url = interpolateUrlTokens(request.url, this.tokenCtx)\n\t\t\t\t\tconst body = {}\n\t\t\t\t\tfor (const [key, value] of Object.entries(request.body || {})) {\n\t\t\t\t\t\tbody[key] = typeof value === 'string' ? fillTemplate(value, this.record || {}) : value\n\t\t\t\t\t}\n\t\t\t\t\tconst method = String(request.method || 'POST').toLowerCase()\n\t\t\t\t\tawait axios[['post', 'put', 'patch'].includes(method) ? method : 'post'](/^https?:\\/\\//i.test(url) ? url : generateUrl(url), { ...body, ...choice })\n\t\t\t\t} else if (this.confirmConfig.action && typeof this.cnDispatchAction === 'function') {\n\t\t\t\t\tawait this.cnDispatchAction({ ...this.confirmConfig.action, args: [...(this.confirmConfig.action.args || []), choice] })\n\t\t\t\t}\n\t\t\t\tthis.done = true\n\t\t\t\temit(PAGE_REFRESH, {})\n\t\t\t\t/** @event done The assignment ran. Payload: the choice as sent. */\n\t\t\t\tthis.$emit('done', choice)\n\t\t\t} catch (failure) {\n\t\t\t\tconst data = failure && failure.response && failure.response.data\n\t\t\t\tthis.refusal = String((data && (data.message || data.error)) || t('nextcloud-vue', 'It was not handed over.'))\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/** Close the dialog, unless the assignment is running. */\n\t\tclose() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/** @event close The dialog was closed. */\n\t\t\tthis.$emit('close')\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-assign-dialog {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 18px;\n}\n\n.cn-assign-dialog__field {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-assign-dialog__hint {\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-assign-dialog__toggle {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tpadding: 12px 14px;\n\tborder: 1px solid var(--color-border-dark);\n\tborder-radius: var(--border-radius-large, 8px);\n}\n\n.cn-assign-dialog__toggle--on {\n\tborder: 2px solid var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n.cn-assign-dialog__toggle-title {\n\tfont-weight: 600;\n}\n\n.cn-assign-dialog__toggle-note {\n\tpadding-inline-start: 44px;\n}\n\n.cn-assign-dialog__error {\n\tmargin: 0;\n\tcolor: var(--color-error-text, var(--color-error));\n}\n</style>\n"],"names":["_createVNode","_createBlock","_createTextVNode","_openBlock","_createElementBlock","_toDisplayString","_Fragment","_renderList"],"mappings":";;;;AAiBoB,EAAA,KAAK,EAAA,kBAAA;;AACjB,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,yBAAiB,GAAA;;;AAajB,EAAA,KAAA,EAAA,wBAAA;;;;AAGQ,EAAA,KAAA,EAAA,yBAAA;;;;AASA,EAAA,KAAA,EAAA,wBAAA;;;;;;AAWO,EAAA,KAAK,EAAA,sDAAA;;;;AAI9B,EAAA,KAAE,EAAA,yBAAA;AACF,EAAA,IAAG,EAAA,OAAA;;;;;AAMK,EAAA,IAAI,EAAC,QAAG;AAAA,EAAA,aAAA,EAAA,uBAAA;;;;;;;;;;;;AAvDjB,IAAA,IAAI,EAAE,QAAI,CAAA,IAAA,CAAC,aAAE,CAAA,KAAA,KAAA,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,QAAA,CAAA;AACb,IAAA,OAAO,EAAE,QAAA,CAAA,IAAI,CAAC,MAAA,CAAA,MAAM,CAAC,OAAO,CAAA;AAC5B,IAAA,QAAQ,EAAE,QAAA,CAAA,IAAI,CAAC,MAAA,CAAA,MAAA,CAAA,QAAA,CAAA;AAChB,IAAA,KAAK,EAAC,MAAM;AACX,IAAA,OAAO,EAAE,KAAI,CAAA,IAAA;AACZ,IAAA,aAAS,EAAC,kBAAI;AACb,IAAA,SAAK,EAAE,QAAK,CAAA,KAAA;;AAqDJ,IAAA,OAAO,UAChB,MAEU;MAFVA,WAEU,CAAA,mBAAA,EAAA;AAFA,QAAA,QAAM,EAAA,KAAA,CAAA,IAAA;AAAA,QAAA,aAAA,EAAA,yBAAA;AAAA,QAAA,OAAA,EAAA,QAAA,CAAA,KAAA;;yBAChB,MAAsB;0CAAnB,KAAI,CAAA,IAAA,GAAG,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,OAAA,CAAA,GAAW,QAAA,CAAA,CAAA,CAAA,eAAA,EAAA,QAAA,CAAA,CAAA,EAAA,CAAA,YAAA;;;;QAEN,KAAA,CAAA,IAAA;wBAAhBC;;AACA,YAAA,OAAO,EAAC,SAAO;AACd,YAAA,QAAQ,GAAG,QAAU,CAAA,UAAA;AACtB,YAAA,aAAU,EAAA,0BAAA;AACT,YAAA,OAAK,EAAE,QAAO,CAAA,OAAA;;AACN,YAAA,IAAA,UACR,MAAO;cAAPD,WAAO,CAAA,iBAAA,EAAA;gBAAA,IAAA,EAAA,QAAA,CAAA,aAAA,CAAA,IAAA,IAAA,gBAAA;AAAA,gBAAA,IAAA,EAAA,EAAA;;;6BACD;AAAA,cAAAE,eAAA,CAAA;;;;;;qBA/DN,MA8CA;QA9CS,KAAI,CAAA,IAAA;AAAb,WAAAC,SAAA,EAAA,EAAAC,kBAAA,CA8CA,OA9CA,UA8CA,EAAA;+BA/BI,iBAAA,EAAA;cAbJJ,WAW8B,CAAA,yBAAA,EAAA;AAV7B,gBAAA,UAAU,EAAE,KAAA,CAAA,MAAM,GAAG,KAAA,CAAA,MAAA,CAAA,EAAA,GAAA,IAAA;AACrB,gBAAA,OAAO,EAAE,KAAS,CAAA,UAAA;AAClB,gBAAA,UAAU,EAAE,QAAK,CAAA,aAAA;AACjB,gBAAA,YAAY,EAAE,IAAI;AAClB,gBAAA,OAAO,EAAE,QAAY,CAAA,YAAA;AACrB,gBAAA,OAAO,EAAE,KAAO,CAAA,SAAA;AAChB,gBAAA,UAAU,EAAE,KAAK;AACjB,gBAAA,WAAW,EAAE,QAAA,CAAA,IAAI,CAAC,QAAA,CAAA,cAAc,CAAC,WAAW,CAAA;AAC7C,gBAAA,aAAG,EAAA,2BAAA;;AAEF,gBAAA,qBAAiB,EAAG,QAAK,CAAA,MAAA;;eACjB,QAAA,CAAA,YAAA;gCAAVI,kBAAU,CAAA,MAAA,EAAV,UAAU,EAAAC,eAAA,CAAA,QAAA,CAAA,YAAA,CAAA,EAAA,CAAA,YAAA;;;AAGA,YAAA,CAAA,MAAA,CAAA,MAAM,CAAC,IAAC,KAAA,KAAA;AAAjB,iBAAAF,SAAA,EAAA,EAAAC,kBAAA,CAUI,OAVJ,UAUI,EAAA;kBATJJ,WAO2B,CAAA,qBAAA,EAAA;AAN1B,oBAAA,EAAE,EAAE,KAAM,CAAA,MAAA;gCACF,KAAI,CAAA,IAAA;iFAAJ,KAAI,CAAA,IAAA,IAAA,MAAA,CAAA,CAAA;AACZ,oBAAA,KAAK,EAAE,QAAS,CAAA,SAAA;AAChB,oBAAA,YAAY,EAAE,KAAK;oBACnB,IAAE,EAAA,QAAA,CAAA,UAAA,CAAA,IAAA,IAAA,CAAA;;AAEH,oBAAA,aAAW,EAAC,uBAAe;;AAChB,kBAAA,CAAA,QAAA,CAAA,UAAM,CAAA,IAAA;AAAlB,uBAAAG,SAAA,EAAA,EAAAC,kBAAA,CAAkB,QAAlB,UAAkB,EAAAC,eAAA,CAAA,aAAA,CAAA,QAAA,CAAA,UAAA,CAAA,IAAA,CAAA,CAAA,EAAA,CAAA,YAAA;;;;gDAYb,CAAAC,QAAA,EAAA,IAAA,EAAAC,UAAA,CATgB,QAAO,CAAA,OAAA,EAAA,CAAjB,MAAM,KAAA;qDASZ,CAAA,KAAA,EAAA;gBARJ,GAAG,EAAE,MAAM,CAAC,KAAK;AACjB,gBAAA,KAAI,kBAAA,0BAA2B,EAAA,EAAA,8BAAA,EACT,WAAA,CAAA,MAAA,CAAA,KAAA,CAAA,EAAA,CAAA,CAAA;gBACtB,aAAW,EAAA,CAAA,wBAAA,EAA6B,MAAM,CAAC,KAAK,CAAA,CAAA;;gBACrDP,WAEe,CAAA,gCAAA,EAAA;AAFX,kBAAA,UAAA,EAAA,KAAA,CAAA,KAAA,CAAA,MAAA,CAAA,KAAA,CAAA,KAAA,IAAA;AAAA,kBAAA,qBAAA,aAAA,KAAA,CAAA,KAAA,CAAA,MAAA,CAAA,KAAA,IAAA,MAAA,CAAA;;;;;;;AAGQ,gBAAA,CAAA,MAAM,CAAC,IAAI;AAAvB,qBAAAG,SAAA,EAAA,EAAAC,kBAAA,CAA8B,QAA9B,UAA8B,EAAAC,eAAA,CAAA,aAAA,CAAA,MAAA,CAAA,IAAA,CAAA,CAAA,EAAA,CAAA,YAAA;;;;aAGtB,KAAI,CAAA,OAAA;gDAKT,CAAA,GAAA,YAAA,EAAAA,eAAA,CADA,KAAO,CAAA,OAAA,CAAA,EAAA,CAAA,YAAA;;;wBAIZD,kBAEK,CAAA,GAAA,EAFL,WAEK,EADDC,eAAA,CAAA,QAAA,CAAA,IAAI,CAAC,MAAM,CAAA,MAAA,CAAC,QAAQ,CAAA,IAAK,QAAC,CAAA,CAAA,CAAA,eAAA,EAAA,MAAA,CAAA,CAAA,EAAA,CAAA,YAAA,CAAA;;;;;;;;"}
@@ -46,6 +46,11 @@ var script = {
46
46
  eyebrow: { type: String, default: '' },
47
47
  /** Sentence under the title (board look). */
48
48
  subtitle: { type: String, default: '' },
49
+ /**
50
+ * Leave out the board header: the body draws its own title and close
51
+ * button (CnUserSettingsDialog). `name` stays the accessible name.
52
+ */
53
+ headless: { type: Boolean, default: false },
49
54
  },
50
55
 
51
56
  emits: ['closing'],
@@ -1 +1 @@
1
- {"version":3,"file":"CnDialog.vue2.js","sources":["../../../../src/components/CnDialog/CnDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<NcDialog\n\t\t:name=\"name\"\n\t\t:size=\"isBoard ? 'normal' : size\"\n\t\t:noClose=\"noClose\"\n\t\t:class=\"frameClass\"\n\t\t:style=\"frameStyle\"\n\t\t@closing=\"onClosing\">\n\t\t<CnDialogHeader v-if=\"isBoard\"\n\t\t\t:title=\"name\"\n\t\t\t:eyebrow=\"eyebrow\"\n\t\t\t:subtitle=\"subtitle\"\n\t\t\t:noClose=\"noClose\"\n\t\t\t@close=\"onClosing()\" />\n\t\t<!-- @slot default The dialog body, below the board header. -->\n\t\t<slot />\n\t\t<template v-if=\"$slots.actions\" #actions>\n\t\t\t<!-- @slot actions The dialog footer buttons. -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { NcDialog } from '@nextcloud/vue'\nimport CnDialogHeader from '../CnDialogHeader/CnDialogHeader.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { resolveDialogWidth } from '../../utils/dialogWidths.js'\n\n/**\n * CnDialog - the one place where a `Cn*` dialog turns into the\n * board dialog (screens-dialog-parity).\n *\n * In the Nextcloud look it is `NcDialog` with the caller's `size`, unchanged.\n * In the board look it passes `size=\"normal\"`, puts `cn-look-board` and\n * `cn-dialog-board` on the teleported container (a class on CnAppRoot cannot\n * reach it), sets `--cn-dialog-width` from the width role, and renders the\n * board header (eyebrow, title, subtitle, round close button) above the\n * default slot. The NcDialog heading stays in the DOM, visually hidden, as the\n * dialog's accessible name.\n *\n * Other attributes (`open`, `data-testid`, listeners such as `update:open`)\n * fall through to NcDialog.\n *\n * @spec openspec/changes/screens-dialog-parity/specs/dialog-system/spec.md\n *\n * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n * @slot default The dialog body, below the board header.\n * @slot actions The dialog footer buttons.\n */\nexport default {\n\tname: 'CnDialog',\n\n\tcomponents: { NcDialog, CnDialogHeader },\n\n\tprops: {\n\t\t/** Dialog title; also the accessible name. */\n\t\tname: { type: String, required: true },\n\t\t/** NcDialog size, used in the Nextcloud look only. */\n\t\tsize: { type: String, default: 'small' },\n\t\t/** Block closing while an operation runs. */\n\t\tnoClose: { type: Boolean, default: false },\n\t\t/** The look; unset follows the injected `cnLook`. */\n\t\tlook: { type: String, default: undefined },\n\t\t/** Width role in the board look (`confirm`, `form`, `wizard`). */\n\t\twidth: { type: String, default: '' },\n\t\t/** The component's own default width role. */\n\t\tdefaultWidth: { type: String, default: 'form' },\n\t\t/** Context line above the title (board look). */\n\t\teyebrow: { type: String, default: '' },\n\t\t/** Sentence under the title (board look). */\n\t\tsubtitle: { type: String, default: '' },\n\t},\n\n\temits: ['closing'],\n\n\tsetup(props) {\n\t\tconst { isBoard, lookClass } = useLook(props)\n\t\treturn { isBoard, lookClass }\n\t},\n\n\tcomputed: {\n\t\tresolvedWidth() {\n\t\t\treturn resolveDialogWidth(this.width, this.defaultWidth)\n\t\t},\n\n\t\tframeClass() {\n\t\t\treturn this.isBoard\n\t\t\t\t? [this.lookClass, 'cn-dialog-board', `cn-dialog-board--${this.resolvedWidth.role}`]\n\t\t\t\t: null\n\t\t},\n\n\t\tframeStyle() {\n\t\t\treturn this.isBoard ? { '--cn-dialog-width': `${this.resolvedWidth.px}px` } : null\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Forward a close request.\n\t\t *\n\t\t * @param {unknown} [result] The NcDialog closing payload.\n\t\t */\n\t\tonClosing(result) {\n\t\t\t/**\n\t\t\t * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n\t\t\t */\n\t\t\tthis.$emit('closing', result)\n\t\t},\n\t},\n}\n</script>\n"],"names":["CnDialogHeader"],"mappings":";;;;;AAiCA;;AAEC;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,UAAU;;AAEhB,CAAA,UAAU,EAAE,EAAE,QAAQ,kBAAEA,YAAgB;;AAExC,CAAA,KAAK,EAAE;AACN;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;AACtC;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS;AACxC;AACA,EAAA,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO;AAC1C;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW;;AAE1C,EAAA,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAC,EAAG;AACpC;AACA,EAAA,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;AAC/C;AACA,EAAA,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;AACtC;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;EACvC;;AAED,CAAA,KAAK,EAAE,CAAC,SAAS,CAAC;;CAElB,KAAK,CAAC,KAAK,EAAE;AACZ,EAAA,MAAM,EAAE,OAAO,EAAE,SAAU,EAAA,GAAI,OAAO,CAAC,KAAK,EAAA;EAC5C,OAAO,EAAE,OAAO,EAAE,SAAU,EAAA;EAC5B;;AAED,CAAA,QAAQ,EAAE;AACT,EAAA,aAAa,GAAG;GACf,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAA;GACvD;;EAED,UAAU,GAAG;AACZ,GAAA,OAAO,IAAI,CAAC,OAAM;AACjB,MAAE,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;MACjF,IAAG;GACN;;EAED,UAAU,GAAG;AACZ,GAAA,OAAO,IAAI,CAAC,OAAQ,GAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,CAAE,EAAA,GAAI,IAAG;GACjF;EACD;;AAED,CAAA,OAAO,EAAE;AACR;AACC;AACA;;;AAGD,EAAA,SAAS,CAAC,MAAM,EAAE;AACjB;;;GAGA,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAA;GAC5B;EACD;AACF;;;;"}
1
+ {"version":3,"file":"CnDialog.vue2.js","sources":["../../../../src/components/CnDialog/CnDialog.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<NcDialog\n\t\t:name=\"name\"\n\t\t:size=\"isBoard ? 'normal' : size\"\n\t\t:noClose=\"noClose\"\n\t\t:class=\"frameClass\"\n\t\t:style=\"frameStyle\"\n\t\t@closing=\"onClosing\">\n\t\t<CnDialogHeader v-if=\"isBoard && !headless\"\n\t\t\t:title=\"name\"\n\t\t\t:eyebrow=\"eyebrow\"\n\t\t\t:subtitle=\"subtitle\"\n\t\t\t:noClose=\"noClose\"\n\t\t\t@close=\"onClosing()\" />\n\t\t<!-- @slot default The dialog body, below the board header. -->\n\t\t<slot />\n\t\t<template v-if=\"$slots.actions\" #actions>\n\t\t\t<!-- @slot actions The dialog footer buttons. -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { NcDialog } from '@nextcloud/vue'\nimport CnDialogHeader from '../CnDialogHeader/CnDialogHeader.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { resolveDialogWidth } from '../../utils/dialogWidths.js'\n\n/**\n * CnDialog - the one place where a `Cn*` dialog turns into the\n * board dialog (screens-dialog-parity).\n *\n * In the Nextcloud look it is `NcDialog` with the caller's `size`, unchanged.\n * In the board look it passes `size=\"normal\"`, puts `cn-look-board` and\n * `cn-dialog-board` on the teleported container (a class on CnAppRoot cannot\n * reach it), sets `--cn-dialog-width` from the width role, and renders the\n * board header (eyebrow, title, subtitle, round close button) above the\n * default slot. The NcDialog heading stays in the DOM, visually hidden, as the\n * dialog's accessible name.\n *\n * Other attributes (`open`, `data-testid`, listeners such as `update:open`)\n * fall through to NcDialog.\n *\n * @spec openspec/changes/screens-dialog-parity/specs/dialog-system/spec.md\n *\n * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n * @slot default The dialog body, below the board header.\n * @slot actions The dialog footer buttons.\n */\nexport default {\n\tname: 'CnDialog',\n\n\tcomponents: { NcDialog, CnDialogHeader },\n\n\tprops: {\n\t\t/** Dialog title; also the accessible name. */\n\t\tname: { type: String, required: true },\n\t\t/** NcDialog size, used in the Nextcloud look only. */\n\t\tsize: { type: String, default: 'small' },\n\t\t/** Block closing while an operation runs. */\n\t\tnoClose: { type: Boolean, default: false },\n\t\t/** The look; unset follows the injected `cnLook`. */\n\t\tlook: { type: String, default: undefined },\n\t\t/** Width role in the board look (`confirm`, `form`, `wizard`). */\n\t\twidth: { type: String, default: '' },\n\t\t/** The component's own default width role. */\n\t\tdefaultWidth: { type: String, default: 'form' },\n\t\t/** Context line above the title (board look). */\n\t\teyebrow: { type: String, default: '' },\n\t\t/** Sentence under the title (board look). */\n\t\tsubtitle: { type: String, default: '' },\n\t\t/**\n\t\t * Leave out the board header: the body draws its own title and close\n\t\t * button (CnUserSettingsDialog). `name` stays the accessible name.\n\t\t */\n\t\theadless: { type: Boolean, default: false },\n\t},\n\n\temits: ['closing'],\n\n\tsetup(props) {\n\t\tconst { isBoard, lookClass } = useLook(props)\n\t\treturn { isBoard, lookClass }\n\t},\n\n\tcomputed: {\n\t\tresolvedWidth() {\n\t\t\treturn resolveDialogWidth(this.width, this.defaultWidth)\n\t\t},\n\n\t\tframeClass() {\n\t\t\treturn this.isBoard\n\t\t\t\t? [this.lookClass, 'cn-dialog-board', `cn-dialog-board--${this.resolvedWidth.role}`]\n\t\t\t\t: null\n\t\t},\n\n\t\tframeStyle() {\n\t\t\treturn this.isBoard ? { '--cn-dialog-width': `${this.resolvedWidth.px}px` } : null\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Forward a close request.\n\t\t *\n\t\t * @param {unknown} [result] The NcDialog closing payload.\n\t\t */\n\t\tonClosing(result) {\n\t\t\t/**\n\t\t\t * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n\t\t\t */\n\t\t\tthis.$emit('closing', result)\n\t\t},\n\t},\n}\n</script>\n"],"names":["CnDialogHeader"],"mappings":";;;;;AAiCA;;AAEC;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;;AAED,aAAe;AACd,CAAA,IAAI,EAAE,UAAU;;AAEhB,CAAA,UAAU,EAAE,EAAE,QAAQ,kBAAEA,YAAgB;;AAExC,CAAA,KAAK,EAAE;AACN;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;AACtC;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS;AACxC;AACA,EAAA,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO;AAC1C;AACA,EAAA,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW;;AAE1C,EAAA,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAC,EAAG;AACpC;AACA,EAAA,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ;AAC/C;AACA,EAAA,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;AACtC;AACA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI;AACvC;;;;AAIA,EAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO;EAC3C;;AAED,CAAA,KAAK,EAAE,CAAC,SAAS,CAAC;;CAElB,KAAK,CAAC,KAAK,EAAE;AACZ,EAAA,MAAM,EAAE,OAAO,EAAE,SAAU,EAAA,GAAI,OAAO,CAAC,KAAK,EAAA;EAC5C,OAAO,EAAE,OAAO,EAAE,SAAU,EAAA;EAC5B;;AAED,CAAA,QAAQ,EAAE;AACT,EAAA,aAAa,GAAG;GACf,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAA;GACvD;;EAED,UAAU,GAAG;AACZ,GAAA,OAAO,IAAI,CAAC,OAAM;AACjB,MAAE,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;MACjF,IAAG;GACN;;EAED,UAAU,GAAG;AACZ,GAAA,OAAO,IAAI,CAAC,OAAQ,GAAE,EAAE,mBAAmB,EAAE,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,CAAE,EAAA,GAAI,IAAG;GACjF;EACD;;AAED,CAAA,OAAO,EAAE;AACR;AACC;AACA;;;AAGD,EAAA,SAAS,CAAC,MAAM,EAAE;AACjB;;;GAGA,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,EAAA;GAC5B;EACD;AACF;;;;"}
@@ -13,7 +13,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
13
13
  onClosing: $options.onClosing
14
14
  }, createSlots({
15
15
  default: withCtx(() => [
16
- ($setup.isBoard)
16
+ ($setup.isBoard && !$props.headless)
17
17
  ? (openBlock(), createBlock(_component_CnDialogHeader, {
18
18
  key: 0,
19
19
  title: $props.name,
@@ -1 +1 @@
1
- {"version":3,"file":"CnDialog.vue3.js","sources":["../../../../src/components/CnDialog/CnDialog.vue?vue&type=template&id=4d1361c0&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<NcDialog\n\t\t:name=\"name\"\n\t\t:size=\"isBoard ? 'normal' : size\"\n\t\t:noClose=\"noClose\"\n\t\t:class=\"frameClass\"\n\t\t:style=\"frameStyle\"\n\t\t@closing=\"onClosing\">\n\t\t<CnDialogHeader v-if=\"isBoard\"\n\t\t\t:title=\"name\"\n\t\t\t:eyebrow=\"eyebrow\"\n\t\t\t:subtitle=\"subtitle\"\n\t\t\t:noClose=\"noClose\"\n\t\t\t@close=\"onClosing()\" />\n\t\t<!-- @slot default The dialog body, below the board header. -->\n\t\t<slot />\n\t\t<template v-if=\"$slots.actions\" #actions>\n\t\t\t<!-- @slot actions The dialog footer buttons. -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { NcDialog } from '@nextcloud/vue'\nimport CnDialogHeader from '../CnDialogHeader/CnDialogHeader.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { resolveDialogWidth } from '../../utils/dialogWidths.js'\n\n/**\n * CnDialog - the one place where a `Cn*` dialog turns into the\n * board dialog (screens-dialog-parity).\n *\n * In the Nextcloud look it is `NcDialog` with the caller's `size`, unchanged.\n * In the board look it passes `size=\"normal\"`, puts `cn-look-board` and\n * `cn-dialog-board` on the teleported container (a class on CnAppRoot cannot\n * reach it), sets `--cn-dialog-width` from the width role, and renders the\n * board header (eyebrow, title, subtitle, round close button) above the\n * default slot. The NcDialog heading stays in the DOM, visually hidden, as the\n * dialog's accessible name.\n *\n * Other attributes (`open`, `data-testid`, listeners such as `update:open`)\n * fall through to NcDialog.\n *\n * @spec openspec/changes/screens-dialog-parity/specs/dialog-system/spec.md\n *\n * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n * @slot default The dialog body, below the board header.\n * @slot actions The dialog footer buttons.\n */\nexport default {\n\tname: 'CnDialog',\n\n\tcomponents: { NcDialog, CnDialogHeader },\n\n\tprops: {\n\t\t/** Dialog title; also the accessible name. */\n\t\tname: { type: String, required: true },\n\t\t/** NcDialog size, used in the Nextcloud look only. */\n\t\tsize: { type: String, default: 'small' },\n\t\t/** Block closing while an operation runs. */\n\t\tnoClose: { type: Boolean, default: false },\n\t\t/** The look; unset follows the injected `cnLook`. */\n\t\tlook: { type: String, default: undefined },\n\t\t/** Width role in the board look (`confirm`, `form`, `wizard`). */\n\t\twidth: { type: String, default: '' },\n\t\t/** The component's own default width role. */\n\t\tdefaultWidth: { type: String, default: 'form' },\n\t\t/** Context line above the title (board look). */\n\t\teyebrow: { type: String, default: '' },\n\t\t/** Sentence under the title (board look). */\n\t\tsubtitle: { type: String, default: '' },\n\t},\n\n\temits: ['closing'],\n\n\tsetup(props) {\n\t\tconst { isBoard, lookClass } = useLook(props)\n\t\treturn { isBoard, lookClass }\n\t},\n\n\tcomputed: {\n\t\tresolvedWidth() {\n\t\t\treturn resolveDialogWidth(this.width, this.defaultWidth)\n\t\t},\n\n\t\tframeClass() {\n\t\t\treturn this.isBoard\n\t\t\t\t? [this.lookClass, 'cn-dialog-board', `cn-dialog-board--${this.resolvedWidth.role}`]\n\t\t\t\t: null\n\t\t},\n\n\t\tframeStyle() {\n\t\t\treturn this.isBoard ? { '--cn-dialog-width': `${this.resolvedWidth.px}px` } : null\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Forward a close request.\n\t\t *\n\t\t * @param {unknown} [result] The NcDialog closing payload.\n\t\t */\n\t\tonClosing(result) {\n\t\t\t/**\n\t\t\t * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n\t\t\t */\n\t\t\tthis.$emit('closing', result)\n\t\t},\n\t},\n}\n</script>\n"],"names":["_createBlock","_renderSlot"],"mappings":";;;;;;uBASEA;AACC,IAAA,IAAI,EAAE,MAAI,CAAA,IAAA;IACV,IAAI,EAAE,MAAO,CAAA,OAAA,GAAA,QAAA,GAAM,MAAA,CAAA,IAAA;AACnB,IAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,IAAA,KAAK,iBAAE,QAAK,CAAA,UAAA,CAAA;AACZ,IAAA,KAAK,iBAAE,QAAU,CAAA,UAAA,CAAA;AACjB,IAAA,SAAO,EAAE,QAAS,CAAA,SAAA;;qBAClB,MAKuB;OALN,MAAA,CAAA,OAAA;wBAAjBA,WAKuB,CAAA,yBAAA,EAAA;;AAJtB,YAAA,KAAK,EAAE,MAAI,CAAA,IAAA;AACX,YAAA,OAAO,EAAE,MAAQ,CAAA,OAAA;AACjB,YAAA,QAAK,EAAA,MAAA,CAAA,QAAA;AACL,YAAA,OAAM,EAAG,MAAO,CAAA,OAAA;AAChB,YAAA,OAAK,uCAAE,QAAS,CAAA,SAAA,EAAA,CAAA,CAAA;;;MAElBC,UAAQ,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,CAAA;;;;AACC,IAAA,CAAA,IAAA,CAAA,MAAA,CAAA,OAAA;;gBAAA,SAAA;;;;;;;;;;;;"}
1
+ {"version":3,"file":"CnDialog.vue3.js","sources":["../../../../src/components/CnDialog/CnDialog.vue?vue&type=template&id=573c17fc&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<NcDialog\n\t\t:name=\"name\"\n\t\t:size=\"isBoard ? 'normal' : size\"\n\t\t:noClose=\"noClose\"\n\t\t:class=\"frameClass\"\n\t\t:style=\"frameStyle\"\n\t\t@closing=\"onClosing\">\n\t\t<CnDialogHeader v-if=\"isBoard && !headless\"\n\t\t\t:title=\"name\"\n\t\t\t:eyebrow=\"eyebrow\"\n\t\t\t:subtitle=\"subtitle\"\n\t\t\t:noClose=\"noClose\"\n\t\t\t@close=\"onClosing()\" />\n\t\t<!-- @slot default The dialog body, below the board header. -->\n\t\t<slot />\n\t\t<template v-if=\"$slots.actions\" #actions>\n\t\t\t<!-- @slot actions The dialog footer buttons. -->\n\t\t\t<slot name=\"actions\" />\n\t\t</template>\n\t</NcDialog>\n</template>\n\n<script>\nimport { NcDialog } from '@nextcloud/vue'\nimport CnDialogHeader from '../CnDialogHeader/CnDialogHeader.vue'\nimport { useLook } from '../../composables/useLook.js'\nimport { resolveDialogWidth } from '../../utils/dialogWidths.js'\n\n/**\n * CnDialog - the one place where a `Cn*` dialog turns into the\n * board dialog (screens-dialog-parity).\n *\n * In the Nextcloud look it is `NcDialog` with the caller's `size`, unchanged.\n * In the board look it passes `size=\"normal\"`, puts `cn-look-board` and\n * `cn-dialog-board` on the teleported container (a class on CnAppRoot cannot\n * reach it), sets `--cn-dialog-width` from the width role, and renders the\n * board header (eyebrow, title, subtitle, round close button) above the\n * default slot. The NcDialog heading stays in the DOM, visually hidden, as the\n * dialog's accessible name.\n *\n * Other attributes (`open`, `data-testid`, listeners such as `update:open`)\n * fall through to NcDialog.\n *\n * @spec openspec/changes/screens-dialog-parity/specs/dialog-system/spec.md\n *\n * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n * @slot default The dialog body, below the board header.\n * @slot actions The dialog footer buttons.\n */\nexport default {\n\tname: 'CnDialog',\n\n\tcomponents: { NcDialog, CnDialogHeader },\n\n\tprops: {\n\t\t/** Dialog title; also the accessible name. */\n\t\tname: { type: String, required: true },\n\t\t/** NcDialog size, used in the Nextcloud look only. */\n\t\tsize: { type: String, default: 'small' },\n\t\t/** Block closing while an operation runs. */\n\t\tnoClose: { type: Boolean, default: false },\n\t\t/** The look; unset follows the injected `cnLook`. */\n\t\tlook: { type: String, default: undefined },\n\t\t/** Width role in the board look (`confirm`, `form`, `wizard`). */\n\t\twidth: { type: String, default: '' },\n\t\t/** The component's own default width role. */\n\t\tdefaultWidth: { type: String, default: 'form' },\n\t\t/** Context line above the title (board look). */\n\t\teyebrow: { type: String, default: '' },\n\t\t/** Sentence under the title (board look). */\n\t\tsubtitle: { type: String, default: '' },\n\t\t/**\n\t\t * Leave out the board header: the body draws its own title and close\n\t\t * button (CnUserSettingsDialog). `name` stays the accessible name.\n\t\t */\n\t\theadless: { type: Boolean, default: false },\n\t},\n\n\temits: ['closing'],\n\n\tsetup(props) {\n\t\tconst { isBoard, lookClass } = useLook(props)\n\t\treturn { isBoard, lookClass }\n\t},\n\n\tcomputed: {\n\t\tresolvedWidth() {\n\t\t\treturn resolveDialogWidth(this.width, this.defaultWidth)\n\t\t},\n\n\t\tframeClass() {\n\t\t\treturn this.isBoard\n\t\t\t\t? [this.lookClass, 'cn-dialog-board', `cn-dialog-board--${this.resolvedWidth.role}`]\n\t\t\t\t: null\n\t\t},\n\n\t\tframeStyle() {\n\t\t\treturn this.isBoard ? { '--cn-dialog-width': `${this.resolvedWidth.px}px` } : null\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Forward a close request.\n\t\t *\n\t\t * @param {unknown} [result] The NcDialog closing payload.\n\t\t */\n\t\tonClosing(result) {\n\t\t\t/**\n\t\t\t * @event closing Emitted when the dialog asks to close (close button, Escape, backdrop). Blocked while `noClose` is set.\n\t\t\t */\n\t\t\tthis.$emit('closing', result)\n\t\t},\n\t},\n}\n</script>\n"],"names":["_createBlock","_renderSlot"],"mappings":";;;;;;uBASEA;AACC,IAAA,IAAI,EAAE,MAAI,CAAA,IAAA;IACV,IAAI,EAAE,MAAO,CAAA,OAAA,GAAA,QAAA,GAAM,MAAA,CAAA,IAAA;AACnB,IAAA,OAAO,EAAE,MAAO,CAAA,OAAA;AAChB,IAAA,KAAK,iBAAE,QAAK,CAAA,UAAA,CAAA;AACZ,IAAA,KAAK,iBAAE,QAAU,CAAA,UAAA,CAAA;AACjB,IAAA,SAAO,EAAE,QAAS,CAAA,SAAA;;qBAClB,MAKuB;AALN,MAAA,CAAA,MAAA,CAAA,OAAA,KAAA,MAAA,CAAA,QAAA;wBAAjBA,WAKuB,CAAA,yBAAA,EAAA;;AAJtB,YAAA,KAAK,EAAE,MAAI,CAAA,IAAA;AACX,YAAA,OAAO,EAAE,MAAQ,CAAA,OAAA;AACjB,YAAA,QAAK,EAAA,MAAA,CAAA,QAAA;AACL,YAAA,OAAM,EAAG,MAAO,CAAA,OAAA;AAChB,YAAA,OAAK,uCAAE,QAAS,CAAA,SAAA,EAAA,CAAA,CAAA;;;MAElBC,UAAQ,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,CAAA;;;;AACC,IAAA,CAAA,IAAA,CAAA,MAAA,CAAA,OAAA;;gBAAA,SAAA;;;;;;;;;;;;"}
@@ -960,6 +960,19 @@ var script = {
960
960
  default: null,
961
961
  },
962
962
 
963
+ /**
964
+ * Whether the board look draws the saved views as chips in the toolbar
965
+ * (manifest `config.savedViewChips`). `false` keeps only Save view,
966
+ * for a page whose views live in the side panel's Weergaven tab
967
+ * (DqZaken, DqZakenSorteren, DqZakenKaart, DqWerkbord, DqFilterBeheren).
968
+ *
969
+ * @spec openspec/changes/saved-view-chips-switch/specs/saved-views/spec.md#requirement-an-index-page-can-leave-the-saved-view-chips-out-of-the-toolbar
970
+ */
971
+ savedViewChips: {
972
+ type: Boolean,
973
+ default: true,
974
+ },
975
+
963
976
  /**
964
977
  * Where the quick-filter chips sit (manifest `config.quickFilterPlacement`).
965
978
  * `''` (the default) as before. `'toolbar'` keeps them on one row with