@conduction/nextcloud-vue 2.79.0 → 2.80.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/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
- package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +10 -8
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +39 -3
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +79 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +133 -96
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +1 -0
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +62 -4
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +736 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/index.js +30 -0
- package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +551 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +183 -0
- package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnFieldListWidget/index.js +29 -0
- package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +18 -3
- package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
- package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +305 -72
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +31 -13
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +387 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +169 -0
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnRecordListWidget/index.js +31 -0
- package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
- package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnSectionsWidget/index.js +35 -0
- package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +122 -7
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +84 -23
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +106 -2
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +105 -53
- package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
- package/dist/esm/composables/useFormDraft.js +140 -9
- package/dist/esm/composables/useFormDraft.js.map +1 -1
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
- package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
- package/dist/esm/integrations/builtin/field-inspection.js +21 -0
- package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
- package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
- package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
- package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
- package/dist/esm/integrations/offline/index.js +2 -1
- package/dist/esm/integrations/offline/index.js.map +1 -1
- package/dist/esm/integrations/offline/offlineDb.js +6 -1
- package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
- package/dist/esm/integrations/offline/syncReplayService.js +8 -2
- package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
- package/dist/esm/l10n/en.json.js +12 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +16 -2
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +1000 -59
- package/dist/esm/utils/detailActionModel.js +60 -3
- package/dist/esm/utils/detailActionModel.js.map +1 -1
- package/dist/esm/utils/fillTemplate.js +114 -0
- package/dist/esm/utils/fillTemplate.js.map +1 -0
- package/dist/esm/utils/libraryWidgetKeys.js +4 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/queryPresets.js +96 -0
- package/dist/esm/utils/queryPresets.js.map +1 -0
- package/dist/esm/utils/resolveFilterTokens.js +11 -0
- package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
- package/dist/esm/utils/schema.js +21 -0
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/sentinelTokens.js +3 -3
- package/dist/esm/utils/sentinelTokens.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/widgetDispatch.js +7 -1
- package/dist/esm/utils/widgetDispatch.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +12368 -7717
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1000 -59
- package/l10n/en.json +12 -1
- package/l10n/nl.json +16 -2
- package/package.json +1 -1
- package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
- package/src/components/CnActionsBar/CnActionsBar.md +4 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +42 -10
- package/src/components/CnBannerWidget/CnBannerWidget.vue +39 -3
- package/src/components/CnCellRenderer/CnCellRenderer.vue +188 -1
- package/src/components/CnDataTable/CnDataTable.vue +1 -0
- package/src/components/CnDetailPage/CnDetailPage.md +1 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +63 -3
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
- package/src/components/CnFactsWidget/CnFactsWidget.vue +1050 -0
- package/src/components/CnFactsWidget/index.js +29 -0
- package/src/components/CnFieldListWidget/CnFieldListWidget.vue +746 -0
- package/src/components/CnFieldListWidget/index.js +28 -0
- package/src/components/CnFormDialog/CnFormDialog.md +9 -3
- package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
- package/src/components/CnFormPage/CnFormPage.vue +18 -3
- package/src/components/CnIndexPage/CnIndexPage.vue +254 -6
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
- package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +603 -0
- package/src/components/CnRecordListWidget/index.js +30 -0
- package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
- package/src/components/CnSectionsWidget/index.js +34 -0
- package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
- package/src/components/CnStatWidget/CnStatWidget.vue +1 -1
- package/src/components/CnTabsWidget/CnTabsWidget.vue +184 -8
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
- package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +188 -4
- package/src/components/index.js +4 -0
- package/src/composables/__tests__/useFormDraft.spec.js +69 -0
- package/src/composables/useFormDraft.js +139 -8
- package/src/css/form-field.css +14 -0
- package/src/css/index-page.css +71 -0
- package/src/css/kpi-card.css +32 -0
- package/src/css/look-board-detail.css +77 -0
- package/src/css/look-board-index.css +51 -0
- package/src/css/look-board.css +37 -2
- package/src/css/table.css +19 -0
- package/src/index.js +4 -0
- package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
- package/src/integrations/builtin/field-inspection.js +21 -0
- package/src/integrations/offline/checklistSubmission.js +137 -0
- package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
- package/src/integrations/offline/index.js +3 -0
- package/src/integrations/offline/offlineDb.js +6 -1
- package/src/integrations/offline/syncReplayService.js +8 -2
- package/src/schemas/app-manifest-v2.schema.json +104 -5
- package/src/utils/detailActionModel.js +59 -2
- package/src/utils/fillTemplate.js +110 -0
- package/src/utils/libraryWidgetKeys.js +4 -0
- package/src/utils/queryPresets.js +93 -0
- package/src/utils/resolveFilterTokens.js +11 -0
- package/src/utils/schema.js +21 -0
- package/src/utils/sentinelTokens.js +3 -3
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/widgetDispatch.js +7 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import script from './CnIndexPageWidgets.vue2.js';
|
|
2
|
+
import { render } from './CnIndexPageWidgets.vue3.js';
|
|
3
|
+
|
|
4
|
+
script.render = render;
|
|
5
|
+
script.__scopeId = "data-v-5ec0c5bc";
|
|
6
|
+
script.__file = "src/components/CnIndexPage/CnIndexPageWidgets.vue";
|
|
7
|
+
const __sfc_main = script;
|
|
8
|
+
|
|
9
|
+
export { __sfc_main as default };
|
|
10
|
+
//# sourceMappingURL=CnIndexPageWidgets.vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnIndexPageWidgets.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import __sfc_main from '../CnKpiGrid/CnKpiGrid.vue.js';
|
|
2
|
+
import __sfc_main$1 from '../CnWidgetWrapper/CnWidgetWrapper.vue.js';
|
|
3
|
+
import { canonicalWidgetType } from '../../utils/widgetTypeAliases.js';
|
|
4
|
+
import { BUILT_IN_WIDGETS } from '../CnWidgetGrid/builtInWidgets.js';
|
|
5
|
+
import { getWidgetTypeEntry } from '../CnWidgetGrid/dashboardWidgetRegistry.js';
|
|
6
|
+
import '../CnWidgetGrid/registerDashboardWidgets.js';
|
|
7
|
+
|
|
8
|
+
var script = {
|
|
9
|
+
name: 'CnIndexPageWidgets',
|
|
10
|
+
|
|
11
|
+
components: {
|
|
12
|
+
CnKpiGrid: __sfc_main,
|
|
13
|
+
CnWidgetWrapper: __sfc_main$1,
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
inject: {
|
|
17
|
+
/** Consumer widget registry provided by CnAppRoot (custom over built-in). */
|
|
18
|
+
cnRegistry: { default: () => ({}) },
|
|
19
|
+
/** Host translate function provided by CnAppRoot. */
|
|
20
|
+
cnTranslate: { default: () => (key) => key },
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
props: {
|
|
24
|
+
/**
|
|
25
|
+
* Widget definitions `{ id, type, title?, content?, headerLink? }`.
|
|
26
|
+
* An entry without an id or with a type no layer resolves is skipped.
|
|
27
|
+
*/
|
|
28
|
+
widgets: {
|
|
29
|
+
type: Array,
|
|
30
|
+
default: () => [],
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/** Where the widgets sit: `stat-row` above the list, `side-panel` beside it. */
|
|
34
|
+
variant: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: 'stat-row',
|
|
37
|
+
validator: (v) => ['stat-row', 'side-panel'].includes(v),
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
computed: {
|
|
42
|
+
/**
|
|
43
|
+
* The renderable entries, in the listed order.
|
|
44
|
+
*
|
|
45
|
+
* @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-stat-row-above-the-list
|
|
46
|
+
* @return {Array<{id: string, title: string, content: object, headerLink: (object|null), renderer: object}>}
|
|
47
|
+
*/
|
|
48
|
+
entries() {
|
|
49
|
+
const list = Array.isArray(this.widgets) ? this.widgets : [];
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const def of list) {
|
|
52
|
+
if (!def || typeof def.id !== 'string' || def.id === '' || typeof def.type !== 'string') {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
const renderer = this.resolveRenderer(def.type);
|
|
56
|
+
if (!renderer) {
|
|
57
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.warn(`[CnIndexPage] ${this.variant} widget "${def.id}" has type "${def.type}", which no widget registry resolves; skipped.`);
|
|
60
|
+
}
|
|
61
|
+
continue
|
|
62
|
+
}
|
|
63
|
+
const translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key;
|
|
64
|
+
out.push({
|
|
65
|
+
id: def.id,
|
|
66
|
+
title: typeof def.title === 'string' && def.title !== '' ? translate(def.title) : '',
|
|
67
|
+
content: (def.content && typeof def.content === 'object') ? def.content : {},
|
|
68
|
+
headerLink: (def.headerLink && typeof def.headerLink === 'object') ? def.headerLink : null,
|
|
69
|
+
renderer,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return out
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
methods: {
|
|
77
|
+
/**
|
|
78
|
+
* Resolve a widget type: the consumer registry, then the dashboard
|
|
79
|
+
* catalog (the type as written, then its alias), then the built-ins.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} type The widget type.
|
|
82
|
+
* @return {object|null} The component, or null.
|
|
83
|
+
*/
|
|
84
|
+
resolveRenderer(type) {
|
|
85
|
+
const consumer = (this.cnRegistry || {})[type];
|
|
86
|
+
if (consumer) {
|
|
87
|
+
return consumer.component ?? consumer
|
|
88
|
+
}
|
|
89
|
+
const entry = getWidgetTypeEntry(type) || getWidgetTypeEntry(canonicalWidgetType(type));
|
|
90
|
+
if (entry && entry.renderer) {
|
|
91
|
+
return entry.renderer
|
|
92
|
+
}
|
|
93
|
+
return BUILT_IN_WIDGETS[type] || BUILT_IN_WIDGETS[canonicalWidgetType(type)] || null
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { script as default };
|
|
99
|
+
//# sourceMappingURL=CnIndexPageWidgets.vue2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnIndexPageWidgets.vue2.js","sources":["../../../../src/components/CnIndexPage/CnIndexPageWidgets.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n\n CnIndexPageWidgets — the widgets an index page draws around its list\n (screens-index-stat-row): the KPI tiles above it (`statRow`, an auto-fit row)\n and the cards beside it (`sidePanel`, a column). Each entry is a dashboard\n widget definition `{ id, type, title?, content, headerLink? }`, resolved like\n a dashboard widget: the app's registry, then the dashboard catalog, then the\n built-in widgets. Internal to CnIndexPage.\n-->\n<template>\n\t<component\n\t\t:is=\"variant === 'stat-row' ? 'CnKpiGrid' : 'aside'\"\n\t\tv-if=\"entries.length > 0\"\n\t\t:columns=\"variant === 'stat-row' ? 'auto' : undefined\"\n\t\tclass=\"cn-index-page-widgets\"\n\t\t:class=\"['cn-index-page-widgets--' + variant]\"\n\t\t:data-testid=\"'cn-index-page-' + variant\">\n\t\t<div\n\t\t\tv-for=\"entry in entries\"\n\t\t\t:key=\"entry.id\"\n\t\t\tclass=\"cn-index-page-widgets__cell\"\n\t\t\t:data-testid=\"'cn-index-page-widget-' + entry.id\">\n\t\t\t<CnWidgetWrapper\n\t\t\t\t:widgetId=\"entry.id\"\n\t\t\t\t:title=\"entry.title\"\n\t\t\t\t:showTitle=\"variant === 'side-panel' && entry.title !== ''\"\n\t\t\t\t:showActions=\"false\"\n\t\t\t\t:showRefresh=\"false\"\n\t\t\t\t:headerLink=\"entry.headerLink\"\n\t\t\t\t:flush=\"variant === 'stat-row'\">\n\t\t\t\t<component\n\t\t\t\t\t:is=\"entry.renderer\"\n\t\t\t\t\t:widgetId=\"entry.id\"\n\t\t\t\t\t:content=\"entry.content\"\n\t\t\t\t\tv-bind=\"entry.content\" />\n\t\t\t</CnWidgetWrapper>\n\t\t</div>\n\t</component>\n</template>\n\n<script>\nimport CnKpiGrid from '../CnKpiGrid/CnKpiGrid.vue'\nimport CnWidgetWrapper from '../CnWidgetWrapper/CnWidgetWrapper.vue'\nimport { canonicalWidgetType } from '../../utils/widgetTypeAliases.js'\nimport { BUILT_IN_WIDGETS } from '../CnWidgetGrid/builtInWidgets.js'\nimport { getWidgetTypeEntry } from '../CnWidgetGrid/dashboardWidgetRegistry.js'\n\n// Populate the dashboard catalog (stat, table, people, …): an index page\n// may be the first surface that resolves a widget type.\nimport '../CnWidgetGrid/registerDashboardWidgets.js'\n\nexport default {\n\tname: 'CnIndexPageWidgets',\n\n\tcomponents: {\n\t\tCnKpiGrid,\n\t\tCnWidgetWrapper,\n\t},\n\n\tinject: {\n\t\t/** Consumer widget registry provided by CnAppRoot (custom over built-in). */\n\t\tcnRegistry: { default: () => ({}) },\n\t\t/** Host translate function provided by CnAppRoot. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Widget definitions `{ id, type, title?, content?, headerLink? }`.\n\t\t * An entry without an id or with a type no layer resolves is skipped.\n\t\t */\n\t\twidgets: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Where the widgets sit: `stat-row` above the list, `side-panel` beside it. */\n\t\tvariant: {\n\t\t\ttype: String,\n\t\t\tdefault: 'stat-row',\n\t\t\tvalidator: (v) => ['stat-row', 'side-panel'].includes(v),\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The renderable entries, in the listed order.\n\t\t *\n\t\t * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-stat-row-above-the-list\n\t\t * @return {Array<{id: string, title: string, content: object, headerLink: (object|null), renderer: object}>}\n\t\t */\n\t\tentries() {\n\t\t\tconst list = Array.isArray(this.widgets) ? this.widgets : []\n\t\t\tconst out = []\n\t\t\tfor (const def of list) {\n\t\t\t\tif (!def || typeof def.id !== 'string' || def.id === '' || typeof def.type !== 'string') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst renderer = this.resolveRenderer(def.type)\n\t\t\t\tif (!renderer) {\n\t\t\t\t\tif (process.env.NODE_ENV !== 'production') {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.warn(`[CnIndexPage] ${this.variant} widget \"${def.id}\" has type \"${def.type}\", which no widget registry resolves; skipped.`)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key\n\t\t\t\tout.push({\n\t\t\t\t\tid: def.id,\n\t\t\t\t\ttitle: typeof def.title === 'string' && def.title !== '' ? translate(def.title) : '',\n\t\t\t\t\tcontent: (def.content && typeof def.content === 'object') ? def.content : {},\n\t\t\t\t\theaderLink: (def.headerLink && typeof def.headerLink === 'object') ? def.headerLink : null,\n\t\t\t\t\trenderer,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn out\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Resolve a widget type: the consumer registry, then the dashboard\n\t\t * catalog (the type as written, then its alias), then the built-ins.\n\t\t *\n\t\t * @param {string} type The widget type.\n\t\t * @return {object|null} The component, or null.\n\t\t */\n\t\tresolveRenderer(type) {\n\t\t\tconst consumer = (this.cnRegistry || {})[type]\n\t\t\tif (consumer) {\n\t\t\t\treturn consumer.component ?? consumer\n\t\t\t}\n\t\t\tconst entry = getWidgetTypeEntry(type) || getWidgetTypeEntry(canonicalWidgetType(type))\n\t\t\tif (entry && entry.renderer) {\n\t\t\t\treturn entry.renderer\n\t\t\t}\n\t\t\treturn BUILT_IN_WIDGETS[type] || BUILT_IN_WIDGETS[canonicalWidgetType(type)] || null\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-index-page-widgets--stat-row {\n\tmargin-bottom: var(--cn-board-section-gap, 20px);\n}\n\n.cn-index-page-widgets__cell {\n\tdisplay: flex;\n\tmin-width: 0;\n}\n\n.cn-index-page-widgets__cell > * {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n/* The side panel column (DqTeamwachtrij: 300px, 16px between cards). Its\n place beside the toolbar and the list is set by CnIndexPage\n (`cn-index-page--with-side-panel`, index-page.css). */\n.cn-index-page-widgets--side-panel {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 16px;\n\tmin-width: 0;\n}\n</style>\n"],"names":["CnKpiGrid","CnWidgetWrapper"],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { resolveComponent, openBlock, createBlock, resolveDynamicComponent, normalizeClass, withCtx, createElementBlock, Fragment, renderList, createVNode, mergeProps, createCommentVNode } from 'vue';
|
|
2
|
+
|
|
3
|
+
const _hoisted_1 = ["data-testid"];
|
|
4
|
+
|
|
5
|
+
function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
6
|
+
const _component_CnWidgetWrapper = resolveComponent("CnWidgetWrapper");
|
|
7
|
+
|
|
8
|
+
return ($options.entries.length > 0)
|
|
9
|
+
? (openBlock(), createBlock(resolveDynamicComponent($props.variant === 'stat-row' ? 'CnKpiGrid' : 'aside'), {
|
|
10
|
+
key: 0,
|
|
11
|
+
columns: $props.variant === 'stat-row' ? 'auto' : undefined,
|
|
12
|
+
class: normalizeClass(["cn-index-page-widgets", ['cn-index-page-widgets--' + $props.variant]]),
|
|
13
|
+
"data-testid": 'cn-index-page-' + $props.variant
|
|
14
|
+
}, {
|
|
15
|
+
default: withCtx(() => [
|
|
16
|
+
(openBlock(true), createElementBlock(Fragment, null, renderList($options.entries, (entry) => {
|
|
17
|
+
return (openBlock(), createElementBlock("div", {
|
|
18
|
+
key: entry.id,
|
|
19
|
+
class: "cn-index-page-widgets__cell",
|
|
20
|
+
"data-testid": 'cn-index-page-widget-' + entry.id
|
|
21
|
+
}, [
|
|
22
|
+
createVNode(_component_CnWidgetWrapper, {
|
|
23
|
+
widgetId: entry.id,
|
|
24
|
+
title: entry.title,
|
|
25
|
+
showTitle: $props.variant === 'side-panel' && entry.title !== '',
|
|
26
|
+
showActions: false,
|
|
27
|
+
showRefresh: false,
|
|
28
|
+
headerLink: entry.headerLink,
|
|
29
|
+
flush: $props.variant === 'stat-row'
|
|
30
|
+
}, {
|
|
31
|
+
default: withCtx(() => [
|
|
32
|
+
(openBlock(), createBlock(resolveDynamicComponent(entry.renderer), mergeProps({
|
|
33
|
+
widgetId: entry.id,
|
|
34
|
+
content: entry.content
|
|
35
|
+
}, { ref_for: true }, entry.content), null, 16 /* FULL_PROPS */, ["widgetId", "content"]))
|
|
36
|
+
]),
|
|
37
|
+
_: 2 /* DYNAMIC */
|
|
38
|
+
}, 1032 /* PROPS, DYNAMIC_SLOTS */, ["widgetId", "title", "showTitle", "headerLink", "flush"])
|
|
39
|
+
], 8 /* PROPS */, _hoisted_1))
|
|
40
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
41
|
+
]),
|
|
42
|
+
_: 1 /* STABLE */
|
|
43
|
+
}, 8 /* PROPS */, ["columns", "class", "data-testid"]))
|
|
44
|
+
: createCommentVNode("v-if", true)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { render };
|
|
48
|
+
//# sourceMappingURL=CnIndexPageWidgets.vue3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CnIndexPageWidgets.vue3.js","sources":["../../../../src/components/CnIndexPage/CnIndexPageWidgets.vue?vue&type=template&id=5ec0c5bc&lang.js"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n\n CnIndexPageWidgets — the widgets an index page draws around its list\n (screens-index-stat-row): the KPI tiles above it (`statRow`, an auto-fit row)\n and the cards beside it (`sidePanel`, a column). Each entry is a dashboard\n widget definition `{ id, type, title?, content, headerLink? }`, resolved like\n a dashboard widget: the app's registry, then the dashboard catalog, then the\n built-in widgets. Internal to CnIndexPage.\n-->\n<template>\n\t<component\n\t\t:is=\"variant === 'stat-row' ? 'CnKpiGrid' : 'aside'\"\n\t\tv-if=\"entries.length > 0\"\n\t\t:columns=\"variant === 'stat-row' ? 'auto' : undefined\"\n\t\tclass=\"cn-index-page-widgets\"\n\t\t:class=\"['cn-index-page-widgets--' + variant]\"\n\t\t:data-testid=\"'cn-index-page-' + variant\">\n\t\t<div\n\t\t\tv-for=\"entry in entries\"\n\t\t\t:key=\"entry.id\"\n\t\t\tclass=\"cn-index-page-widgets__cell\"\n\t\t\t:data-testid=\"'cn-index-page-widget-' + entry.id\">\n\t\t\t<CnWidgetWrapper\n\t\t\t\t:widgetId=\"entry.id\"\n\t\t\t\t:title=\"entry.title\"\n\t\t\t\t:showTitle=\"variant === 'side-panel' && entry.title !== ''\"\n\t\t\t\t:showActions=\"false\"\n\t\t\t\t:showRefresh=\"false\"\n\t\t\t\t:headerLink=\"entry.headerLink\"\n\t\t\t\t:flush=\"variant === 'stat-row'\">\n\t\t\t\t<component\n\t\t\t\t\t:is=\"entry.renderer\"\n\t\t\t\t\t:widgetId=\"entry.id\"\n\t\t\t\t\t:content=\"entry.content\"\n\t\t\t\t\tv-bind=\"entry.content\" />\n\t\t\t</CnWidgetWrapper>\n\t\t</div>\n\t</component>\n</template>\n\n<script>\nimport CnKpiGrid from '../CnKpiGrid/CnKpiGrid.vue'\nimport CnWidgetWrapper from '../CnWidgetWrapper/CnWidgetWrapper.vue'\nimport { canonicalWidgetType } from '../../utils/widgetTypeAliases.js'\nimport { BUILT_IN_WIDGETS } from '../CnWidgetGrid/builtInWidgets.js'\nimport { getWidgetTypeEntry } from '../CnWidgetGrid/dashboardWidgetRegistry.js'\n\n// Populate the dashboard catalog (stat, table, people, …): an index page\n// may be the first surface that resolves a widget type.\nimport '../CnWidgetGrid/registerDashboardWidgets.js'\n\nexport default {\n\tname: 'CnIndexPageWidgets',\n\n\tcomponents: {\n\t\tCnKpiGrid,\n\t\tCnWidgetWrapper,\n\t},\n\n\tinject: {\n\t\t/** Consumer widget registry provided by CnAppRoot (custom over built-in). */\n\t\tcnRegistry: { default: () => ({}) },\n\t\t/** Host translate function provided by CnAppRoot. */\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * Widget definitions `{ id, type, title?, content?, headerLink? }`.\n\t\t * An entry without an id or with a type no layer resolves is skipped.\n\t\t */\n\t\twidgets: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Where the widgets sit: `stat-row` above the list, `side-panel` beside it. */\n\t\tvariant: {\n\t\t\ttype: String,\n\t\t\tdefault: 'stat-row',\n\t\t\tvalidator: (v) => ['stat-row', 'side-panel'].includes(v),\n\t\t},\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The renderable entries, in the listed order.\n\t\t *\n\t\t * @spec openspec/changes/screens-index-stat-row/specs/index-page/spec.md#requirement-an-index-page-can-draw-a-stat-row-above-the-list\n\t\t * @return {Array<{id: string, title: string, content: object, headerLink: (object|null), renderer: object}>}\n\t\t */\n\t\tentries() {\n\t\t\tconst list = Array.isArray(this.widgets) ? this.widgets : []\n\t\t\tconst out = []\n\t\t\tfor (const def of list) {\n\t\t\t\tif (!def || typeof def.id !== 'string' || def.id === '' || typeof def.type !== 'string') {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst renderer = this.resolveRenderer(def.type)\n\t\t\t\tif (!renderer) {\n\t\t\t\t\tif (process.env.NODE_ENV !== 'production') {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.warn(`[CnIndexPage] ${this.variant} widget \"${def.id}\" has type \"${def.type}\", which no widget registry resolves; skipped.`)\n\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key\n\t\t\t\tout.push({\n\t\t\t\t\tid: def.id,\n\t\t\t\t\ttitle: typeof def.title === 'string' && def.title !== '' ? translate(def.title) : '',\n\t\t\t\t\tcontent: (def.content && typeof def.content === 'object') ? def.content : {},\n\t\t\t\t\theaderLink: (def.headerLink && typeof def.headerLink === 'object') ? def.headerLink : null,\n\t\t\t\t\trenderer,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn out\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Resolve a widget type: the consumer registry, then the dashboard\n\t\t * catalog (the type as written, then its alias), then the built-ins.\n\t\t *\n\t\t * @param {string} type The widget type.\n\t\t * @return {object|null} The component, or null.\n\t\t */\n\t\tresolveRenderer(type) {\n\t\t\tconst consumer = (this.cnRegistry || {})[type]\n\t\t\tif (consumer) {\n\t\t\t\treturn consumer.component ?? consumer\n\t\t\t}\n\t\t\tconst entry = getWidgetTypeEntry(type) || getWidgetTypeEntry(canonicalWidgetType(type))\n\t\t\tif (entry && entry.renderer) {\n\t\t\t\treturn entry.renderer\n\t\t\t}\n\t\t\treturn BUILT_IN_WIDGETS[type] || BUILT_IN_WIDGETS[canonicalWidgetType(type)] || null\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-index-page-widgets--stat-row {\n\tmargin-bottom: var(--cn-board-section-gap, 20px);\n}\n\n.cn-index-page-widgets__cell {\n\tdisplay: flex;\n\tmin-width: 0;\n}\n\n.cn-index-page-widgets__cell > * {\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n/* The side panel column (DqTeamwachtrij: 300px, 16px between cards). Its\n place beside the toolbar and the list is set by CnIndexPage\n (`cn-index-page--with-side-panel`, index-page.css). */\n.cn-index-page-widgets--side-panel {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 16px;\n\tmin-width: 0;\n}\n</style>\n"],"names":["_normalizeClass"],"mappings":";;;;;;;AAyBQ,EAAA,OAAA,CAAA,QAAA,CAAA,OAAO,CAAC,MAAM,GAAA,CAAA;wDADf,MAAO,CAAA,OAAA,KAAA,UAAA,GAAA,WAAA,GAAA,OAAA,CAAA,EAAA;;QAEV,OAAM,EAAE,MAAO,CAAA,OAAA,KAAA,UAAA,GAAA,MAAA,GAAI,SAAA;aAChB,EAAAA,cAAA,CAAA,CAAC,uBAAuB,EAAA,CAAA,yBAAA,GACR,MAAA,CAAA,OAAA,CAAA,CAAA,CAAA;AACnB,QAAA,aAAU,qBAAS,MAAA,CAAA,OAAA;;+BAEI;0EAAP,QAAM,CAAA,OAAA,EAAA,CAAhB,KAAK,KAAA;;cACX,GAAG,EAAE,KAAI,CAAA,EAAA;AACR,cAAA,KAAG,EAAC,6BAAe;cACnB,aAAU,EAAA,uBAAA,GAAS,KAAA,CAAA,EAAA;;;gBAEnB,QAAQ,EAAE,KAAK,CAAC,EAAE;gBAClB,KAAK,EAAE,KAAK,CAAC,KAAE;AACf,gBAAA,SAAE,EAAA,MAAA,CAAA,OAAA,KAAA,YAAA,IAAA,KAAA,CAAA,KAAA,KAAA,EAAA;AACF,gBAAA,WAAO,EAAA,KAAA;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -14,6 +14,7 @@ import { pageIdForRoute, splitIdForRoute, pageHasSplitView, splitRouteName } fro
|
|
|
14
14
|
import { reportDiagnosticOnce, reportDiagnostic } from '../../utils/diagnostics.js';
|
|
15
15
|
import { openRowTarget } from '../../utils/linkNavigation.js';
|
|
16
16
|
import { listContextFromRoute, listContextToQuery } from '../../utils/listNavigation.js';
|
|
17
|
+
import { matchQueryPreset, applyQueryPreset } from '../../utils/queryPresets.js';
|
|
17
18
|
import { resolveRouteSentinels } from '../../utils/resolveRouteSentinels.js';
|
|
18
19
|
import { parseSortKeys } from '../../utils/routeFilters.js';
|
|
19
20
|
import { routePathFor, buildRouteParams } from '../../utils/routeParams.js';
|
|
@@ -760,7 +761,25 @@ var script = {
|
|
|
760
761
|
return 'none'
|
|
761
762
|
}
|
|
762
763
|
const cfg = (page.config && typeof page.config === 'object' && !Array.isArray(page.config)) ? page.config : {};
|
|
763
|
-
|
|
764
|
+
// A query preset swaps the lenses and columns, so it remounts the
|
|
765
|
+
// page: the active lens index belongs to the lenses it indexes.
|
|
766
|
+
const preset = this.activeQueryPresetIndex >= 0 ? `:preset-${this.activeQueryPresetIndex}` : '';
|
|
767
|
+
return [page.id, cfg.register || '', cfg.schema || ''].join(':') + preset
|
|
768
|
+
},
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* The index of the current index page's query preset that the route
|
|
772
|
+
* query matches, or -1.
|
|
773
|
+
*
|
|
774
|
+
* @return {number}
|
|
775
|
+
* @spec openspec/changes/screens-index-query-presets/specs/index-query-presets/spec.md#requirement-a-query-preset-overlays-lenses-columns-and-copy
|
|
776
|
+
*/
|
|
777
|
+
activeQueryPresetIndex() {
|
|
778
|
+
const page = this.currentPage;
|
|
779
|
+
if (!page || page.type !== 'index' || !page.config || !Array.isArray(page.config.queryPresets)) {
|
|
780
|
+
return -1
|
|
781
|
+
}
|
|
782
|
+
return matchQueryPreset(page.config.queryPresets, this.$route?.query || {})
|
|
764
783
|
},
|
|
765
784
|
|
|
766
785
|
/**
|
|
@@ -1007,6 +1026,15 @@ var script = {
|
|
|
1007
1026
|
// container before forwarding — CnIndexPage has no
|
|
1008
1027
|
// `actionToggles` prop.
|
|
1009
1028
|
const isIndex = page?.type === 'index';
|
|
1029
|
+
// A query preset (`config.queryPresets`): the menu entry's query
|
|
1030
|
+
// brings its own lenses, columns and copy to the same page.
|
|
1031
|
+
if (isIndex && Array.isArray(config.queryPresets)) {
|
|
1032
|
+
const preset = config.queryPresets[this.activeQueryPresetIndex] || null;
|
|
1033
|
+
config = applyQueryPreset(config, preset);
|
|
1034
|
+
if (preset && typeof preset.title === 'string' && preset.title !== '') {
|
|
1035
|
+
topLevel.title = preset.title;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1010
1038
|
// When an index page has somewhere to open a row, make a row click
|
|
1011
1039
|
// go there: set `rowClickToView` so the row body emits `row-click`
|
|
1012
1040
|
// (→ onRowOpen navigates) even though the page is selectable.
|