@conduction/nextcloud-vue 2.127.0 → 2.128.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  2. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +3 -113
  3. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  4. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +12 -12
  5. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  6. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +34 -1
  7. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  8. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +16 -8
  9. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  10. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +153 -8
  11. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  12. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +169 -58
  13. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  14. package/dist/esm/components/CnTileWidget/CnTileWidget.vue.js +1 -1
  15. package/dist/esm/components/CnTileWidget/CnTileWidget.vue2.js +11 -0
  16. package/dist/esm/components/CnTileWidget/CnTileWidget.vue2.js.map +1 -1
  17. package/dist/esm/components/CnTileWidget/CnTileWidget.vue3.js +14 -4
  18. package/dist/esm/components/CnTileWidget/CnTileWidget.vue3.js.map +1 -1
  19. package/dist/esm/library-style.js +1 -1
  20. package/dist/esm/mixins/pageFilters.js +142 -0
  21. package/dist/esm/mixins/pageFilters.js.map +1 -0
  22. package/dist/esm/nextcloud-vue.css +269 -74
  23. package/dist/esm/utils/actionLink.js +9 -3
  24. package/dist/esm/utils/actionLink.js.map +1 -1
  25. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  26. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  27. package/dist/nextcloud-vue.cjs.js +1176 -828
  28. package/dist/nextcloud-vue.cjs.js.map +2 -2
  29. package/dist/nextcloud-vue.css +269 -74
  30. package/package.json +1 -1
  31. package/src/components/CnDashboardPage/CnDashboardPage.vue +3 -113
  32. package/src/components/CnDataTable/CnDataTable.vue +40 -1
  33. package/src/components/CnDetailPage/CnDetailPage.md +2 -0
  34. package/src/components/CnDetailPage/CnDetailPage.vue +237 -8
  35. package/src/components/CnTileWidget/CnTileWidget.vue +30 -2
  36. package/src/css/detail-page.css +42 -0
  37. package/src/css/dialog.css +13 -0
  38. package/src/css/look-board-detail.css +1 -1
  39. package/src/css/look-board-index.css +8 -0
  40. package/src/css/look-board.css +97 -0
  41. package/src/css/table.css +12 -0
  42. package/src/mixins/pageFilters.js +138 -0
  43. package/src/schemas/app-manifest-v2.schema.json +41 -3
  44. package/src/utils/actionLink.js +9 -3
  45. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -0,0 +1,142 @@
