@conduction/nextcloud-vue 2.140.0 → 2.141.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +10 -2
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +11 -3
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +12 -0
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +57 -40
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +1 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +5 -3
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +65 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +120 -69
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue.js +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js +47 -9
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMapWidget/CnMapWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +3 -3
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +2 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordNoteRows.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordNoteRows.vue2.js +10 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordNoteRows.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordNoteRows.vue3.js +34 -26
- package/dist/esm/components/CnRecordListWidget/CnRecordNoteRows.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +2 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +2 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +652 -391
- package/dist/esm/utils/groupSublines.js +120 -0
- package/dist/esm/utils/groupSublines.js.map +1 -0
- package/dist/nextcloud-vue.cjs.js +974 -638
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +652 -391
- package/l10n/en.json +2 -1
- package/l10n/nl.json +2 -1
- package/package.json +1 -1
- package/src/components/CnAssignDialog/CnAssignDialog.vue +10 -2
- package/src/components/CnCellRenderer/CnCellRenderer.vue +11 -3
- package/src/components/CnChartWidget/CnChartWidget.md +1 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +49 -4
- package/src/components/CnDashboardPage/CnDashboardPage.vue +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +6 -3
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +101 -3
- package/src/components/CnMapWidget/CnMapWidget.vue +47 -9
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +3 -3
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +20 -1
- package/src/components/CnRecordListWidget/CnRecordNoteRows.vue +33 -9
- package/src/css/dialog.css +13 -1
- package/src/css/look-board-detail.css +12 -9
- package/src/css/look-board-index.css +90 -7
- package/src/css/look-board.css +92 -0
- package/src/css/table.css +12 -0
- package/src/utils/groupSublines.js +125 -0
|
@@ -2,7 +2,7 @@ import script from './CnRecordNoteRows.vue2.js';
|
|
|
2
2
|
import { render } from './CnRecordNoteRows.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-949ca7ea";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -196,6 +196,16 @@ var script = {
|
|
|
196
196
|
this.drafts = { ...this.drafts, [key]: String(value ?? '') };
|
|
197
197
|
},
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* The id of a row's note field, for its label.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} key The row key.
|
|
203
|
+
* @return {string} The id.
|
|
204
|
+
*/
|
|
205
|
+
fieldId(key) {
|
|
206
|
+
return `cn-record-notes-${this.$.uid}-${String(key).replace(/[^A-Za-z0-9_-]/g, '-')}`
|
|
207
|
+
},
|
|
208
|
+
|
|
199
209
|
/**
|
|
200
210
|
* @param {string} key The row key.
|
|
201
211
|
* @return {boolean} Whether the row has a note typed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnRecordNoteRows.vue2.js","sources":["../../../../src/components/CnRecordListWidget/CnRecordNoteRows.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-record-notes\" data-testid=\"cn-record-list-notes\">\n\t\t<p class=\"cn-record-notes__ready\" data-testid=\"cn-record-list-notes-ready\">\n\t\t\t<span class=\"cn-record-notes__ready-figure\">{{ readyCount }}</span>\n\t\t\t<span class=\"cn-record-notes__ready-label\">{{ readyLabel }}</span>\n\t\t</p>\n\t\t<div\n\t\t\tv-for=\"item in items\"\n\t\t\t:key=\"item.key\"\n\t\t\tclass=\"cn-record-notes__row\"\n\t\t\tdata-testid=\"cn-record-list-item\">\n\t\t\t<div class=\"cn-record-notes__head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"item.pill\"\n\t\t\t\t\t:label=\"item.pill.label\"\n\t\t\t\t\t:variant=\"item.pill.variant\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"item.tag\"\n\t\t\t\t\tv-if=\"item.title\"\n\t\t\t\t\tclass=\"cn-record-notes__title\"\n\t\t\t\t\t:class=\"{ 'cn-record-notes__title--link': item.tag !== 'div' }\"\n\t\t\t\t\tv-bind=\"item.attrs\">\n\t\t\t\t\t{{ item.title }}\n\t\t\t\t</component>\n\t\t\t\t<span v-if=\"item.meta\" class=\"cn-record-notes__meta\">{{ item.meta }}</span>\n\t\t\t\t<span class=\"cn-record-notes__spacer\" />\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"item.due\"\n\t\t\t\t\tclass=\"cn-record-notes__due\"\n\t\t\t\t\t:class=\"`cn-record-notes__due--${dueToneOf(item.due)}`\"\n\t\t\t\t\tdata-testid=\"cn-record-list-due\">{{ item.due.text }}</span>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__fields\">\n\t\t\t\t<NcTextField\n\t\t\t\t\tclass=\"cn-record-notes__field\"\n\t\t\t\t\t:modelValue=\"drafts[item.key] || ''\"\n\t\t\t\t\t:label=\"fieldLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:placeholder=\"placeholder\"\n\t\t\t\t\t:disabled=\"busy\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-note-${item.key}`\"\n\t\t\t\t\t@update:modelValue=\"setDraft(item.key, $event)\" />\n\t\t\t\t<div v-if=\"leaf && leafProvider\" class=\"cn-record-notes__leaf\" :data-testid=\"`cn-record-list-leaf-${item.key}`\">\n\t\t\t\t\t<CnLeafMountHost\n\t\t\t\t\t\tv-if=\"leafIsMount\"\n\t\t\t\t\t\t:provider=\"leafProvider\"\n\t\t\t\t\t\t:mountProps=\"leafProps(item.row)\" />\n\t\t\t\t\t<component :is=\"leafComponent\" v-else-if=\"leafComponent\" v-bind=\"leafProps(item.row)\" />\n\t\t\t\t</div>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t:disabled=\"busy || !hasDraft(item.key)\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-record-${item.key}`\"\n\t\t\t\t\t@click=\"record(item)\">\n\t\t\t\t\t{{ recordLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p\n\t\t\t\tv-if=\"leafUnavailable\"\n\t\t\t\tclass=\"cn-record-notes__leaf-missing\"\n\t\t\t\t:data-testid=\"`cn-record-list-leaf-missing-${item.key}`\">\n\t\t\t\t{{ leafUnavailableText }}\n\t\t\t</p>\n\t\t</div>\n\t\t<p v-if=\"error\"\n\t\t\tclass=\"cn-record-notes__error\"\n\t\t\trole=\"alert\"\n\t\t\tdata-testid=\"cn-record-list-notes-error\">\n\t\t\t{{ error }}\n\t\t</p>\n\t\t<div v-if=\"recordAll\" class=\"cn-record-notes__all\" data-testid=\"cn-record-list-record-all\">\n\t\t\t<div class=\"cn-record-notes__all-text\">\n\t\t\t\t<h3 v-if=\"recordAll.title\" class=\"cn-record-notes__all-title\">\n\t\t\t\t\t{{ recordAll.title }}\n\t\t\t\t</h3>\n\t\t\t\t<p v-if=\"recordAll.text\" class=\"cn-record-notes__all-sentence\">\n\t\t\t\t\t{{ recordAll.text }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__all-actions\">\n\t\t\t\t<NcButton v-if=\"recordAll.cancel\" variant=\"secondary\" :to=\"recordAll.cancel.to\">\n\t\t\t\t\t{{ recordAll.cancel.label }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"busy || readyCount === 0\"\n\t\t\t\t\tdata-testid=\"cn-record-list-record-all-button\"\n\t\t\t\t\t@click=\"recordEvery\">\n\t\t\t\t\t<template v-if=\"recordAll.icon\" #icon>\n\t\t\t\t\t\t<CnIcon :name=\"recordAll.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ recordAll.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcTextField } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnLeafMountHost from '../CnLeafMountHost/CnLeafMountHost.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\n\n/** The bus channel every endpoint-bound widget on the page refetches on. */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * The document event a recorded note sends, so a row's leaf (humaniq's\n * hours) can record what it holds for the same object at the same moment.\n * `detail` is the row's leaf props plus `note`.\n */\nconst NOTE_RECORDED_EVENT = 'cn-record-notes:recorded'\n\n/**\n * The rows of a record list drawn as notes to record (`presentation:\n * \"notes\"`, DqDagAfsluiten \"Nog open van vandaag\"): per row its pill, title,\n * meta and due text, a field for what happened, an optional integration leaf\n * (humaniq's hours) and a button that records the note on the row's own\n * notes endpoint. What is typed and not yet recorded stays in this browser\n * (session storage) and is counted as the \"ready to record\" figure; one\n * button records every filled row. After a note is recorded the page's\n * endpoint widgets refetch, so the row moves to whatever lists the server\n * keeps of recorded work.\n *\n * @spec openspec/changes/record-list-notes/specs/record-list-notes/spec.md#requirement-a-record-list-can-collect-and-record-a-note-per-row\n */\nexport default {\n\tname: 'CnRecordNoteRows',\n\n\tcomponents: { CnIcon, CnLeafMountHost, CnStatusBadge, NcButton, NcTextField },\n\n\tprops: {\n\t\t/** The list's rows as the record list builds them (`key`, `row`, `tag`, `attrs`, `title`, `meta`, `pill`, `due`). */\n\t\titems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * `noteAction`, already translated: `{ urlField?, url?, bodyField?,\n\t\t * label, fieldLabel, placeholder?, readyLabel, draftsKey?, errorText? }`.\n\t\t */\n\t\taction: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** `recordAll`, already translated: `{ label, title?, text?, icon?, cancel?: { label, to } }`, or null. */\n\t\trecordAll: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** `rowLeaf`: `{ id, app?, register?, objectIdField, schemaField?, schema?, unavailableText? }`, or null. */\n\t\tleaf: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup() {\n\t\tconst { getById } = useIntegrationRegistry()\n\t\treturn { getProvider: getById }\n\t},\n\n\tdata() {\n\t\treturn { drafts: this.readDrafts(), busy: false, error: '' }\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The session storage key of this list's drafts. */\n\t\tdraftsKey() {\n\t\t\treturn `cn-record-list-notes:${this.action.draftsKey || 'default'}`\n\t\t},\n\n\t\t/** @return {number} The rows with a note typed and not yet recorded. */\n\t\treadyCount() {\n\t\t\treturn this.items.filter((item) => this.hasDraft(item.key)).length\n\t\t},\n\n\t\t/** @return {string} The label of the ready figure. */\n\t\treadyLabel() {\n\t\t\treturn this.action.readyLabel || t('nextcloud-vue', 'filled in, not recorded yet')\n\t\t},\n\n\t\t/** @return {string} */\n\t\trecordLabel() {\n\t\t\treturn this.action.label || t('nextcloud-vue', 'Record')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tfieldLabel() {\n\t\t\treturn this.action.fieldLabel || t('nextcloud-vue', 'Note')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tplaceholder() {\n\t\t\treturn this.action.placeholder || ''\n\t\t},\n\n\t\t/** @return {object|null} The leaf's integration provider, when one is registered. */\n\t\tleafProvider() {\n\t\t\treturn this.leaf && this.leaf.id ? (this.getProvider(this.leaf.id) || null) : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the leaf mounts itself (`renderMode: \"mount\"`). */\n\t\tleafIsMount() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn Boolean(provider) && provider.renderMode === 'mount' && typeof provider.mount === 'function'\n\t\t},\n\n\t\t/** @return {object|null} The leaf's component, in component mode. */\n\t\tleafComponent() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn provider ? (provider.tab || provider.widget || null) : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the leaf's app is installed but the leaf is not available, so\n\t\t * the row says so instead of silently showing no field.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tleafUnavailable() {\n\t\t\treturn Boolean(this.leaf && this.leaf.app && !this.leafProvider && isAppInstalled(this.leaf.app))\n\t\t},\n\n\t\t/** @return {string} */\n\t\tleafUnavailableText() {\n\t\t\treturn this.leaf?.unavailableText || t('nextcloud-vue', 'This field is not available here.')\n\t\t},\n\t},\n\n\twatch: {\n\t\tdrafts: {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.saveDrafts()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * The drafts this browser session kept, by row key.\n\t\t *\n\t\t * @return {Object<string, string>}\n\t\t */\n\t\treadDrafts() {\n\t\t\ttry {\n\t\t\t\tconst raw = window.sessionStorage.getItem(`cn-record-list-notes:${this.action?.draftsKey || 'default'}`)\n\t\t\t\tconst parsed = raw ? JSON.parse(raw) : {}\n\t\t\t\treturn parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}\n\t\t\t} catch {\n\t\t\t\treturn {}\n\t\t\t}\n\t\t},\n\n\t\t/** @return {void} */\n\t\tsaveDrafts() {\n\t\t\ttry {\n\t\t\t\twindow.sessionStorage.setItem(this.draftsKey, JSON.stringify(this.drafts))\n\t\t\t} catch {\n\t\t\t\t// Without session storage the drafts live as long as the page.\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The colour of a due text: a term that ended or ends today in the\n\t\t * error colour, one still to come in the warning colour.\n\t\t *\n\t\t * @param {{tone: string}} due The due text.\n\t\t * @return {string} `error`, `warning` or `muted`.\n\t\t */\n\t\tdueToneOf(due) {\n\t\t\tif (due.tone === 'danger' || due.tone === 'today') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due.tone === 'upcoming' ? 'warning' : 'muted'\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @param {string} value The typed note.\n\t\t * @return {void}\n\t\t */\n\t\tsetDraft(key, value) {\n\t\t\tthis.drafts = { ...this.drafts, [key]: String(value ?? '') }\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @return {boolean} Whether the row has a note typed.\n\t\t */\n\t\thasDraft(key) {\n\t\t\treturn String(this.drafts[key] ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * The props the row's leaf gets: the row's object, register and schema.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {object}\n\t\t */\n\t\tleafProps(row) {\n\t\t\tconst leaf = this.leaf || {}\n\t\t\treturn {\n\t\t\t\tobjectId: String(readPath(row, leaf.objectIdField || 'id') ?? ''),\n\t\t\t\tregister: leaf.register || '',\n\t\t\t\tschema: leaf.schemaField ? String(readPath(row, leaf.schemaField) ?? '') : (leaf.schema || ''),\n\t\t\t\tsurface: 'row',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The row's notes endpoint: the row's `urlField`, else `url` with\n\t\t * `{field}` filled from the row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {string} The URL, or ''.\n\t\t */\n\t\turlOf(row) {\n\t\t\tif (this.action.urlField) {\n\t\t\t\treturn String(readPath(row, this.action.urlField) ?? '')\n\t\t\t}\n\t\t\tconst template = String(this.action.url || '')\n\t\t\treturn template.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (_, path) => encodeURIComponent(String(readPath(row, path) ?? '')))\n\t\t},\n\n\t\t/**\n\t\t * Record one row's note, then let the page refetch.\n\t\t *\n\t\t * @param {object} item The row item.\n\t\t * @param {boolean} [refresh] Whether to refresh the page after it.\n\t\t * @return {Promise<boolean>} Whether it was recorded.\n\t\t */\n\t\tasync record(item, refresh = true) {\n\t\t\tconst text = String(this.drafts[item.key] ?? '').trim()\n\t\t\tconst url = this.urlOf(item.row)\n\t\t\tif (text === '' || url === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tawait axios.post(prefixUrl(url), { [this.action.bodyField || 'message']: text })\n\t\t\t\tif (this.leaf) {\n\t\t\t\t\tdocument.dispatchEvent(new CustomEvent(NOTE_RECORDED_EVENT, { detail: { ...this.leafProps(item.row), note: text } }))\n\t\t\t\t}\n\t\t\t\tconst { [item.key]: done, ...rest } = this.drafts\n\t\t\t\tthis.drafts = rest\n\t\t\t\tif (refresh) {\n\t\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\tthis.error = this.action.errorText || t('nextcloud-vue', 'The note could not be recorded. It is kept here; try again.')\n\t\t\t\treturn false\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Record every row with a note, one after another, then refresh once.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync recordEvery() {\n\t\t\tconst filled = this.items.filter((item) => this.hasDraft(item.key))\n\t\t\tlet any = false\n\t\t\tfor (const item of filled) {\n\t\t\t\tany = (await this.record(item, false)) || any\n\t\t\t}\n\t\t\tif (any) {\n\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-record-notes {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0;\n}\n\n.cn-record-notes__ready {\n\tdisplay: flex;\n\talign-items: baseline;\n\tgap: 6px;\n\tmargin: 0 0 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__ready-figure {\n\tfont-weight: 700;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tpadding: 14px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__head {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-record-notes__title {\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__title--link {\n\ttext-decoration: underline;\n}\n\n.cn-record-notes__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__spacer {\n\tflex: 1 1 auto;\n}\n\n.cn-record-notes__due {\n\tfont-weight: 600;\n}\n\n.cn-record-notes__due--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__due--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-record-notes__due--muted {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 400;\n}\n\n.cn-record-notes__fields {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 10px;\n}\n\n.cn-record-notes__field {\n\tflex: 1 1 260px;\n}\n\n.cn-record-notes__leaf {\n\tflex: 0 0 auto;\n}\n\n.cn-record-notes__leaf-missing,\n.cn-record-notes__error {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__all {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n\tmargin-top: 8px;\n\tpadding-top: 14px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__all-title {\n\tmargin: 0;\n\tfont-size: 16px;\n}\n\n.cn-record-notes__all-sentence {\n\tmargin: 4px 0 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__all-actions {\n\tdisplay: flex;\n\tgap: 8px;\n}\n</style>\n"],"names":["CnIcon","CnLeafMountHost","CnStatusBadge","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnRecordNoteRows.vue2.js","sources":["../../../../src/components/CnRecordListWidget/CnRecordNoteRows.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-record-notes\" data-testid=\"cn-record-list-notes\">\n\t\t<p class=\"cn-record-notes__ready\" data-testid=\"cn-record-list-notes-ready\">\n\t\t\t<span class=\"cn-record-notes__ready-figure\">{{ readyCount }}</span>\n\t\t\t<span class=\"cn-record-notes__ready-label\">{{ readyLabel }}</span>\n\t\t</p>\n\t\t<div\n\t\t\tv-for=\"item in items\"\n\t\t\t:key=\"item.key\"\n\t\t\tclass=\"cn-record-notes__row\"\n\t\t\tdata-testid=\"cn-record-list-item\">\n\t\t\t<div class=\"cn-record-notes__head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"item.pill\"\n\t\t\t\t\t:label=\"item.pill.label\"\n\t\t\t\t\t:variant=\"item.pill.variant\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"item.tag\"\n\t\t\t\t\tv-if=\"item.title\"\n\t\t\t\t\tclass=\"cn-record-notes__title\"\n\t\t\t\t\t:class=\"{ 'cn-record-notes__title--link': item.tag !== 'div' }\"\n\t\t\t\t\tv-bind=\"item.attrs\">\n\t\t\t\t\t{{ item.title }}\n\t\t\t\t</component>\n\t\t\t\t<span v-if=\"item.meta\" class=\"cn-record-notes__meta\">{{ item.meta }}</span>\n\t\t\t\t<span class=\"cn-record-notes__spacer\" />\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"item.due\"\n\t\t\t\t\tclass=\"cn-record-notes__due\"\n\t\t\t\t\t:class=\"`cn-record-notes__due--${dueToneOf(item.due)}`\"\n\t\t\t\t\tdata-testid=\"cn-record-list-due\">{{ item.due.text }}</span>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__fields\">\n\t\t\t\t<!-- The label stands above the field, as the leaf's own beside it\n\t\t\t\t (humaniq \"Uren\"), so both fields share one line. -->\n\t\t\t\t<div class=\"cn-record-notes__field\">\n\t\t\t\t\t<label :for=\"fieldId(item.key)\" class=\"cn-record-notes__field-label\">{{ fieldLabel }}</label>\n\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t:id=\"fieldId(item.key)\"\n\t\t\t\t\t\t:modelValue=\"drafts[item.key] || ''\"\n\t\t\t\t\t\t:label=\"fieldLabel\"\n\t\t\t\t\t\tlabelOutside\n\t\t\t\t\t\t:placeholder=\"placeholder\"\n\t\t\t\t\t\t:disabled=\"busy\"\n\t\t\t\t\t\t:data-testid=\"`cn-record-list-note-${item.key}`\"\n\t\t\t\t\t\t@update:modelValue=\"setDraft(item.key, $event)\" />\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"leaf && leafProvider\" class=\"cn-record-notes__leaf\" :data-testid=\"`cn-record-list-leaf-${item.key}`\">\n\t\t\t\t\t<CnLeafMountHost\n\t\t\t\t\t\tv-if=\"leafIsMount\"\n\t\t\t\t\t\t:provider=\"leafProvider\"\n\t\t\t\t\t\t:mountProps=\"leafProps(item.row)\" />\n\t\t\t\t\t<component :is=\"leafComponent\" v-else-if=\"leafComponent\" v-bind=\"leafProps(item.row)\" />\n\t\t\t\t</div>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t:disabled=\"busy || !hasDraft(item.key)\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-record-${item.key}`\"\n\t\t\t\t\t@click=\"record(item)\">\n\t\t\t\t\t{{ recordLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p\n\t\t\t\tv-if=\"leafUnavailable\"\n\t\t\t\tclass=\"cn-record-notes__leaf-missing\"\n\t\t\t\t:data-testid=\"`cn-record-list-leaf-missing-${item.key}`\">\n\t\t\t\t{{ leafUnavailableText }}\n\t\t\t</p>\n\t\t</div>\n\t\t<p v-if=\"error\"\n\t\t\tclass=\"cn-record-notes__error\"\n\t\t\trole=\"alert\"\n\t\t\tdata-testid=\"cn-record-list-notes-error\">\n\t\t\t{{ error }}\n\t\t</p>\n\t\t<div v-if=\"recordAll\" class=\"cn-record-notes__all\" data-testid=\"cn-record-list-record-all\">\n\t\t\t<div class=\"cn-record-notes__all-text\">\n\t\t\t\t<h3 v-if=\"recordAll.title\" class=\"cn-record-notes__all-title\">\n\t\t\t\t\t{{ recordAll.title }}\n\t\t\t\t</h3>\n\t\t\t\t<p v-if=\"recordAll.text\" class=\"cn-record-notes__all-sentence\">\n\t\t\t\t\t{{ recordAll.text }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__all-actions\">\n\t\t\t\t<NcButton v-if=\"recordAll.cancel\" variant=\"secondary\" :to=\"recordAll.cancel.to\">\n\t\t\t\t\t{{ recordAll.cancel.label }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"busy || readyCount === 0\"\n\t\t\t\t\tdata-testid=\"cn-record-list-record-all-button\"\n\t\t\t\t\t@click=\"recordEvery\">\n\t\t\t\t\t<template v-if=\"recordAll.icon\" #icon>\n\t\t\t\t\t\t<CnIcon :name=\"recordAll.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ recordAll.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcTextField } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnLeafMountHost from '../CnLeafMountHost/CnLeafMountHost.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\n\n/** The bus channel every endpoint-bound widget on the page refetches on. */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * The document event a recorded note sends, so a row's leaf (humaniq's\n * hours) can record what it holds for the same object at the same moment.\n * `detail` is the row's leaf props plus `note`.\n */\nconst NOTE_RECORDED_EVENT = 'cn-record-notes:recorded'\n\n/**\n * The rows of a record list drawn as notes to record (`presentation:\n * \"notes\"`, DqDagAfsluiten \"Nog open van vandaag\"): per row its pill, title,\n * meta and due text, a field for what happened, an optional integration leaf\n * (humaniq's hours) and a button that records the note on the row's own\n * notes endpoint. What is typed and not yet recorded stays in this browser\n * (session storage) and is counted as the \"ready to record\" figure; one\n * button records every filled row. After a note is recorded the page's\n * endpoint widgets refetch, so the row moves to whatever lists the server\n * keeps of recorded work.\n *\n * @spec openspec/changes/record-list-notes/specs/record-list-notes/spec.md#requirement-a-record-list-can-collect-and-record-a-note-per-row\n */\nexport default {\n\tname: 'CnRecordNoteRows',\n\n\tcomponents: { CnIcon, CnLeafMountHost, CnStatusBadge, NcButton, NcTextField },\n\n\tprops: {\n\t\t/** The list's rows as the record list builds them (`key`, `row`, `tag`, `attrs`, `title`, `meta`, `pill`, `due`). */\n\t\titems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * `noteAction`, already translated: `{ urlField?, url?, bodyField?,\n\t\t * label, fieldLabel, placeholder?, readyLabel, draftsKey?, errorText? }`.\n\t\t */\n\t\taction: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** `recordAll`, already translated: `{ label, title?, text?, icon?, cancel?: { label, to } }`, or null. */\n\t\trecordAll: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** `rowLeaf`: `{ id, app?, register?, objectIdField, schemaField?, schema?, unavailableText? }`, or null. */\n\t\tleaf: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup() {\n\t\tconst { getById } = useIntegrationRegistry()\n\t\treturn { getProvider: getById }\n\t},\n\n\tdata() {\n\t\treturn { drafts: this.readDrafts(), busy: false, error: '' }\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The session storage key of this list's drafts. */\n\t\tdraftsKey() {\n\t\t\treturn `cn-record-list-notes:${this.action.draftsKey || 'default'}`\n\t\t},\n\n\t\t/** @return {number} The rows with a note typed and not yet recorded. */\n\t\treadyCount() {\n\t\t\treturn this.items.filter((item) => this.hasDraft(item.key)).length\n\t\t},\n\n\t\t/** @return {string} The label of the ready figure. */\n\t\treadyLabel() {\n\t\t\treturn this.action.readyLabel || t('nextcloud-vue', 'filled in, not recorded yet')\n\t\t},\n\n\t\t/** @return {string} */\n\t\trecordLabel() {\n\t\t\treturn this.action.label || t('nextcloud-vue', 'Record')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tfieldLabel() {\n\t\t\treturn this.action.fieldLabel || t('nextcloud-vue', 'Note')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tplaceholder() {\n\t\t\treturn this.action.placeholder || ''\n\t\t},\n\n\t\t/** @return {object|null} The leaf's integration provider, when one is registered. */\n\t\tleafProvider() {\n\t\t\treturn this.leaf && this.leaf.id ? (this.getProvider(this.leaf.id) || null) : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the leaf mounts itself (`renderMode: \"mount\"`). */\n\t\tleafIsMount() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn Boolean(provider) && provider.renderMode === 'mount' && typeof provider.mount === 'function'\n\t\t},\n\n\t\t/** @return {object|null} The leaf's component, in component mode. */\n\t\tleafComponent() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn provider ? (provider.tab || provider.widget || null) : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the leaf's app is installed but the leaf is not available, so\n\t\t * the row says so instead of silently showing no field.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tleafUnavailable() {\n\t\t\treturn Boolean(this.leaf && this.leaf.app && !this.leafProvider && isAppInstalled(this.leaf.app))\n\t\t},\n\n\t\t/** @return {string} */\n\t\tleafUnavailableText() {\n\t\t\treturn this.leaf?.unavailableText || t('nextcloud-vue', 'This field is not available here.')\n\t\t},\n\t},\n\n\twatch: {\n\t\tdrafts: {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.saveDrafts()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * The drafts this browser session kept, by row key.\n\t\t *\n\t\t * @return {Object<string, string>}\n\t\t */\n\t\treadDrafts() {\n\t\t\ttry {\n\t\t\t\tconst raw = window.sessionStorage.getItem(`cn-record-list-notes:${this.action?.draftsKey || 'default'}`)\n\t\t\t\tconst parsed = raw ? JSON.parse(raw) : {}\n\t\t\t\treturn parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}\n\t\t\t} catch {\n\t\t\t\treturn {}\n\t\t\t}\n\t\t},\n\n\t\t/** @return {void} */\n\t\tsaveDrafts() {\n\t\t\ttry {\n\t\t\t\twindow.sessionStorage.setItem(this.draftsKey, JSON.stringify(this.drafts))\n\t\t\t} catch {\n\t\t\t\t// Without session storage the drafts live as long as the page.\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The colour of a due text: a term that ended or ends today in the\n\t\t * error colour, one still to come in the warning colour.\n\t\t *\n\t\t * @param {{tone: string}} due The due text.\n\t\t * @return {string} `error`, `warning` or `muted`.\n\t\t */\n\t\tdueToneOf(due) {\n\t\t\tif (due.tone === 'danger' || due.tone === 'today') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due.tone === 'upcoming' ? 'warning' : 'muted'\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @param {string} value The typed note.\n\t\t * @return {void}\n\t\t */\n\t\tsetDraft(key, value) {\n\t\t\tthis.drafts = { ...this.drafts, [key]: String(value ?? '') }\n\t\t},\n\n\t\t/**\n\t\t * The id of a row's note field, for its label.\n\t\t *\n\t\t * @param {string} key The row key.\n\t\t * @return {string} The id.\n\t\t */\n\t\tfieldId(key) {\n\t\t\treturn `cn-record-notes-${this.$.uid}-${String(key).replace(/[^A-Za-z0-9_-]/g, '-')}`\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @return {boolean} Whether the row has a note typed.\n\t\t */\n\t\thasDraft(key) {\n\t\t\treturn String(this.drafts[key] ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * The props the row's leaf gets: the row's object, register and schema.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {object}\n\t\t */\n\t\tleafProps(row) {\n\t\t\tconst leaf = this.leaf || {}\n\t\t\treturn {\n\t\t\t\tobjectId: String(readPath(row, leaf.objectIdField || 'id') ?? ''),\n\t\t\t\tregister: leaf.register || '',\n\t\t\t\tschema: leaf.schemaField ? String(readPath(row, leaf.schemaField) ?? '') : (leaf.schema || ''),\n\t\t\t\tsurface: 'row',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The row's notes endpoint: the row's `urlField`, else `url` with\n\t\t * `{field}` filled from the row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {string} The URL, or ''.\n\t\t */\n\t\turlOf(row) {\n\t\t\tif (this.action.urlField) {\n\t\t\t\treturn String(readPath(row, this.action.urlField) ?? '')\n\t\t\t}\n\t\t\tconst template = String(this.action.url || '')\n\t\t\treturn template.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (_, path) => encodeURIComponent(String(readPath(row, path) ?? '')))\n\t\t},\n\n\t\t/**\n\t\t * Record one row's note, then let the page refetch.\n\t\t *\n\t\t * @param {object} item The row item.\n\t\t * @param {boolean} [refresh] Whether to refresh the page after it.\n\t\t * @return {Promise<boolean>} Whether it was recorded.\n\t\t */\n\t\tasync record(item, refresh = true) {\n\t\t\tconst text = String(this.drafts[item.key] ?? '').trim()\n\t\t\tconst url = this.urlOf(item.row)\n\t\t\tif (text === '' || url === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tawait axios.post(prefixUrl(url), { [this.action.bodyField || 'message']: text })\n\t\t\t\tif (this.leaf) {\n\t\t\t\t\tdocument.dispatchEvent(new CustomEvent(NOTE_RECORDED_EVENT, { detail: { ...this.leafProps(item.row), note: text } }))\n\t\t\t\t}\n\t\t\t\tconst { [item.key]: done, ...rest } = this.drafts\n\t\t\t\tthis.drafts = rest\n\t\t\t\tif (refresh) {\n\t\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\tthis.error = this.action.errorText || t('nextcloud-vue', 'The note could not be recorded. It is kept here; try again.')\n\t\t\t\treturn false\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Record every row with a note, one after another, then refresh once.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync recordEvery() {\n\t\t\tconst filled = this.items.filter((item) => this.hasDraft(item.key))\n\t\t\tlet any = false\n\t\t\tfor (const item of filled) {\n\t\t\t\tany = (await this.record(item, false)) || any\n\t\t\t}\n\t\t\tif (any) {\n\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-record-notes {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0;\n}\n\n.cn-record-notes__ready {\n\tdisplay: flex;\n\talign-items: baseline;\n\tgap: 6px;\n\tmargin: 0 0 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__ready-figure {\n\tfont-weight: 700;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tpadding: 14px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__head {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-record-notes__title {\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__title--link {\n\ttext-decoration: underline;\n}\n\n.cn-record-notes__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__spacer {\n\tflex: 1 1 auto;\n}\n\n.cn-record-notes__due {\n\tfont-weight: 600;\n}\n\n.cn-record-notes__due--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__due--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-record-notes__due--muted {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 400;\n}\n\n.cn-record-notes__fields {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 10px;\n}\n\n.cn-record-notes__field {\n\tdisplay: flex;\n\tflex: 1 1 260px;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-record-notes__field-label {\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n\tfont-weight: 600;\n}\n\n.cn-record-notes__leaf {\n\tflex: 0 0 auto;\n}\n\n.cn-record-notes__leaf-missing,\n.cn-record-notes__error {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__all {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n\tmargin-top: 8px;\n\tpadding-top: 14px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__all-title {\n\tmargin: 0;\n\tfont-size: 16px;\n}\n\n.cn-record-notes__all-sentence {\n\tmargin: 4px 0 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__all-actions {\n\tdisplay: flex;\n\tgap: 8px;\n}\n</style>\n"],"names":["CnIcon","CnLeafMountHost","CnStatusBadge","t"],"mappings":"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"}
|
|
@@ -16,29 +16,31 @@ const _hoisted_6 = {
|
|
|
16
16
|
class: "cn-record-notes__meta"
|
|
17
17
|
};
|
|
18
18
|
const _hoisted_7 = { class: "cn-record-notes__fields" };
|
|
19
|
-
const _hoisted_8 =
|
|
20
|
-
const _hoisted_9 = ["
|
|
21
|
-
const _hoisted_10 =
|
|
19
|
+
const _hoisted_8 = { class: "cn-record-notes__field" };
|
|
20
|
+
const _hoisted_9 = ["for"];
|
|
21
|
+
const _hoisted_10 = ["data-testid"];
|
|
22
|
+
const _hoisted_11 = ["data-testid"];
|
|
23
|
+
const _hoisted_12 = {
|
|
22
24
|
key: 0,
|
|
23
25
|
class: "cn-record-notes__error",
|
|
24
26
|
role: "alert",
|
|
25
27
|
"data-testid": "cn-record-list-notes-error"
|
|
26
28
|
};
|
|
27
|
-
const
|
|
29
|
+
const _hoisted_13 = {
|
|
28
30
|
key: 1,
|
|
29
31
|
class: "cn-record-notes__all",
|
|
30
32
|
"data-testid": "cn-record-list-record-all"
|
|
31
33
|
};
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
+
const _hoisted_14 = { class: "cn-record-notes__all-text" };
|
|
35
|
+
const _hoisted_15 = {
|
|
34
36
|
key: 0,
|
|
35
37
|
class: "cn-record-notes__all-title"
|
|
36
38
|
};
|
|
37
|
-
const
|
|
39
|
+
const _hoisted_16 = {
|
|
38
40
|
key: 1,
|
|
39
41
|
class: "cn-record-notes__all-sentence"
|
|
40
42
|
};
|
|
41
|
-
const
|
|
43
|
+
const _hoisted_17 = { class: "cn-record-notes__all-actions" };
|
|
42
44
|
|
|
43
45
|
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
44
46
|
const _component_CnStatusBadge = resolveComponent("CnStatusBadge");
|
|
@@ -91,16 +93,22 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
91
93
|
: createCommentVNode("v-if", true)
|
|
92
94
|
]),
|
|
93
95
|
createElementVNode("div", _hoisted_7, [
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
createElementVNode("div", _hoisted_8, [
|
|
97
|
+
createElementVNode("label", {
|
|
98
|
+
for: $options.fieldId(item.key),
|
|
99
|
+
class: "cn-record-notes__field-label"
|
|
100
|
+
}, toDisplayString($options.fieldLabel), 9 /* TEXT, PROPS */, _hoisted_9),
|
|
101
|
+
createVNode(_component_NcTextField, {
|
|
102
|
+
id: $options.fieldId(item.key),
|
|
103
|
+
modelValue: $data.drafts[item.key] || '',
|
|
104
|
+
label: $options.fieldLabel,
|
|
105
|
+
labelOutside: "",
|
|
106
|
+
placeholder: $options.placeholder,
|
|
107
|
+
disabled: $data.busy,
|
|
108
|
+
"data-testid": `cn-record-list-note-${item.key}`,
|
|
109
|
+
"onUpdate:modelValue": $event => ($options.setDraft(item.key, $event))
|
|
110
|
+
}, null, 8 /* PROPS */, ["id", "modelValue", "label", "placeholder", "disabled", "data-testid", "onUpdate:modelValue"])
|
|
111
|
+
]),
|
|
104
112
|
($props.leaf && $options.leafProvider)
|
|
105
113
|
? (openBlock(), createElementBlock("div", {
|
|
106
114
|
key: 0,
|
|
@@ -119,7 +127,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
119
127
|
ref_for: true
|
|
120
128
|
}, $options.leafProps(item.row)), null, 16 /* FULL_PROPS */))
|
|
121
129
|
: createCommentVNode("v-if", true)
|
|
122
|
-
], 8 /* PROPS */,
|
|
130
|
+
], 8 /* PROPS */, _hoisted_10))
|
|
123
131
|
: createCommentVNode("v-if", true),
|
|
124
132
|
createVNode(_component_NcButton, {
|
|
125
133
|
variant: "secondary",
|
|
@@ -138,24 +146,24 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
138
146
|
key: 0,
|
|
139
147
|
class: "cn-record-notes__leaf-missing",
|
|
140
148
|
"data-testid": `cn-record-list-leaf-missing-${item.key}`
|
|
141
|
-
}, toDisplayString($options.leafUnavailableText), 9 /* TEXT, PROPS */,
|
|
149
|
+
}, toDisplayString($options.leafUnavailableText), 9 /* TEXT, PROPS */, _hoisted_11))
|
|
142
150
|
: createCommentVNode("v-if", true)
|
|
143
151
|
]))
|
|
144
152
|
}), 128 /* KEYED_FRAGMENT */)),
|
|
145
153
|
($data.error)
|
|
146
|
-
? (openBlock(), createElementBlock("p",
|
|
154
|
+
? (openBlock(), createElementBlock("p", _hoisted_12, toDisplayString($data.error), 1 /* TEXT */))
|
|
147
155
|
: createCommentVNode("v-if", true),
|
|
148
156
|
($props.recordAll)
|
|
149
|
-
? (openBlock(), createElementBlock("div",
|
|
150
|
-
createElementVNode("div",
|
|
157
|
+
? (openBlock(), createElementBlock("div", _hoisted_13, [
|
|
158
|
+
createElementVNode("div", _hoisted_14, [
|
|
151
159
|
($props.recordAll.title)
|
|
152
|
-
? (openBlock(), createElementBlock("h3",
|
|
160
|
+
? (openBlock(), createElementBlock("h3", _hoisted_15, toDisplayString($props.recordAll.title), 1 /* TEXT */))
|
|
153
161
|
: createCommentVNode("v-if", true),
|
|
154
162
|
($props.recordAll.text)
|
|
155
|
-
? (openBlock(), createElementBlock("p",
|
|
163
|
+
? (openBlock(), createElementBlock("p", _hoisted_16, toDisplayString($props.recordAll.text), 1 /* TEXT */))
|
|
156
164
|
: createCommentVNode("v-if", true)
|
|
157
165
|
]),
|
|
158
|
-
createElementVNode("div",
|
|
166
|
+
createElementVNode("div", _hoisted_17, [
|
|
159
167
|
($props.recordAll.cancel)
|
|
160
168
|
? (openBlock(), createBlock(_component_NcButton, {
|
|
161
169
|
key: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnRecordNoteRows.vue3.js","sources":["../../../../src/components/CnRecordListWidget/CnRecordNoteRows.vue?vue&type=template&id=56a223c4&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-record-notes\" data-testid=\"cn-record-list-notes\">\n\t\t<p class=\"cn-record-notes__ready\" data-testid=\"cn-record-list-notes-ready\">\n\t\t\t<span class=\"cn-record-notes__ready-figure\">{{ readyCount }}</span>\n\t\t\t<span class=\"cn-record-notes__ready-label\">{{ readyLabel }}</span>\n\t\t</p>\n\t\t<div\n\t\t\tv-for=\"item in items\"\n\t\t\t:key=\"item.key\"\n\t\t\tclass=\"cn-record-notes__row\"\n\t\t\tdata-testid=\"cn-record-list-item\">\n\t\t\t<div class=\"cn-record-notes__head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"item.pill\"\n\t\t\t\t\t:label=\"item.pill.label\"\n\t\t\t\t\t:variant=\"item.pill.variant\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"item.tag\"\n\t\t\t\t\tv-if=\"item.title\"\n\t\t\t\t\tclass=\"cn-record-notes__title\"\n\t\t\t\t\t:class=\"{ 'cn-record-notes__title--link': item.tag !== 'div' }\"\n\t\t\t\t\tv-bind=\"item.attrs\">\n\t\t\t\t\t{{ item.title }}\n\t\t\t\t</component>\n\t\t\t\t<span v-if=\"item.meta\" class=\"cn-record-notes__meta\">{{ item.meta }}</span>\n\t\t\t\t<span class=\"cn-record-notes__spacer\" />\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"item.due\"\n\t\t\t\t\tclass=\"cn-record-notes__due\"\n\t\t\t\t\t:class=\"`cn-record-notes__due--${dueToneOf(item.due)}`\"\n\t\t\t\t\tdata-testid=\"cn-record-list-due\">{{ item.due.text }}</span>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__fields\">\n\t\t\t\t<NcTextField\n\t\t\t\t\tclass=\"cn-record-notes__field\"\n\t\t\t\t\t:modelValue=\"drafts[item.key] || ''\"\n\t\t\t\t\t:label=\"fieldLabel\"\n\t\t\t\t\t:labelOutside=\"false\"\n\t\t\t\t\t:placeholder=\"placeholder\"\n\t\t\t\t\t:disabled=\"busy\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-note-${item.key}`\"\n\t\t\t\t\t@update:modelValue=\"setDraft(item.key, $event)\" />\n\t\t\t\t<div v-if=\"leaf && leafProvider\" class=\"cn-record-notes__leaf\" :data-testid=\"`cn-record-list-leaf-${item.key}`\">\n\t\t\t\t\t<CnLeafMountHost\n\t\t\t\t\t\tv-if=\"leafIsMount\"\n\t\t\t\t\t\t:provider=\"leafProvider\"\n\t\t\t\t\t\t:mountProps=\"leafProps(item.row)\" />\n\t\t\t\t\t<component :is=\"leafComponent\" v-else-if=\"leafComponent\" v-bind=\"leafProps(item.row)\" />\n\t\t\t\t</div>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t:disabled=\"busy || !hasDraft(item.key)\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-record-${item.key}`\"\n\t\t\t\t\t@click=\"record(item)\">\n\t\t\t\t\t{{ recordLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p\n\t\t\t\tv-if=\"leafUnavailable\"\n\t\t\t\tclass=\"cn-record-notes__leaf-missing\"\n\t\t\t\t:data-testid=\"`cn-record-list-leaf-missing-${item.key}`\">\n\t\t\t\t{{ leafUnavailableText }}\n\t\t\t</p>\n\t\t</div>\n\t\t<p v-if=\"error\"\n\t\t\tclass=\"cn-record-notes__error\"\n\t\t\trole=\"alert\"\n\t\t\tdata-testid=\"cn-record-list-notes-error\">\n\t\t\t{{ error }}\n\t\t</p>\n\t\t<div v-if=\"recordAll\" class=\"cn-record-notes__all\" data-testid=\"cn-record-list-record-all\">\n\t\t\t<div class=\"cn-record-notes__all-text\">\n\t\t\t\t<h3 v-if=\"recordAll.title\" class=\"cn-record-notes__all-title\">\n\t\t\t\t\t{{ recordAll.title }}\n\t\t\t\t</h3>\n\t\t\t\t<p v-if=\"recordAll.text\" class=\"cn-record-notes__all-sentence\">\n\t\t\t\t\t{{ recordAll.text }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__all-actions\">\n\t\t\t\t<NcButton v-if=\"recordAll.cancel\" variant=\"secondary\" :to=\"recordAll.cancel.to\">\n\t\t\t\t\t{{ recordAll.cancel.label }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"busy || readyCount === 0\"\n\t\t\t\t\tdata-testid=\"cn-record-list-record-all-button\"\n\t\t\t\t\t@click=\"recordEvery\">\n\t\t\t\t\t<template v-if=\"recordAll.icon\" #icon>\n\t\t\t\t\t\t<CnIcon :name=\"recordAll.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ recordAll.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcTextField } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnLeafMountHost from '../CnLeafMountHost/CnLeafMountHost.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\n\n/** The bus channel every endpoint-bound widget on the page refetches on. */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * The document event a recorded note sends, so a row's leaf (humaniq's\n * hours) can record what it holds for the same object at the same moment.\n * `detail` is the row's leaf props plus `note`.\n */\nconst NOTE_RECORDED_EVENT = 'cn-record-notes:recorded'\n\n/**\n * The rows of a record list drawn as notes to record (`presentation:\n * \"notes\"`, DqDagAfsluiten \"Nog open van vandaag\"): per row its pill, title,\n * meta and due text, a field for what happened, an optional integration leaf\n * (humaniq's hours) and a button that records the note on the row's own\n * notes endpoint. What is typed and not yet recorded stays in this browser\n * (session storage) and is counted as the \"ready to record\" figure; one\n * button records every filled row. After a note is recorded the page's\n * endpoint widgets refetch, so the row moves to whatever lists the server\n * keeps of recorded work.\n *\n * @spec openspec/changes/record-list-notes/specs/record-list-notes/spec.md#requirement-a-record-list-can-collect-and-record-a-note-per-row\n */\nexport default {\n\tname: 'CnRecordNoteRows',\n\n\tcomponents: { CnIcon, CnLeafMountHost, CnStatusBadge, NcButton, NcTextField },\n\n\tprops: {\n\t\t/** The list's rows as the record list builds them (`key`, `row`, `tag`, `attrs`, `title`, `meta`, `pill`, `due`). */\n\t\titems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * `noteAction`, already translated: `{ urlField?, url?, bodyField?,\n\t\t * label, fieldLabel, placeholder?, readyLabel, draftsKey?, errorText? }`.\n\t\t */\n\t\taction: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** `recordAll`, already translated: `{ label, title?, text?, icon?, cancel?: { label, to } }`, or null. */\n\t\trecordAll: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** `rowLeaf`: `{ id, app?, register?, objectIdField, schemaField?, schema?, unavailableText? }`, or null. */\n\t\tleaf: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup() {\n\t\tconst { getById } = useIntegrationRegistry()\n\t\treturn { getProvider: getById }\n\t},\n\n\tdata() {\n\t\treturn { drafts: this.readDrafts(), busy: false, error: '' }\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The session storage key of this list's drafts. */\n\t\tdraftsKey() {\n\t\t\treturn `cn-record-list-notes:${this.action.draftsKey || 'default'}`\n\t\t},\n\n\t\t/** @return {number} The rows with a note typed and not yet recorded. */\n\t\treadyCount() {\n\t\t\treturn this.items.filter((item) => this.hasDraft(item.key)).length\n\t\t},\n\n\t\t/** @return {string} The label of the ready figure. */\n\t\treadyLabel() {\n\t\t\treturn this.action.readyLabel || t('nextcloud-vue', 'filled in, not recorded yet')\n\t\t},\n\n\t\t/** @return {string} */\n\t\trecordLabel() {\n\t\t\treturn this.action.label || t('nextcloud-vue', 'Record')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tfieldLabel() {\n\t\t\treturn this.action.fieldLabel || t('nextcloud-vue', 'Note')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tplaceholder() {\n\t\t\treturn this.action.placeholder || ''\n\t\t},\n\n\t\t/** @return {object|null} The leaf's integration provider, when one is registered. */\n\t\tleafProvider() {\n\t\t\treturn this.leaf && this.leaf.id ? (this.getProvider(this.leaf.id) || null) : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the leaf mounts itself (`renderMode: \"mount\"`). */\n\t\tleafIsMount() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn Boolean(provider) && provider.renderMode === 'mount' && typeof provider.mount === 'function'\n\t\t},\n\n\t\t/** @return {object|null} The leaf's component, in component mode. */\n\t\tleafComponent() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn provider ? (provider.tab || provider.widget || null) : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the leaf's app is installed but the leaf is not available, so\n\t\t * the row says so instead of silently showing no field.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tleafUnavailable() {\n\t\t\treturn Boolean(this.leaf && this.leaf.app && !this.leafProvider && isAppInstalled(this.leaf.app))\n\t\t},\n\n\t\t/** @return {string} */\n\t\tleafUnavailableText() {\n\t\t\treturn this.leaf?.unavailableText || t('nextcloud-vue', 'This field is not available here.')\n\t\t},\n\t},\n\n\twatch: {\n\t\tdrafts: {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.saveDrafts()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * The drafts this browser session kept, by row key.\n\t\t *\n\t\t * @return {Object<string, string>}\n\t\t */\n\t\treadDrafts() {\n\t\t\ttry {\n\t\t\t\tconst raw = window.sessionStorage.getItem(`cn-record-list-notes:${this.action?.draftsKey || 'default'}`)\n\t\t\t\tconst parsed = raw ? JSON.parse(raw) : {}\n\t\t\t\treturn parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}\n\t\t\t} catch {\n\t\t\t\treturn {}\n\t\t\t}\n\t\t},\n\n\t\t/** @return {void} */\n\t\tsaveDrafts() {\n\t\t\ttry {\n\t\t\t\twindow.sessionStorage.setItem(this.draftsKey, JSON.stringify(this.drafts))\n\t\t\t} catch {\n\t\t\t\t// Without session storage the drafts live as long as the page.\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The colour of a due text: a term that ended or ends today in the\n\t\t * error colour, one still to come in the warning colour.\n\t\t *\n\t\t * @param {{tone: string}} due The due text.\n\t\t * @return {string} `error`, `warning` or `muted`.\n\t\t */\n\t\tdueToneOf(due) {\n\t\t\tif (due.tone === 'danger' || due.tone === 'today') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due.tone === 'upcoming' ? 'warning' : 'muted'\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @param {string} value The typed note.\n\t\t * @return {void}\n\t\t */\n\t\tsetDraft(key, value) {\n\t\t\tthis.drafts = { ...this.drafts, [key]: String(value ?? '') }\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @return {boolean} Whether the row has a note typed.\n\t\t */\n\t\thasDraft(key) {\n\t\t\treturn String(this.drafts[key] ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * The props the row's leaf gets: the row's object, register and schema.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {object}\n\t\t */\n\t\tleafProps(row) {\n\t\t\tconst leaf = this.leaf || {}\n\t\t\treturn {\n\t\t\t\tobjectId: String(readPath(row, leaf.objectIdField || 'id') ?? ''),\n\t\t\t\tregister: leaf.register || '',\n\t\t\t\tschema: leaf.schemaField ? String(readPath(row, leaf.schemaField) ?? '') : (leaf.schema || ''),\n\t\t\t\tsurface: 'row',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The row's notes endpoint: the row's `urlField`, else `url` with\n\t\t * `{field}` filled from the row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {string} The URL, or ''.\n\t\t */\n\t\turlOf(row) {\n\t\t\tif (this.action.urlField) {\n\t\t\t\treturn String(readPath(row, this.action.urlField) ?? '')\n\t\t\t}\n\t\t\tconst template = String(this.action.url || '')\n\t\t\treturn template.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (_, path) => encodeURIComponent(String(readPath(row, path) ?? '')))\n\t\t},\n\n\t\t/**\n\t\t * Record one row's note, then let the page refetch.\n\t\t *\n\t\t * @param {object} item The row item.\n\t\t * @param {boolean} [refresh] Whether to refresh the page after it.\n\t\t * @return {Promise<boolean>} Whether it was recorded.\n\t\t */\n\t\tasync record(item, refresh = true) {\n\t\t\tconst text = String(this.drafts[item.key] ?? '').trim()\n\t\t\tconst url = this.urlOf(item.row)\n\t\t\tif (text === '' || url === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tawait axios.post(prefixUrl(url), { [this.action.bodyField || 'message']: text })\n\t\t\t\tif (this.leaf) {\n\t\t\t\t\tdocument.dispatchEvent(new CustomEvent(NOTE_RECORDED_EVENT, { detail: { ...this.leafProps(item.row), note: text } }))\n\t\t\t\t}\n\t\t\t\tconst { [item.key]: done, ...rest } = this.drafts\n\t\t\t\tthis.drafts = rest\n\t\t\t\tif (refresh) {\n\t\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\tthis.error = this.action.errorText || t('nextcloud-vue', 'The note could not be recorded. It is kept here; try again.')\n\t\t\t\treturn false\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Record every row with a note, one after another, then refresh once.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync recordEvery() {\n\t\t\tconst filled = this.items.filter((item) => this.hasDraft(item.key))\n\t\t\tlet any = false\n\t\t\tfor (const item of filled) {\n\t\t\t\tany = (await this.record(item, false)) || any\n\t\t\t}\n\t\t\tif (any) {\n\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-record-notes {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0;\n}\n\n.cn-record-notes__ready {\n\tdisplay: flex;\n\talign-items: baseline;\n\tgap: 6px;\n\tmargin: 0 0 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__ready-figure {\n\tfont-weight: 700;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tpadding: 14px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__head {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-record-notes__title {\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__title--link {\n\ttext-decoration: underline;\n}\n\n.cn-record-notes__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__spacer {\n\tflex: 1 1 auto;\n}\n\n.cn-record-notes__due {\n\tfont-weight: 600;\n}\n\n.cn-record-notes__due--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__due--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-record-notes__due--muted {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 400;\n}\n\n.cn-record-notes__fields {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 10px;\n}\n\n.cn-record-notes__field {\n\tflex: 1 1 260px;\n}\n\n.cn-record-notes__leaf {\n\tflex: 0 0 auto;\n}\n\n.cn-record-notes__leaf-missing,\n.cn-record-notes__error {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__all {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n\tmargin-top: 8px;\n\tpadding-top: 14px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__all-title {\n\tmargin: 0;\n\tfont-size: 16px;\n}\n\n.cn-record-notes__all-sentence {\n\tmargin: 4px 0 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__all-actions {\n\tdisplay: flex;\n\tgap: 8px;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_Fragment","_renderList","_createBlock","_resolveDynamicComponent","_mergeProps","_createTextVNode","_createVNode"],"mappings":";;;AAWK,EAAA,KAAA,EAAA,iBAAA;AAAA,EAAA,aAAA,EAAA,sBAAA;;;AACA,EAAA,KAAK,EAAC,wBAAY;AAAA,EAAA,aAAA,EAAA,4BAAA;;AACd,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,+BAAE,GAAA;AACR,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,8BAAe,GAAA;AAOtB,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,uBAAK,GAAA;;;AAcQ,EAAA,KAAK,EAAC,uBAAuB;;AAQhD,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,yBAAW,GAAA;;;;;AAiCtB,EAAA,KAAK,EAAC,wBAAwB;AAC9B,EAAA,IAAK,EAAA,OAAO;eACD,EAAC,4BAA4B;;;;AAGnB,EAAA,KAAK,EAAC,sBAAsB;AAAC,EAAA,aAAW,EAAC,2BAAC;;AAC1D,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,2BAAU,GAAA;;;AACjB,EAAA,KAAA,EAAA,4BAAA;;;;AAGsB,EAAA,KAAK,EAAC,+BAA+B;;AAI1D,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,8BAAO,GAAA;;;;;;;;;AA/EnB,EAAA,QAAAA,SAAA,EAAA,EAAAC,kBAAA,QAAA;AACC,IAAAC,kBAAA,CAGG,KAHH,UAGG,EAAA;MAFHA,kBAAc,CAAA,MAAA,EAAd,UAAc,EAAAC,eAAA,CAAA,QAAA,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;MACdD,kBAA2B,CAAA,MAAA,EAA3B,UAA2B,EAAAC,eAAA,CAAA,QAAA,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;;sBAE3BF,kBA0DK,CAAAG,QAAA,EAAA,IAAA,EAAAC,UAAA,CAzDS,MAAA,CAAA,KAAA,EAAA,CAAP,IAAI,KAAA;2BADXJ,kBA0DK,CAAA,KAAA,EAAA;QAxDH,GAAE,EAAE,IAAI,CAAC,GAAG;aACT,EAAC,sBAAmB;qBACd,EAAC,qBAAiB;;2BAsBvB,iBAAA,EAAA;AAnBE,UAAA,CAAA,IAAI,CAAC,IAAE;4BADdK,WAIgB,CAAA,wBAAA,EAAA;;AAFd,gBAAA,KAAK,EAAE,IAAI,CAAC,IAAG,CAAA,KAAA;AACf,gBAAA,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;AAC3B,gBAAA,IAAI,EAAC,OAAO;;;AAGN,UAAA,CAAA,IAAI,CAAA,KAAA;AAFV,eAAAN,SAAA,EAAA,EAAAM,WAAA,CAOWC,uBANN,CAAA,IAAI,CAAC,GAAE,GADZC,UAOW,CAAA;;AAJX,gBAAA,KAAK,EAAC,CAAA,wBAAwB,EACQ,EAAA,8BAAA,EAAA,IAAA,CAAA,GAAA,KAAA,KAAA,EAAA,CAAA;AACnC,eAAA,EAAA,EAAA,OAAA,EAAA,IAAA,EAAA,EAAA,IAAA,CAAA,KAAA,CAAA,EAAA;iCACH,MAAc;AAAX,kBAAAC,eAAA,CAAAN,eAAA,CAAA,IAAI,CAAC,KAAK,CAAA,EAAA,CAAA,YAAA;;;;;AAEF,UAAA,CAAA,IAAI,CAAC,IAAI;+CAAkC,kBAAA,EAAAA,eAAA,CAAA,IAAA,CAAA,IAAA,CAAA,EAAA,CAAA,YAAA;;sDACf,CAAA,MAAA,EAAA,EAAlC,KAAK,EAAC,yBAAyB,EAAA,EAAA,IAAA,EAAA,CAAA,CAAA,cAAA,CAAA;AAE9B,UAAA,CAAA,IAAI,CAAC,GAAG;4BADfF,kBAIoC,CAAA,MAAA,EAAA;;AAFnC,gBAAA,KAAK,kBAAC,sBAAI,EAAA,CAAA,sBAAA,EACmB,kBAAA,CAAA,IAAA,CAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAC7B,gBAAA,aAAW,EAAC,oBAAmB;iCAAI,IAAA,CAAA,GAAA,CAAA,IAAA,CAAA,EAAA,CAAA,mBAAA;;;AAEnC,QAAAC,kBAAA,CAwBI,OAxBJ,UAwBI,EAAA;qBAfgC,CAAA,sBAAA,EAAA;AAPpC,YAAA,KAAK,EAAC,wBAAS;AACd,YAAA,UAAU,EAAE,KAAA,CAAA,MAAM,CAAC,IAAI,CAAC,GAAG,CAAA,IAAA,EAAA;AAC3B,YAAA,KAAK,EAAE,QAAU,CAAA,UAAA;AACjB,YAAA,YAAY,EAAE,KAAK;AACnB,YAAA,WAAW,EAAE,QAAC,CAAA,WAAA;AACd,YAAA,QAAQ,EAAE,KAAI,CAAA,IAAA;YACd,aAAW,EAAA,CAAA,oBAAA,EAAY,IAAA,CAAA,GAAA,CAAA,CAAA;AACvB,YAAA,qBAAiB,aAAE,QAAQ,CAAA,QAAA,CAAC,IAAI,IAAG,EAAA,MAAA,CAAA,CAAA;;AACzB,UAAA,CAAA,MAAA,CAAA,IAAG,IAAI,QAAa,CAAA,YAAA;4BAA/BD,kBAMK,CAAA,KAAA,EAAA;;AAN2B,gBAAA,KAAK,EAAC,uBAAuB;gBAAE,aAAW,EAAA,CAAA,oBAAA,EAAa,IAAA,CAAA,GAAA,CAAA,CAAA;;iBAEhF,QAAA,CAAA,WAAA;kCADPK,WAGqC,CAAA,0BAAA,EAAA;;AADnC,sBAAA,QAAQ,EAAE,QAAM,CAAA,YAAA;AAChB,sBAAA,UAAU,EAAE,QAAA,CAAA,SAAS,CAAC,IAAI,CAAC,GAAG,CAAA;;qBACU,QAAO,CAAA,aAAA;oCAAjDA,WAAiD,CAAAC,uBAAA,CAAjC,QAAa,CAAA,aAAA,CAAA,EAA7BC,UAAiD,CAAA;;;yBAAA,QAAA,CAAA,SAAA,CAAA,IAAA,CAAA,GAAA,CAAA,CAAA,EAAA,IAAA,EAAA,EAAA,kBAAA;;;;UAEjDE,WAMU,CAAA,mBAAA,EAAA;AALV,YAAA,OAAO,EAAC,WAAC;AACR,YAAA,QAAE,EAAA,KAAA,CAAA,IAAA,IAAA,CAAA,iBAAA,CAAA,IAAA,CAAA,GAAA,CAAA;YACJ,aAAA,EAAA,CAAA,sBAAA,EAAA,IAAA,CAAA,GAAA,CAAA,CAAA;YACE,OAAK,EAAA,MAAA,KAAE,QAAM,CAAA,MAAA,CAAC,IAAI,CAAA,CAAA;;6BACnB,MAAiB;8CAAd,QAAW,CAAA,WAAA,CAAA,EAAA,CAAA,YAAA;;;;;SAIZ,QAAA,CAAA,eAAA;0BADJT,kBAKI,CAAA,GAAA,EAAA;;AAHJ,cAAA,KAAM,EAAC,+BAAM;cACX,aAAW,EAAA,CAAA,4BAAA,EAAgB,IAAA,CAAA,GAAA,CAAA,CAAA;+BACzB,QAAO,CAAA,mBAAA,CAAA,EAAA,CAAA,oBAAA,UAAA,CAAA;;;;KAGT,KAAA,CAAA,KAAA;sBAAHA,kBAKI,CAAA,GAAA,EALJ,WAKI,EAAAE,eAAA,CADA,KAAK,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;;KAEE,MAAS,CAAA,SAAA;;AACjB,UAAAD,kBAAA,CAOI,OAPJ,WAOI,EAAA;AANF,YAAA,CAAA,MAAA,CAAA,SAAA,CAAA,KAAA;AAAH,iBAAAF,SAAA,EAAA,EAAAC,kBAAA,CAEK,IAFL,EAAA,WAEK,EADDE,eAAA,CAAA,MAAA,CAAA,SAAA,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;;AAEM,YAAA,CAAA,MAAA,CAAA,SAAQ,CAAC,IAAI;AAAvB,iBAAAH,SAAA,EAAA,EAAAC,kBAAA,CAEI,GAFJ,EAAA,WAEI,EADAE,eAAA,CAAA,MAAA,CAAA,SAAS,CAAC,IAAI,CAAA,EAAA,CAAA,YAAA;;;AAGjB,UAAAD,kBAAA,QAAA;AACc,YAAA,CAAA,MAAA,CAAA,SAAU,CAAC,MAAM;8BAA/BI,WAEU,CAAA,mBAAA,EAAA;;yBAFyB,EAAA,WAAA;AAAA,kBAAA,EAAA,EAAA,MAAA,CAAA,SAAA,CAAA,MAAA,CAAA,EAAA;;mCACnC,MAA4B;oDAAzB,MAAS,CAAA,SAAA,CAAC,MAAM,CAAC,KAAK,CAAA,EAAA,CAAA,YAAA;;;;;YAEzBI;AACC,cAAA,OAAM,WAAU;cAChB,QAAQ,EAAC,KAAA,CAAA,IAAA,IAAA,QAAA,CAAA,UAAA,KAAA,CAAA;AACV,cAAA,aAAW,EAAC,kCAAQ;AACnB,cAAA,OAAK,EAAE,QAAC,CAAA,WAAA;;+BAGR;gCAAA;;;;AAFE,cAAA,CAAA,MAAA,CAAA,SAAA,CAAA,IAAA;;0BAAA,MAAA;gCACF,MAAC;sBAADA,WAAC,CAAA,iBAAA,EAAA;wBAAA,IAAA,EAAA,MAAA,CAAA,SAAA,CAAA,IAAA;AAAA,wBAAA,IAAA,EAAA,EAAA;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"CnRecordNoteRows.vue3.js","sources":["../../../../src/components/CnRecordListWidget/CnRecordNoteRows.vue?vue&type=template&id=949ca7ea&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-record-notes\" data-testid=\"cn-record-list-notes\">\n\t\t<p class=\"cn-record-notes__ready\" data-testid=\"cn-record-list-notes-ready\">\n\t\t\t<span class=\"cn-record-notes__ready-figure\">{{ readyCount }}</span>\n\t\t\t<span class=\"cn-record-notes__ready-label\">{{ readyLabel }}</span>\n\t\t</p>\n\t\t<div\n\t\t\tv-for=\"item in items\"\n\t\t\t:key=\"item.key\"\n\t\t\tclass=\"cn-record-notes__row\"\n\t\t\tdata-testid=\"cn-record-list-item\">\n\t\t\t<div class=\"cn-record-notes__head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"item.pill\"\n\t\t\t\t\t:label=\"item.pill.label\"\n\t\t\t\t\t:variant=\"item.pill.variant\"\n\t\t\t\t\tsize=\"small\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"item.tag\"\n\t\t\t\t\tv-if=\"item.title\"\n\t\t\t\t\tclass=\"cn-record-notes__title\"\n\t\t\t\t\t:class=\"{ 'cn-record-notes__title--link': item.tag !== 'div' }\"\n\t\t\t\t\tv-bind=\"item.attrs\">\n\t\t\t\t\t{{ item.title }}\n\t\t\t\t</component>\n\t\t\t\t<span v-if=\"item.meta\" class=\"cn-record-notes__meta\">{{ item.meta }}</span>\n\t\t\t\t<span class=\"cn-record-notes__spacer\" />\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"item.due\"\n\t\t\t\t\tclass=\"cn-record-notes__due\"\n\t\t\t\t\t:class=\"`cn-record-notes__due--${dueToneOf(item.due)}`\"\n\t\t\t\t\tdata-testid=\"cn-record-list-due\">{{ item.due.text }}</span>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__fields\">\n\t\t\t\t<!-- The label stands above the field, as the leaf's own beside it\n\t\t\t\t (humaniq \"Uren\"), so both fields share one line. -->\n\t\t\t\t<div class=\"cn-record-notes__field\">\n\t\t\t\t\t<label :for=\"fieldId(item.key)\" class=\"cn-record-notes__field-label\">{{ fieldLabel }}</label>\n\t\t\t\t\t<NcTextField\n\t\t\t\t\t\t:id=\"fieldId(item.key)\"\n\t\t\t\t\t\t:modelValue=\"drafts[item.key] || ''\"\n\t\t\t\t\t\t:label=\"fieldLabel\"\n\t\t\t\t\t\tlabelOutside\n\t\t\t\t\t\t:placeholder=\"placeholder\"\n\t\t\t\t\t\t:disabled=\"busy\"\n\t\t\t\t\t\t:data-testid=\"`cn-record-list-note-${item.key}`\"\n\t\t\t\t\t\t@update:modelValue=\"setDraft(item.key, $event)\" />\n\t\t\t\t</div>\n\t\t\t\t<div v-if=\"leaf && leafProvider\" class=\"cn-record-notes__leaf\" :data-testid=\"`cn-record-list-leaf-${item.key}`\">\n\t\t\t\t\t<CnLeafMountHost\n\t\t\t\t\t\tv-if=\"leafIsMount\"\n\t\t\t\t\t\t:provider=\"leafProvider\"\n\t\t\t\t\t\t:mountProps=\"leafProps(item.row)\" />\n\t\t\t\t\t<component :is=\"leafComponent\" v-else-if=\"leafComponent\" v-bind=\"leafProps(item.row)\" />\n\t\t\t\t</div>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t:disabled=\"busy || !hasDraft(item.key)\"\n\t\t\t\t\t:data-testid=\"`cn-record-list-record-${item.key}`\"\n\t\t\t\t\t@click=\"record(item)\">\n\t\t\t\t\t{{ recordLabel }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p\n\t\t\t\tv-if=\"leafUnavailable\"\n\t\t\t\tclass=\"cn-record-notes__leaf-missing\"\n\t\t\t\t:data-testid=\"`cn-record-list-leaf-missing-${item.key}`\">\n\t\t\t\t{{ leafUnavailableText }}\n\t\t\t</p>\n\t\t</div>\n\t\t<p v-if=\"error\"\n\t\t\tclass=\"cn-record-notes__error\"\n\t\t\trole=\"alert\"\n\t\t\tdata-testid=\"cn-record-list-notes-error\">\n\t\t\t{{ error }}\n\t\t</p>\n\t\t<div v-if=\"recordAll\" class=\"cn-record-notes__all\" data-testid=\"cn-record-list-record-all\">\n\t\t\t<div class=\"cn-record-notes__all-text\">\n\t\t\t\t<h3 v-if=\"recordAll.title\" class=\"cn-record-notes__all-title\">\n\t\t\t\t\t{{ recordAll.title }}\n\t\t\t\t</h3>\n\t\t\t\t<p v-if=\"recordAll.text\" class=\"cn-record-notes__all-sentence\">\n\t\t\t\t\t{{ recordAll.text }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t\t<div class=\"cn-record-notes__all-actions\">\n\t\t\t\t<NcButton v-if=\"recordAll.cancel\" variant=\"secondary\" :to=\"recordAll.cancel.to\">\n\t\t\t\t\t{{ recordAll.cancel.label }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"busy || readyCount === 0\"\n\t\t\t\t\tdata-testid=\"cn-record-list-record-all-button\"\n\t\t\t\t\t@click=\"recordEvery\">\n\t\t\t\t\t<template v-if=\"recordAll.icon\" #icon>\n\t\t\t\t\t\t<CnIcon :name=\"recordAll.icon\" :size=\"20\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t{{ recordAll.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { emit } from '@nextcloud/event-bus'\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcTextField } from '@nextcloud/vue'\nimport CnIcon from '../CnIcon/CnIcon.vue'\nimport CnLeafMountHost from '../CnLeafMountHost/CnLeafMountHost.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { isAppInstalled } from '../../utils/appInstalled.js'\nimport { prefixUrl } from '../../utils/headers.js'\nimport { readPath } from '../../utils/readPath.js'\n\n/** The bus channel every endpoint-bound widget on the page refetches on. */\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * The document event a recorded note sends, so a row's leaf (humaniq's\n * hours) can record what it holds for the same object at the same moment.\n * `detail` is the row's leaf props plus `note`.\n */\nconst NOTE_RECORDED_EVENT = 'cn-record-notes:recorded'\n\n/**\n * The rows of a record list drawn as notes to record (`presentation:\n * \"notes\"`, DqDagAfsluiten \"Nog open van vandaag\"): per row its pill, title,\n * meta and due text, a field for what happened, an optional integration leaf\n * (humaniq's hours) and a button that records the note on the row's own\n * notes endpoint. What is typed and not yet recorded stays in this browser\n * (session storage) and is counted as the \"ready to record\" figure; one\n * button records every filled row. After a note is recorded the page's\n * endpoint widgets refetch, so the row moves to whatever lists the server\n * keeps of recorded work.\n *\n * @spec openspec/changes/record-list-notes/specs/record-list-notes/spec.md#requirement-a-record-list-can-collect-and-record-a-note-per-row\n */\nexport default {\n\tname: 'CnRecordNoteRows',\n\n\tcomponents: { CnIcon, CnLeafMountHost, CnStatusBadge, NcButton, NcTextField },\n\n\tprops: {\n\t\t/** The list's rows as the record list builds them (`key`, `row`, `tag`, `attrs`, `title`, `meta`, `pill`, `due`). */\n\t\titems: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * `noteAction`, already translated: `{ urlField?, url?, bodyField?,\n\t\t * label, fieldLabel, placeholder?, readyLabel, draftsKey?, errorText? }`.\n\t\t */\n\t\taction: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** `recordAll`, already translated: `{ label, title?, text?, icon?, cancel?: { label, to } }`, or null. */\n\t\trecordAll: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** `rowLeaf`: `{ id, app?, register?, objectIdField, schemaField?, schema?, unavailableText? }`, or null. */\n\t\tleaf: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup() {\n\t\tconst { getById } = useIntegrationRegistry()\n\t\treturn { getProvider: getById }\n\t},\n\n\tdata() {\n\t\treturn { drafts: this.readDrafts(), busy: false, error: '' }\n\t},\n\n\tcomputed: {\n\t\t/** @return {string} The session storage key of this list's drafts. */\n\t\tdraftsKey() {\n\t\t\treturn `cn-record-list-notes:${this.action.draftsKey || 'default'}`\n\t\t},\n\n\t\t/** @return {number} The rows with a note typed and not yet recorded. */\n\t\treadyCount() {\n\t\t\treturn this.items.filter((item) => this.hasDraft(item.key)).length\n\t\t},\n\n\t\t/** @return {string} The label of the ready figure. */\n\t\treadyLabel() {\n\t\t\treturn this.action.readyLabel || t('nextcloud-vue', 'filled in, not recorded yet')\n\t\t},\n\n\t\t/** @return {string} */\n\t\trecordLabel() {\n\t\t\treturn this.action.label || t('nextcloud-vue', 'Record')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tfieldLabel() {\n\t\t\treturn this.action.fieldLabel || t('nextcloud-vue', 'Note')\n\t\t},\n\n\t\t/** @return {string} */\n\t\tplaceholder() {\n\t\t\treturn this.action.placeholder || ''\n\t\t},\n\n\t\t/** @return {object|null} The leaf's integration provider, when one is registered. */\n\t\tleafProvider() {\n\t\t\treturn this.leaf && this.leaf.id ? (this.getProvider(this.leaf.id) || null) : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the leaf mounts itself (`renderMode: \"mount\"`). */\n\t\tleafIsMount() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn Boolean(provider) && provider.renderMode === 'mount' && typeof provider.mount === 'function'\n\t\t},\n\n\t\t/** @return {object|null} The leaf's component, in component mode. */\n\t\tleafComponent() {\n\t\t\tconst provider = this.leafProvider\n\t\t\treturn provider ? (provider.tab || provider.widget || null) : null\n\t\t},\n\n\t\t/**\n\t\t * Whether the leaf's app is installed but the leaf is not available, so\n\t\t * the row says so instead of silently showing no field.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tleafUnavailable() {\n\t\t\treturn Boolean(this.leaf && this.leaf.app && !this.leafProvider && isAppInstalled(this.leaf.app))\n\t\t},\n\n\t\t/** @return {string} */\n\t\tleafUnavailableText() {\n\t\t\treturn this.leaf?.unavailableText || t('nextcloud-vue', 'This field is not available here.')\n\t\t},\n\t},\n\n\twatch: {\n\t\tdrafts: {\n\t\t\tdeep: true,\n\t\t\thandler() {\n\t\t\t\tthis.saveDrafts()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * The drafts this browser session kept, by row key.\n\t\t *\n\t\t * @return {Object<string, string>}\n\t\t */\n\t\treadDrafts() {\n\t\t\ttry {\n\t\t\t\tconst raw = window.sessionStorage.getItem(`cn-record-list-notes:${this.action?.draftsKey || 'default'}`)\n\t\t\t\tconst parsed = raw ? JSON.parse(raw) : {}\n\t\t\t\treturn parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {}\n\t\t\t} catch {\n\t\t\t\treturn {}\n\t\t\t}\n\t\t},\n\n\t\t/** @return {void} */\n\t\tsaveDrafts() {\n\t\t\ttry {\n\t\t\t\twindow.sessionStorage.setItem(this.draftsKey, JSON.stringify(this.drafts))\n\t\t\t} catch {\n\t\t\t\t// Without session storage the drafts live as long as the page.\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The colour of a due text: a term that ended or ends today in the\n\t\t * error colour, one still to come in the warning colour.\n\t\t *\n\t\t * @param {{tone: string}} due The due text.\n\t\t * @return {string} `error`, `warning` or `muted`.\n\t\t */\n\t\tdueToneOf(due) {\n\t\t\tif (due.tone === 'danger' || due.tone === 'today') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due.tone === 'upcoming' ? 'warning' : 'muted'\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @param {string} value The typed note.\n\t\t * @return {void}\n\t\t */\n\t\tsetDraft(key, value) {\n\t\t\tthis.drafts = { ...this.drafts, [key]: String(value ?? '') }\n\t\t},\n\n\t\t/**\n\t\t * The id of a row's note field, for its label.\n\t\t *\n\t\t * @param {string} key The row key.\n\t\t * @return {string} The id.\n\t\t */\n\t\tfieldId(key) {\n\t\t\treturn `cn-record-notes-${this.$.uid}-${String(key).replace(/[^A-Za-z0-9_-]/g, '-')}`\n\t\t},\n\n\t\t/**\n\t\t * @param {string} key The row key.\n\t\t * @return {boolean} Whether the row has a note typed.\n\t\t */\n\t\thasDraft(key) {\n\t\t\treturn String(this.drafts[key] ?? '').trim() !== ''\n\t\t},\n\n\t\t/**\n\t\t * The props the row's leaf gets: the row's object, register and schema.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {object}\n\t\t */\n\t\tleafProps(row) {\n\t\t\tconst leaf = this.leaf || {}\n\t\t\treturn {\n\t\t\t\tobjectId: String(readPath(row, leaf.objectIdField || 'id') ?? ''),\n\t\t\t\tregister: leaf.register || '',\n\t\t\t\tschema: leaf.schemaField ? String(readPath(row, leaf.schemaField) ?? '') : (leaf.schema || ''),\n\t\t\t\tsurface: 'row',\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The row's notes endpoint: the row's `urlField`, else `url` with\n\t\t * `{field}` filled from the row.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @return {string} The URL, or ''.\n\t\t */\n\t\turlOf(row) {\n\t\t\tif (this.action.urlField) {\n\t\t\t\treturn String(readPath(row, this.action.urlField) ?? '')\n\t\t\t}\n\t\t\tconst template = String(this.action.url || '')\n\t\t\treturn template.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (_, path) => encodeURIComponent(String(readPath(row, path) ?? '')))\n\t\t},\n\n\t\t/**\n\t\t * Record one row's note, then let the page refetch.\n\t\t *\n\t\t * @param {object} item The row item.\n\t\t * @param {boolean} [refresh] Whether to refresh the page after it.\n\t\t * @return {Promise<boolean>} Whether it was recorded.\n\t\t */\n\t\tasync record(item, refresh = true) {\n\t\t\tconst text = String(this.drafts[item.key] ?? '').trim()\n\t\t\tconst url = this.urlOf(item.row)\n\t\t\tif (text === '' || url === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst { default: axios } = await import('@nextcloud/axios')\n\t\t\t\tawait axios.post(prefixUrl(url), { [this.action.bodyField || 'message']: text })\n\t\t\t\tif (this.leaf) {\n\t\t\t\t\tdocument.dispatchEvent(new CustomEvent(NOTE_RECORDED_EVENT, { detail: { ...this.leafProps(item.row), note: text } }))\n\t\t\t\t}\n\t\t\t\tconst { [item.key]: done, ...rest } = this.drafts\n\t\t\t\tthis.drafts = rest\n\t\t\t\tif (refresh) {\n\t\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\tthis.error = this.action.errorText || t('nextcloud-vue', 'The note could not be recorded. It is kept here; try again.')\n\t\t\t\treturn false\n\t\t\t} finally {\n\t\t\t\tthis.busy = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Record every row with a note, one after another, then refresh once.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync recordEvery() {\n\t\t\tconst filled = this.items.filter((item) => this.hasDraft(item.key))\n\t\t\tlet any = false\n\t\t\tfor (const item of filled) {\n\t\t\t\tany = (await this.record(item, false)) || any\n\t\t\t}\n\t\t\tif (any) {\n\t\t\t\temit(PAGE_REFRESH_CHANNEL, {})\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-record-notes {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0;\n}\n\n.cn-record-notes__ready {\n\tdisplay: flex;\n\talign-items: baseline;\n\tgap: 6px;\n\tmargin: 0 0 8px;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__ready-figure {\n\tfont-weight: 700;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__row {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 10px;\n\tpadding: 14px 0;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__head {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-record-notes__title {\n\tfont-weight: 600;\n\tcolor: var(--color-main-text);\n}\n\n.cn-record-notes__title--link {\n\ttext-decoration: underline;\n}\n\n.cn-record-notes__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__spacer {\n\tflex: 1 1 auto;\n}\n\n.cn-record-notes__due {\n\tfont-weight: 600;\n}\n\n.cn-record-notes__due--error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__due--warning {\n\tcolor: var(--color-warning-text);\n}\n\n.cn-record-notes__due--muted {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 400;\n}\n\n.cn-record-notes__fields {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 10px;\n}\n\n.cn-record-notes__field {\n\tdisplay: flex;\n\tflex: 1 1 260px;\n\tflex-direction: column;\n\tgap: 6px;\n}\n\n.cn-record-notes__field-label {\n\tcolor: var(--color-main-text);\n\tfont-size: 14px;\n\tfont-weight: 600;\n}\n\n.cn-record-notes__leaf {\n\tflex: 0 0 auto;\n}\n\n.cn-record-notes__leaf-missing,\n.cn-record-notes__error {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-record-notes__error {\n\tcolor: var(--color-error-text);\n}\n\n.cn-record-notes__all {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 12px;\n\tmargin-top: 8px;\n\tpadding-top: 14px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-record-notes__all-title {\n\tmargin: 0;\n\tfont-size: 16px;\n}\n\n.cn-record-notes__all-sentence {\n\tmargin: 4px 0 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-record-notes__all-actions {\n\tdisplay: flex;\n\tgap: 8px;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createElementVNode","_toDisplayString","_Fragment","_renderList","_createBlock","_resolveDynamicComponent","_mergeProps","_createTextVNode","_createVNode"],"mappings":"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"}
|
package/dist/esm/l10n/en.json.js
CHANGED
|
@@ -2380,7 +2380,8 @@ var translations = {
|
|
|
2380
2380
|
me: "me",
|
|
2381
2381
|
"Open profile": "Open profile",
|
|
2382
2382
|
"Link a contact from your address book.": "Link a contact from your address book.",
|
|
2383
|
-
"The value could not be shown.": "The value could not be shown."
|
|
2383
|
+
"The value could not be shown.": "The value could not be shown.",
|
|
2384
|
+
"No value": "No value"
|
|
2384
2385
|
};
|
|
2385
2386
|
var plurals = {
|
|
2386
2387
|
"{count} member": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"en.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/esm/l10n/nl.json.js
CHANGED
|
@@ -2633,7 +2633,8 @@ var translations = {
|
|
|
2633
2633
|
"The value could not be shown.": "De waarde kon niet worden getoond.",
|
|
2634
2634
|
"Save as draft": "Opslaan als concept",
|
|
2635
2635
|
"Draft saved at {time}": "Concept opgeslagen om {time}",
|
|
2636
|
-
"The draft could not be saved": "Het concept kon niet worden opgeslagen"
|
|
2636
|
+
"The draft could not be saved": "Het concept kon niet worden opgeslagen",
|
|
2637
|
+
"No value": "Geen waarde"
|
|
2637
2638
|
};
|
|
2638
2639
|
var plurals = {
|
|
2639
2640
|
"{count} member": [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nl.json.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|