@conduction/nextcloud-vue 2.114.0 → 2.115.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/CnAdvancedFormDialog/CnPropertyValueCell.vue.js +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdvancedFormDialog/CnPropertyValueCell.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +6 -2
- 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/CnChoiceCards/CnChoiceCards.vue.js +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js +2 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
- package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +19 -2
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -3
- 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 +2 -2
- 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 +37 -1
- 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/CnIndexPage/rowsToCsv.js +90 -0
- package/dist/esm/components/CnIndexPage/rowsToCsv.js.map +1 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue.js +9 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue.js.map +1 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue2.js +161 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue3.js +97 -0
- package/dist/esm/components/CnMacrosWidget/CnMacrosWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue.js +9 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue.js.map +1 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue2.js +63 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue2.js.map +1 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue3.js +54 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue3.js.map +1 -0
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue.js +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js +15 -9
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js +55 -63
- package/dist/esm/components/CnRetentionWidget/CnRetentionWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue.js +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js +2 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +13 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +2 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue.js +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue2.js.map +1 -1
- package/dist/esm/components/CnStepper/CnStepper.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +10 -5
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue.js +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +2 -2
- package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +32 -20
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/composables/indexSources.js +43 -11
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/composables/useTaskInboxStore.js +41 -0
- package/dist/esm/composables/useTaskInboxStore.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +4 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +9 -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 +482 -330
- package/dist/esm/utils/contentHeaderLink.js +37 -1
- package/dist/esm/utils/contentHeaderLink.js.map +1 -1
- package/dist/esm/utils/declaredMacros.js +31 -0
- package/dist/esm/utils/declaredMacros.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2673 -1977
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +482 -330
- package/l10n/en.json +4 -1
- package/l10n/nl.json +9 -1
- package/package.json +1 -1
- package/src/components/CnAdvancedFormDialog/CnPropertyValueCell.vue +1 -1
- package/src/components/CnCellRenderer/CnCellRenderer.vue +6 -2
- package/src/components/CnChoiceCards/CnChoiceCards.vue +2 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +45 -3
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
- package/src/components/CnIndexPage/CnIndexPage.vue +37 -1
- package/src/components/CnIndexPage/rowsToCsv.js +87 -0
- package/src/components/CnMacrosWidget/CnMacrosWidget.md +30 -0
- package/src/components/CnMacrosWidget/CnMacrosWidget.vue +266 -0
- package/src/components/CnMacrosWidget/index.js +6 -0
- package/src/components/CnRetentionWidget/CnRetentionRecomputeDialog.vue +104 -0
- package/src/components/CnRetentionWidget/CnRetentionWidget.vue +53 -38
- package/src/components/CnSegmentedControl/CnSegmentedControl.vue +2 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +28 -4
- package/src/components/CnStepper/CnStepper.vue +2 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +11 -6
- package/src/components/CnTasksWidget/CnTasksWidget.vue +2 -2
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/src/components/index.js +1 -0
- package/src/composables/indexSources.js +43 -11
- package/src/composables/useTaskInboxStore.js +41 -0
- package/src/css/look-board-detail.css +4 -3
- package/src/css/look-board-index.css +62 -0
- package/src/css/look-board.css +20 -0
- package/src/index.js +1 -0
- package/src/utils/contentHeaderLink.js +35 -0
- package/src/utils/declaredMacros.js +28 -0
- package/src/utils/libraryWidgetKeys.js +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnTasksWidget.vue3.js","sources":["../../../../src/components/CnTasksWidget/CnTasksWidget.vue?vue&type=template&id=0fd2a8fc&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-tasks-widget\" :class=\"{ 'cn-tasks-widget--list': isList }\">\n\t\t<!-- One quiet line on failure, never a leaked axios status string\n\t\t (ADR-062). The real error goes to the console. -->\n\t\t<p v-if=\"error\" class=\"cn-tasks-widget__error\">\n\t\t\t{{ tr('Could not load the tasks') }}\n\t\t</p>\n\t\t<div v-else-if=\"loading && rows.length === 0\" class=\"cn-tasks-widget__loading\">\n\t\t\t<NcLoadingIcon :size=\"24\" />\n\t\t</div>\n\t\t<!-- An empty inbox is the GOOD state, not an error and not a void:\n\t\t one muted line, no illustration. -->\n\t\t<template v-else-if=\"isTable\">\n\t\t\t<!-- The create form the header's \"New task\" opens: a title and a\n\t\t\t deadline, posted as an open task on this record. -->\n\t\t\t<form\n\t\t\t\tv-if=\"createOpen\"\n\t\t\t\tclass=\"cn-tasks-widget__create\"\n\t\t\t\tdata-testid=\"cn-tasks-widget-create\"\n\t\t\t\t@submit.prevent=\"createTask\">\n\t\t\t\t<NcTextField\n\t\t\t\t\t:modelValue=\"newTitle\"\n\t\t\t\t\t:label=\"tr('Task')\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-title\"\n\t\t\t\t\t@update:modelValue=\"(value) => (newTitle = String(value ?? ''))\" />\n\t\t\t\t<NcTextField\n\t\t\t\t\t:modelValue=\"newDue\"\n\t\t\t\t\ttype=\"date\"\n\t\t\t\t\t:label=\"tr('Deadline')\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-due\"\n\t\t\t\t\t@update:modelValue=\"(value) => (newDue = String(value ?? ''))\" />\n\t\t\t\t<NcButton\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"creating || newTitle.trim() === ''\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-save\">\n\t\t\t\t\t{{ tr('Add task') }}\n\t\t\t\t</NcButton>\n\t\t\t</form>\n\t\t\t<p v-if=\"tableRows.length === 0\" class=\"cn-tasks-widget__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</p>\n\t\t\t<table v-else class=\"cn-tasks-widget__table\" data-testid=\"cn-tasks-widget-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Task') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Handler') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Deadline') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Status') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t<span class=\"hidden-visually\">{{ tr('Task actions') }}</span>\n\t\t\t\t\t\t</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr\n\t\t\t\t\t\tv-for=\"task in tableRows\"\n\t\t\t\t\t\t:key=\"task.uuid\"\n\t\t\t\t\t\tclass=\"cn-tasks-widget__table-row\"\n\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__table-row--done': task.isTerminal === true }\"\n\t\t\t\t\t\t:data-state=\"task.state\"\n\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-row-${task.uuid}`\">\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-task\">\n\t\t\t\t\t\t\t<CheckCircle\n\t\t\t\t\t\t\t\tv-if=\"task.isTerminal === true\"\n\t\t\t\t\t\t\t\t:size=\"20\"\n\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__state-icon cn-tasks-widget__state-icon--done\" />\n\t\t\t\t\t\t\t<CircleOutline v-else :size=\"20\" class=\"cn-tasks-widget__state-icon\" />\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__name\"\n\t\t\t\t\t\t\t\t\t@click=\"onRowClick(task, $event)\"\n\t\t\t\t\t\t\t\t\t@auxclick=\"onRowAuxClick(task, $event)\">\n\t\t\t\t\t\t\t\t\t{{ titleOf(task) }}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<span v-if=\"tableMeta(task)\" class=\"cn-tasks-widget__meta\">{{ tableMeta(task) }}</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-handler\">\n\t\t\t\t\t\t\t<span v-if=\"task.assignee\" class=\"cn-tasks-widget__handler\">\n\t\t\t\t\t\t\t\t<NcAvatar\n\t\t\t\t\t\t\t\t\t:user=\"String(task.assignee)\"\n\t\t\t\t\t\t\t\t\t:displayName=\"handlerName(task)\"\n\t\t\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t\t\t{{ handlerName(task) }}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span v-else class=\"cn-tasks-widget__meta\">{{ tr('Unassigned') }}</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__cell-due\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true && task.isTerminal !== true }\">\n\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<CnStatusBadge :label=\"stateLabel(task)\" :variant=\"task.isTerminal === true ? 'default' : 'info'\" />\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-actions\">\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"canClaim(task)\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-claim-${task.uuid}`\"\n\t\t\t\t\t\t\t\t@click=\"claim(task)\">\n\t\t\t\t\t\t\t\t{{ tr('Claim') }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-else-if=\"canCompleteRow(task) && outcomesOf(task).length === 1\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-complete-${task.uuid}`\"\n\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcomesOf(task)[0]))\">\n\t\t\t\t\t\t\t\t{{ tr('Complete') }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t<NcActions\n\t\t\t\t\t\t\t\tv-if=\"(canCompleteRow(task) && outcomesOf(task).length > 1) || canCancelRow(task)\"\n\t\t\t\t\t\t\t\t:forceMenu=\"true\"\n\t\t\t\t\t\t\t\t:aria-label=\"tr('Task actions')\">\n\t\t\t\t\t\t\t\t<template v-if=\"canCompleteRow(task) && outcomesOf(task).length > 1\">\n\t\t\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\t\t\tv-for=\"outcome in outcomesOf(task)\"\n\t\t\t\t\t\t\t\t\t\t:key=\"outcomeId(outcome)\"\n\t\t\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcome))\">\n\t\t\t\t\t\t\t\t\t\t{{ completeLabel(outcome) }}\n\t\t\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\t\tv-if=\"canCancelRow(task)\"\n\t\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-cancel-${task.uuid}`\"\n\t\t\t\t\t\t\t\t\t@click=\"cancel(task)\">\n\t\t\t\t\t\t\t\t\t{{ tr('Cancel task') }}\n\t\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t\t</NcActions>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</template>\n\t\t<p v-else-if=\"rows.length === 0\" class=\"cn-tasks-widget__empty\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<template v-else>\n\t\t\t<!-- The count states the server TOTAL, never the rendered length\n\t\t\t (ADR-062): the number a person acts on is how much work\n\t\t\t exists, not how much fits the cell. -->\n\t\t\t<p v-if=\"!isList\" class=\"cn-tasks-widget__count\">\n\t\t\t\t{{ countLabel }}\n\t\t\t</p>\n\t\t\t<ul class=\"cn-tasks-widget__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"task in rows\"\n\t\t\t\t\t:key=\"task.uuid\"\n\t\t\t\t\tclass=\"cn-tasks-widget__row\"\n\t\t\t\t\t:data-state=\"task.state\"\n\t\t\t\t\t@click=\"onRowClick(task, $event)\"\n\t\t\t\t\t@mousedown=\"preventMiddleClickAutoscroll\"\n\t\t\t\t\t@auxclick=\"onRowAuxClick(task, $event)\">\n\t\t\t\t\t<!-- List variant: a checkbox completes the viewer's own task\n\t\t\t\t\t (the task with a declared outcome list keeps the menu, as\n\t\t\t\t\t a checkbox cannot choose an outcome). Other rows get a\n\t\t\t\t\t spacer so the titles stay aligned. -->\n\t\t\t\t\t<template v-if=\"isList\">\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tv-if=\"canCheck(task)\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__check\"\n\t\t\t\t\t\t\t:checked=\"completing.includes(String(task.uuid))\"\n\t\t\t\t\t\t\t:disabled=\"completing.includes(String(task.uuid))\"\n\t\t\t\t\t\t\t:aria-label=\"tr('Mark {title} as done').replace('{title}', titleOf(task))\"\n\t\t\t\t\t\t\tdata-testid=\"cn-tasks-widget-check\"\n\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t@change=\"check(task)\">\n\t\t\t\t\t\t<span v-else class=\"cn-tasks-widget__check-spacer\" aria-hidden=\"true\" />\n\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__name\">{{ titleOf(task) }}</span>\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__meta cn-tasks-widget__meta--split\">\n\t\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__subject\">{{ subjectOf(task) }}</span>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__due\"\n\t\t\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true }\">\n\t\t\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__name\">{{ titleOf(task) }}</span>\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__meta\">{{ metaLine(task) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<!-- Overdue is carried by the WORDING (taskDueLabel) and by\n\t\t\t\t\t\t weight; the colour only reinforces it. -->\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__due\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true }\">\n\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<!-- Only verbs the contract can accept are offered; the\n\t\t\t\t\t server still authorizes, and a refusal is toasted in\n\t\t\t\t\t its own words. Stopped clicks: the menu must not also\n\t\t\t\t\t open the row. -->\n\t\t\t\t\t<NcActions\n\t\t\t\t\t\tv-if=\"(canClaim(task) || canComplete(task)) && !(isList && canCheck(task))\"\n\t\t\t\t\t\tclass=\"cn-tasks-widget__actions\"\n\t\t\t\t\t\t:forceMenu=\"true\"\n\t\t\t\t\t\t:aria-label=\"tr('Task actions')\"\n\t\t\t\t\t\t@click.stop>\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tv-if=\"canClaim(task)\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t@click=\"claim(task)\">\n\t\t\t\t\t\t\t{{ tr('Claim') }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<template v-if=\"canComplete(task)\">\n\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\tv-for=\"outcome in outcomesOf(task)\"\n\t\t\t\t\t\t\t\t:key=\"outcomeId(outcome)\"\n\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcome))\">\n\t\t\t\t\t\t\t\t{{ completeLabel(outcome) }}\n\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcActions>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<!-- The remainder is a count, never a scrollbar (ADR-062). -->\n\t\t\t<p v-if=\"hiddenCount > 0\" class=\"cn-tasks-widget__more\">\n\t\t\t\t{{ moreLabel }}\n\t\t\t</p>\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { showError } from '@nextcloud/dialogs'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcActionButton, NcActions, NcAvatar, NcButton, NcLoadingIcon, NcTextField } from '@nextcloud/vue'\nimport { inject, ref } from 'vue'\nimport CheckCircle from 'vue-material-design-icons/CheckCircle.vue'\nimport CircleOutline from 'vue-material-design-icons/CircleOutline.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { taskDeepLink, taskDueLabel } from '../../composables/indexSources.js'\nimport { useEndpointSource } from '../../composables/useEndpointSource.js'\nimport { contentHeaderLink } from '../../utils/contentHeaderLink.js'\nimport { openRowTarget } from '../../utils/linkNavigation.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { userDisplayName } from '../../utils/userDisplayName.js'\n\n/**\n * The OpenRegister inbox read (openregister flow-task-entity). One endpoint\n * for the whole fleet: every app's human tasks live on OpenRegister's one\n * task store, so the widget is app-agnostic and ships no controller.\n *\n * @type {string}\n */\nconst FLOW_TASKS_URL = '/apps/openregister/api/flow-tasks'\n\n/**\n * The CMMN states, in the reading a dashboard needs. Labels double as the\n * meta-line words, so state never rests on styling.\n *\n * @type {Record<string, string>}\n */\nconst STATE_LABELS = {\n\tavailable: 'Available',\n\tenabled: 'Ready to claim',\n\tactive: 'In progress',\n\tcompleted: 'Completed',\n\tterminated: 'Terminated',\n\tdisabled: 'Disabled',\n}\n\n/**\n * The priority vocabulary (openregister Task::PRIORITIES).\n *\n * @type {Record<string, string>}\n */\nconst PRIORITY_LABELS = {\n\tlow: 'Low',\n\tnormal: 'Normal',\n\thigh: 'High',\n\turgent: 'Urgent',\n}\n\n/**\n * CnTasksWidget — the viewer's open tasks, from OpenRegister's task inbox.\n *\n * Reads `flow-tasks` with `isTerminal=false` (an inbox widget that showed\n * finished tasks would never drain), scoped by `content.scope` and sorted by\n * due date so the most urgent row sits on top. Placed by its registry type\n * key `tasks`:\n *\n * ```js\n * { id: 'my-tasks', type: 'tasks', title: 'My tasks',\n * content: { scope: 'assigned', limit: 6, pollSeconds: 30 } }\n * ```\n *\n * Why it polls: tasks are handed out, claimed and completed by OTHER people\n * and by flows, so a widget that only reflected its mount moment would be\n * wrong within minutes and look identical to being right. Polling pauses\n * while the tab is hidden.\n *\n * Quick actions offer only what the row's contract can accept: claim on a\n * pooled row, complete (per declared outcome) on the viewer's own open row.\n * The server still authorizes; a refusal surfaces its `error` message as a\n * toast and the widget refetches, so a lost claim race corrects the row.\n *\n * @spec openspec/changes/cn-tasks-entity-source/specs/cn-tasks-entity-source/spec.md\n */\nexport default {\n\tname: 'CnTasksWidget',\n\n\tcomponents: {\n\t\tCheckCircle,\n\t\tCircleOutline,\n\t\tCnStatusBadge,\n\t\tNcActions,\n\t\tNcActionButton,\n\t\tNcAvatar,\n\t\tNcButton,\n\t\tNcLoadingIcon,\n\t\tNcTextField,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Host translate function, provided by CnAppRoot (identity by default)\n\t\t * so a library string localises through the consuming app's l10n.\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget's persisted configuration blob.\n\t\t *\n\t\t * - `scope` — whose relationship to list: `assigned` (default),\n\t\t * `pooled`, `watched` or `all`. Whose INBOX it is stays the\n\t\t * endpoint's decision; scope never names another user.\n\t\t * - `limit` — rows to request AND show (1–50, default 6). The count\n\t\t * line always states the server total regardless of this cap.\n\t\t * - `pollSeconds` — refetch interval (default 30; `0` disables).\n\t\t * - `rowRoute` — vue-router route NAME to open on a row click,\n\t\t * receiving the task uuid as `:id`. Omitted = the click opens the\n\t\t * task's openregister deep link instead.\n\t\t * - `emptyText` — override for the empty-inbox line.\n\t\t * - `variant` — `list` draws a checkbox list: a checkbox that completes\n\t\t * the viewer's own task, the title, the subject on a second muted\n\t\t * line and the due date at its right. Default: the compact rows.\n\t\t * - `viewAllRoute` / `viewAllLabel` — a \"View all\" text link in the\n\t\t * card header: a route name or location `{ name, params?, query? }`,\n\t\t * and its label (default \"View all\"). `headerLink` works too.\n\t\t * - `objectUuid` — the tasks on one record (`\"@objectId\"` reads the\n\t\t * page's record), every assignee's, instead of the viewer's inbox.\n\t\t * - `includeDone` — also list finished tasks (after the open ones).\n\t\t * - `variant: 'table'` — the record's task table (board DqZaakTaken):\n\t\t * task, handler, deadline, status and the row's verbs, with the\n\t\t * summary (\"1 open, 3 done · sorted by deadline\") and a \"New task\"\n\t\t * action in the card header.\n\t\t * - `create` — offer \"New task\": `true`, or `{ appId?, label? }`; the\n\t\t * task is posted as an open task on `objectUuid`.\n\t\t * - `completeAny` — offer Complete on every open row, not only the\n\t\t * viewer's own (the server still decides); `cancel` — offer Cancel.\n\t\t *\n\t\t * @type {{scope?: string, limit?: number, pollSeconds?: number, rowRoute?: string, emptyText?: string, variant?: string, viewAllRoute?: (string|object), viewAllLabel?: string, objectUuid?: string, includeDone?: boolean, create?: (boolean|{appId?: string, label?: string}), completeAny?: boolean, cancel?: boolean}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Widget placement id, so the per-widget Refresh action\n\t\t * (`cn:widget:refresh`) reaches this instance's fetch.\n\t\t */\n\t\twidgetId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The page's record id, for `objectUuid: \"@objectId\"`. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to the injected `cnTranslate`.\n\t\t * Provide explicitly when mounting outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['header'],\n\n\tsetup(props) {\n\t\t// The shared endpoint engine owns request dedup, the short-TTL cache\n\t\t// and the cn:page:refresh / cn:widget:refresh subscriptions — the\n\t\t// same binding CnFlowRunsWidget uses, so a page-level Refresh updates\n\t\t// this widget with everything else on the page.\n\t\tconst widgetIdRef = ref(props.widgetId)\n\t\tconst source = () => {\n\t\t\tconst content = props.content || {}\n\t\t\tconst objectUuid = recordUuid(content.objectUuid, props.objectId)\n\t\t\tconst params = {\n\t\t\t\t// A record's tasks are everyone's: scoping them to the viewer\n\t\t\t\t// would make the record look finished while a colleague works.\n\t\t\t\tscope: objectUuid !== '' && !content.scope ? 'all' : normaliseScope(content.scope),\n\t\t\t\t// Ascending due date: the most urgent (overdue first) on top.\n\t\t\t\tsort: 'dueAt',\n\t\t\t\tlimit: normaliseLimit(content.limit),\n\t\t\t}\n\t\t\tif (objectUuid !== '') {\n\t\t\t\tparams.objectUuid = objectUuid\n\t\t\t}\n\t\t\t// An inbox drains: finished tasks leave the widget, unless the\n\t\t\t// widget lists a record's work, done included (`includeDone`).\n\t\t\tif (content.includeDone !== true) {\n\t\t\t\tparams.isTerminal = 'false'\n\t\t\t}\n\t\t\treturn { url: FLOW_TASKS_URL, method: 'GET', params }\n\t\t}\n\t\tconst { data, loading, error, refetch } = useEndpointSource(source, {\n\t\t\twidgetId: widgetIdRef,\n\t\t})\n\n\t\t// `inject` is re-read in setup so Vue 2.7 and Vue 3 resolve it\n\t\t// identically to the Options `inject` block (CnStatWidget precedent).\n\t\tconst injectedTranslate = inject('cnTranslate', null)\n\n\t\treturn {\n\t\t\tpayload: data,\n\t\t\tloading,\n\t\t\terror,\n\t\t\trefetch,\n\t\t\tinjectedTranslate,\n\t\t}\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tpollTimer: null,\n\t\t\t/** Uuids of the tasks a checkbox is completing, until the next read. */\n\t\t\tcompleting: [],\n\t\t\t/** Whether the table's create form is open. */\n\t\t\tcreateOpen: false,\n\t\t\t/** The new task's title and deadline. */\n\t\t\tnewTitle: '',\n\t\t\tnewDue: '',\n\t\t\t/** Whether the new task is being posted. */\n\t\t\tcreating: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the rows draw as the checkbox list (`content.variant: 'list'`).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisList() {\n\t\t\treturn this.content.variant === 'list'\n\t\t},\n\n\t\t/**\n\t\t * Whether the rows draw as the record's task table (`variant: 'table'`).\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tisTable() {\n\t\t\treturn this.content.variant === 'table'\n\t\t},\n\n\t\t/**\n\t\t * The table's rows: the open tasks first, then the finished ones, each\n\t\t * in due order as the endpoint sorted them.\n\t\t *\n\t\t * @return {Array<object>} The rows.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\ttableRows() {\n\t\t\treturn [...this.rows.filter((task) => task.isTerminal !== true), ...this.rows.filter((task) => task.isTerminal === true)]\n\t\t},\n\n\t\t/**\n\t\t * The table's summary for the card header: \"1 open, 3 done · sorted by deadline\".\n\t\t *\n\t\t * @return {string} The line.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tsummaryLabel() {\n\t\t\tconst open = this.rows.filter((task) => task.isTerminal !== true).length\n\t\t\tconst done = this.rows.length - open\n\t\t\treturn this.tr('{open} open, {done} done · sorted by deadline')\n\t\t\t\t.replace('{open}', String(open))\n\t\t\t\t.replace('{done}', String(done))\n\t\t},\n\n\t\t/**\n\t\t * The card header's parts: the \"View all\" link, and for the table the\n\t\t * summary under the title and the \"New task\" action.\n\t\t *\n\t\t * @return {object} The header.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\theader() {\n\t\t\tconst header = { link: this.recordLink(this.headerLink), note: '' }\n\t\t\tif (!this.isTable) {\n\t\t\t\treturn header\n\t\t\t}\n\t\t\theader.subtitle = this.loading && this.rows.length === 0 ? '' : this.summaryLabel\n\t\t\tif (this.content.create && this.recordUuid !== '') {\n\t\t\t\tconst label = typeof this.content.create === 'object' && this.content.create.label ? this.tr(this.content.create.label) : this.tr('New task')\n\t\t\t\theader.action = { label, icon: 'Plus', variant: 'primary', run: this.toggleCreate }\n\t\t\t}\n\t\t\treturn header\n\t\t},\n\n\t\t/**\n\t\t * The record the table lists tasks for, '' without one.\n\t\t *\n\t\t * @return {string} The uuid.\n\t\t */\n\t\trecordUuid() {\n\t\t\treturn recordUuid(this.content.objectUuid, this.objectId)\n\t\t},\n\n\t\t/**\n\t\t * The header \"View all\" link the content declares, or null.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\theaderLink() {\n\t\t\treturn contentHeaderLink(this.content)\n\t\t},\n\n\t\t/**\n\t\t * Effective translate function: the explicit prop, then the injected\n\t\t * host one, then `@nextcloud/l10n` under the library's own app id.\n\t\t *\n\t\t * @return {(key: string) => string}\n\t\t */\n\t\ttr() {\n\t\t\tconst fn = this.translate ?? this.injectedTranslate ?? this.cnTranslate\n\t\t\tif (typeof fn === 'function') {\n\t\t\t\treturn (key) => fn(key)\n\t\t\t}\n\t\t\treturn (key) => t('nextcloud-vue', key)\n\t\t},\n\n\t\t/**\n\t\t * The signed-in viewer's uid, for the per-row action offer. Empty\n\t\t * outside a Nextcloud session (the offer then collapses to claim on\n\t\t * pooled rows only, which is the safe reading).\n\t\t *\n\t\t * @return {string} The uid, or ''.\n\t\t */\n\t\tviewerUid() {\n\t\t\treturn getCurrentUser()?.uid || ''\n\t\t},\n\n\t\t/**\n\t\t * The rows to render — the endpoint's bounded page, defensively\n\t\t * re-capped so a wider server default can never overflow the cell.\n\t\t *\n\t\t * @return {Array<object>} The task rows.\n\t\t */\n\t\trows() {\n\t\t\tconst results = (this.payload && this.payload.results) || []\n\t\t\tif (Array.isArray(results) === false) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn results.slice(0, normaliseLimit(this.content.limit))\n\t\t},\n\n\t\t/**\n\t\t * The server's honest total, independent of the rendered page.\n\t\t *\n\t\t * @return {number} The open-task total (never negative).\n\t\t */\n\t\ttotal() {\n\t\t\tconst total = Number((this.payload && this.payload.total) ?? this.rows.length)\n\t\t\tif (Number.isFinite(total) === false) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn Math.max(0, total)\n\t\t},\n\n\t\t/** The count line above the rows. */\n\t\tcountLabel() {\n\t\t\tif (this.total === 1) {\n\t\t\t\treturn this.tr('1 open task')\n\t\t\t}\n\t\t\treturn this.tr('{count} open tasks').replace('{count}', String(this.total))\n\t\t},\n\n\t\t/**\n\t\t * How many open tasks exist beyond the rendered rows.\n\t\t *\n\t\t * @return {number} The hidden task count (never negative).\n\t\t */\n\t\thiddenCount() {\n\t\t\treturn Math.max(0, this.total - this.rows.length)\n\t\t},\n\n\t\t/** The \"+N more\" line. */\n\t\tmoreLabel() {\n\t\t\treturn this.tr('+{count} more').replace('{count}', String(this.hiddenCount))\n\t\t},\n\n\t\t/** The empty-inbox line. */\n\t\temptyLabel() {\n\t\t\tconst override = this.content.emptyText\n\t\t\tif (typeof override === 'string' && override !== '') {\n\t\t\t\treturn this.tr(override)\n\t\t\t}\n\t\t\treturn this.tr('No open tasks')\n\t\t},\n\n\t\t/**\n\t\t * Poll interval in ms, or 0 when polling is off. Floored at 5s so a\n\t\t * mis-authored `pollSeconds: 0.1` cannot turn a dashboard into a\n\t\t * request storm; `0` remains an explicit opt-out.\n\t\t *\n\t\t * @return {number} The interval in milliseconds.\n\t\t */\n\t\tpollMs() {\n\t\t\tconst raw = this.content.pollSeconds\n\t\t\tconst seconds = (raw === undefined || raw === null) ? 30 : Number(raw)\n\t\t\tif (Number.isFinite(seconds) === false || seconds <= 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn Math.max(5, seconds) * 1000\n\t\t},\n\t},\n\n\twatch: {\n\t\theader: {\n\t\t\timmediate: true,\n\t\t\thandler(header) {\n\t\t\t\t/**\n\t\t\t\t * @event header Emitted with the card header's parts: the \"View all\" link, if any, and for the table its summary and \"New task\".\n\t\t\t\t * @type {{link: (object|null), note: string, subtitle?: string, action?: object}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('header', header)\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.startPolling()\n\t\tdocument.addEventListener('visibilitychange', this.onVisibilityChange)\n\t},\n\n\tbeforeUnmount() {\n\t\tthis.stopPolling()\n\t\tdocument.removeEventListener('visibilitychange', this.onVisibilityChange)\n\t},\n\n\tmethods: {\n\t\tpreventMiddleClickAutoscroll,\n\n\t\t/**\n\t\t * Start (or restart) the refetch interval, unless polling is off.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstartPolling() {\n\t\t\tthis.stopPolling()\n\t\t\tif (this.pollMs === 0 || document.hidden === true) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.pollTimer = setInterval(() => {\n\t\t\t\tthis.refetch(true)\n\t\t\t}, this.pollMs)\n\t\t},\n\n\t\t/**\n\t\t * Clear the refetch interval.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstopPolling() {\n\t\t\tif (this.pollTimer !== null) {\n\t\t\t\tclearInterval(this.pollTimer)\n\t\t\t\tthis.pollTimer = null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Pause polling while the tab is hidden; refetch once and resume on\n\t\t * return, so the dashboard shows current work rather than whatever\n\t\t * was true when the tab was backgrounded.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonVisibilityChange() {\n\t\t\tif (document.hidden === true) {\n\t\t\t\tthis.stopPolling()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.refetch(true)\n\t\t\tthis.startPolling()\n\t\t},\n\n\t\t/**\n\t\t * The row's display title (server-synthesized when untitled).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The title.\n\t\t */\n\t\ttitleOf(task) {\n\t\t\treturn task.displayTitle || task.title || String(task.uuid || '')\n\t\t},\n\n\t\t/**\n\t\t * The subject (the case a task sits on), for the list variant's second line.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The subject's title, or ''.\n\t\t */\n\t\tsubjectOf(task) {\n\t\t\treturn task.subject && task.subject.title ? String(task.subject.title) : ''\n\t\t},\n\n\t\t/**\n\t\t * Whether the list variant draws a checkbox on the row: the viewer's own\n\t\t * open task, with no outcome list to choose from.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t */\n\t\tcanCheck(task) {\n\t\t\treturn this.canComplete(task) && !(Array.isArray(task.outcomes) && task.outcomes.length > 0)\n\t\t},\n\n\t\t/**\n\t\t * Complete a task from its checkbox, with the server's default outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync check(task) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '' || this.completing.includes(uuid)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.completing = [...this.completing, uuid]\n\t\t\tawait this.postVerb(task, 'complete', { outcome: 'done' })\n\t\t\tthis.completing = this.completing.filter((id) => id !== uuid)\n\t\t},\n\n\t\t/**\n\t\t * The secondary line: subject, state and priority — whichever of\n\t\t * those the row actually carries, in words.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The meta line.\n\t\t */\n\t\tmetaLine(task) {\n\t\t\tconst parts = []\n\t\t\tif (task.subject && task.subject.title) {\n\t\t\t\tparts.push(String(task.subject.title))\n\t\t\t}\n\t\t\tconst state = STATE_LABELS[task.state]\n\t\t\tparts.push(state ? this.tr(state) : String(task.state || ''))\n\t\t\tconst priority = PRIORITY_LABELS[task.priority]\n\t\t\tif (priority && task.priority !== 'normal') {\n\t\t\t\tparts.push(this.tr(priority))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The due wording for a row, from the server's derived projection.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The due label, or '' without a due date.\n\t\t */\n\t\tdueLabel(task) {\n\t\t\treturn taskDueLabel(task)\n\t\t},\n\n\t\t/**\n\t\t * Whether the row offers claim: pooled (no assignee) and still open.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean} True when claim is offered.\n\t\t */\n\t\tcanClaim(task) {\n\t\t\treturn !task.assignee && task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Whether the row offers complete: the viewer's own open task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean} True when complete is offered.\n\t\t */\n\t\tcanComplete(task) {\n\t\t\treturn this.viewerUid !== ''\n\t\t\t\t&& task.assignee === this.viewerUid\n\t\t\t\t&& task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Whether a table row offers Complete: the viewer's own open task, or\n\t\t * any open task with `completeAny` (the server still decides).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tcanCompleteRow(task) {\n\t\t\tif (task.isTerminal === true || this.canClaim(task)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.content.completeAny === true || this.canComplete(task)\n\t\t},\n\n\t\t/**\n\t\t * Whether a table row offers Cancel (`content.cancel`), for an open task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t */\n\t\tcanCancelRow(task) {\n\t\t\treturn this.content.cancel === true && task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Cancel a task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tcancel(task) {\n\t\t\treturn this.postVerb(task, 'cancel', {})\n\t\t},\n\n\t\t/**\n\t\t * The handler's display name, the uid until it resolves.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The name.\n\t\t */\n\t\thandlerName(task) {\n\t\t\treturn userDisplayName(task.assignee) || String(task.assignee || '')\n\t\t},\n\n\t\t/**\n\t\t * A table row's status in words.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The label.\n\t\t */\n\t\tstateLabel(task) {\n\t\t\tconst state = STATE_LABELS[task.state]\n\t\t\treturn state ? this.tr(state) : String(task.state || '')\n\t\t},\n\n\t\t/**\n\t\t * A table row's second line: its description and a priority above normal.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The line, or ''.\n\t\t */\n\t\ttableMeta(task) {\n\t\t\tconst parts = []\n\t\t\tif (typeof task.description === 'string' && task.description.trim() !== '') {\n\t\t\t\tparts.push(task.description.trim().split('\\n')[0])\n\t\t\t}\n\t\t\tconst priority = PRIORITY_LABELS[task.priority]\n\t\t\tif (priority && task.priority !== 'normal') {\n\t\t\t\tparts.push(this.tr(priority))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The header link with `@objectId` in its query read from the page's\n\t\t * record (\"all tasks of this case\" on the Tasks page).\n\t\t *\n\t\t * @param {object|null} link The declared link.\n\t\t * @return {object|null} The link.\n\t\t */\n\t\trecordLink(link) {\n\t\t\tif (!link || !link.query || typeof link.query !== 'object') {\n\t\t\t\treturn link\n\t\t\t}\n\t\t\tconst query = Object.fromEntries(Object.entries(link.query).map(([key, value]) => [key, value === '@objectId' ? String(this.objectId ?? '') : value]))\n\t\t\treturn { ...link, query }\n\t\t},\n\n\t\t/**\n\t\t * Open or close the create form (the header's \"New task\").\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttoggleCreate() {\n\t\t\tthis.createOpen = !this.createOpen\n\t\t},\n\n\t\t/**\n\t\t * Post the create form as an open task on the record, then refetch.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tasync createTask() {\n\t\t\tconst title = this.newTitle.trim()\n\t\t\tif (title === '' || this.recordUuid === '' || this.creating) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst create = typeof this.content.create === 'object' && this.content.create ? this.content.create : {}\n\t\t\tconst payload = { title, objectUuid: this.recordUuid, state: 'available' }\n\t\t\tif (typeof create.appId === 'string' && create.appId !== '') {\n\t\t\t\tpayload.appId = create.appId\n\t\t\t}\n\t\t\tif (this.newDue !== '') {\n\t\t\t\tpayload.dueAt = this.newDue\n\t\t\t}\n\t\t\tthis.creating = true\n\t\t\ttry {\n\t\t\t\tawait axios.post(generateUrl(FLOW_TASKS_URL), payload)\n\t\t\t\tthis.newTitle = ''\n\t\t\t\tthis.newDue = ''\n\t\t\t\tthis.createOpen = false\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error?.response?.data?.error\n\t\t\t\tshowError(typeof message === 'string' && message !== '' ? message : this.tr('The task could not be added'))\n\t\t\t}\n\t\t\tthis.creating = false\n\t\t\tthis.refetch(true)\n\t\t},\n\n\t\t/**\n\t\t * The outcomes to offer on complete: the row's declared list, else\n\t\t * one entry for the server's default outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Array<object|string>} The outcome entries.\n\t\t */\n\t\toutcomesOf(task) {\n\t\t\tif (Array.isArray(task.outcomes) && task.outcomes.length > 0) {\n\t\t\t\treturn task.outcomes\n\t\t\t}\n\t\t\treturn ['done']\n\t\t},\n\n\t\t/**\n\t\t * The wire value of one outcome entry (a string, or `{id, label}`).\n\t\t *\n\t\t * @param {object|string} outcome The outcome entry.\n\t\t * @return {string} The outcome id.\n\t\t */\n\t\toutcomeId(outcome) {\n\t\t\tif (outcome && typeof outcome === 'object') {\n\t\t\t\treturn String(outcome.id ?? outcome.value ?? outcome.label ?? '')\n\t\t\t}\n\t\t\treturn String(outcome ?? '')\n\t\t},\n\n\t\t/**\n\t\t * The menu label for one complete entry.\n\t\t *\n\t\t * @param {object|string} outcome The outcome entry.\n\t\t * @return {string} The label.\n\t\t */\n\t\tcompleteLabel(outcome) {\n\t\t\tconst id = this.outcomeId(outcome)\n\t\t\tconst label = (outcome && typeof outcome === 'object' && outcome.label)\n\t\t\t\t? String(outcome.label)\n\t\t\t\t: id\n\t\t\tif (id === 'done') {\n\t\t\t\treturn this.tr('Complete')\n\t\t\t}\n\t\t\treturn this.tr('Complete: {outcome}').replace('{outcome}', label)\n\t\t},\n\n\t\t/**\n\t\t * Claim a pooled task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tclaim(task) {\n\t\t\treturn this.postVerb(task, 'claim', {})\n\t\t},\n\n\t\t/**\n\t\t * Complete the viewer's own task with an outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @param {string} outcome The chosen outcome id.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tcomplete(task, outcome) {\n\t\t\treturn this.postVerb(task, 'complete', { outcome })\n\t\t},\n\n\t\t/**\n\t\t * POST one lifecycle verb and refetch either way: on success the row\n\t\t * moved, and on a refusal (a lost claim race, a revoked task) the\n\t\t * list is stale in exactly the way the refusal proves. The refusal\n\t\t * itself is toasted in the SERVER'S words (ADR-062 forbids leaking\n\t\t * the raw status line, and the endpoint's `error` string is written\n\t\t * for people).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @param {string} verb The lifecycle verb.\n\t\t * @param {object} body The verb body.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tasync postVerb(task, verb, body) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait axios.post(generateUrl(`${FLOW_TASKS_URL}/${uuid}/${verb}`), body)\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error?.response?.data?.error\n\t\t\t\tshowError(typeof message === 'string' && message !== ''\n\t\t\t\t\t? message\n\t\t\t\t\t: this.tr('The task action was refused'))\n\t\t\t}\n\t\t\tthis.refetch(true)\n\t\t},\n\n\t\t/**\n\t\t * Open the clicked task: the configured route with the uuid as `id`,\n\t\t * else the task's openregister deep link. A ctrl/cmd/shift or middle\n\t\t * click opens it in a new tab.\n\t\t *\n\t\t * @param {object} task The clicked task row.\n\t\t * @param {MouseEvent} [event] The originating click/auxclick event.\n\t\t * @return {void}\n\t\t */\n\t\tonRowClick(task, event) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst rowRoute = this.content.rowRoute\n\t\t\tif (typeof rowRoute === 'string' && rowRoute !== '' && this.$router) {\n\t\t\t\topenRowTarget(event, { name: rowRoute, params: { id: uuid } }, this.$router)\n\t\t\t\treturn\n\t\t\t}\n\t\t\topenRowTarget(event, taskDeepLink(uuid))\n\t\t},\n\n\t\t/**\n\t\t * Middle click on a task row: open it in a new tab.\n\t\t *\n\t\t * @param {object} task The clicked task row.\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t * @return {void}\n\t\t */\n\t\tonRowAuxClick(task, event) {\n\t\t\tif (isRowMiddleClick(event)) {\n\t\t\t\tthis.onRowClick(task, event)\n\t\t\t}\n\t\t},\n\t},\n}\n\n/**\n * Clamp a configured row limit into the range the endpoint accepts.\n *\n * @param {unknown} raw The configured limit.\n * @return {number} A limit between 1 and 50 (default 6).\n */\nfunction normaliseLimit(raw) {\n\tconst n = Number(raw)\n\tif (Number.isFinite(n) === false || n <= 0) {\n\t\treturn 6\n\t}\n\treturn Math.min(50, Math.round(n))\n}\n\n/**\n * Clamp a configured scope onto the endpoint's vocabulary.\n *\n * @param {unknown} raw The configured scope.\n * @return {string} One of assigned, pooled, watched, all (default assigned).\n */\nfunction normaliseScope(raw) {\n\treturn ['assigned', 'pooled', 'watched', 'all'].includes(raw) ? raw : 'assigned'\n}\n\n/**\n * The record a widget lists tasks for: `objectUuid` as written, with\n * `@objectId` read from the page's record.\n *\n * @param {unknown} configured The `objectUuid` setting.\n * @param {unknown} objectId The page's record id.\n * @return {string} The uuid, or ''.\n */\nfunction recordUuid(configured, objectId) {\n\tif (typeof configured !== 'string' || configured === '') {\n\t\treturn ''\n\t}\n\treturn configured === '@objectId' ? String(objectId ?? '') : configured\n}\n</script>\n\n<style scoped>\n/* The record's task table (`variant: 'table'`, board DqZaakTaken): a head\n row of muted 14px labels on a near-white ground, rows divided by hairlines,\n the title at 600 over a muted line, a finished task struck through. */\n.cn-tasks-widget__create {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 12px;\n\tmargin-block-end: 12px;\n}\n\n.cn-tasks-widget__table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n\tfont-size: 14px;\n}\n\n.cn-tasks-widget__table th {\n\tpadding: 12px 16px;\n\tbackground: color-mix(in srgb, var(--color-background-hover) 40%, var(--color-main-background));\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 600;\n\ttext-align: start;\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget__table td {\n\tpadding: 12px 16px;\n\tborder-top: 1px solid var(--color-border);\n\tvertical-align: middle;\n}\n\n.cn-tasks-widget__cell-task {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tgap: 12px;\n}\n\n.cn-tasks-widget__state-icon {\n\tflex: none;\n\tcolor: var(--color-primary-element);\n}\n\n.cn-tasks-widget__state-icon--done {\n\tcolor: var(--color-success-text, var(--color-success));\n}\n\n.cn-tasks-widget__table .cn-tasks-widget__name {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tbackground: none;\n\tcolor: var(--color-main-text);\n\tfont: inherit;\n\tfont-size: 15px;\n\tfont-weight: 600;\n\ttext-align: start;\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__table .cn-tasks-widget__name:hover,\n.cn-tasks-widget__table .cn-tasks-widget__name:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-tasks-widget__table-row--done .cn-tasks-widget__name {\n\ttext-decoration: line-through;\n}\n\n.cn-tasks-widget__handler {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-tasks-widget__cell-due {\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget__cell-due.cn-tasks-widget__due--overdue {\n\tcolor: var(--color-warning-text, var(--color-warning));\n\tfont-weight: 600;\n}\n\n.cn-tasks-widget__cell-actions {\n\ttext-align: end;\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n}\n\n.cn-tasks-widget__loading {\n\tdisplay: flex;\n\tjustify-content: center;\n\tpadding: 8px 0;\n}\n\n.cn-tasks-widget__empty,\n.cn-tasks-widget__error,\n.cn-tasks-widget__more {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-tasks-widget__more {\n\tpadding-top: 4px;\n}\n\n.cn-tasks-widget__count {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\tfont-weight: 600;\n\ttext-transform: uppercase;\n\tletter-spacing: 0.04em;\n}\n\n.cn-tasks-widget__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tmin-width: 0;\n}\n\n.cn-tasks-widget__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tmin-width: 0;\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-tasks-widget__body {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1 1 auto;\n}\n\n.cn-tasks-widget__name {\n\tfont-weight: 600;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget__row:hover .cn-tasks-widget__name {\n\ttext-decoration: underline;\n}\n\n.cn-tasks-widget__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget__due {\n\tflex: 0 0 auto;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n/* List variant, after the dashboard board's My tasks card: a checkbox, the\n title, the subject on a muted second line and the due date at its right. */\n.cn-tasks-widget--list .cn-tasks-widget__row {\n\talign-items: flex-start;\n\tgap: 12px;\n\tpadding: 12px 0;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__name {\n\tfont-weight: 400;\n\tfont-size: 15px;\n\tline-height: 1.35;\n\tcolor: var(--color-main-text);\n}\n\n.cn-tasks-widget__check,\n.cn-tasks-widget__check-spacer {\n\tflex: none;\n\twidth: 20px;\n\theight: 20px;\n\tmargin: 1px 0 0;\n}\n\n.cn-tasks-widget__check {\n\taccent-color: var(--color-primary-element);\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__meta--split {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tgap: 8px;\n\tfont-size: 13px;\n\toverflow: visible;\n}\n\n.cn-tasks-widget__subject {\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__due {\n\tfont-size: 13px;\n\tfont-weight: 500;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__due--overdue {\n\tfont-weight: 600;\n}\n\n/* Overdue: weight AND colour on top of the wording, which already says\n \"Overdue by N days\" — the signal survives monochrome. */\n.cn-tasks-widget__due--overdue {\n\tcolor: var(--color-error, #d91f2d);\n\tfont-weight: 600;\n}\n\n.cn-tasks-widget__actions {\n\tflex: 0 0 auto;\n}\n</style>\n"],"names":["_normalizeClass","_toDisplayString","_openBlock","_createElementBlock","_createVNode","_Fragment","_createElementVNode","_renderList","_createBlock","_createTextVNode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnTasksWidget.vue3.js","sources":["../../../../src/components/CnTasksWidget/CnTasksWidget.vue?vue&type=template&id=38d5d358&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<div class=\"cn-tasks-widget\" :class=\"{ 'cn-tasks-widget--list': isList }\">\n\t\t<!-- One quiet line on failure, never a leaked axios status string\n\t\t (ADR-062). The real error goes to the console. -->\n\t\t<p v-if=\"error\" class=\"cn-tasks-widget__error\">\n\t\t\t{{ tr('Could not load the tasks') }}\n\t\t</p>\n\t\t<div v-else-if=\"loading && rows.length === 0\" class=\"cn-tasks-widget__loading\">\n\t\t\t<NcLoadingIcon :size=\"24\" />\n\t\t</div>\n\t\t<!-- An empty inbox is the GOOD state, not an error and not a void:\n\t\t one muted line, no illustration. -->\n\t\t<template v-else-if=\"isTable\">\n\t\t\t<!-- The create form the header's \"New task\" opens: a title and a\n\t\t\t deadline, posted as an open task on this record. -->\n\t\t\t<form\n\t\t\t\tv-if=\"createOpen\"\n\t\t\t\tclass=\"cn-tasks-widget__create\"\n\t\t\t\tdata-testid=\"cn-tasks-widget-create\"\n\t\t\t\t@submit.prevent=\"createTask\">\n\t\t\t\t<NcTextField\n\t\t\t\t\t:modelValue=\"newTitle\"\n\t\t\t\t\t:label=\"tr('Task')\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-title\"\n\t\t\t\t\t@update:modelValue=\"(value) => (newTitle = String(value ?? ''))\" />\n\t\t\t\t<NcTextField\n\t\t\t\t\t:modelValue=\"newDue\"\n\t\t\t\t\ttype=\"date\"\n\t\t\t\t\t:label=\"tr('Task deadline')\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-due\"\n\t\t\t\t\t@update:modelValue=\"(value) => (newDue = String(value ?? ''))\" />\n\t\t\t\t<NcButton\n\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t:disabled=\"creating || newTitle.trim() === ''\"\n\t\t\t\t\tdata-testid=\"cn-tasks-widget-create-save\">\n\t\t\t\t\t{{ tr('Add task') }}\n\t\t\t\t</NcButton>\n\t\t\t</form>\n\t\t\t<p v-if=\"tableRows.length === 0\" class=\"cn-tasks-widget__empty\">\n\t\t\t\t{{ emptyLabel }}\n\t\t\t</p>\n\t\t\t<table v-else class=\"cn-tasks-widget__table\" data-testid=\"cn-tasks-widget-table\">\n\t\t\t\t<thead>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Task') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Handler') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Task deadline') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t{{ tr('Status') }}\n\t\t\t\t\t\t</th>\n\t\t\t\t\t\t<th scope=\"col\">\n\t\t\t\t\t\t\t<span class=\"hidden-visually\">{{ tr('Task actions') }}</span>\n\t\t\t\t\t\t</th>\n\t\t\t\t\t</tr>\n\t\t\t\t</thead>\n\t\t\t\t<tbody>\n\t\t\t\t\t<tr\n\t\t\t\t\t\tv-for=\"task in tableRows\"\n\t\t\t\t\t\t:key=\"task.uuid\"\n\t\t\t\t\t\tclass=\"cn-tasks-widget__table-row\"\n\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__table-row--done': task.isTerminal === true }\"\n\t\t\t\t\t\t:data-state=\"task.state\"\n\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-row-${task.uuid}`\">\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-task\">\n\t\t\t\t\t\t\t<CheckCircle\n\t\t\t\t\t\t\t\tv-if=\"task.isTerminal === true\"\n\t\t\t\t\t\t\t\t:size=\"20\"\n\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__state-icon cn-tasks-widget__state-icon--done\" />\n\t\t\t\t\t\t\t<CircleOutline v-else :size=\"20\" class=\"cn-tasks-widget__state-icon\" />\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__name\"\n\t\t\t\t\t\t\t\t\t@click=\"onRowClick(task, $event)\"\n\t\t\t\t\t\t\t\t\t@auxclick=\"onRowAuxClick(task, $event)\">\n\t\t\t\t\t\t\t\t\t{{ titleOf(task) }}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t<span v-if=\"tableMeta(task)\" class=\"cn-tasks-widget__meta\">{{ tableMeta(task) }}</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-handler\">\n\t\t\t\t\t\t\t<span v-if=\"task.assignee\" class=\"cn-tasks-widget__handler\">\n\t\t\t\t\t\t\t\t<NcAvatar\n\t\t\t\t\t\t\t\t\t:user=\"String(task.assignee)\"\n\t\t\t\t\t\t\t\t\t:displayName=\"handlerName(task)\"\n\t\t\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t\t\t{{ handlerName(task) }}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t<span v-else class=\"cn-tasks-widget__meta\">{{ tr('Unassigned') }}</span>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__cell-due\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true && task.isTerminal !== true }\">\n\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t<CnStatusBadge :label=\"stateLabel(task)\" :variant=\"task.isTerminal === true ? 'default' : 'info'\" />\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"cn-tasks-widget__cell-actions\">\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-if=\"canClaim(task)\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-claim-${task.uuid}`\"\n\t\t\t\t\t\t\t\t@click=\"claim(task)\">\n\t\t\t\t\t\t\t\t{{ tr('Claim') }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\t\tv-else-if=\"canCompleteRow(task) && outcomesOf(task).length === 1\"\n\t\t\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-complete-${task.uuid}`\"\n\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcomesOf(task)[0]))\">\n\t\t\t\t\t\t\t\t{{ tr('Complete') }}\n\t\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t\t\t<NcActions\n\t\t\t\t\t\t\t\tv-if=\"(canCompleteRow(task) && outcomesOf(task).length > 1) || canCancelRow(task)\"\n\t\t\t\t\t\t\t\t:forceMenu=\"true\"\n\t\t\t\t\t\t\t\t:aria-label=\"tr('Task actions')\">\n\t\t\t\t\t\t\t\t<template v-if=\"canCompleteRow(task) && outcomesOf(task).length > 1\">\n\t\t\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\t\t\tv-for=\"outcome in outcomesOf(task)\"\n\t\t\t\t\t\t\t\t\t\t:key=\"outcomeId(outcome)\"\n\t\t\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcome))\">\n\t\t\t\t\t\t\t\t\t\t{{ completeLabel(outcome) }}\n\t\t\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\t\tv-if=\"canCancelRow(task)\"\n\t\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t\t:data-testid=\"`cn-tasks-widget-cancel-${task.uuid}`\"\n\t\t\t\t\t\t\t\t\t@click=\"cancel(task)\">\n\t\t\t\t\t\t\t\t\t{{ tr('Cancel task') }}\n\t\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t\t</NcActions>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n\t\t\t\t</tbody>\n\t\t\t</table>\n\t\t</template>\n\t\t<p v-else-if=\"rows.length === 0\" class=\"cn-tasks-widget__empty\">\n\t\t\t{{ emptyLabel }}\n\t\t</p>\n\t\t<template v-else>\n\t\t\t<!-- The count states the server TOTAL, never the rendered length\n\t\t\t (ADR-062): the number a person acts on is how much work\n\t\t\t exists, not how much fits the cell. -->\n\t\t\t<p v-if=\"!isList\" class=\"cn-tasks-widget__count\">\n\t\t\t\t{{ countLabel }}\n\t\t\t</p>\n\t\t\t<ul class=\"cn-tasks-widget__list\">\n\t\t\t\t<li\n\t\t\t\t\tv-for=\"task in rows\"\n\t\t\t\t\t:key=\"task.uuid\"\n\t\t\t\t\tclass=\"cn-tasks-widget__row\"\n\t\t\t\t\t:data-state=\"task.state\"\n\t\t\t\t\t@click=\"onRowClick(task, $event)\"\n\t\t\t\t\t@mousedown=\"preventMiddleClickAutoscroll\"\n\t\t\t\t\t@auxclick=\"onRowAuxClick(task, $event)\">\n\t\t\t\t\t<!-- List variant: a checkbox completes the viewer's own task\n\t\t\t\t\t (the task with a declared outcome list keeps the menu, as\n\t\t\t\t\t a checkbox cannot choose an outcome). Other rows get a\n\t\t\t\t\t spacer so the titles stay aligned. -->\n\t\t\t\t\t<template v-if=\"isList\">\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tv-if=\"canCheck(task)\"\n\t\t\t\t\t\t\ttype=\"checkbox\"\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__check\"\n\t\t\t\t\t\t\t:checked=\"completing.includes(String(task.uuid))\"\n\t\t\t\t\t\t\t:disabled=\"completing.includes(String(task.uuid))\"\n\t\t\t\t\t\t\t:aria-label=\"tr('Mark {title} as done').replace('{title}', titleOf(task))\"\n\t\t\t\t\t\t\tdata-testid=\"cn-tasks-widget-check\"\n\t\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t\t@change=\"check(task)\">\n\t\t\t\t\t\t<span v-else class=\"cn-tasks-widget__check-spacer\" aria-hidden=\"true\" />\n\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__name\">{{ titleOf(task) }}</span>\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__meta cn-tasks-widget__meta--split\">\n\t\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__subject\">{{ subjectOf(task) }}</span>\n\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\tclass=\"cn-tasks-widget__due\"\n\t\t\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true }\">\n\t\t\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template v-else>\n\t\t\t\t\t\t<span class=\"cn-tasks-widget__body\">\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__name\">{{ titleOf(task) }}</span>\n\t\t\t\t\t\t\t<span class=\"cn-tasks-widget__meta\">{{ metaLine(task) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<!-- Overdue is carried by the WORDING (taskDueLabel) and by\n\t\t\t\t\t\t weight; the colour only reinforces it. -->\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tclass=\"cn-tasks-widget__due\"\n\t\t\t\t\t\t\t:class=\"{ 'cn-tasks-widget__due--overdue': task.overdue === true }\">\n\t\t\t\t\t\t\t{{ dueLabel(task) }}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<!-- Only verbs the contract can accept are offered; the\n\t\t\t\t\t server still authorizes, and a refusal is toasted in\n\t\t\t\t\t its own words. Stopped clicks: the menu must not also\n\t\t\t\t\t open the row. -->\n\t\t\t\t\t<NcActions\n\t\t\t\t\t\tv-if=\"(canClaim(task) || canComplete(task)) && !(isList && canCheck(task))\"\n\t\t\t\t\t\tclass=\"cn-tasks-widget__actions\"\n\t\t\t\t\t\t:forceMenu=\"true\"\n\t\t\t\t\t\t:aria-label=\"tr('Task actions')\"\n\t\t\t\t\t\t@click.stop>\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tv-if=\"canClaim(task)\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t@click=\"claim(task)\">\n\t\t\t\t\t\t\t{{ tr('Claim') }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<template v-if=\"canComplete(task)\">\n\t\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\t\tv-for=\"outcome in outcomesOf(task)\"\n\t\t\t\t\t\t\t\t:key=\"outcomeId(outcome)\"\n\t\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t\t@click=\"complete(task, outcomeId(outcome))\">\n\t\t\t\t\t\t\t\t{{ completeLabel(outcome) }}\n\t\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t</template>\n\t\t\t\t\t</NcActions>\n\t\t\t\t</li>\n\t\t\t</ul>\n\t\t\t<!-- The remainder is a count, never a scrollbar (ADR-062). -->\n\t\t\t<p v-if=\"hiddenCount > 0\" class=\"cn-tasks-widget__more\">\n\t\t\t\t{{ moreLabel }}\n\t\t\t</p>\n\t\t</template>\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { showError } from '@nextcloud/dialogs'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { NcActionButton, NcActions, NcAvatar, NcButton, NcLoadingIcon, NcTextField } from '@nextcloud/vue'\nimport { inject, ref } from 'vue'\nimport CheckCircle from 'vue-material-design-icons/CheckCircle.vue'\nimport CircleOutline from 'vue-material-design-icons/CircleOutline.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport { taskDeepLink, taskDueLabel } from '../../composables/indexSources.js'\nimport { useEndpointSource } from '../../composables/useEndpointSource.js'\nimport { contentHeaderLink } from '../../utils/contentHeaderLink.js'\nimport { openRowTarget } from '../../utils/linkNavigation.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { userDisplayName } from '../../utils/userDisplayName.js'\n\n/**\n * The OpenRegister inbox read (openregister flow-task-entity). One endpoint\n * for the whole fleet: every app's human tasks live on OpenRegister's one\n * task store, so the widget is app-agnostic and ships no controller.\n *\n * @type {string}\n */\nconst FLOW_TASKS_URL = '/apps/openregister/api/flow-tasks'\n\n/**\n * The CMMN states, in the reading a dashboard needs. Labels double as the\n * meta-line words, so state never rests on styling.\n *\n * @type {Record<string, string>}\n */\nconst STATE_LABELS = {\n\tavailable: 'Available',\n\tenabled: 'Ready to claim',\n\tactive: 'In progress',\n\tcompleted: 'Completed',\n\tterminated: 'Terminated',\n\tdisabled: 'Disabled',\n}\n\n/**\n * The priority vocabulary (openregister Task::PRIORITIES).\n *\n * @type {Record<string, string>}\n */\nconst PRIORITY_LABELS = {\n\tlow: 'Low',\n\tnormal: 'Normal',\n\thigh: 'High',\n\turgent: 'Urgent',\n}\n\n/**\n * CnTasksWidget — the viewer's open tasks, from OpenRegister's task inbox.\n *\n * Reads `flow-tasks` with `isTerminal=false` (an inbox widget that showed\n * finished tasks would never drain), scoped by `content.scope` and sorted by\n * due date so the most urgent row sits on top. Placed by its registry type\n * key `tasks`:\n *\n * ```js\n * { id: 'my-tasks', type: 'tasks', title: 'My tasks',\n * content: { scope: 'assigned', limit: 6, pollSeconds: 30 } }\n * ```\n *\n * Why it polls: tasks are handed out, claimed and completed by OTHER people\n * and by flows, so a widget that only reflected its mount moment would be\n * wrong within minutes and look identical to being right. Polling pauses\n * while the tab is hidden.\n *\n * Quick actions offer only what the row's contract can accept: claim on a\n * pooled row, complete (per declared outcome) on the viewer's own open row.\n * The server still authorizes; a refusal surfaces its `error` message as a\n * toast and the widget refetches, so a lost claim race corrects the row.\n *\n * @spec openspec/changes/cn-tasks-entity-source/specs/cn-tasks-entity-source/spec.md\n */\nexport default {\n\tname: 'CnTasksWidget',\n\n\tcomponents: {\n\t\tCheckCircle,\n\t\tCircleOutline,\n\t\tCnStatusBadge,\n\t\tNcActions,\n\t\tNcActionButton,\n\t\tNcAvatar,\n\t\tNcButton,\n\t\tNcLoadingIcon,\n\t\tNcTextField,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Host translate function, provided by CnAppRoot (identity by default)\n\t\t * so a library string localises through the consuming app's l10n.\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget's persisted configuration blob.\n\t\t *\n\t\t * - `scope` — whose relationship to list: `assigned` (default),\n\t\t * `pooled`, `watched` or `all`. Whose INBOX it is stays the\n\t\t * endpoint's decision; scope never names another user.\n\t\t * - `limit` — rows to request AND show (1–50, default 6). The count\n\t\t * line always states the server total regardless of this cap.\n\t\t * - `pollSeconds` — refetch interval (default 30; `0` disables).\n\t\t * - `rowRoute` — vue-router route NAME to open on a row click,\n\t\t * receiving the task uuid as `:id`. Omitted = the click opens the\n\t\t * task's openregister deep link instead.\n\t\t * - `emptyText` — override for the empty-inbox line.\n\t\t * - `variant` — `list` draws a checkbox list: a checkbox that completes\n\t\t * the viewer's own task, the title, the subject on a second muted\n\t\t * line and the due date at its right. Default: the compact rows.\n\t\t * - `viewAllRoute` / `viewAllLabel` — a \"View all\" text link in the\n\t\t * card header: a route name or location `{ name, params?, query? }`,\n\t\t * and its label (default \"View all\"). `headerLink` works too.\n\t\t * - `objectUuid` — the tasks on one record (`\"@objectId\"` reads the\n\t\t * page's record), every assignee's, instead of the viewer's inbox.\n\t\t * - `includeDone` — also list finished tasks (after the open ones).\n\t\t * - `variant: 'table'` — the record's task table (board DqZaakTaken):\n\t\t * task, handler, deadline, status and the row's verbs, with the\n\t\t * summary (\"1 open, 3 done · sorted by deadline\") and a \"New task\"\n\t\t * action in the card header.\n\t\t * - `create` — offer \"New task\": `true`, or `{ appId?, label? }`; the\n\t\t * task is posted as an open task on `objectUuid`.\n\t\t * - `completeAny` — offer Complete on every open row, not only the\n\t\t * viewer's own (the server still decides); `cancel` — offer Cancel.\n\t\t *\n\t\t * @type {{scope?: string, limit?: number, pollSeconds?: number, rowRoute?: string, emptyText?: string, variant?: string, viewAllRoute?: (string|object), viewAllLabel?: string, objectUuid?: string, includeDone?: boolean, create?: (boolean|{appId?: string, label?: string}), completeAny?: boolean, cancel?: boolean}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Widget placement id, so the per-widget Refresh action\n\t\t * (`cn:widget:refresh`) reaches this instance's fetch.\n\t\t */\n\t\twidgetId: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** The page's record id, for `objectUuid: \"@objectId\"`. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to the injected `cnTranslate`.\n\t\t * Provide explicitly when mounting outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: ['header'],\n\n\tsetup(props) {\n\t\t// The shared endpoint engine owns request dedup, the short-TTL cache\n\t\t// and the cn:page:refresh / cn:widget:refresh subscriptions — the\n\t\t// same binding CnFlowRunsWidget uses, so a page-level Refresh updates\n\t\t// this widget with everything else on the page.\n\t\tconst widgetIdRef = ref(props.widgetId)\n\t\tconst source = () => {\n\t\t\tconst content = props.content || {}\n\t\t\tconst objectUuid = recordUuid(content.objectUuid, props.objectId)\n\t\t\tconst params = {\n\t\t\t\t// A record's tasks are everyone's: scoping them to the viewer\n\t\t\t\t// would make the record look finished while a colleague works.\n\t\t\t\tscope: objectUuid !== '' && !content.scope ? 'all' : normaliseScope(content.scope),\n\t\t\t\t// Ascending due date: the most urgent (overdue first) on top.\n\t\t\t\tsort: 'dueAt',\n\t\t\t\tlimit: normaliseLimit(content.limit),\n\t\t\t}\n\t\t\tif (objectUuid !== '') {\n\t\t\t\tparams.objectUuid = objectUuid\n\t\t\t}\n\t\t\t// An inbox drains: finished tasks leave the widget, unless the\n\t\t\t// widget lists a record's work, done included (`includeDone`).\n\t\t\tif (content.includeDone !== true) {\n\t\t\t\tparams.isTerminal = 'false'\n\t\t\t}\n\t\t\treturn { url: FLOW_TASKS_URL, method: 'GET', params }\n\t\t}\n\t\tconst { data, loading, error, refetch } = useEndpointSource(source, {\n\t\t\twidgetId: widgetIdRef,\n\t\t})\n\n\t\t// `inject` is re-read in setup so Vue 2.7 and Vue 3 resolve it\n\t\t// identically to the Options `inject` block (CnStatWidget precedent).\n\t\tconst injectedTranslate = inject('cnTranslate', null)\n\n\t\treturn {\n\t\t\tpayload: data,\n\t\t\tloading,\n\t\t\terror,\n\t\t\trefetch,\n\t\t\tinjectedTranslate,\n\t\t}\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tpollTimer: null,\n\t\t\t/** Uuids of the tasks a checkbox is completing, until the next read. */\n\t\t\tcompleting: [],\n\t\t\t/** Whether the table's create form is open. */\n\t\t\tcreateOpen: false,\n\t\t\t/** The new task's title and deadline. */\n\t\t\tnewTitle: '',\n\t\t\tnewDue: '',\n\t\t\t/** Whether the new task is being posted. */\n\t\t\tcreating: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the rows draw as the checkbox list (`content.variant: 'list'`).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisList() {\n\t\t\treturn this.content.variant === 'list'\n\t\t},\n\n\t\t/**\n\t\t * Whether the rows draw as the record's task table (`variant: 'table'`).\n\t\t *\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tisTable() {\n\t\t\treturn this.content.variant === 'table'\n\t\t},\n\n\t\t/**\n\t\t * The table's rows: the open tasks first, then the finished ones, each\n\t\t * in due order as the endpoint sorted them.\n\t\t *\n\t\t * @return {Array<object>} The rows.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\ttableRows() {\n\t\t\treturn [...this.rows.filter((task) => task.isTerminal !== true), ...this.rows.filter((task) => task.isTerminal === true)]\n\t\t},\n\n\t\t/**\n\t\t * The table's summary for the card header: \"1 open, 3 done · sorted by deadline\".\n\t\t *\n\t\t * @return {string} The line.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tsummaryLabel() {\n\t\t\tconst open = this.rows.filter((task) => task.isTerminal !== true).length\n\t\t\tconst done = this.rows.length - open\n\t\t\treturn this.tr('{open} open, {done} done · sorted by deadline')\n\t\t\t\t.replace('{open}', String(open))\n\t\t\t\t.replace('{done}', String(done))\n\t\t},\n\n\t\t/**\n\t\t * The card header's parts: the \"View all\" link, and for the table the\n\t\t * summary under the title and the \"New task\" action.\n\t\t *\n\t\t * @return {object} The header.\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\theader() {\n\t\t\tconst header = { link: this.recordLink(this.headerLink), note: '' }\n\t\t\tif (!this.isTable) {\n\t\t\t\treturn header\n\t\t\t}\n\t\t\theader.subtitle = this.loading && this.rows.length === 0 ? '' : this.summaryLabel\n\t\t\tif (this.content.create && this.recordUuid !== '') {\n\t\t\t\tconst label = typeof this.content.create === 'object' && this.content.create.label ? this.tr(this.content.create.label) : this.tr('New task')\n\t\t\t\theader.action = { label, icon: 'Plus', variant: 'primary', run: this.toggleCreate }\n\t\t\t}\n\t\t\treturn header\n\t\t},\n\n\t\t/**\n\t\t * The record the table lists tasks for, '' without one.\n\t\t *\n\t\t * @return {string} The uuid.\n\t\t */\n\t\trecordUuid() {\n\t\t\treturn recordUuid(this.content.objectUuid, this.objectId)\n\t\t},\n\n\t\t/**\n\t\t * The header \"View all\" link the content declares, or null.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\theaderLink() {\n\t\t\treturn contentHeaderLink(this.content)\n\t\t},\n\n\t\t/**\n\t\t * Effective translate function: the explicit prop, then the injected\n\t\t * host one, then `@nextcloud/l10n` under the library's own app id.\n\t\t *\n\t\t * @return {(key: string) => string}\n\t\t */\n\t\ttr() {\n\t\t\tconst fn = this.translate ?? this.injectedTranslate ?? this.cnTranslate\n\t\t\tif (typeof fn === 'function') {\n\t\t\t\treturn (key) => fn(key)\n\t\t\t}\n\t\t\treturn (key) => t('nextcloud-vue', key)\n\t\t},\n\n\t\t/**\n\t\t * The signed-in viewer's uid, for the per-row action offer. Empty\n\t\t * outside a Nextcloud session (the offer then collapses to claim on\n\t\t * pooled rows only, which is the safe reading).\n\t\t *\n\t\t * @return {string} The uid, or ''.\n\t\t */\n\t\tviewerUid() {\n\t\t\treturn getCurrentUser()?.uid || ''\n\t\t},\n\n\t\t/**\n\t\t * The rows to render — the endpoint's bounded page, defensively\n\t\t * re-capped so a wider server default can never overflow the cell.\n\t\t *\n\t\t * @return {Array<object>} The task rows.\n\t\t */\n\t\trows() {\n\t\t\tconst results = (this.payload && this.payload.results) || []\n\t\t\tif (Array.isArray(results) === false) {\n\t\t\t\treturn []\n\t\t\t}\n\t\t\treturn results.slice(0, normaliseLimit(this.content.limit))\n\t\t},\n\n\t\t/**\n\t\t * The server's honest total, independent of the rendered page.\n\t\t *\n\t\t * @return {number} The open-task total (never negative).\n\t\t */\n\t\ttotal() {\n\t\t\tconst total = Number((this.payload && this.payload.total) ?? this.rows.length)\n\t\t\tif (Number.isFinite(total) === false) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn Math.max(0, total)\n\t\t},\n\n\t\t/** The count line above the rows. */\n\t\tcountLabel() {\n\t\t\tif (this.total === 1) {\n\t\t\t\treturn this.tr('1 open task')\n\t\t\t}\n\t\t\treturn this.tr('{count} open tasks').replace('{count}', String(this.total))\n\t\t},\n\n\t\t/**\n\t\t * How many open tasks exist beyond the rendered rows.\n\t\t *\n\t\t * @return {number} The hidden task count (never negative).\n\t\t */\n\t\thiddenCount() {\n\t\t\treturn Math.max(0, this.total - this.rows.length)\n\t\t},\n\n\t\t/** The \"+N more\" line. */\n\t\tmoreLabel() {\n\t\t\treturn this.tr('+{count} more').replace('{count}', String(this.hiddenCount))\n\t\t},\n\n\t\t/** The empty-inbox line. */\n\t\temptyLabel() {\n\t\t\tconst override = this.content.emptyText\n\t\t\tif (typeof override === 'string' && override !== '') {\n\t\t\t\treturn this.tr(override)\n\t\t\t}\n\t\t\treturn this.tr('No open tasks')\n\t\t},\n\n\t\t/**\n\t\t * Poll interval in ms, or 0 when polling is off. Floored at 5s so a\n\t\t * mis-authored `pollSeconds: 0.1` cannot turn a dashboard into a\n\t\t * request storm; `0` remains an explicit opt-out.\n\t\t *\n\t\t * @return {number} The interval in milliseconds.\n\t\t */\n\t\tpollMs() {\n\t\t\tconst raw = this.content.pollSeconds\n\t\t\tconst seconds = (raw === undefined || raw === null) ? 30 : Number(raw)\n\t\t\tif (Number.isFinite(seconds) === false || seconds <= 0) {\n\t\t\t\treturn 0\n\t\t\t}\n\t\t\treturn Math.max(5, seconds) * 1000\n\t\t},\n\t},\n\n\twatch: {\n\t\theader: {\n\t\t\timmediate: true,\n\t\t\thandler(header) {\n\t\t\t\t/**\n\t\t\t\t * @event header Emitted with the card header's parts: the \"View all\" link, if any, and for the table its summary and \"New task\".\n\t\t\t\t * @type {{link: (object|null), note: string, subtitle?: string, action?: object}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('header', header)\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.startPolling()\n\t\tdocument.addEventListener('visibilitychange', this.onVisibilityChange)\n\t},\n\n\tbeforeUnmount() {\n\t\tthis.stopPolling()\n\t\tdocument.removeEventListener('visibilitychange', this.onVisibilityChange)\n\t},\n\n\tmethods: {\n\t\tpreventMiddleClickAutoscroll,\n\n\t\t/**\n\t\t * Start (or restart) the refetch interval, unless polling is off.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstartPolling() {\n\t\t\tthis.stopPolling()\n\t\t\tif (this.pollMs === 0 || document.hidden === true) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.pollTimer = setInterval(() => {\n\t\t\t\tthis.refetch(true)\n\t\t\t}, this.pollMs)\n\t\t},\n\n\t\t/**\n\t\t * Clear the refetch interval.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tstopPolling() {\n\t\t\tif (this.pollTimer !== null) {\n\t\t\t\tclearInterval(this.pollTimer)\n\t\t\t\tthis.pollTimer = null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Pause polling while the tab is hidden; refetch once and resume on\n\t\t * return, so the dashboard shows current work rather than whatever\n\t\t * was true when the tab was backgrounded.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonVisibilityChange() {\n\t\t\tif (document.hidden === true) {\n\t\t\t\tthis.stopPolling()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.refetch(true)\n\t\t\tthis.startPolling()\n\t\t},\n\n\t\t/**\n\t\t * The row's display title (server-synthesized when untitled).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The title.\n\t\t */\n\t\ttitleOf(task) {\n\t\t\treturn task.displayTitle || task.title || String(task.uuid || '')\n\t\t},\n\n\t\t/**\n\t\t * The subject (the case a task sits on), for the list variant's second line.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The subject's title, or ''.\n\t\t */\n\t\tsubjectOf(task) {\n\t\t\treturn task.subject && task.subject.title ? String(task.subject.title) : ''\n\t\t},\n\n\t\t/**\n\t\t * Whether the list variant draws a checkbox on the row: the viewer's own\n\t\t * open task, with no outcome list to choose from.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t */\n\t\tcanCheck(task) {\n\t\t\treturn this.canComplete(task) && !(Array.isArray(task.outcomes) && task.outcomes.length > 0)\n\t\t},\n\n\t\t/**\n\t\t * Complete a task from its checkbox, with the server's default outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync check(task) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '' || this.completing.includes(uuid)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.completing = [...this.completing, uuid]\n\t\t\tawait this.postVerb(task, 'complete', { outcome: 'done' })\n\t\t\tthis.completing = this.completing.filter((id) => id !== uuid)\n\t\t},\n\n\t\t/**\n\t\t * The secondary line: subject, state and priority — whichever of\n\t\t * those the row actually carries, in words.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The meta line.\n\t\t */\n\t\tmetaLine(task) {\n\t\t\tconst parts = []\n\t\t\tif (task.subject && task.subject.title) {\n\t\t\t\tparts.push(String(task.subject.title))\n\t\t\t}\n\t\t\tconst state = STATE_LABELS[task.state]\n\t\t\tparts.push(state ? this.tr(state) : String(task.state || ''))\n\t\t\tconst priority = PRIORITY_LABELS[task.priority]\n\t\t\tif (priority && task.priority !== 'normal') {\n\t\t\t\tparts.push(this.tr(priority))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The due wording for a row, from the server's derived projection.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The due label, or '' without a due date.\n\t\t */\n\t\tdueLabel(task) {\n\t\t\treturn taskDueLabel(task)\n\t\t},\n\n\t\t/**\n\t\t * Whether the row offers claim: pooled (no assignee) and still open.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean} True when claim is offered.\n\t\t */\n\t\tcanClaim(task) {\n\t\t\treturn !task.assignee && task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Whether the row offers complete: the viewer's own open task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean} True when complete is offered.\n\t\t */\n\t\tcanComplete(task) {\n\t\t\treturn this.viewerUid !== ''\n\t\t\t\t&& task.assignee === this.viewerUid\n\t\t\t\t&& task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Whether a table row offers Complete: the viewer's own open task, or\n\t\t * any open task with `completeAny` (the server still decides).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tcanCompleteRow(task) {\n\t\t\tif (task.isTerminal === true || this.canClaim(task)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn this.content.completeAny === true || this.canComplete(task)\n\t\t},\n\n\t\t/**\n\t\t * Whether a table row offers Cancel (`content.cancel`), for an open task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {boolean}\n\t\t */\n\t\tcanCancelRow(task) {\n\t\t\treturn this.content.cancel === true && task.isTerminal !== true\n\t\t},\n\n\t\t/**\n\t\t * Cancel a task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tcancel(task) {\n\t\t\treturn this.postVerb(task, 'cancel', {})\n\t\t},\n\n\t\t/**\n\t\t * The handler's display name, the uid until it resolves.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The name.\n\t\t */\n\t\thandlerName(task) {\n\t\t\treturn userDisplayName(task.assignee) || String(task.assignee || '')\n\t\t},\n\n\t\t/**\n\t\t * A table row's status in words.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The label.\n\t\t */\n\t\tstateLabel(task) {\n\t\t\tconst state = STATE_LABELS[task.state]\n\t\t\treturn state ? this.tr(state) : String(task.state || '')\n\t\t},\n\n\t\t/**\n\t\t * A table row's second line: its description and a priority above normal.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {string} The line, or ''.\n\t\t */\n\t\ttableMeta(task) {\n\t\t\tconst parts = []\n\t\t\tif (typeof task.description === 'string' && task.description.trim() !== '') {\n\t\t\t\tparts.push(task.description.trim().split('\\n')[0])\n\t\t\t}\n\t\t\tconst priority = PRIORITY_LABELS[task.priority]\n\t\t\tif (priority && task.priority !== 'normal') {\n\t\t\t\tparts.push(this.tr(priority))\n\t\t\t}\n\t\t\treturn parts.join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The header link with `@objectId` in its query read from the page's\n\t\t * record (\"all tasks of this case\" on the Tasks page).\n\t\t *\n\t\t * @param {object|null} link The declared link.\n\t\t * @return {object|null} The link.\n\t\t */\n\t\trecordLink(link) {\n\t\t\tif (!link || !link.query || typeof link.query !== 'object') {\n\t\t\t\treturn link\n\t\t\t}\n\t\t\tconst query = Object.fromEntries(Object.entries(link.query).map(([key, value]) => [key, value === '@objectId' ? String(this.objectId ?? '') : value]))\n\t\t\treturn { ...link, query }\n\t\t},\n\n\t\t/**\n\t\t * Open or close the create form (the header's \"New task\").\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\ttoggleCreate() {\n\t\t\tthis.createOpen = !this.createOpen\n\t\t},\n\n\t\t/**\n\t\t * Post the create form as an open task on the record, then refetch.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/record-task-table/specs/record-task-table/spec.md#requirement-a-records-tasks-show-as-a-table-with-their-summary-and-new-task-in-the-header\n\t\t */\n\t\tasync createTask() {\n\t\t\tconst title = this.newTitle.trim()\n\t\t\tif (title === '' || this.recordUuid === '' || this.creating) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst create = typeof this.content.create === 'object' && this.content.create ? this.content.create : {}\n\t\t\tconst payload = { title, objectUuid: this.recordUuid, state: 'available' }\n\t\t\tif (typeof create.appId === 'string' && create.appId !== '') {\n\t\t\t\tpayload.appId = create.appId\n\t\t\t}\n\t\t\tif (this.newDue !== '') {\n\t\t\t\tpayload.dueAt = this.newDue\n\t\t\t}\n\t\t\tthis.creating = true\n\t\t\ttry {\n\t\t\t\tawait axios.post(generateUrl(FLOW_TASKS_URL), payload)\n\t\t\t\tthis.newTitle = ''\n\t\t\t\tthis.newDue = ''\n\t\t\t\tthis.createOpen = false\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error?.response?.data?.error\n\t\t\t\tshowError(typeof message === 'string' && message !== '' ? message : this.tr('The task could not be added'))\n\t\t\t}\n\t\t\tthis.creating = false\n\t\t\tthis.refetch(true)\n\t\t},\n\n\t\t/**\n\t\t * The outcomes to offer on complete: the row's declared list, else\n\t\t * one entry for the server's default outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Array<object|string>} The outcome entries.\n\t\t */\n\t\toutcomesOf(task) {\n\t\t\tif (Array.isArray(task.outcomes) && task.outcomes.length > 0) {\n\t\t\t\treturn task.outcomes\n\t\t\t}\n\t\t\treturn ['done']\n\t\t},\n\n\t\t/**\n\t\t * The wire value of one outcome entry (a string, or `{id, label}`).\n\t\t *\n\t\t * @param {object|string} outcome The outcome entry.\n\t\t * @return {string} The outcome id.\n\t\t */\n\t\toutcomeId(outcome) {\n\t\t\tif (outcome && typeof outcome === 'object') {\n\t\t\t\treturn String(outcome.id ?? outcome.value ?? outcome.label ?? '')\n\t\t\t}\n\t\t\treturn String(outcome ?? '')\n\t\t},\n\n\t\t/**\n\t\t * The menu label for one complete entry.\n\t\t *\n\t\t * @param {object|string} outcome The outcome entry.\n\t\t * @return {string} The label.\n\t\t */\n\t\tcompleteLabel(outcome) {\n\t\t\tconst id = this.outcomeId(outcome)\n\t\t\tconst label = (outcome && typeof outcome === 'object' && outcome.label)\n\t\t\t\t? String(outcome.label)\n\t\t\t\t: id\n\t\t\tif (id === 'done') {\n\t\t\t\treturn this.tr('Complete')\n\t\t\t}\n\t\t\treturn this.tr('Complete: {outcome}').replace('{outcome}', label)\n\t\t},\n\n\t\t/**\n\t\t * Claim a pooled task.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tclaim(task) {\n\t\t\treturn this.postVerb(task, 'claim', {})\n\t\t},\n\n\t\t/**\n\t\t * Complete the viewer's own task with an outcome.\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @param {string} outcome The chosen outcome id.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tcomplete(task, outcome) {\n\t\t\treturn this.postVerb(task, 'complete', { outcome })\n\t\t},\n\n\t\t/**\n\t\t * POST one lifecycle verb and refetch either way: on success the row\n\t\t * moved, and on a refusal (a lost claim race, a revoked task) the\n\t\t * list is stale in exactly the way the refusal proves. The refusal\n\t\t * itself is toasted in the SERVER'S words (ADR-062 forbids leaking\n\t\t * the raw status line, and the endpoint's `error` string is written\n\t\t * for people).\n\t\t *\n\t\t * @param {object} task The task row.\n\t\t * @param {string} verb The lifecycle verb.\n\t\t * @param {object} body The verb body.\n\t\t * @return {Promise<void>} Resolves when the verb settled.\n\t\t */\n\t\tasync postVerb(task, verb, body) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait axios.post(generateUrl(`${FLOW_TASKS_URL}/${uuid}/${verb}`), body)\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error?.response?.data?.error\n\t\t\t\tshowError(typeof message === 'string' && message !== ''\n\t\t\t\t\t? message\n\t\t\t\t\t: this.tr('The task action was refused'))\n\t\t\t}\n\t\t\tthis.refetch(true)\n\t\t},\n\n\t\t/**\n\t\t * Open the clicked task: the configured route with the uuid as `id`,\n\t\t * else the task's openregister deep link. A ctrl/cmd/shift or middle\n\t\t * click opens it in a new tab.\n\t\t *\n\t\t * @param {object} task The clicked task row.\n\t\t * @param {MouseEvent} [event] The originating click/auxclick event.\n\t\t * @return {void}\n\t\t */\n\t\tonRowClick(task, event) {\n\t\t\tconst uuid = String(task.uuid || '')\n\t\t\tif (uuid === '') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst rowRoute = this.content.rowRoute\n\t\t\tif (typeof rowRoute === 'string' && rowRoute !== '' && this.$router) {\n\t\t\t\topenRowTarget(event, { name: rowRoute, params: { id: uuid } }, this.$router)\n\t\t\t\treturn\n\t\t\t}\n\t\t\topenRowTarget(event, taskDeepLink(uuid))\n\t\t},\n\n\t\t/**\n\t\t * Middle click on a task row: open it in a new tab.\n\t\t *\n\t\t * @param {object} task The clicked task row.\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t * @return {void}\n\t\t */\n\t\tonRowAuxClick(task, event) {\n\t\t\tif (isRowMiddleClick(event)) {\n\t\t\t\tthis.onRowClick(task, event)\n\t\t\t}\n\t\t},\n\t},\n}\n\n/**\n * Clamp a configured row limit into the range the endpoint accepts.\n *\n * @param {unknown} raw The configured limit.\n * @return {number} A limit between 1 and 50 (default 6).\n */\nfunction normaliseLimit(raw) {\n\tconst n = Number(raw)\n\tif (Number.isFinite(n) === false || n <= 0) {\n\t\treturn 6\n\t}\n\treturn Math.min(50, Math.round(n))\n}\n\n/**\n * Clamp a configured scope onto the endpoint's vocabulary.\n *\n * @param {unknown} raw The configured scope.\n * @return {string} One of assigned, pooled, watched, all (default assigned).\n */\nfunction normaliseScope(raw) {\n\treturn ['assigned', 'pooled', 'watched', 'all'].includes(raw) ? raw : 'assigned'\n}\n\n/**\n * The record a widget lists tasks for: `objectUuid` as written, with\n * `@objectId` read from the page's record.\n *\n * @param {unknown} configured The `objectUuid` setting.\n * @param {unknown} objectId The page's record id.\n * @return {string} The uuid, or ''.\n */\nfunction recordUuid(configured, objectId) {\n\tif (typeof configured !== 'string' || configured === '') {\n\t\treturn ''\n\t}\n\treturn configured === '@objectId' ? String(objectId ?? '') : configured\n}\n</script>\n\n<style scoped>\n/* The record's task table (`variant: 'table'`, board DqZaakTaken): a head\n row of muted 14px labels on a near-white ground, rows divided by hairlines,\n the title at 600 over a muted line, a finished task struck through. */\n.cn-tasks-widget__create {\n\tdisplay: flex;\n\tflex-wrap: wrap;\n\talign-items: flex-end;\n\tgap: 12px;\n\tmargin-block-end: 12px;\n}\n\n.cn-tasks-widget__table {\n\twidth: 100%;\n\tborder-collapse: collapse;\n\tfont-size: 14px;\n}\n\n.cn-tasks-widget__table th {\n\tpadding: 12px 16px;\n\tbackground: color-mix(in srgb, var(--color-background-hover) 40%, var(--color-main-background));\n\tcolor: var(--color-text-maxcontrast);\n\tfont-weight: 600;\n\ttext-align: start;\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget__table td {\n\tpadding: 12px 16px;\n\tborder-top: 1px solid var(--color-border);\n\tvertical-align: middle;\n}\n\n.cn-tasks-widget__cell-task {\n\tdisplay: flex;\n\talign-items: flex-start;\n\tgap: 12px;\n}\n\n.cn-tasks-widget__state-icon {\n\tflex: none;\n\tcolor: var(--color-primary-element);\n}\n\n.cn-tasks-widget__state-icon--done {\n\tcolor: var(--color-success-text, var(--color-success));\n}\n\n.cn-tasks-widget__table .cn-tasks-widget__name {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n\tbackground: none;\n\tcolor: var(--color-main-text);\n\tfont: inherit;\n\tfont-size: 15px;\n\tfont-weight: 600;\n\ttext-align: start;\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__table .cn-tasks-widget__name:hover,\n.cn-tasks-widget__table .cn-tasks-widget__name:focus-visible {\n\ttext-decoration: underline;\n}\n\n.cn-tasks-widget__table-row--done .cn-tasks-widget__name {\n\ttext-decoration: line-through;\n}\n\n.cn-tasks-widget__handler {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 8px;\n}\n\n.cn-tasks-widget__cell-due {\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget__cell-due.cn-tasks-widget__due--overdue {\n\tcolor: var(--color-warning-text, var(--color-warning));\n\tfont-weight: 600;\n}\n\n.cn-tasks-widget__cell-actions {\n\ttext-align: end;\n\twhite-space: nowrap;\n}\n\n.cn-tasks-widget {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n\tmin-width: 0;\n}\n\n.cn-tasks-widget__loading {\n\tdisplay: flex;\n\tjustify-content: center;\n\tpadding: 8px 0;\n}\n\n.cn-tasks-widget__empty,\n.cn-tasks-widget__error,\n.cn-tasks-widget__more {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-tasks-widget__more {\n\tpadding-top: 4px;\n}\n\n.cn-tasks-widget__count {\n\tmargin: 0;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\tfont-weight: 600;\n\ttext-transform: uppercase;\n\tletter-spacing: 0.04em;\n}\n\n.cn-tasks-widget__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tmin-width: 0;\n}\n\n.cn-tasks-widget__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 10px;\n\tpadding: 6px 0;\n\tborder-bottom: 1px solid var(--color-border);\n\tmin-width: 0;\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__row:last-child {\n\tborder-bottom: none;\n}\n\n.cn-tasks-widget__body {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmin-width: 0;\n\tflex: 1 1 auto;\n}\n\n.cn-tasks-widget__name {\n\tfont-weight: 600;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget__row:hover .cn-tasks-widget__name {\n\ttext-decoration: underline;\n}\n\n.cn-tasks-widget__meta {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\twhite-space: nowrap;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget__due {\n\tflex: 0 0 auto;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 12px;\n\tfont-variant-numeric: tabular-nums;\n}\n\n/* List variant, after the dashboard board's My tasks card: a checkbox, the\n title, the subject on a muted second line and the due date at its right. */\n.cn-tasks-widget--list .cn-tasks-widget__row {\n\talign-items: flex-start;\n\tgap: 12px;\n\tpadding: 12px 0;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__name {\n\tfont-weight: 400;\n\tfont-size: 15px;\n\tline-height: 1.35;\n\tcolor: var(--color-main-text);\n}\n\n.cn-tasks-widget__check,\n.cn-tasks-widget__check-spacer {\n\tflex: none;\n\twidth: 20px;\n\theight: 20px;\n\tmargin: 1px 0 0;\n}\n\n.cn-tasks-widget__check {\n\taccent-color: var(--color-primary-element);\n\tcursor: pointer;\n}\n\n.cn-tasks-widget__meta--split {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tgap: 8px;\n\tfont-size: 13px;\n\toverflow: visible;\n}\n\n.cn-tasks-widget__subject {\n\tmin-width: 0;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__due {\n\tfont-size: 13px;\n\tfont-weight: 500;\n}\n\n.cn-tasks-widget--list .cn-tasks-widget__due--overdue {\n\tfont-weight: 600;\n}\n\n/* Overdue: weight AND colour on top of the wording, which already says\n \"Overdue by N days\" — the signal survives monochrome. */\n.cn-tasks-widget__due--overdue {\n\tcolor: var(--color-error, #d91f2d);\n\tfont-weight: 600;\n}\n\n.cn-tasks-widget__actions {\n\tflex: 0 0 auto;\n}\n</style>\n"],"names":["_normalizeClass","_toDisplayString","_openBlock","_createElementBlock","_createVNode","_Fragment","_createElementVNode","_renderList","_createBlock","_createTextVNode"],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import __sfc_main$l from '../CnAiCompanion/CnAiChatWidget.vue.js';
|
|
2
2
|
import __sfc_main from '../CnChartWidget/CnChartWidget.vue.js';
|
|
3
3
|
import __sfc_main$1 from '../CnChartWidgetForm/CnChartWidgetForm.vue.js';
|
|
4
|
-
import __sfc_main$
|
|
4
|
+
import __sfc_main$n from '../CnConversationThread/CnConversationWidget.vue.js';
|
|
5
5
|
import __sfc_main$e from '../CnCountdownWidget/CnCountdownWidget.vue.js';
|
|
6
6
|
import __sfc_main$f from '../CnCountdownWidgetForm/CnCountdownWidgetForm.vue.js';
|
|
7
7
|
import __sfc_main$k from '../CnDocumentReviewList/CnDocumentReviewWidget.vue.js';
|
|
8
|
+
import __sfc_main$m from '../CnMacrosWidget/CnMacrosWidget.vue.js';
|
|
8
9
|
import __sfc_main$c from '../CnMapWidget/CnMapWidget.vue.js';
|
|
9
10
|
import __sfc_main$d from '../CnMapWidgetForm/CnMapWidgetForm.vue.js';
|
|
10
11
|
import __sfc_main$8 from '../CnMarkdownWidget/CnMarkdownWidget.vue.js';
|
|
@@ -18,17 +19,17 @@ import __sfc_main$b from '../CnRelatedObjectsWidgetForm/CnRelatedObjectsWidgetFo
|
|
|
18
19
|
import __sfc_main$h from '../CnRetentionWidget/CnRetentionWidget.vue.js';
|
|
19
20
|
import __sfc_main$6 from '../CnSavedViewWidget/CnSavedViewWidget.vue.js';
|
|
20
21
|
import __sfc_main$7 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue.js';
|
|
21
|
-
import __sfc_main$
|
|
22
|
-
import __sfc_main$
|
|
23
|
-
import __sfc_main$
|
|
24
|
-
import __sfc_main$
|
|
22
|
+
import __sfc_main$u from '../CnStackedBarWidget/CnStackedBarWidget.vue.js';
|
|
23
|
+
import __sfc_main$v from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue.js';
|
|
24
|
+
import __sfc_main$o from '../CnStagesWidget/CnStagesWidget.vue.js';
|
|
25
|
+
import __sfc_main$p from '../CnStagesWidgetForm/CnStagesWidgetForm.vue.js';
|
|
25
26
|
import __sfc_main$2 from '../CnStatsBlockWidget/CnStatsBlockWidget.vue.js';
|
|
26
27
|
import __sfc_main$3 from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue.js';
|
|
27
|
-
import __sfc_main$
|
|
28
|
-
import __sfc_main$
|
|
29
|
-
import __sfc_main$
|
|
30
|
-
import __sfc_main$
|
|
31
|
-
import __sfc_main$
|
|
28
|
+
import __sfc_main$q from '../CnTabsWidget/CnTabsWidget.vue.js';
|
|
29
|
+
import __sfc_main$r from '../CnTabsWidgetForm/CnTabsWidgetForm.vue.js';
|
|
30
|
+
import __sfc_main$w from '../CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js';
|
|
31
|
+
import __sfc_main$s from '../CnWeekStripWidget/CnWeekStripWidget.vue.js';
|
|
32
|
+
import __sfc_main$t from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue.js';
|
|
32
33
|
import __sfc_main$j from '../CnWorkQueue/CnWorkQueue.vue.js';
|
|
33
34
|
import { registerDashboardWidget } from './dashboardWidgetRegistry.js';
|
|
34
35
|
import '../CnLabelWidget/index.js';
|
|
@@ -338,9 +339,20 @@ registerDashboardWidget('ai-chat', {
|
|
|
338
339
|
ownsTitle: true,
|
|
339
340
|
});
|
|
340
341
|
|
|
341
|
-
|
|
342
|
+
// The macros the record's schema declares, each run by a button
|
|
343
|
+
// (DqZaakAssistent "Macro's").
|
|
344
|
+
registerDashboardWidget('macros', {
|
|
342
345
|
renderer: __sfc_main$m,
|
|
343
346
|
form: null,
|
|
347
|
+
defaultContent: { description: '', emptyText: '' },
|
|
348
|
+
displayName: 'Macros',
|
|
349
|
+
icon: 'PlayBoxMultipleOutline',
|
|
350
|
+
surfaces: ['detail-page'],
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
registerDashboardWidget('conversation', {
|
|
354
|
+
renderer: __sfc_main$n,
|
|
355
|
+
form: null,
|
|
344
356
|
defaultContent: { field: 'messages', endpoint: '' },
|
|
345
357
|
displayName: 'Conversation',
|
|
346
358
|
icon: 'ForumOutline',
|
|
@@ -351,8 +363,8 @@ registerDashboardWidget('conversation', {
|
|
|
351
363
|
// The record's stages, where clicking a stage moves the record there.
|
|
352
364
|
// Registered inline for the same tree-shaking reason as `map` above.
|
|
353
365
|
registerDashboardWidget('stages', {
|
|
354
|
-
renderer: __sfc_main$
|
|
355
|
-
form: __sfc_main$
|
|
366
|
+
renderer: __sfc_main$o,
|
|
367
|
+
form: __sfc_main$p,
|
|
356
368
|
defaultContent: {
|
|
357
369
|
currentField: 'status',
|
|
358
370
|
orientation: 'horizontal',
|
|
@@ -372,8 +384,8 @@ registerDashboardWidget('stages', {
|
|
|
372
384
|
});
|
|
373
385
|
|
|
374
386
|
registerDashboardWidget('tabs', {
|
|
375
|
-
renderer: __sfc_main$
|
|
376
|
-
form: __sfc_main$
|
|
387
|
+
renderer: __sfc_main$q,
|
|
388
|
+
form: __sfc_main$r,
|
|
377
389
|
defaultContent: {
|
|
378
390
|
tabs: [],
|
|
379
391
|
ariaLabel: '',
|
|
@@ -392,8 +404,8 @@ registerDashboardWidget('tabs', {
|
|
|
392
404
|
// The current week as day columns, with the dated items under each day.
|
|
393
405
|
// Registered inline for the same tree-shaking reason as `map` above.
|
|
394
406
|
registerDashboardWidget('week-strip', {
|
|
395
|
-
renderer: __sfc_main$
|
|
396
|
-
form: __sfc_main$
|
|
407
|
+
renderer: __sfc_main$s,
|
|
408
|
+
form: __sfc_main$t,
|
|
397
409
|
defaultContent: {
|
|
398
410
|
source: { register: '', schema: '', filter: {} },
|
|
399
411
|
dateField: '',
|
|
@@ -409,8 +421,8 @@ registerDashboardWidget('week-strip', {
|
|
|
409
421
|
|
|
410
422
|
// One segmented bar with a legend that carries the numbers.
|
|
411
423
|
registerDashboardWidget('stacked-bar', {
|
|
412
|
-
renderer: __sfc_main$
|
|
413
|
-
form: __sfc_main$
|
|
424
|
+
renderer: __sfc_main$u,
|
|
425
|
+
form: __sfc_main$v,
|
|
414
426
|
defaultContent: {
|
|
415
427
|
source: { register: '', schema: '', groupBy: '', filter: {} },
|
|
416
428
|
order: [],
|
|
@@ -425,7 +437,7 @@ registerDashboardWidget('stacked-bar', {
|
|
|
425
437
|
// person's open count from the app (DqTeamwachtrij "Team vandaag"). Placed
|
|
426
438
|
// from the manifest: there is no config form yet.
|
|
427
439
|
registerDashboardWidget('team-workload', {
|
|
428
|
-
renderer: __sfc_main$
|
|
440
|
+
renderer: __sfc_main$w,
|
|
429
441
|
form: null,
|
|
430
442
|
defaultContent: { source: { url: '', responsePath: '', userField: 'userId', nameField: 'displayName', countField: 'count' } },
|
|
431
443
|
displayName: 'Team workload',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerDashboardWidgets.js","sources":["../../../../src/components/CnWidgetGrid/registerDashboardWidgets.js"],"sourcesContent":["/**\n * Side-effect aggregator for the cn-widget-library dashboard widget catalog.\n *\n * Importing this module imports every migrated widget's `index.js`, each of\n * which self-registers its `{ renderer, form, defaultContent, displayName,\n * icon }` into `dashboardWidgetRegistry` at load time. The library barrel\n * imports this module so the catalog is populated whenever a consuming app\n * imports `@conduction/nextcloud-vue`; `CnWidgetGrid` then resolves widgets by\n * type key and `CnAddWidgetModal` lists the addable types.\n *\n * The individual widget components are intentionally NOT public exports — they\n * are resolved by their registry type key (the whole point of the registry),\n * so consumers reference them via the manifest `widgetKey`, not by import.\n *\n * @module components/CnWidgetGrid/registerDashboardWidgets\n */\n\nimport CnAiChatWidget from '../CnAiCompanion/CnAiChatWidget.vue'\nimport CnChartWidget from '../CnChartWidget/CnChartWidget.vue'\nimport CnChartWidgetForm from '../CnChartWidgetForm/CnChartWidgetForm.vue'\nimport CnConversationWidget from '../CnConversationThread/CnConversationWidget.vue'\nimport CnCountdownWidget from '../CnCountdownWidget/CnCountdownWidget.vue'\nimport CnCountdownWidgetForm from '../CnCountdownWidgetForm/CnCountdownWidgetForm.vue'\nimport CnDocumentReviewWidget from '../CnDocumentReviewList/CnDocumentReviewWidget.vue'\nimport CnMapWidget from '../CnMapWidget/CnMapWidget.vue'\nimport CnMapWidgetForm from '../CnMapWidgetForm/CnMapWidgetForm.vue'\nimport CnMarkdownWidget2 from '../CnMarkdownWidget/CnMarkdownWidget.vue'\nimport CnMarkdownWidgetForm2 from '../CnMarkdownWidgetForm/CnMarkdownWidgetForm.vue'\nimport CnNextStepWidget from '../CnNextStepCard/CnNextStepWidget.vue'\nimport CnObjectListWidget2 from '../CnObjectListWidget/CnObjectListWidget.vue'\nimport CnObjectListWidgetForm2 from '../CnObjectListWidgetForm/CnObjectListWidgetForm.vue'\nimport CnPlanWidget from '../CnPlanWidget/CnPlanWidget.vue'\nimport CnRelatedObjectsWidget from '../CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue'\nimport CnRelatedObjectsWidgetForm from '../CnRelatedObjectsWidgetForm/CnRelatedObjectsWidgetForm.vue'\nimport CnRetentionWidget from '../CnRetentionWidget/CnRetentionWidget.vue'\nimport CnSavedViewWidget2 from '../CnSavedViewWidget/CnSavedViewWidget.vue'\nimport CnSavedViewWidgetForm2 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue'\nimport CnStackedBarWidget from '../CnStackedBarWidget/CnStackedBarWidget.vue'\nimport CnStackedBarWidgetForm from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue'\nimport CnStagesWidget from '../CnStagesWidget/CnStagesWidget.vue'\nimport CnStagesWidgetForm from '../CnStagesWidgetForm/CnStagesWidgetForm.vue'\nimport CnStatsBlockWidget from '../CnStatsBlockWidget/CnStatsBlockWidget.vue'\nimport CnStatsBlockWidgetForm from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue'\nimport CnTabsWidget from '../CnTabsWidget/CnTabsWidget.vue'\nimport CnTabsWidgetForm from '../CnTabsWidgetForm/CnTabsWidgetForm.vue'\nimport CnTeamWorkloadWidget from '../CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue'\nimport CnWeekStripWidget from '../CnWeekStripWidget/CnWeekStripWidget.vue'\nimport CnWeekStripWidgetForm from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue'\nimport CnWorkQueue from '../CnWorkQueue/CnWorkQueue.vue'\n// Typed widgets registered with an explicit renderer + config FORM. chart /\n// stats-block render through CnDashboardPage's own isChart()/isStatsBlock()\n// branches and `related` through CnDetailPage's isRelatedWidget() branch — the\n// registry entry exists so the cog editor + Add-widget picker get a form (and,\n// for `related`, the detail-page surface). `table` aliases the object-list\n// renderer/form for legacy manifests using type:'table'.\nimport { registerDashboardWidget } from './dashboardWidgetRegistry.js'\n\nimport '../CnLabelWidget/index.js'\nimport '../CnTextWidget/index.js'\nimport '../CnImageWidget/index.js'\nimport '../CnLinkButtonWidget/index.js'\nimport '../CnDividerWidget/index.js'\nimport '../CnHeaderWidget/index.js'\nimport '../CnQuicklinksWidget/index.js'\nimport '../CnVideoWidget/index.js'\nimport '../CnDashTileWidget/index.js'\nimport '../CnLinksWidget/index.js'\nimport '../CnMenuWidget/index.js'\nimport '../CnContainerWidget/index.js'\nimport '../CnFilesWidget/index.js'\nimport '../CnPeopleWidget/index.js'\nimport '../CnCalendarWidget/index.js'\nimport '../CnNcWidgetWidget/index.js'\nimport '../CnSpendAnalyticsWidget/index.js'\nimport '../CnStatWidget/index.js'\nimport '../CnDeltaWidget/index.js'\nimport '../CnGaugeWidget/index.js'\nimport '../CnFlowRunsWidget/index.js'\nimport '../CnTasksWidget/index.js'\nimport '../CnSectionsWidget/index.js'\nimport '../CnFactsWidget/index.js'\nimport '../CnLinkedWidget/index.js'\nimport '../CnDeviceFramesWidget/index.js'\nimport '../CnGroupedCardsWidget/index.js'\nimport '../CnChecklistRunWidget/index.js'\nimport '../CnMailTab/index.js'\nimport '../CnWorkingCalendarWidget/index.js'\nimport '../CnPartyActionsWidget/index.js'\nimport '../CnFieldListWidget/index.js'\nimport '../CnSettingsFormWidget/index.js'\nimport '../CnSwitchRowsWidget/index.js'\nimport '../CnRadioCardsWidget/index.js'\nimport '../CnChipsFieldWidget/index.js'\nimport '../CnToggleTableWidget/index.js'\nimport '../CnChoicePickerWidget/index.js'\nimport '../CnRecordListWidget/index.js'\nimport '../CnSavedViewsWidget/index.js'\nimport '../CnNotepadWidget/index.js'\nimport '../CnObjectDataWidget/dashboardRegistration.js'\nimport '../CnObjectGeoWidget/dashboardRegistration.js'\nimport '../CnWidgetObjectTable/dashboardRegistration.js'\nimport '../CnAuditTrailWidget/dashboardRegistration.js'\nimport '../CnTimelineWidget/dashboardRegistration.js'\nimport '../CnKbSearchWidget/index.js'\nimport '../CnInteractionFormWidget/index.js'\nimport '../CnBannerWidget/index.js'\nimport '../CnWorkspaceFilterWidget/index.js'\n\nregisterDashboardWidget('chart', {\n\trenderer: CnChartWidget,\n\tform: CnChartWidgetForm,\n\tdefaultContent: {\n\t\tchartKind: 'area',\n\t\tdataSource: { register: '', schema: '', filter: {}, bucket: { field: '', interval: 'month', metric: 'count', metricField: '' } },\n\t},\n\tdisplayName: 'Chart',\n\ticon: 'ChartLine',\n})\n\nregisterDashboardWidget('stats-block', {\n\trenderer: CnStatsBlockWidget,\n\tform: CnStatsBlockWidgetForm,\n\tdefaultContent: {\n\t\ttitle: '',\n\t\tprops: { countLabel: '', variant: 'default', iconClass: '' },\n\t\tdataSource: { register: '', schema: '', metric: 'count', field: '', filter: {} },\n\t},\n\tdisplayName: 'Statistic card',\n\ticon: 'ChartBar',\n\t// Card family (docs/architecture/cards-and-widgets.md), like `stat` and\n\t// `delta`: the tile headlines itself with its own title, so the wrapper\n\t// renders no header of its own and would otherwise show the title twice.\n\tcard: true,\n})\n\n// `table` and `object-list` (below) are legacy aliases of `object-table` — same\n// config form (CnObjectListWidgetForm), same job. They stay registered so\n// existing placements keep rendering, but are hidden from every Add-widget\n// picker via a sentinel surface no picker queries (see widgetTypeAllowsSurface):\n// `object-table` is the one to add now. Rendering resolves through\n// getWidgetTypeEntry, which ignores `surfaces`, so hidden ≠ broken.\nregisterDashboardWidget('table', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 10,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Table',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `object-list` is registered HERE and only here. Registering it from\n// CnObjectListWidget/index.js instead is not enough: package.json declares\n// `sideEffects: [\"**/*.css\"]` (ADR-061 tree-shaking), which lets\n// rollup/webpack legally DROP bare imports of side-effect-free JS modules —\n// the dist bundle shipped without the object-list registration and every\n// manifest `type:\"object-list\"` widget rendered blank. Inline calls in this\n// module survive because consumers import live bindings from the registry.\n//\n// That index.js ALSO self-registered, with a divergent entry (limit 5, no\n// `surfaces`), so both ran in a consumer's build — components/index.js\n// re-exports it, so it was never tree-shaken — and last-registration-wins\n// decided whether this legacy alias stayed hidden from the Add-widget picker.\n// The self-registration is gone; this entry is the one that already won.\nregisterDashboardWidget('object-list', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 25,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Object list',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `saved-view`: a list driven by one of the reader's saved views. The only data\n// widget a user may add themselves, because the view carries the register and\n// schema a user would otherwise have to name. Registered inline for the same\n// tree-shaking reason as `object-list` above.\n// @spec openspec/changes/a-saved-view-drives-a-widget/tasks.md#task-1.1\nregisterDashboardWidget('saved-view', {\n\trenderer: CnSavedViewWidget2,\n\tform: CnSavedViewWidgetForm2,\n\tdefaultContent: { viewId: '', limit: 10 },\n\tdisplayName: 'Saved view',\n\ticon: 'ClipboardList',\n\tuserAddable: true,\n})\n\n// `markdown`: prose inside a grid page, through the one shared renderer. The\n// only catalog widget a PUBLIC host may mount so far: every other entry is\n// `public: false` until its author opts in deliberately.\n// @spec openspec/changes/widget-registry-public-flag/tasks.md#task-4\nregisterDashboardWidget('markdown', {\n\trenderer: CnMarkdownWidget2,\n\tform: CnMarkdownWidgetForm2,\n\tdefaultContent: { markdown: '' },\n\tdisplayName: 'Markdown',\n\ticon: 'FormatTitle',\n\tpublic: true,\n})\n\nregisterDashboardWidget('related', {\n\trenderer: CnRelatedObjectsWidget,\n\tform: CnRelatedObjectsWidgetForm,\n\tdefaultContent: { title: '', groups: [], hideSingleTabTitle: true, showTotalCount: true },\n\tdisplayName: 'Object relations',\n\ticon: 'FileTreeOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// `map` is registered here for the same tree-shaking reason as `object-list`\n// above — a bare `import '../CnMapWidget/index.js'` is a side-effect-free JS module\n// as far as the bundler is concerned, so it may legally be dropped and the widget\n// would silently never appear in Add Widget. CnMapWidget/index.js carried a\n// byte-identical copy of this entry, which only produced a duplicate-registration\n// warning on every consumer's boot; it no longer registers.\nregisterDashboardWidget('map', {\n\trenderer: CnMapWidget,\n\tform: CnMapWidgetForm,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\t// The Netherlands, roughly — only visible until autoFit frames the objects.\n\t\tcenter: [52.13, 5.29],\n\t\tzoom: 7,\n\t\theight: '400px',\n\t\tpopupField: '',\n\t\tclustering: false,\n\t\tautoFit: true,\n\t\t// A map with no tile layer renders as a grey box. `basemaps` is opt-in and\n\t\t// empty by default (so consumers declaring a `tile` entry in `layers` are\n\t\t// unaffected), which meant a freshly-placed Map widget had NO background at\n\t\t// all. Ship OpenStreetMap — the Nextcloud CSP already allows *.tile.openstreetmap.org.\n\t\tbasemaps: [\n\t\t\t{\n\t\t\t\tname: 'OpenStreetMap',\n\t\t\t\turl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n\t\t\t\tattribution: '© OpenStreetMap contributors',\n\t\t\t\toptions: { maxZoom: 19 },\n\t\t\t},\n\t\t],\n\t\tmarkers: {\n\t\t\tdataSource: { register: '', schema: '' },\n\t\t\tpopupField: '',\n\t\t\tclustering: false,\n\t\t},\n\t},\n\tdisplayName: 'Map',\n\ticon: 'Map',\n})\n\nregisterDashboardWidget('countdown', {\n\trenderer: CnCountdownWidget,\n\tform: CnCountdownWidgetForm,\n\tdefaultContent: {\n\t\tlabel: '',\n\t\tfield: '',\n\t\ticon: 'ClockOutline',\n\t\tthresholds: {},\n\t\tshowDate: true,\n\t},\n\tdisplayName: 'Countdown',\n\ticon: 'ClockOutline',\n\t// Card family: the tile headlines itself, so the wrapper draws no header.\n\tcard: true,\n\t// It reads a date off the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\n// The case surfaces (detail-action-model-and-case-surfaces). Each reads the\n// BOUND RECORD, which only a detail page has, and none has a config form yet,\n// so `form: null` keeps them out of the Add-widget picker: they are placed\n// from the manifest. Registered inline for the same tree-shaking reason as\n// `map` above.\nregisterDashboardWidget('next-step', {\n\trenderer: CnNextStepWidget,\n\tform: null,\n\tdefaultContent: { field: 'status', stages: {} },\n\tdisplayName: 'Next step',\n\ticon: 'CheckCircleOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('retention', {\n\trenderer: CnRetentionWidget,\n\tform: null,\n\tdefaultContent: { statusField: '', archivedValues: [], archivistGroups: ['archivaris'] },\n\tdisplayName: 'Retention',\n\ticon: 'ArchiveOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('plan', {\n\trenderer: CnPlanWidget,\n\tform: null,\n\tdefaultContent: { emptyText: '' },\n\tdisplayName: 'Plan',\n\ticon: 'FormatListChecks',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('work-queue', {\n\trenderer: CnWorkQueue,\n\tform: null,\n\tdefaultContent: { source: null },\n\tdisplayName: 'Work queue',\n\ticon: 'TrayFull',\n})\n\nregisterDashboardWidget('document-review', {\n\trenderer: CnDocumentReviewWidget,\n\tform: null,\n\tdefaultContent: { field: 'documents', statusField: 'reviewStatus', statuses: [] },\n\tdisplayName: 'Document review',\n\ticon: 'FileDocumentCheckOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The AI Chat Companion embedded in the page: the assistant as a tab or card\n// rather than the launcher's floating window (DqZaakAssistent).\nregisterDashboardWidget('ai-chat', {\n\trenderer: CnAiChatWidget,\n\tform: null,\n\tdefaultContent: { chatAppId: '' },\n\tdisplayName: 'Assistant',\n\ticon: 'Creation',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('conversation', {\n\trenderer: CnConversationWidget,\n\tform: null,\n\tdefaultContent: { field: 'messages', endpoint: '' },\n\tdisplayName: 'Conversation',\n\ticon: 'ForumOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The record's stages, where clicking a stage moves the record there.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('stages', {\n\trenderer: CnStagesWidget,\n\tform: CnStagesWidgetForm,\n\tdefaultContent: {\n\t\tcurrentField: 'status',\n\t\torientation: 'horizontal',\n\t\tsize: 'medium',\n\t\tstagesEndpoint: { url: '', path: '' },\n\t\t// The LIFECYCLE, not a record write. OpenRegister decides what is\n\t\t// reachable and re-validates the move; a field write has neither.\n\t\ttransition: { kind: 'lifecycle' },\n\t},\n\tdisplayName: 'Stages',\n\ticon: 'Timeline',\n\t// Card family on the detail grid: a titled wrapper around a self-contained\n\t// strip, like the KPI tiles it usually sits beside.\n\tcard: true,\n\t// It reads and moves the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\nregisterDashboardWidget('tabs', {\n\trenderer: CnTabsWidget,\n\tform: CnTabsWidgetForm,\n\tdefaultContent: {\n\t\ttabs: [],\n\t\tariaLabel: '',\n\t},\n\tdisplayName: 'Tabs',\n\ticon: 'TabPlus',\n\t// Renders OTHER widgets, so CnDetailWidgetHost hands it the surface's\n\t// sibling definitions and the context its children will need.\n\tcontainer: true,\n\t// The strip's labels ARE the titles, so a card header above them would name\n\t// the group twice.\n\townsTitle: true,\n\tsurfaces: ['detail-page'],\n})\n\n// The current week as day columns, with the dated items under each day.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('week-strip', {\n\trenderer: CnWeekStripWidget,\n\tform: CnWeekStripWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', filter: {} },\n\t\tdateField: '',\n\t\ttitleField: '',\n\t\tmetaFields: [],\n\t\tdays: 5,\n\t\titemRoute: '',\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Week strip',\n\ticon: 'Calendar',\n})\n\n// One segmented bar with a legend that carries the numbers.\nregisterDashboardWidget('stacked-bar', {\n\trenderer: CnStackedBarWidget,\n\tform: CnStackedBarWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', groupBy: '', filter: {} },\n\t\torder: [],\n\t\tlabels: {},\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Stacked bar',\n\ticon: 'ChartBar',\n})\n\n// The team today: availability from the Nextcloud user status and each\n// person's open count from the app (DqTeamwachtrij \"Team vandaag\"). Placed\n// from the manifest: there is no config form yet.\nregisterDashboardWidget('team-workload', {\n\trenderer: CnTeamWorkloadWidget,\n\tform: null,\n\tdefaultContent: { source: { url: '', responsePath: '', userField: 'userId', nameField: 'displayName', countField: 'count' } },\n\tdisplayName: 'Team workload',\n\ticon: 'AccountGroup',\n})\n\n/**\n * Explicit no-op that guarantees this module (and therefore every widget's\n * self-registration side effect) is evaluated. Now optional: `CnDashboardPage`\n * and `CnDetailPage` import this module themselves, and a second call changes\n * nothing because the module body runs once.\n *\n * @return {void}\n */\nexport function registerBuiltinDashboardWidgets() {}\n"],"names":["CnChartWidget","CnChartWidgetForm","CnStatsBlockWidget","CnStatsBlockWidgetForm","CnObjectListWidget2","CnObjectListWidgetForm2","CnSavedViewWidget2","CnSavedViewWidgetForm2","CnMarkdownWidget2","CnMarkdownWidgetForm2","CnRelatedObjectsWidget","CnRelatedObjectsWidgetForm","CnMapWidget","CnMapWidgetForm","CnCountdownWidget","CnCountdownWidgetForm","CnNextStepWidget","CnRetentionWidget","CnPlanWidget","CnWorkQueue","CnDocumentReviewWidget","CnAiChatWidget","CnConversationWidget","CnStagesWidget","CnStagesWidgetForm","CnTabsWidget","CnTabsWidgetForm","CnWeekStripWidget","CnWeekStripWidgetForm","CnStackedBarWidget","CnStackedBarWidgetForm","CnTeamWorkloadWidget"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registerDashboardWidgets.js","sources":["../../../../src/components/CnWidgetGrid/registerDashboardWidgets.js"],"sourcesContent":["/**\n * Side-effect aggregator for the cn-widget-library dashboard widget catalog.\n *\n * Importing this module imports every migrated widget's `index.js`, each of\n * which self-registers its `{ renderer, form, defaultContent, displayName,\n * icon }` into `dashboardWidgetRegistry` at load time. The library barrel\n * imports this module so the catalog is populated whenever a consuming app\n * imports `@conduction/nextcloud-vue`; `CnWidgetGrid` then resolves widgets by\n * type key and `CnAddWidgetModal` lists the addable types.\n *\n * The individual widget components are intentionally NOT public exports — they\n * are resolved by their registry type key (the whole point of the registry),\n * so consumers reference them via the manifest `widgetKey`, not by import.\n *\n * @module components/CnWidgetGrid/registerDashboardWidgets\n */\n\nimport CnAiChatWidget from '../CnAiCompanion/CnAiChatWidget.vue'\nimport CnChartWidget from '../CnChartWidget/CnChartWidget.vue'\nimport CnChartWidgetForm from '../CnChartWidgetForm/CnChartWidgetForm.vue'\nimport CnConversationWidget from '../CnConversationThread/CnConversationWidget.vue'\nimport CnCountdownWidget from '../CnCountdownWidget/CnCountdownWidget.vue'\nimport CnCountdownWidgetForm from '../CnCountdownWidgetForm/CnCountdownWidgetForm.vue'\nimport CnDocumentReviewWidget from '../CnDocumentReviewList/CnDocumentReviewWidget.vue'\nimport CnMacrosWidget from '../CnMacrosWidget/CnMacrosWidget.vue'\nimport CnMapWidget from '../CnMapWidget/CnMapWidget.vue'\nimport CnMapWidgetForm from '../CnMapWidgetForm/CnMapWidgetForm.vue'\nimport CnMarkdownWidget2 from '../CnMarkdownWidget/CnMarkdownWidget.vue'\nimport CnMarkdownWidgetForm2 from '../CnMarkdownWidgetForm/CnMarkdownWidgetForm.vue'\nimport CnNextStepWidget from '../CnNextStepCard/CnNextStepWidget.vue'\nimport CnObjectListWidget2 from '../CnObjectListWidget/CnObjectListWidget.vue'\nimport CnObjectListWidgetForm2 from '../CnObjectListWidgetForm/CnObjectListWidgetForm.vue'\nimport CnPlanWidget from '../CnPlanWidget/CnPlanWidget.vue'\nimport CnRelatedObjectsWidget from '../CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue'\nimport CnRelatedObjectsWidgetForm from '../CnRelatedObjectsWidgetForm/CnRelatedObjectsWidgetForm.vue'\nimport CnRetentionWidget from '../CnRetentionWidget/CnRetentionWidget.vue'\nimport CnSavedViewWidget2 from '../CnSavedViewWidget/CnSavedViewWidget.vue'\nimport CnSavedViewWidgetForm2 from '../CnSavedViewWidgetForm/CnSavedViewWidgetForm.vue'\nimport CnStackedBarWidget from '../CnStackedBarWidget/CnStackedBarWidget.vue'\nimport CnStackedBarWidgetForm from '../CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue'\nimport CnStagesWidget from '../CnStagesWidget/CnStagesWidget.vue'\nimport CnStagesWidgetForm from '../CnStagesWidgetForm/CnStagesWidgetForm.vue'\nimport CnStatsBlockWidget from '../CnStatsBlockWidget/CnStatsBlockWidget.vue'\nimport CnStatsBlockWidgetForm from '../CnStatsBlockWidgetForm/CnStatsBlockWidgetForm.vue'\nimport CnTabsWidget from '../CnTabsWidget/CnTabsWidget.vue'\nimport CnTabsWidgetForm from '../CnTabsWidgetForm/CnTabsWidgetForm.vue'\nimport CnTeamWorkloadWidget from '../CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue'\nimport CnWeekStripWidget from '../CnWeekStripWidget/CnWeekStripWidget.vue'\nimport CnWeekStripWidgetForm from '../CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue'\nimport CnWorkQueue from '../CnWorkQueue/CnWorkQueue.vue'\n// Typed widgets registered with an explicit renderer + config FORM. chart /\n// stats-block render through CnDashboardPage's own isChart()/isStatsBlock()\n// branches and `related` through CnDetailPage's isRelatedWidget() branch — the\n// registry entry exists so the cog editor + Add-widget picker get a form (and,\n// for `related`, the detail-page surface). `table` aliases the object-list\n// renderer/form for legacy manifests using type:'table'.\nimport { registerDashboardWidget } from './dashboardWidgetRegistry.js'\n\nimport '../CnLabelWidget/index.js'\nimport '../CnTextWidget/index.js'\nimport '../CnImageWidget/index.js'\nimport '../CnLinkButtonWidget/index.js'\nimport '../CnDividerWidget/index.js'\nimport '../CnHeaderWidget/index.js'\nimport '../CnQuicklinksWidget/index.js'\nimport '../CnVideoWidget/index.js'\nimport '../CnDashTileWidget/index.js'\nimport '../CnLinksWidget/index.js'\nimport '../CnMenuWidget/index.js'\nimport '../CnContainerWidget/index.js'\nimport '../CnFilesWidget/index.js'\nimport '../CnPeopleWidget/index.js'\nimport '../CnCalendarWidget/index.js'\nimport '../CnNcWidgetWidget/index.js'\nimport '../CnSpendAnalyticsWidget/index.js'\nimport '../CnStatWidget/index.js'\nimport '../CnDeltaWidget/index.js'\nimport '../CnGaugeWidget/index.js'\nimport '../CnFlowRunsWidget/index.js'\nimport '../CnTasksWidget/index.js'\nimport '../CnSectionsWidget/index.js'\nimport '../CnFactsWidget/index.js'\nimport '../CnLinkedWidget/index.js'\nimport '../CnDeviceFramesWidget/index.js'\nimport '../CnGroupedCardsWidget/index.js'\nimport '../CnChecklistRunWidget/index.js'\nimport '../CnMailTab/index.js'\nimport '../CnWorkingCalendarWidget/index.js'\nimport '../CnPartyActionsWidget/index.js'\nimport '../CnFieldListWidget/index.js'\nimport '../CnSettingsFormWidget/index.js'\nimport '../CnSwitchRowsWidget/index.js'\nimport '../CnRadioCardsWidget/index.js'\nimport '../CnChipsFieldWidget/index.js'\nimport '../CnToggleTableWidget/index.js'\nimport '../CnChoicePickerWidget/index.js'\nimport '../CnRecordListWidget/index.js'\nimport '../CnSavedViewsWidget/index.js'\nimport '../CnNotepadWidget/index.js'\nimport '../CnObjectDataWidget/dashboardRegistration.js'\nimport '../CnObjectGeoWidget/dashboardRegistration.js'\nimport '../CnWidgetObjectTable/dashboardRegistration.js'\nimport '../CnAuditTrailWidget/dashboardRegistration.js'\nimport '../CnTimelineWidget/dashboardRegistration.js'\nimport '../CnKbSearchWidget/index.js'\nimport '../CnInteractionFormWidget/index.js'\nimport '../CnBannerWidget/index.js'\nimport '../CnWorkspaceFilterWidget/index.js'\n\nregisterDashboardWidget('chart', {\n\trenderer: CnChartWidget,\n\tform: CnChartWidgetForm,\n\tdefaultContent: {\n\t\tchartKind: 'area',\n\t\tdataSource: { register: '', schema: '', filter: {}, bucket: { field: '', interval: 'month', metric: 'count', metricField: '' } },\n\t},\n\tdisplayName: 'Chart',\n\ticon: 'ChartLine',\n})\n\nregisterDashboardWidget('stats-block', {\n\trenderer: CnStatsBlockWidget,\n\tform: CnStatsBlockWidgetForm,\n\tdefaultContent: {\n\t\ttitle: '',\n\t\tprops: { countLabel: '', variant: 'default', iconClass: '' },\n\t\tdataSource: { register: '', schema: '', metric: 'count', field: '', filter: {} },\n\t},\n\tdisplayName: 'Statistic card',\n\ticon: 'ChartBar',\n\t// Card family (docs/architecture/cards-and-widgets.md), like `stat` and\n\t// `delta`: the tile headlines itself with its own title, so the wrapper\n\t// renders no header of its own and would otherwise show the title twice.\n\tcard: true,\n})\n\n// `table` and `object-list` (below) are legacy aliases of `object-table` — same\n// config form (CnObjectListWidgetForm), same job. They stay registered so\n// existing placements keep rendering, but are hidden from every Add-widget\n// picker via a sentinel surface no picker queries (see widgetTypeAllowsSurface):\n// `object-table` is the one to add now. Rendering resolves through\n// getWidgetTypeEntry, which ignores `surfaces`, so hidden ≠ broken.\nregisterDashboardWidget('table', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 10,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Table',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `object-list` is registered HERE and only here. Registering it from\n// CnObjectListWidget/index.js instead is not enough: package.json declares\n// `sideEffects: [\"**/*.css\"]` (ADR-061 tree-shaking), which lets\n// rollup/webpack legally DROP bare imports of side-effect-free JS modules —\n// the dist bundle shipped without the object-list registration and every\n// manifest `type:\"object-list\"` widget rendered blank. Inline calls in this\n// module survive because consumers import live bindings from the registry.\n//\n// That index.js ALSO self-registered, with a divergent entry (limit 5, no\n// `surfaces`), so both ran in a consumer's build — components/index.js\n// re-exports it, so it was never tree-shaken — and last-registration-wins\n// decided whether this legacy alias stayed hidden from the Add-widget picker.\n// The self-registration is gone; this entry is the one that already won.\nregisterDashboardWidget('object-list', {\n\trenderer: CnObjectListWidget2,\n\tform: CnObjectListWidgetForm2,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\tfilter: {},\n\t\tsort: { field: '', dir: 'asc' },\n\t\tlimit: 25,\n\t\tcolumns: [],\n\t},\n\tdisplayName: 'Object list',\n\ticon: 'ClipboardList',\n\tsurfaces: ['legacy'],\n})\n\n// `saved-view`: a list driven by one of the reader's saved views. The only data\n// widget a user may add themselves, because the view carries the register and\n// schema a user would otherwise have to name. Registered inline for the same\n// tree-shaking reason as `object-list` above.\n// @spec openspec/changes/a-saved-view-drives-a-widget/tasks.md#task-1.1\nregisterDashboardWidget('saved-view', {\n\trenderer: CnSavedViewWidget2,\n\tform: CnSavedViewWidgetForm2,\n\tdefaultContent: { viewId: '', limit: 10 },\n\tdisplayName: 'Saved view',\n\ticon: 'ClipboardList',\n\tuserAddable: true,\n})\n\n// `markdown`: prose inside a grid page, through the one shared renderer. The\n// only catalog widget a PUBLIC host may mount so far: every other entry is\n// `public: false` until its author opts in deliberately.\n// @spec openspec/changes/widget-registry-public-flag/tasks.md#task-4\nregisterDashboardWidget('markdown', {\n\trenderer: CnMarkdownWidget2,\n\tform: CnMarkdownWidgetForm2,\n\tdefaultContent: { markdown: '' },\n\tdisplayName: 'Markdown',\n\ticon: 'FormatTitle',\n\tpublic: true,\n})\n\nregisterDashboardWidget('related', {\n\trenderer: CnRelatedObjectsWidget,\n\tform: CnRelatedObjectsWidgetForm,\n\tdefaultContent: { title: '', groups: [], hideSingleTabTitle: true, showTotalCount: true },\n\tdisplayName: 'Object relations',\n\ticon: 'FileTreeOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// `map` is registered here for the same tree-shaking reason as `object-list`\n// above — a bare `import '../CnMapWidget/index.js'` is a side-effect-free JS module\n// as far as the bundler is concerned, so it may legally be dropped and the widget\n// would silently never appear in Add Widget. CnMapWidget/index.js carried a\n// byte-identical copy of this entry, which only produced a duplicate-registration\n// warning on every consumer's boot; it no longer registers.\nregisterDashboardWidget('map', {\n\trenderer: CnMapWidget,\n\tform: CnMapWidgetForm,\n\tdefaultContent: {\n\t\tregister: '',\n\t\tschema: '',\n\t\t// The Netherlands, roughly — only visible until autoFit frames the objects.\n\t\tcenter: [52.13, 5.29],\n\t\tzoom: 7,\n\t\theight: '400px',\n\t\tpopupField: '',\n\t\tclustering: false,\n\t\tautoFit: true,\n\t\t// A map with no tile layer renders as a grey box. `basemaps` is opt-in and\n\t\t// empty by default (so consumers declaring a `tile` entry in `layers` are\n\t\t// unaffected), which meant a freshly-placed Map widget had NO background at\n\t\t// all. Ship OpenStreetMap — the Nextcloud CSP already allows *.tile.openstreetmap.org.\n\t\tbasemaps: [\n\t\t\t{\n\t\t\t\tname: 'OpenStreetMap',\n\t\t\t\turl: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n\t\t\t\tattribution: '© OpenStreetMap contributors',\n\t\t\t\toptions: { maxZoom: 19 },\n\t\t\t},\n\t\t],\n\t\tmarkers: {\n\t\t\tdataSource: { register: '', schema: '' },\n\t\t\tpopupField: '',\n\t\t\tclustering: false,\n\t\t},\n\t},\n\tdisplayName: 'Map',\n\ticon: 'Map',\n})\n\nregisterDashboardWidget('countdown', {\n\trenderer: CnCountdownWidget,\n\tform: CnCountdownWidgetForm,\n\tdefaultContent: {\n\t\tlabel: '',\n\t\tfield: '',\n\t\ticon: 'ClockOutline',\n\t\tthresholds: {},\n\t\tshowDate: true,\n\t},\n\tdisplayName: 'Countdown',\n\ticon: 'ClockOutline',\n\t// Card family: the tile headlines itself, so the wrapper draws no header.\n\tcard: true,\n\t// It reads a date off the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\n// The case surfaces (detail-action-model-and-case-surfaces). Each reads the\n// BOUND RECORD, which only a detail page has, and none has a config form yet,\n// so `form: null` keeps them out of the Add-widget picker: they are placed\n// from the manifest. Registered inline for the same tree-shaking reason as\n// `map` above.\nregisterDashboardWidget('next-step', {\n\trenderer: CnNextStepWidget,\n\tform: null,\n\tdefaultContent: { field: 'status', stages: {} },\n\tdisplayName: 'Next step',\n\ticon: 'CheckCircleOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('retention', {\n\trenderer: CnRetentionWidget,\n\tform: null,\n\tdefaultContent: { statusField: '', archivedValues: [], archivistGroups: ['archivaris'] },\n\tdisplayName: 'Retention',\n\ticon: 'ArchiveOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('plan', {\n\trenderer: CnPlanWidget,\n\tform: null,\n\tdefaultContent: { emptyText: '' },\n\tdisplayName: 'Plan',\n\ticon: 'FormatListChecks',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\nregisterDashboardWidget('work-queue', {\n\trenderer: CnWorkQueue,\n\tform: null,\n\tdefaultContent: { source: null },\n\tdisplayName: 'Work queue',\n\ticon: 'TrayFull',\n})\n\nregisterDashboardWidget('document-review', {\n\trenderer: CnDocumentReviewWidget,\n\tform: null,\n\tdefaultContent: { field: 'documents', statusField: 'reviewStatus', statuses: [] },\n\tdisplayName: 'Document review',\n\ticon: 'FileDocumentCheckOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The AI Chat Companion embedded in the page: the assistant as a tab or card\n// rather than the launcher's floating window (DqZaakAssistent).\nregisterDashboardWidget('ai-chat', {\n\trenderer: CnAiChatWidget,\n\tform: null,\n\tdefaultContent: { chatAppId: '' },\n\tdisplayName: 'Assistant',\n\ticon: 'Creation',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The macros the record's schema declares, each run by a button\n// (DqZaakAssistent \"Macro's\").\nregisterDashboardWidget('macros', {\n\trenderer: CnMacrosWidget,\n\tform: null,\n\tdefaultContent: { description: '', emptyText: '' },\n\tdisplayName: 'Macros',\n\ticon: 'PlayBoxMultipleOutline',\n\tsurfaces: ['detail-page'],\n})\n\nregisterDashboardWidget('conversation', {\n\trenderer: CnConversationWidget,\n\tform: null,\n\tdefaultContent: { field: 'messages', endpoint: '' },\n\tdisplayName: 'Conversation',\n\ticon: 'ForumOutline',\n\tsurfaces: ['detail-page'],\n\townsTitle: true,\n})\n\n// The record's stages, where clicking a stage moves the record there.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('stages', {\n\trenderer: CnStagesWidget,\n\tform: CnStagesWidgetForm,\n\tdefaultContent: {\n\t\tcurrentField: 'status',\n\t\torientation: 'horizontal',\n\t\tsize: 'medium',\n\t\tstagesEndpoint: { url: '', path: '' },\n\t\t// The LIFECYCLE, not a record write. OpenRegister decides what is\n\t\t// reachable and re-validates the move; a field write has neither.\n\t\ttransition: { kind: 'lifecycle' },\n\t},\n\tdisplayName: 'Stages',\n\ticon: 'Timeline',\n\t// Card family on the detail grid: a titled wrapper around a self-contained\n\t// strip, like the KPI tiles it usually sits beside.\n\tcard: true,\n\t// It reads and moves the BOUND RECORD, which only a detail page has.\n\tsurfaces: ['detail-page'],\n})\n\nregisterDashboardWidget('tabs', {\n\trenderer: CnTabsWidget,\n\tform: CnTabsWidgetForm,\n\tdefaultContent: {\n\t\ttabs: [],\n\t\tariaLabel: '',\n\t},\n\tdisplayName: 'Tabs',\n\ticon: 'TabPlus',\n\t// Renders OTHER widgets, so CnDetailWidgetHost hands it the surface's\n\t// sibling definitions and the context its children will need.\n\tcontainer: true,\n\t// The strip's labels ARE the titles, so a card header above them would name\n\t// the group twice.\n\townsTitle: true,\n\tsurfaces: ['detail-page'],\n})\n\n// The current week as day columns, with the dated items under each day.\n// Registered inline for the same tree-shaking reason as `map` above.\nregisterDashboardWidget('week-strip', {\n\trenderer: CnWeekStripWidget,\n\tform: CnWeekStripWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', filter: {} },\n\t\tdateField: '',\n\t\ttitleField: '',\n\t\tmetaFields: [],\n\t\tdays: 5,\n\t\titemRoute: '',\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Week strip',\n\ticon: 'Calendar',\n})\n\n// One segmented bar with a legend that carries the numbers.\nregisterDashboardWidget('stacked-bar', {\n\trenderer: CnStackedBarWidget,\n\tform: CnStackedBarWidgetForm,\n\tdefaultContent: {\n\t\tsource: { register: '', schema: '', groupBy: '', filter: {} },\n\t\torder: [],\n\t\tlabels: {},\n\t\temptyText: '',\n\t},\n\tdisplayName: 'Stacked bar',\n\ticon: 'ChartBar',\n})\n\n// The team today: availability from the Nextcloud user status and each\n// person's open count from the app (DqTeamwachtrij \"Team vandaag\"). Placed\n// from the manifest: there is no config form yet.\nregisterDashboardWidget('team-workload', {\n\trenderer: CnTeamWorkloadWidget,\n\tform: null,\n\tdefaultContent: { source: { url: '', responsePath: '', userField: 'userId', nameField: 'displayName', countField: 'count' } },\n\tdisplayName: 'Team workload',\n\ticon: 'AccountGroup',\n})\n\n/**\n * Explicit no-op that guarantees this module (and therefore every widget's\n * self-registration side effect) is evaluated. Now optional: `CnDashboardPage`\n * and `CnDetailPage` import this module themselves, and a second call changes\n * nothing because the module body runs once.\n *\n * @return {void}\n */\nexport function registerBuiltinDashboardWidgets() {}\n"],"names":["CnChartWidget","CnChartWidgetForm","CnStatsBlockWidget","CnStatsBlockWidgetForm","CnObjectListWidget2","CnObjectListWidgetForm2","CnSavedViewWidget2","CnSavedViewWidgetForm2","CnMarkdownWidget2","CnMarkdownWidgetForm2","CnRelatedObjectsWidget","CnRelatedObjectsWidgetForm","CnMapWidget","CnMapWidgetForm","CnCountdownWidget","CnCountdownWidgetForm","CnNextStepWidget","CnRetentionWidget","CnPlanWidget","CnWorkQueue","CnDocumentReviewWidget","CnAiChatWidget","CnMacrosWidget","CnConversationWidget","CnStagesWidget","CnStagesWidgetForm","CnTabsWidget","CnTabsWidgetForm","CnWeekStripWidget","CnWeekStripWidgetForm","CnStackedBarWidget","CnStackedBarWidgetForm","CnTeamWorkloadWidget"],"mappings":"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"}
|