@conduction/nextcloud-vue 2.117.0 → 2.118.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +2 -1
- package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +6 -6
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +2 -1
- package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +18 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +14 -8
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +11 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +9 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue2.js +2 -1
- package/dist/esm/components/CnMailTab/CnMailTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue.js +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +71 -0
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +25 -9
- 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 +11 -2
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue.js +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js +161 -5
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue2.js.map +1 -1
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js +9 -9
- package/dist/esm/components/CnSearchPage/CnSearchPage.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +35 -5
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue.js +9 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue.js.map +1 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js +435 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue2.js.map +1 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js +300 -0
- package/dist/esm/components/CnTransitionInputFields/CnTransitionInputFields.vue3.js.map +1 -0
- package/dist/esm/composables/useEndpointSource.js +1 -36
- package/dist/esm/composables/useEndpointSource.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue.js +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +57 -336
- package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +18 -155
- package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.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 +308 -229
- package/dist/esm/utils/actionsDispatcher.js +3 -2
- package/dist/esm/utils/actionsDispatcher.js.map +1 -1
- package/dist/esm/utils/interpolateUrlTokens.js +43 -0
- package/dist/esm/utils/interpolateUrlTokens.js.map +1 -0
- package/dist/esm/utils/labelsByField.js +72 -0
- package/dist/esm/utils/labelsByField.js.map +1 -0
- package/dist/esm/utils/listCreateAction.js +91 -0
- package/dist/esm/utils/listCreateAction.js.map +1 -0
- package/dist/esm/utils/transitionInputs.js +493 -0
- package/dist/esm/utils/transitionInputs.js.map +1 -0
- package/dist/esm/utils/visibleWhen.js +9 -2
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +6690 -5404
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +308 -229
- package/l10n/en.json +2 -1
- package/l10n/nl.json +2 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.vue +6 -6
- package/src/components/CnDashboardPage/CnDashboardPage.vue +27 -5
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +11 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +9 -4
- package/src/components/CnObjectListWidget/CnObjectListWidget.vue +86 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +11 -2
- package/src/components/CnSearchPage/CnSearchPage.vue +170 -14
- package/src/components/CnTabsWidget/CnTabsWidget.vue +35 -5
- package/src/components/CnTransitionInputFields/CnTransitionInputFields.vue +750 -0
- package/src/components/CnTransitionInputFields/index.js +11 -0
- package/src/components/index.js +1 -0
- package/src/composables/useEndpointSource.js +3 -36
- package/src/dialogs/CnTransitionInputDialog.vue +73 -465
- package/src/index.js +2 -0
- package/src/utils/interpolateUrlTokens.js +40 -0
- package/src/utils/labelsByField.js +69 -0
- package/src/utils/listCreateAction.js +87 -0
- package/src/utils/transitionInputs.js +489 -0
- package/src/utils/visibleWhen.js +9 -2
|
@@ -3,8 +3,9 @@ import { NcButton, NcNoteCard, NcSelect } from '@nextcloud/vue';
|
|
|
3
3
|
import EmailOffOutline from 'vue-material-design-icons/EmailOffOutline.vue';
|
|
4
4
|
import __sfc_main from '../../integrations/builtin/email/CnEmailTab.vue.js';
|
|
5
5
|
import __sfc_main$1 from '../CnEmptyContent/CnEmptyContent.vue.js';
|
|
6
|
-
import {
|
|
6
|
+
import { fetchEndpointSource } from '../../composables/useEndpointSource.js';
|
|
7
7
|
import { evaluateVisibleWhenLocal } from '../../utils/visibleWhen.js';
|
|
8
|
+
import { interpolateUrlTokens } from '../../utils/interpolateUrlTokens.js';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Read a reference that may be a slug, an id or an object carrying either.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnMailTab.vue2.js","sources":["../../../../src/components/CnMailTab/CnMailTab.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-mail-tab\" data-testid=\"cn-mail-tab\">\n\t\t<CnEmptyContent\n\t\t\tv-if=\"unavailable\"\n\t\t\t:name=\"t('nextcloud-vue', 'Mail is not available')\"\n\t\t\t:description=\"t('nextcloud-vue', 'Install Nextcloud Mail to draft and link mail here.')\">\n\t\t\t<template #icon>\n\t\t\t\t<EmailOffOutline :size=\"48\" />\n\t\t\t</template>\n\t\t</CnEmptyContent>\n\n\t\t<template v-else>\n\t\t\t<h3 v-if=\"heading\" class=\"cn-mail-tab__title\">\n\t\t\t\t{{ heading }}\n\t\t\t</h3>\n\t\t\t<p v-if=\"description\" class=\"cn-mail-tab__subtitle\">\n\t\t\t\t{{ description }}\n\t\t\t</p>\n\n\t\t\t<div v-if=\"draftEnabled\" class=\"cn-mail-tab__template-row\" data-testid=\"cn-mail-tab-template-row\">\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-if=\"templatesEnabled\"\n\t\t\t\t\tv-model=\"selectedTemplate\"\n\t\t\t\t\tclass=\"cn-mail-tab__template-select\"\n\t\t\t\t\t:options=\"templates\"\n\t\t\t\t\t:disabled=\"templates.length === 0\"\n\t\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Email template')\"\n\t\t\t\t\t:label=\"templateLabelField\"\n\t\t\t\t\t:trackBy=\"templateIdField\"\n\t\t\t\t\t:placeholder=\"templatePlaceholder\"\n\t\t\t\t\t:clearable=\"true\" />\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"templatesEnabled\"\n\t\t\t\t\t:disabled=\"closed || drafting || !selectedTemplate\"\n\t\t\t\t\tdata-testid=\"cn-mail-tab-draft-template\"\n\t\t\t\t\t@click=\"draftFromTemplate\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Open draft from template') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"closed || drafting\"\n\t\t\t\t\tdata-testid=\"cn-mail-tab-draft-blank\"\n\t\t\t\t\t@click=\"draftBlank\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Empty draft') }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p v-if=\"hint\" class=\"cn-mail-tab__hint\">\n\t\t\t\t{{ hint }}\n\t\t\t</p>\n\n\t\t\t<NcNoteCard\n\t\t\t\tv-if=\"error\"\n\t\t\t\ttype=\"error\"\n\t\t\t\t:heading=\"t('nextcloud-vue', 'Could not open draft')\"\n\t\t\t\trole=\"alert\">\n\t\t\t\t{{ error }}\n\t\t\t</NcNoteCard>\n\t\t\t<NcNoteCard\n\t\t\t\tv-if=\"unresolved.length > 0\"\n\t\t\t\ttype=\"warning\"\n\t\t\t\trole=\"status\"\n\t\t\t\tdata-testid=\"cn-mail-tab-unresolved\">\n\t\t\t\t<p>{{ t('nextcloud-vue', 'Some template fields could not be filled. Fill these in the draft yourself:') }}</p>\n\t\t\t\t<ul class=\"cn-mail-tab__unresolved\">\n\t\t\t\t\t<li v-for=\"name in unresolved\" :key=\"name\">\n\t\t\t\t\t\t<code>{{ placeholderOf(name) }}</code>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</NcNoteCard>\n\n\t\t\t<CnEmailTab\n\t\t\t\tv-if=\"linkedMail && objectKey\"\n\t\t\t\tclass=\"cn-mail-tab__linked\"\n\t\t\t\t:objectId=\"objectKey\"\n\t\t\t\t:register=\"registerKey\"\n\t\t\t\t:schema=\"schemaKey\" />\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcNoteCard, NcSelect } from '@nextcloud/vue'\nimport EmailOffOutline from 'vue-material-design-icons/EmailOffOutline.vue'\nimport CnEmailTab from '../../integrations/builtin/email/CnEmailTab.vue'\nimport CnEmptyContent from '../CnEmptyContent/CnEmptyContent.vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { evaluateVisibleWhenLocal } from '../../utils/visibleWhen.js'\n\n/**\n * Read a reference that may be a slug, an id or an object carrying either.\n *\n * @param {string|number|object} value The reference.\n * @return {string} The slug or id, or ''.\n */\nfunction keyOf(value) {\n\tif (value === null || value === undefined) {\n\t\treturn ''\n\t}\n\tif (typeof value === 'object') {\n\t\treturn String(value.slug || value.id || value.uuid || '')\n\t}\n\treturn String(value)\n}\n\n/**\n * CnMailTab — the mail of one record: drafts in Nextcloud Mail, from a\n * template or empty, above the mail linked to the record.\n *\n * Registered as the `mail` widget type. The app owns the endpoints and the\n * texts; the tab never sends mail. A draft is a POST to `draft.url`, whose\n * response may carry `draftUrl` (opened in a new tab) and `unresolved` (the\n * template fields the server could not fill). A 404 there means the app has\n * no Mail to draft into, and the tab says so instead of the controls.\n *\n * ```json\n * {\n * \"type\": \"mail\",\n * \"content\": {\n * \"heading\": \"Email\",\n * \"description\": \"Mail linked to this case\",\n * \"hint\": \"The draft opens in Nextcloud Mail.\",\n * \"templates\": { \"url\": \"/apps/app/api/types/@object.type/templates\", \"responsePath\": \"results\", \"labelField\": \"name\", \"idField\": \"id\" },\n * \"noTemplatesText\": \"No templates for this type yet\",\n * \"draft\": { \"url\": \"/apps/app/api/records/@objectId/templates/{templateId}/draft\", \"blankTemplateId\": \"blank\" },\n * \"closedWhen\": { \"field\": \"endDate\", \"op\": \"notEmpty\" },\n * \"linkedMail\": true\n * }\n * }\n * ```\n *\n * URLs take the `@objectId` / `@object.<field>` tokens of `endpointSource`;\n * `{templateId}` in the draft URL is the chosen template's id, or\n * `blankTemplateId` for an empty draft. Without `templates` the row offers\n * the empty draft only; without `draft` there is no row. `closedWhen` is a\n * local visibleWhen condition on the record that disables drafting.\n * `linkedMail: false` leaves the linked mail to a separate `email`\n * integration card. Texts go through the host's translate.\n */\nexport default {\n\tname: 'CnMailTab',\n\n\tcomponents: {\n\t\tCnEmailTab,\n\t\tCnEmptyContent,\n\t\tEmailOffOutline,\n\t\tNcButton,\n\t\tNcNoteCard,\n\t\tNcSelect,\n\t},\n\n\tinject: {\n\t\t/** The detail page's object context (`{ objectId, object }`), for tokens. */\n\t\tcnObjectContext: { default: null },\n\t\t/** The host's translate, for the manifest texts. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget config: `{ heading?, description?, hint?, templates?,\n\t\t * noTemplatesText?, draft?, closedWhen?, linkedMail? }`, as in the\n\t\t * component description and docs/components/cn-mail-tab.md.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The bound record's id, for `@objectId` and the linked mail. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The bound record, for `@object.<field>` and `closedWhen`. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The bound record's register, for the linked mail. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The bound record's schema, for the linked mail. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['drafted'],\n\n\tdata() {\n\t\treturn {\n\t\t\ttemplates: [],\n\t\t\tselectedTemplate: null,\n\t\t\tdrafting: false,\n\t\t\terror: '',\n\t\t\tunresolved: [],\n\t\t\tunavailable: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The record, from the prop or the page context. */\n\t\trecord() {\n\t\t\tif (this.objectData) {\n\t\t\t\treturn this.objectData\n\t\t\t}\n\t\t\tconst ctx = this.cnObjectContext\n\t\t\tconst value = ctx && typeof ctx === 'object' && 'value' in ctx ? ctx.value : ctx\n\t\t\treturn (value && value.object) || {}\n\t\t},\n\n\t\t/** @return {string} The record id. */\n\t\tobjectKey() {\n\t\t\treturn keyOf(this.objectId) || keyOf(this.record.id) || keyOf(this.record['@self'] && this.record['@self'].id)\n\t\t},\n\n\t\t/** @return {string} The register slug or id. */\n\t\tregisterKey() {\n\t\t\treturn keyOf(this.register)\n\t\t},\n\n\t\t/** @return {string} The schema slug or id. */\n\t\tschemaKey() {\n\t\t\treturn keyOf(this.schema)\n\t\t},\n\n\t\t/** @return {object} The token context for the URLs. */\n\t\ttokenContext() {\n\t\t\treturn { objectId: this.objectKey, object: this.record }\n\t\t},\n\n\t\t/** @return {string} The heading, translated, or ''. */\n\t\theading() {\n\t\t\treturn this.tr(this.content.heading)\n\t\t},\n\n\t\t/** @return {string} The line under the heading, translated, or ''. */\n\t\tdescription() {\n\t\t\treturn this.tr(this.content.description)\n\t\t},\n\n\t\t/** @return {string} The line under the template row, translated, or ''. */\n\t\thint() {\n\t\t\treturn this.tr(this.content.hint)\n\t\t},\n\n\t\t/** @return {object|null} The templates endpoint, or null. */\n\t\ttemplatesSource() {\n\t\t\tconst source = this.content.templates\n\t\t\treturn source && typeof source === 'object' && source.url ? source : null\n\t\t},\n\n\t\t/** @return {object|null} The draft endpoint, or null. */\n\t\tdraftSource() {\n\t\t\tconst source = this.content.draft\n\t\t\treturn source && typeof source === 'object' && source.url ? source : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the template select and its button show. */\n\t\ttemplatesEnabled() {\n\t\t\treturn this.templatesSource !== null\n\t\t},\n\n\t\t/** @return {boolean} Whether the template row shows. */\n\t\tdraftEnabled() {\n\t\t\treturn this.draftSource !== null\n\t\t},\n\n\t\t/** @return {string} The template field shown in the select. */\n\t\ttemplateLabelField() {\n\t\t\treturn (this.templatesSource && this.templatesSource.labelField) || 'name'\n\t\t},\n\n\t\t/** @return {string} The template field that identifies it. */\n\t\ttemplateIdField() {\n\t\t\treturn (this.templatesSource && this.templatesSource.idField) || 'id'\n\t\t},\n\n\t\t/** @return {string} The select's placeholder. */\n\t\ttemplatePlaceholder() {\n\t\t\tif (this.templates.length === 0) {\n\t\t\t\treturn this.tr(this.content.noTemplatesText) || t('nextcloud-vue', 'No templates yet')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Select a template (optional)…')\n\t\t},\n\n\t\t/** @return {boolean} Whether `closedWhen` holds for the record. */\n\t\tclosed() {\n\t\t\tconst cond = this.content.closedWhen\n\t\t\tif (!cond) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn evaluateVisibleWhenLocal(cond, this.record)\n\t\t},\n\n\t\t/** @return {string} The templates URL after tokens, to refetch on change. */\n\t\ttemplatesUrl() {\n\t\t\treturn this.templatesSource ? interpolateUrlTokens(this.templatesSource.url, this.tokenContext) : ''\n\t\t},\n\n\t\t/** @return {boolean} Whether the linked mail list shows. */\n\t\tlinkedMail() {\n\t\t\treturn this.content.linkedMail !== false\n\t\t},\n\t},\n\n\twatch: {\n\t\ttemplatesUrl: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.loadTemplates()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Translate a manifest text through the host.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The translation, or '' for no text.\n\t\t */\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.cnTranslate(text)\n\t\t},\n\n\t\t/**\n\t\t * Read the templates. A failed read leaves the empty draft usable.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadTemplates() {\n\t\t\tif (!this.templatesSource) {\n\t\t\t\tthis.templates = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst payload = await fetchEndpointSource(this.templatesSource, this.tokenContext)\n\t\t\t\tconst list = Array.isArray(payload) ? payload : (payload && Array.isArray(payload.results) ? payload.results : [])\n\t\t\t\tthis.templates = list\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[CnMailTab] could not read the templates', err)\n\t\t\t\tthis.templates = []\n\t\t\t}\n\t\t},\n\n\t\t/** @return {Promise<void>} */\n\t\tdraftFromTemplate() {\n\t\t\treturn this.openDraft(this.selectedTemplate)\n\t\t},\n\n\t\t/** @return {Promise<void>} */\n\t\tdraftBlank() {\n\t\t\tthis.selectedTemplate = null\n\t\t\treturn this.openDraft(null)\n\t\t},\n\n\t\t/**\n\t\t * Ask the app to create a Nextcloud Mail draft and open it.\n\t\t *\n\t\t * @param {object|null} template The chosen template, or null for an empty draft.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync openDraft(template) {\n\t\t\tif (this.closed || !this.draftSource) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.drafting = true\n\t\t\tthis.error = ''\n\t\t\tthis.unresolved = []\n\t\t\ttry {\n\t\t\t\tconst id = template ? template[this.templateIdField] : (this.draftSource.blankTemplateId || 'blank')\n\t\t\t\tconst path = interpolateUrlTokens(this.draftSource.url, this.tokenContext)\n\t\t\t\t\t.replace('{templateId}', encodeURIComponent(String(id)))\n\t\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\t\timport('@nextcloud/router'),\n\t\t\t\t])\n\t\t\t\tconst { data } = await axios.post(generateUrl(path), {})\n\t\t\t\tthis.unresolved = Array.isArray(data && data.unresolved) ? data.unresolved : []\n\t\t\t\tif (data && data.draftUrl) {\n\t\t\t\t\twindow.open(data.draftUrl, '_blank', 'noopener')\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event drafted A draft was made from a template. Carries the\n\t\t\t\t * draft endpoint's response, including `draftUrl` and\n\t\t\t\t * `unresolved` when the endpoint returns them.\n\t\t\t\t * @type {object}\n\t\t\t\t */\n\t\t\t\tthis.$emit('drafted', data)\n\t\t\t} catch (err) {\n\t\t\t\tconst response = err && err.response\n\t\t\t\tif (response && response.status === 404) {\n\t\t\t\t\tthis.unavailable = true\n\t\t\t\t}\n\t\t\t\tthis.error = (response && response.data && response.data.message)\n\t\t\t\t\t|| (err && err.message)\n\t\t\t\t\t|| t('nextcloud-vue', 'The draft could not be opened.')\n\t\t\t} finally {\n\t\t\t\tthis.drafting = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Write a template field the way the template spells it.\n\t\t *\n\t\t * @param {string} name The field name.\n\t\t * @return {string} `{{name}}`.\n\t\t */\n\t\tplaceholderOf(name) {\n\t\t\treturn `{{${name}}}`\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-mail-tab {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 16px;\n\tpadding: 12px;\n}\n\n.cn-mail-tab__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: bold;\n}\n\n.cn-mail-tab__subtitle,\n.cn-mail-tab__hint {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-mail-tab__template-row {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 8px;\n}\n\n.cn-mail-tab__template-select {\n\tflex: 1 1 260px;\n}\n\n.cn-mail-tab__unresolved {\n\tmargin: 4px 0 0;\n\tpadding-inline-start: 20px;\n}\n\n.cn-mail-tab__unresolved code {\n\tbackground: var(--color-background-dark);\n\tpadding: 2px 6px;\n\tborder-radius: var(--border-radius);\n\tfont-family: var(--font-face-mono, monospace);\n}\n</style>\n"],"names":["CnEmailTab","CnEmptyContent","t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnMailTab.vue2.js","sources":["../../../../src/components/CnMailTab/CnMailTab.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-mail-tab\" data-testid=\"cn-mail-tab\">\n\t\t<CnEmptyContent\n\t\t\tv-if=\"unavailable\"\n\t\t\t:name=\"t('nextcloud-vue', 'Mail is not available')\"\n\t\t\t:description=\"t('nextcloud-vue', 'Install Nextcloud Mail to draft and link mail here.')\">\n\t\t\t<template #icon>\n\t\t\t\t<EmailOffOutline :size=\"48\" />\n\t\t\t</template>\n\t\t</CnEmptyContent>\n\n\t\t<template v-else>\n\t\t\t<h3 v-if=\"heading\" class=\"cn-mail-tab__title\">\n\t\t\t\t{{ heading }}\n\t\t\t</h3>\n\t\t\t<p v-if=\"description\" class=\"cn-mail-tab__subtitle\">\n\t\t\t\t{{ description }}\n\t\t\t</p>\n\n\t\t\t<div v-if=\"draftEnabled\" class=\"cn-mail-tab__template-row\" data-testid=\"cn-mail-tab-template-row\">\n\t\t\t\t<NcSelect\n\t\t\t\t\tv-if=\"templatesEnabled\"\n\t\t\t\t\tv-model=\"selectedTemplate\"\n\t\t\t\t\tclass=\"cn-mail-tab__template-select\"\n\t\t\t\t\t:options=\"templates\"\n\t\t\t\t\t:disabled=\"templates.length === 0\"\n\t\t\t\t\t:inputLabel=\"t('nextcloud-vue', 'Email template')\"\n\t\t\t\t\t:label=\"templateLabelField\"\n\t\t\t\t\t:trackBy=\"templateIdField\"\n\t\t\t\t\t:placeholder=\"templatePlaceholder\"\n\t\t\t\t\t:clearable=\"true\" />\n\t\t\t\t<NcButton\n\t\t\t\t\tv-if=\"templatesEnabled\"\n\t\t\t\t\t:disabled=\"closed || drafting || !selectedTemplate\"\n\t\t\t\t\tdata-testid=\"cn-mail-tab-draft-template\"\n\t\t\t\t\t@click=\"draftFromTemplate\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Open draft from template') }}\n\t\t\t\t</NcButton>\n\t\t\t\t<NcButton\n\t\t\t\t\t:disabled=\"closed || drafting\"\n\t\t\t\t\tdata-testid=\"cn-mail-tab-draft-blank\"\n\t\t\t\t\t@click=\"draftBlank\">\n\t\t\t\t\t{{ t('nextcloud-vue', 'Empty draft') }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t\t<p v-if=\"hint\" class=\"cn-mail-tab__hint\">\n\t\t\t\t{{ hint }}\n\t\t\t</p>\n\n\t\t\t<NcNoteCard\n\t\t\t\tv-if=\"error\"\n\t\t\t\ttype=\"error\"\n\t\t\t\t:heading=\"t('nextcloud-vue', 'Could not open draft')\"\n\t\t\t\trole=\"alert\">\n\t\t\t\t{{ error }}\n\t\t\t</NcNoteCard>\n\t\t\t<NcNoteCard\n\t\t\t\tv-if=\"unresolved.length > 0\"\n\t\t\t\ttype=\"warning\"\n\t\t\t\trole=\"status\"\n\t\t\t\tdata-testid=\"cn-mail-tab-unresolved\">\n\t\t\t\t<p>{{ t('nextcloud-vue', 'Some template fields could not be filled. Fill these in the draft yourself:') }}</p>\n\t\t\t\t<ul class=\"cn-mail-tab__unresolved\">\n\t\t\t\t\t<li v-for=\"name in unresolved\" :key=\"name\">\n\t\t\t\t\t\t<code>{{ placeholderOf(name) }}</code>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t</NcNoteCard>\n\n\t\t\t<CnEmailTab\n\t\t\t\tv-if=\"linkedMail && objectKey\"\n\t\t\t\tclass=\"cn-mail-tab__linked\"\n\t\t\t\t:objectId=\"objectKey\"\n\t\t\t\t:register=\"registerKey\"\n\t\t\t\t:schema=\"schemaKey\" />\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcNoteCard, NcSelect } from '@nextcloud/vue'\nimport EmailOffOutline from 'vue-material-design-icons/EmailOffOutline.vue'\nimport CnEmailTab from '../../integrations/builtin/email/CnEmailTab.vue'\nimport CnEmptyContent from '../CnEmptyContent/CnEmptyContent.vue'\nimport { fetchEndpointSource, interpolateUrlTokens } from '../../composables/useEndpointSource.js'\nimport { evaluateVisibleWhenLocal } from '../../utils/visibleWhen.js'\n\n/**\n * Read a reference that may be a slug, an id or an object carrying either.\n *\n * @param {string|number|object} value The reference.\n * @return {string} The slug or id, or ''.\n */\nfunction keyOf(value) {\n\tif (value === null || value === undefined) {\n\t\treturn ''\n\t}\n\tif (typeof value === 'object') {\n\t\treturn String(value.slug || value.id || value.uuid || '')\n\t}\n\treturn String(value)\n}\n\n/**\n * CnMailTab — the mail of one record: drafts in Nextcloud Mail, from a\n * template or empty, above the mail linked to the record.\n *\n * Registered as the `mail` widget type. The app owns the endpoints and the\n * texts; the tab never sends mail. A draft is a POST to `draft.url`, whose\n * response may carry `draftUrl` (opened in a new tab) and `unresolved` (the\n * template fields the server could not fill). A 404 there means the app has\n * no Mail to draft into, and the tab says so instead of the controls.\n *\n * ```json\n * {\n * \"type\": \"mail\",\n * \"content\": {\n * \"heading\": \"Email\",\n * \"description\": \"Mail linked to this case\",\n * \"hint\": \"The draft opens in Nextcloud Mail.\",\n * \"templates\": { \"url\": \"/apps/app/api/types/@object.type/templates\", \"responsePath\": \"results\", \"labelField\": \"name\", \"idField\": \"id\" },\n * \"noTemplatesText\": \"No templates for this type yet\",\n * \"draft\": { \"url\": \"/apps/app/api/records/@objectId/templates/{templateId}/draft\", \"blankTemplateId\": \"blank\" },\n * \"closedWhen\": { \"field\": \"endDate\", \"op\": \"notEmpty\" },\n * \"linkedMail\": true\n * }\n * }\n * ```\n *\n * URLs take the `@objectId` / `@object.<field>` tokens of `endpointSource`;\n * `{templateId}` in the draft URL is the chosen template's id, or\n * `blankTemplateId` for an empty draft. Without `templates` the row offers\n * the empty draft only; without `draft` there is no row. `closedWhen` is a\n * local visibleWhen condition on the record that disables drafting.\n * `linkedMail: false` leaves the linked mail to a separate `email`\n * integration card. Texts go through the host's translate.\n */\nexport default {\n\tname: 'CnMailTab',\n\n\tcomponents: {\n\t\tCnEmailTab,\n\t\tCnEmptyContent,\n\t\tEmailOffOutline,\n\t\tNcButton,\n\t\tNcNoteCard,\n\t\tNcSelect,\n\t},\n\n\tinject: {\n\t\t/** The detail page's object context (`{ objectId, object }`), for tokens. */\n\t\tcnObjectContext: { default: null },\n\t\t/** The host's translate, for the manifest texts. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget config: `{ heading?, description?, hint?, templates?,\n\t\t * noTemplatesText?, draft?, closedWhen?, linkedMail? }`, as in the\n\t\t * component description and docs/components/cn-mail-tab.md.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The bound record's id, for `@objectId` and the linked mail. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The bound record, for `@object.<field>` and `closedWhen`. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The bound record's register, for the linked mail. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The bound record's schema, for the linked mail. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['drafted'],\n\n\tdata() {\n\t\treturn {\n\t\t\ttemplates: [],\n\t\t\tselectedTemplate: null,\n\t\t\tdrafting: false,\n\t\t\terror: '',\n\t\t\tunresolved: [],\n\t\t\tunavailable: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/** @return {object} The record, from the prop or the page context. */\n\t\trecord() {\n\t\t\tif (this.objectData) {\n\t\t\t\treturn this.objectData\n\t\t\t}\n\t\t\tconst ctx = this.cnObjectContext\n\t\t\tconst value = ctx && typeof ctx === 'object' && 'value' in ctx ? ctx.value : ctx\n\t\t\treturn (value && value.object) || {}\n\t\t},\n\n\t\t/** @return {string} The record id. */\n\t\tobjectKey() {\n\t\t\treturn keyOf(this.objectId) || keyOf(this.record.id) || keyOf(this.record['@self'] && this.record['@self'].id)\n\t\t},\n\n\t\t/** @return {string} The register slug or id. */\n\t\tregisterKey() {\n\t\t\treturn keyOf(this.register)\n\t\t},\n\n\t\t/** @return {string} The schema slug or id. */\n\t\tschemaKey() {\n\t\t\treturn keyOf(this.schema)\n\t\t},\n\n\t\t/** @return {object} The token context for the URLs. */\n\t\ttokenContext() {\n\t\t\treturn { objectId: this.objectKey, object: this.record }\n\t\t},\n\n\t\t/** @return {string} The heading, translated, or ''. */\n\t\theading() {\n\t\t\treturn this.tr(this.content.heading)\n\t\t},\n\n\t\t/** @return {string} The line under the heading, translated, or ''. */\n\t\tdescription() {\n\t\t\treturn this.tr(this.content.description)\n\t\t},\n\n\t\t/** @return {string} The line under the template row, translated, or ''. */\n\t\thint() {\n\t\t\treturn this.tr(this.content.hint)\n\t\t},\n\n\t\t/** @return {object|null} The templates endpoint, or null. */\n\t\ttemplatesSource() {\n\t\t\tconst source = this.content.templates\n\t\t\treturn source && typeof source === 'object' && source.url ? source : null\n\t\t},\n\n\t\t/** @return {object|null} The draft endpoint, or null. */\n\t\tdraftSource() {\n\t\t\tconst source = this.content.draft\n\t\t\treturn source && typeof source === 'object' && source.url ? source : null\n\t\t},\n\n\t\t/** @return {boolean} Whether the template select and its button show. */\n\t\ttemplatesEnabled() {\n\t\t\treturn this.templatesSource !== null\n\t\t},\n\n\t\t/** @return {boolean} Whether the template row shows. */\n\t\tdraftEnabled() {\n\t\t\treturn this.draftSource !== null\n\t\t},\n\n\t\t/** @return {string} The template field shown in the select. */\n\t\ttemplateLabelField() {\n\t\t\treturn (this.templatesSource && this.templatesSource.labelField) || 'name'\n\t\t},\n\n\t\t/** @return {string} The template field that identifies it. */\n\t\ttemplateIdField() {\n\t\t\treturn (this.templatesSource && this.templatesSource.idField) || 'id'\n\t\t},\n\n\t\t/** @return {string} The select's placeholder. */\n\t\ttemplatePlaceholder() {\n\t\t\tif (this.templates.length === 0) {\n\t\t\t\treturn this.tr(this.content.noTemplatesText) || t('nextcloud-vue', 'No templates yet')\n\t\t\t}\n\t\t\treturn t('nextcloud-vue', 'Select a template (optional)…')\n\t\t},\n\n\t\t/** @return {boolean} Whether `closedWhen` holds for the record. */\n\t\tclosed() {\n\t\t\tconst cond = this.content.closedWhen\n\t\t\tif (!cond) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn evaluateVisibleWhenLocal(cond, this.record)\n\t\t},\n\n\t\t/** @return {string} The templates URL after tokens, to refetch on change. */\n\t\ttemplatesUrl() {\n\t\t\treturn this.templatesSource ? interpolateUrlTokens(this.templatesSource.url, this.tokenContext) : ''\n\t\t},\n\n\t\t/** @return {boolean} Whether the linked mail list shows. */\n\t\tlinkedMail() {\n\t\t\treturn this.content.linkedMail !== false\n\t\t},\n\t},\n\n\twatch: {\n\t\ttemplatesUrl: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.loadTemplates()\n\t\t\t},\n\t\t},\n\t},\n\n\tmethods: {\n\t\tt,\n\n\t\t/**\n\t\t * Translate a manifest text through the host.\n\t\t *\n\t\t * @param {string} text The text.\n\t\t * @return {string} The translation, or '' for no text.\n\t\t */\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn this.cnTranslate(text)\n\t\t},\n\n\t\t/**\n\t\t * Read the templates. A failed read leaves the empty draft usable.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadTemplates() {\n\t\t\tif (!this.templatesSource) {\n\t\t\t\tthis.templates = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst payload = await fetchEndpointSource(this.templatesSource, this.tokenContext)\n\t\t\t\tconst list = Array.isArray(payload) ? payload : (payload && Array.isArray(payload.results) ? payload.results : [])\n\t\t\t\tthis.templates = list\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn('[CnMailTab] could not read the templates', err)\n\t\t\t\tthis.templates = []\n\t\t\t}\n\t\t},\n\n\t\t/** @return {Promise<void>} */\n\t\tdraftFromTemplate() {\n\t\t\treturn this.openDraft(this.selectedTemplate)\n\t\t},\n\n\t\t/** @return {Promise<void>} */\n\t\tdraftBlank() {\n\t\t\tthis.selectedTemplate = null\n\t\t\treturn this.openDraft(null)\n\t\t},\n\n\t\t/**\n\t\t * Ask the app to create a Nextcloud Mail draft and open it.\n\t\t *\n\t\t * @param {object|null} template The chosen template, or null for an empty draft.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync openDraft(template) {\n\t\t\tif (this.closed || !this.draftSource) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.drafting = true\n\t\t\tthis.error = ''\n\t\t\tthis.unresolved = []\n\t\t\ttry {\n\t\t\t\tconst id = template ? template[this.templateIdField] : (this.draftSource.blankTemplateId || 'blank')\n\t\t\t\tconst path = interpolateUrlTokens(this.draftSource.url, this.tokenContext)\n\t\t\t\t\t.replace('{templateId}', encodeURIComponent(String(id)))\n\t\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\t\timport('@nextcloud/router'),\n\t\t\t\t])\n\t\t\t\tconst { data } = await axios.post(generateUrl(path), {})\n\t\t\t\tthis.unresolved = Array.isArray(data && data.unresolved) ? data.unresolved : []\n\t\t\t\tif (data && data.draftUrl) {\n\t\t\t\t\twindow.open(data.draftUrl, '_blank', 'noopener')\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event drafted A draft was made from a template. Carries the\n\t\t\t\t * draft endpoint's response, including `draftUrl` and\n\t\t\t\t * `unresolved` when the endpoint returns them.\n\t\t\t\t * @type {object}\n\t\t\t\t */\n\t\t\t\tthis.$emit('drafted', data)\n\t\t\t} catch (err) {\n\t\t\t\tconst response = err && err.response\n\t\t\t\tif (response && response.status === 404) {\n\t\t\t\t\tthis.unavailable = true\n\t\t\t\t}\n\t\t\t\tthis.error = (response && response.data && response.data.message)\n\t\t\t\t\t|| (err && err.message)\n\t\t\t\t\t|| t('nextcloud-vue', 'The draft could not be opened.')\n\t\t\t} finally {\n\t\t\t\tthis.drafting = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Write a template field the way the template spells it.\n\t\t *\n\t\t * @param {string} name The field name.\n\t\t * @return {string} `{{name}}`.\n\t\t */\n\t\tplaceholderOf(name) {\n\t\t\treturn `{{${name}}}`\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-mail-tab {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 16px;\n\tpadding: 12px;\n}\n\n.cn-mail-tab__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: bold;\n}\n\n.cn-mail-tab__subtitle,\n.cn-mail-tab__hint {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n}\n\n.cn-mail-tab__template-row {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 8px;\n}\n\n.cn-mail-tab__template-select {\n\tflex: 1 1 260px;\n}\n\n.cn-mail-tab__unresolved {\n\tmargin: 4px 0 0;\n\tpadding-inline-start: 20px;\n}\n\n.cn-mail-tab__unresolved code {\n\tbackground: var(--color-background-dark);\n\tpadding: 2px 6px;\n\tborder-radius: var(--border-radius);\n\tfont-family: var(--font-face-mono, monospace);\n}\n</style>\n"],"names":["CnEmailTab","CnEmptyContent","t"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import script from './CnObjectListWidget.vue2.js';
|
|
|
2
2
|
import { render } from './CnObjectListWidget.vue3.js';
|
|
3
3
|
|
|
4
4
|
script.render = render;
|
|
5
|
-
script.__scopeId = "data-v-
|
|
5
|
+
script.__scopeId = "data-v-20226ff6";
|
|
6
6
|
const __sfc_main = script;
|
|
7
7
|
|
|
8
8
|
export { __sfc_main as default };
|
|
@@ -11,11 +11,13 @@ import { useWriteFeedback } from '../../composables/useWriteFeedback.js';
|
|
|
11
11
|
import { hasActionTargetTokens, actionLink, dispatchAction } from '../../utils/actionsDispatcher.js';
|
|
12
12
|
import { buildExportUrl } from '../../utils/indexExportHelpers.js';
|
|
13
13
|
import { resolveHref, followLinkClick, openRowTarget } from '../../utils/linkNavigation.js';
|
|
14
|
+
import { createActionState } from '../../utils/listCreateAction.js';
|
|
14
15
|
import { objectFieldValue, objectDisplayName } from '../../utils/objectName.js';
|
|
15
16
|
import { rowIdOf, renumberRows, moveIndex } from '../../utils/reorderRows.js';
|
|
16
17
|
import { dropOptionalUnresolved, resolveFilterTokens, hasUnresolvedTokens } from '../../utils/resolveFilterTokens.js';
|
|
17
18
|
import { markNewTabHandled } from '../../utils/rowAuxClick.js';
|
|
18
19
|
import { changedKeys } from '../../utils/saveEdited.js';
|
|
20
|
+
import { evaluateVisibleWhenLocal } from '../../utils/visibleWhen.js';
|
|
19
21
|
import { dispatchObjectCreated } from '../../utils/walkthroughSignals.js';
|
|
20
22
|
import { getCurrentUserGroups } from '../../utils/widgetVisibility.js';
|
|
21
23
|
import __sfc_main$4 from '../CnRowActions/CnRowActions.vue.js';
|
|
@@ -141,6 +143,17 @@ var script = {
|
|
|
141
143
|
* those carrying a selected value. Client-side over the fetched page,
|
|
142
144
|
* like the rest of this widget's row set.
|
|
143
145
|
*
|
|
146
|
+
* `createAction` (one action of the `rowActions` shape) replaces the
|
|
147
|
+
* list's own create form: every Add, here and in the host card's menu,
|
|
148
|
+
* runs it instead, labelled with its `label`. Its `visibleWhen` is
|
|
149
|
+
* evaluated against the page record, and while it fails the Add is
|
|
150
|
+
* hidden and `hiddenNote` (a string, or `[{ when, text }]` where the
|
|
151
|
+
* first holding entry wins) is shown in its place.
|
|
152
|
+
*
|
|
153
|
+
* `summary` (`{ text, counts }`) is a line under the rows: `{total}` is
|
|
154
|
+
* the number of loaded rows and each `counts` key the number of loaded
|
|
155
|
+
* rows its `visibleWhen`-shaped condition holds for.
|
|
156
|
+
*
|
|
144
157
|
* `hideHeader: true` drops the table's column header row (CnDataTable's
|
|
145
158
|
* `hideHeader`), for a short list that reads as rows, not as a table.
|
|
146
159
|
*
|
|
@@ -785,9 +798,55 @@ var script = {
|
|
|
785
798
|
/** Whether the create affordance renders (on by default; `content.allowCreate: false` opts out). */
|
|
786
799
|
allowCreate() {
|
|
787
800
|
const c = this.content || {};
|
|
801
|
+
if (this.createState.action) {
|
|
802
|
+
return c.allowCreate !== false && this.createState.visible
|
|
803
|
+
}
|
|
788
804
|
return c.allowCreate !== false && Boolean(c.register) && Boolean(c.schema)
|
|
789
805
|
},
|
|
790
806
|
|
|
807
|
+
/**
|
|
808
|
+
* The declared `content.createAction` against the page record: the
|
|
809
|
+
* action, whether it shows, and the untranslated note when it does not.
|
|
810
|
+
*
|
|
811
|
+
* @return {{action: (object|null), visible: boolean, note: string}}
|
|
812
|
+
*/
|
|
813
|
+
createState() {
|
|
814
|
+
return createActionState(this.content, this.objectCtx ? this.objectCtx.object : null)
|
|
815
|
+
},
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* Why the create action is withheld, through the host translate, or ''.
|
|
819
|
+
*
|
|
820
|
+
* @return {string}
|
|
821
|
+
*/
|
|
822
|
+
createHiddenNote() {
|
|
823
|
+
const note = this.createState.note;
|
|
824
|
+
const fn = typeof this.cnTranslate === 'function' ? this.cnTranslate : (k) => k;
|
|
825
|
+
return note ? fn(note) : ''
|
|
826
|
+
},
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* `content.summary` filled in: `{total}` is the number of loaded rows
|
|
830
|
+
* and every `counts` key the number of loaded rows its condition holds
|
|
831
|
+
* for. The text goes through the host translate first, so a catalogue
|
|
832
|
+
* entry keeps its placeholders.
|
|
833
|
+
*
|
|
834
|
+
* @return {string}
|
|
835
|
+
*/
|
|
836
|
+
resolvedSummary() {
|
|
837
|
+
const summary = this.content.summary;
|
|
838
|
+
if (!summary || typeof summary.text !== 'string' || summary.text === '') {
|
|
839
|
+
return ''
|
|
840
|
+
}
|
|
841
|
+
const fn = typeof this.cnTranslate === 'function' ? this.cnTranslate : (k) => k;
|
|
842
|
+
const values = { total: this.rows.length };
|
|
843
|
+
const counts = summary.counts && typeof summary.counts === 'object' ? summary.counts : {};
|
|
844
|
+
for (const [key, cond] of Object.entries(counts)) {
|
|
845
|
+
values[key] = this.rows.filter((row) => evaluateVisibleWhenLocal(cond, row)).length;
|
|
846
|
+
}
|
|
847
|
+
return fn(summary.text).replace(/\{(\w+)\}/g, (match, key) => (key in values ? String(values[key]) : match))
|
|
848
|
+
},
|
|
849
|
+
|
|
791
850
|
/**
|
|
792
851
|
* NcDialog size for the create dialog (`content.formSize`).
|
|
793
852
|
*
|
|
@@ -908,6 +967,11 @@ var script = {
|
|
|
908
967
|
// `prompt`. It used to print raw, so a Dutch user read the English
|
|
909
968
|
// manifest string. A label an app already translated has no key
|
|
910
969
|
// of its own in the catalogue and comes back unchanged.
|
|
970
|
+
const action = this.createState.action;
|
|
971
|
+
if (action && typeof action.label === 'string' && action.label !== '') {
|
|
972
|
+
const fn = typeof this.cnTranslate === 'function' ? this.cnTranslate : (k) => k;
|
|
973
|
+
return fn(action.label)
|
|
974
|
+
}
|
|
911
975
|
if (this.content.addLabel) {
|
|
912
976
|
const fn = typeof this.cnTranslate === 'function' ? this.cnTranslate : (k) => k;
|
|
913
977
|
return fn(this.content.addLabel)
|
|
@@ -1406,6 +1470,13 @@ var script = {
|
|
|
1406
1470
|
|
|
1407
1471
|
async openCreate() {
|
|
1408
1472
|
const c = this.content || {};
|
|
1473
|
+
const { action, visible } = this.createState;
|
|
1474
|
+
if (action) {
|
|
1475
|
+
if (visible) {
|
|
1476
|
+
this.dispatch(action);
|
|
1477
|
+
}
|
|
1478
|
+
return
|
|
1479
|
+
}
|
|
1409
1480
|
if (!c.schema) {
|
|
1410
1481
|
return
|
|
1411
1482
|
}
|