1
+ import { isOptionsFrom, loadOptionsFrom } from '../utils/optionsFrom.js';
2
+ import { generatedPageFilterOptions } from '../utils/periodOptions.js';
3
+
4
+ /**
5
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
6
+ * SPDX-License-Identifier: EUPL-1.2
7
+ */
8
+
9
+
10
+ /**
11
+ * Page-level filters (manifest `config.pageFilters`), shared by CnDashboardPage
12
+ * and CnDetailPage: seeding each filter's value, reading its options and
13
+ * writing a choice into the page's workspace context, where a widget reads it
14
+ * through `@page.<key>` / `@workspace.<key>`.
15
+ *
16
+ * The host provides `pageFilters` (the declared filters), `workspaceContext`
17
+ * (the reactive bag it provides as `cnWorkspaceContext`) and
18
+ * `effectiveTranslate` (the host app's translate).
19
+ *
20
+ * @spec openspec/changes/detail-page-filters/specs/detail-page/spec.md#requirement-a-detail-page-can-draw-page-filters-that-its-widgets-read
21
+ */
22
+ const pageFilters = {
23
+ data() {
24
+ return {
25
+ /** Options read through a page filter's `optionsFrom`, by filter key. */
26
+ pageFilterFetched: {},
27
+ /** Whether a page filter's `optionsFrom` read is in flight, by filter key. */
28
+ pageFilterLoading: {},
29
+ }
30
+ },
31
+
32
+ methods: {
33
+ /**
34
+ * Seed the reactive workspace context with each page filter's default
35
+ * (its `default`, else the first option's value) so endpoint-bound
36
+ * widgets have a value to interpolate on first render. Only writes keys
37
+ * that aren't already present, so a value another widget set survives.
38
+ *
39
+ * @return {void}
40
+ */
41
+ initPageFilters() {
42
+ for (const pf of this.pageFilters || []) {
43
+ if (!pf || !pf.key) {
44
+ continue
45
+ }
46
+ if (this.workspaceContext[pf.key] !== undefined) {
47
+ continue
48
+ }
49
+ const listed = Array.isArray(pf.options) ? pf.options : generatedPageFilterOptions(pf);
50
+ const fallback = (listed && listed.length && pf.clearable !== true) ? listed[0].value : undefined;
51
+ const value = pf.default !== undefined ? pf.default : fallback;
52
+ if (value !== undefined) {
53
+ this.workspaceContext[pf.key] = value;
54
+ }
55
+ }
56
+ },
57
+
58
+ /**
59
+ * The currently-selected option object for a page filter's NcSelect
60
+ * (matched by `value` against the workspace context), or null.
61
+ *
62
+ * @param {object} pf The page-filter descriptor.
63
+ * @return {object|null}
64
+ */
65
+ selectedPageFilterOption(pf) {
66
+ if (!pf || !pf.key) {
67
+ return null
68
+ }
69
+ const current = this.workspaceContext[pf.key];
70
+ return this.pageFilterSegments(pf).find((o) => o.value === current) || null
71
+ },
72
+
73
+ /**
74
+ * A page filter's options, labels through the host translate: the
75
+ * segments of a segmented filter and the options of a select.
76
+ *
77
+ * @spec openspec/changes/dashboard-board-termijnen/specs/dashboard-page/spec.md#requirement-a-page-filter-as-a-segmented-group-on-the-description-line
78
+ * @param {object} pf The page-filter descriptor.
79
+ * @return {Array<{value: (string|number), label: string}>}
80
+ */
81
+ pageFilterSegments(pf) {
82
+ const options = Array.isArray(pf.options) ? pf.options : (generatedPageFilterOptions(pf) || this.pageFilterFetched[pf.key] || []);
83
+ return options.map((o) => ({ value: o.value, label: o.label ? this.effectiveTranslate(o.label) : String(o.value) }))
84
+ },
85
+
86
+ /**
87
+ * Read the options of every page filter with `optionsFrom`, then seed
88
+ * a filter that is not clearable with its first option when it has no
89
+ * value yet.
90
+ *
91
+ * @spec openspec/changes/page-filter-options-from/specs/dashboard-page/spec.md#requirement-a-page-filter-can-read-its-options
92
+ * @return {Promise<void>}
93
+ */
94
+ async loadPageFilterOptions() {
95
+ const ctx = { workspace: this.workspaceContext || {} };
96
+ await Promise.all((this.pageFilters || [])
97
+ .filter((pf) => pf && pf.key && !Array.isArray(pf.options) && pf.optionsFrom && typeof pf.optionsFrom === 'object')
98
+ .map(async (pf) => {
99
+ const from = pf.optionsFrom;
100
+ if (!isOptionsFrom(from)) {
101
+ return
102
+ }
103
+ this.pageFilterLoading = { ...this.pageFilterLoading, [pf.key]: true };
104
+ let options;
105
+ try {
106
+ options = (await loadOptionsFrom(from, ctx)).map((o) => ({ value: o.id, label: o.label }));
107
+ } catch {
108
+ options = [];
109
+ }
110
+ this.pageFilterFetched = { ...this.pageFilterFetched, [pf.key]: options };
111
+ this.pageFilterLoading = { ...this.pageFilterLoading, [pf.key]: false };
112
+ if (pf.clearable !== true && pf.default === undefined && this.workspaceContext[pf.key] === undefined && options.length > 0) {
113
+ this.workspaceContext[pf.key] = options[0].value;
114
+ }
115
+ }));
116
+ },
117
+
118
+ /**
119
+ * Write a page filter's new selection into the reactive workspace
120
+ * context so every `@page.<key>` / `@workspace.<key>` token re-resolves.
121
+ *
122
+ * @param {object} pf The page-filter descriptor.
123
+ * @param {object|null} option The chosen NcSelect option (`{ value, label }`).
124
+ * @return {void}
125
+ */
126
+ onPageFilterChange(pf, option) {
127
+ if (!pf || !pf.key) {
128
+ return
129
+ }
130
+ const value = option && typeof option === 'object' ? option.value : (option ?? null);
131
+ this.workspaceContext[pf.key] = value;
132
+ /**
133
+ * @event page-filter-change Emitted when a page-level filter selection changes.
134
+ * @type {{ key: string, value: (string|number|null) }}
135
+ */
136
+ this.$emit('page-filter-change', { key: pf.key, value });
137
+ },
138
+ },
139
+ };
140
+
141
+ export { pageFilters };
142
+ //# sourceMappingURL=pageFilters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pageFilters.js","sources":["../../../src/mixins/pageFilters.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n */\n\nimport { isOptionsFrom, loadOptionsFrom } from '../utils/optionsFrom.js'\nimport { generatedPageFilterOptions } from '../utils/periodOptions.js'\n\n/**\n * Page-level filters (manifest `config.pageFilters`), shared by CnDashboardPage\n * and CnDetailPage: seeding each filter's value, reading its options and\n * writing a choice into the page's workspace context, where a widget reads it\n * through `@page.<key>` / `@workspace.<key>`.\n *\n * The host provides `pageFilters` (the declared filters), `workspaceContext`\n * (the reactive bag it provides as `cnWorkspaceContext`) and\n * `effectiveTranslate` (the host app's translate).\n *\n * @spec openspec/changes/detail-page-filters/specs/detail-page/spec.md#requirement-a-detail-page-can-draw-page-filters-that-its-widgets-read\n */\nexport const pageFilters = {\n\tdata() {\n\t\treturn {\n\t\t\t/** Options read through a page filter's `optionsFrom`, by filter key. */\n\t\t\tpageFilterFetched: {},\n\t\t\t/** Whether a page filter's `optionsFrom` read is in flight, by filter key. */\n\t\t\tpageFilterLoading: {},\n\t\t}\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Seed the reactive workspace context with each page filter's default\n\t\t * (its `default`, else the first option's value) so endpoint-bound\n\t\t * widgets have a value to interpolate on first render. Only writes keys\n\t\t * that aren't already present, so a value another widget set survives.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tinitPageFilters() {\n\t\t\tfor (const pf of this.pageFilters || []) {\n\t\t\t\tif (!pf || !pf.key) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif (this.workspaceContext[pf.key] !== undefined) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tconst listed = Array.isArray(pf.options) ? pf.options : generatedPageFilterOptions(pf)\n\t\t\t\tconst fallback = (listed && listed.length && pf.clearable !== true) ? listed[0].value : undefined\n\t\t\t\tconst value = pf.default !== undefined ? pf.default : fallback\n\t\t\t\tif (value !== undefined) {\n\t\t\t\t\tthis.workspaceContext[pf.key] = value\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The currently-selected option object for a page filter's NcSelect\n\t\t * (matched by `value` against the workspace context), or null.\n\t\t *\n\t\t * @param {object} pf The page-filter descriptor.\n\t\t * @return {object|null}\n\t\t */\n\t\tselectedPageFilterOption(pf) {\n\t\t\tif (!pf || !pf.key) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst current = this.workspaceContext[pf.key]\n\t\t\treturn this.pageFilterSegments(pf).find((o) => o.value === current) || null\n\t\t},\n\n\t\t/**\n\t\t * A page filter's options, labels through the host translate: the\n\t\t * segments of a segmented filter and the options of a select.\n\t\t *\n\t\t * @spec openspec/changes/dashboard-board-termijnen/specs/dashboard-page/spec.md#requirement-a-page-filter-as-a-segmented-group-on-the-description-line\n\t\t * @param {object} pf The page-filter descriptor.\n\t\t * @return {Array<{value: (string|number), label: string}>}\n\t\t */\n\t\tpageFilterSegments(pf) {\n\t\t\tconst options = Array.isArray(pf.options) ? pf.options : (generatedPageFilterOptions(pf) || this.pageFilterFetched[pf.key] || [])\n\t\t\treturn options.map((o) => ({ value: o.value, label: o.label ? this.effectiveTranslate(o.label) : String(o.value) }))\n\t\t},\n\n\t\t/**\n\t\t * Read the options of every page filter with `optionsFrom`, then seed\n\t\t * a filter that is not clearable with its first option when it has no\n\t\t * value yet.\n\t\t *\n\t\t * @spec openspec/changes/page-filter-options-from/specs/dashboard-page/spec.md#requirement-a-page-filter-can-read-its-options\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync loadPageFilterOptions() {\n\t\t\tconst ctx = { workspace: this.workspaceContext || {} }\n\t\t\tawait Promise.all((this.pageFilters || [])\n\t\t\t\t.filter((pf) => pf && pf.key && !Array.isArray(pf.options) && pf.optionsFrom && typeof pf.optionsFrom === 'object')\n\t\t\t\t.map(async (pf) => {\n\t\t\t\t\tconst from = pf.optionsFrom\n\t\t\t\t\tif (!isOptionsFrom(from)) {\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tthis.pageFilterLoading = { ...this.pageFilterLoading, [pf.key]: true }\n\t\t\t\t\tlet options\n\t\t\t\t\ttry {\n\t\t\t\t\t\toptions = (await loadOptionsFrom(from, ctx)).map((o) => ({ value: o.id, label: o.label }))\n\t\t\t\t\t} catch {\n\t\t\t\t\t\toptions = []\n\t\t\t\t\t}\n\t\t\t\t\tthis.pageFilterFetched = { ...this.pageFilterFetched, [pf.key]: options }\n\t\t\t\t\tthis.pageFilterLoading = { ...this.pageFilterLoading, [pf.key]: false }\n\t\t\t\t\tif (pf.clearable !== true && pf.default === undefined && this.workspaceContext[pf.key] === undefined && options.length > 0) {\n\t\t\t\t\t\tthis.workspaceContext[pf.key] = options[0].value\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t},\n\n\t\t/**\n\t\t * Write a page filter's new selection into the reactive workspace\n\t\t * context so every `@page.<key>` / `@workspace.<key>` token re-resolves.\n\t\t *\n\t\t * @param {object} pf The page-filter descriptor.\n\t\t * @param {object|null} option The chosen NcSelect option (`{ value, label }`).\n\t\t * @return {void}\n\t\t */\n\t\tonPageFilterChange(pf, option) {\n\t\t\tif (!pf || !pf.key) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst value = option && typeof option === 'object' ? option.value : (option ?? null)\n\t\t\tthis.workspaceContext[pf.key] = value\n\t\t\t/**\n\t\t\t * @event page-filter-change Emitted when a page-level filter selection changes.\n\t\t\t * @type {{ key: string, value: (string|number|null) }}\n\t\t\t */\n\t\t\tthis.$emit('page-filter-change', { key: pf.key, value })\n\t\t},\n\t},\n}\n"],"names":[],"mappings":"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"}