@conduction/nextcloud-vue 2.64.0 → 2.66.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/CnAppNav/CnAppNav.vue2.js +99 -3
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +23 -7
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js +13 -0
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +2 -1
- package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +125 -4
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +439 -381
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +9 -3
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +1 -1
- package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +142 -26
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +195 -124
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnFkResolveCell/CnFkResolveCell.vue2.js +3 -1
- package/dist/esm/components/CnFkResolveCell/CnFkResolveCell.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +144 -4
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
- package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +84 -11
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +3 -2
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js +11 -0
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js +2 -1
- package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
- 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 +22 -3
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +10 -3
- package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
- package/dist/esm/l10n/en.json.js +3 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +3 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/mixins/pageViews.js +400 -0
- package/dist/esm/mixins/pageViews.js.map +1 -0
- package/dist/esm/nextcloud-vue.css +182 -0
- package/dist/esm/store/useObjectStore.js +118 -33
- package/dist/esm/store/useObjectStore.js.map +1 -1
- package/dist/esm/utils/actionsDispatcher.js +25 -2
- package/dist/esm/utils/actionsDispatcher.js.map +1 -1
- package/dist/esm/utils/columnFilters.js +27 -3
- package/dist/esm/utils/columnFilters.js.map +1 -1
- package/dist/esm/utils/schema.js +40 -2
- package/dist/esm/utils/schema.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +2001 -684
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +182 -0
- package/l10n/en.json +3 -0
- package/l10n/nl.json +3 -0
- package/package.json +1 -1
- package/src/components/CnAppNav/CnAppNav.vue +148 -7
- package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +14 -0
- package/src/components/CnDashboardPage/CnDashboardPage.vue +194 -10
- package/src/components/CnDataTable/CnColumnFilterPopover.vue +11 -5
- package/src/components/CnDetailPage/CnDetailPage.md +5 -1
- package/src/components/CnDetailPage/CnDetailPage.vue +208 -11
- package/src/components/CnFkResolveCell/CnFkResolveCell.vue +3 -1
- package/src/components/CnFormDialog/CnFormDialog.vue +144 -4
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +100 -13
- package/src/components/CnSegmentedControl/CnSegmentedControl.md +1 -1
- package/src/components/CnSegmentedControl/CnSegmentedControl.vue +12 -0
- package/src/components/CnStagesWidget/CnStagesWidget.vue +9 -0
- package/src/components/CnStatWidget/CnStatWidget.vue +33 -5
- package/src/css/detail-page.css +27 -0
- package/src/css/kpi-card.css +47 -0
- package/src/mixins/pageViews.js +396 -0
- package/src/schemas/app-manifest-v2.schema.json +51 -2
- package/src/store/useObjectStore.js +118 -33
- package/src/utils/actionsDispatcher.js +25 -2
- package/src/utils/columnFilters.js +29 -2
- package/src/utils/schema.js +40 -2
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -9,6 +9,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
9
9
|
? (openBlock(), createBlock(_component_NcBreadcrumbs, {
|
|
10
10
|
key: 0,
|
|
11
11
|
"aria-label": $props.ariaLabel,
|
|
12
|
+
rootIcon: $props.rootText ? '' : undefined,
|
|
12
13
|
"data-testid": "cn-breadcrumbs"
|
|
13
14
|
}, {
|
|
14
15
|
default: withCtx(() => [
|
|
@@ -37,7 +38,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
37
38
|
}), 128 /* KEYED_FRAGMENT */))
|
|
38
39
|
]),
|
|
39
40
|
_: 1 /* STABLE */
|
|
40
|
-
}, 8 /* PROPS */, ["aria-label"]))
|
|
41
|
+
}, 8 /* PROPS */, ["aria-label", "rootIcon"]))
|
|
41
42
|
: createCommentVNode("v-if", true)
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnBreadcrumbs.vue3.js","sources":["../../../../src/components/CnBreadcrumbs/CnBreadcrumbs.vue?vue&type=template&id=296fde9b&lang.js"],"sourcesContent":["<!--\n CnBreadcrumbs — declarative breadcrumb trail wrapping NcBreadcrumbs.\n\n Renders a `crumbs` array as NcBreadcrumb entries: every crumb but the\n last navigates via `to` (router target) or `href` (plain anchor); the\n LAST crumb is the current location — rendered without a link target and\n carrying aria-current=\"page\" so assistive tech announces the position\n in the trail. Crumb icons resolve by PascalCase MDI name through the\n shared CnIcon registry, so a home crumb is `{ icon: 'Home', to: … }`\n without the consumer importing an icon component.\n\n NcBreadcrumbs supplies the nav landmark, the chevron separators and the\n responsive collapse of middle crumbs into an overflow menu; this wrapper\n only owns the array-in API and the last-crumb semantics, keeping fleet\n apps from hand-rolling the same v-for.\n-->\n<template>\n\t<NcBreadcrumbs\n\t\tv-if=\"crumbs.length > 0\"\n\t\t:aria-label=\"ariaLabel\"\n\t\tdata-testid=\"cn-breadcrumbs\">\n\t\t<!-- `name` falls back to '' because NcBreadcrumb declares it a REQUIRED\n\t\t String and warns per render on the label-less icon-only crumb. The\n\t\t empty string never shows: NcBreadcrumb prints `name` only for\n\t\t crumbs without an icon slot. -->\n\t\t<NcBreadcrumb\n\t\t\tv-for=\"(crumb, index) in crumbs\"\n\t\t\t:key=\"`${index}-${crumb.label ?? crumb.icon}`\"\n\t\t\t:name=\"crumb.label ?? ''\"\n\t\t\t:to=\"isCurrent(index) ? undefined : crumb.to\"\n\t\t\t:href=\"isCurrent(index) ? undefined : crumb.href\"\n\t\t\t:aria-current=\"isCurrent(index) ? 'page' : undefined\"\n\t\t\t:data-testid=\"`cn-breadcrumbs-crumb-${index}`\">\n\t\t\t<template v-if=\"crumb.icon\" #icon>\n\t\t\t\t<CnIcon :name=\"crumb.icon\" :size=\"20\" />\n\t\t\t</template>\n\t\t</NcBreadcrumb>\n\t</NcBreadcrumbs>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcBreadcrumb, NcBreadcrumbs } from '@nextcloud/vue'\nimport { CnIcon } from '../CnIcon/index.js'\n\n/**\n * CnBreadcrumbs — declarative breadcrumb trail wrapping NcBreadcrumbs.\n *\n * Feed it the whole trail as one `crumbs` array — first entry is the root\n * (typically a Home crumb), last entry is the CURRENT location. Every crumb\n * but the last links via its `to` (router) or `href` (anchor); the last one\n * is rendered unlinked with `aria-current=\"page\"`, per the WAI-ARIA\n * breadcrumb pattern.\n *\n * ```vue\n * <CnBreadcrumbs\n * :crumbs=\"[\n * { icon: 'Home', to: { name: 'SecretList' } },\n * { label: 'Team vault', to: { name: 'SecretListFolder', params: { folderId: '7' } } },\n * { label: 'Production' },\n * ]\" />\n * ```\n */\nexport default {\n\tname: 'CnBreadcrumbs',\n\n\tcomponents: {\n\t\tNcBreadcrumbs,\n\t\tNcBreadcrumb,\n\t\tCnIcon,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The trail, root first, current location LAST. Each crumb:\n\t\t * `{ label, to?, href?, icon? }` — `label` is the visible (already\n\t\t * translated) text, `to` a vue-router target, `href` a plain URL\n\t\t * (use one or the other; both are ignored on the last crumb), and\n\t\t * `icon` a PascalCase MDI name resolved via the CnIcon registry\n\t\t * (register it with `registerIcons()` at boot).\n\t\t *\n\t\t * @type {Array<{label: string, to?: (object|string), href?: string, icon?: string}>}\n\t\t */\n\t\tcrumbs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t\tvalidator: (value) => value.every((crumb) => crumb && typeof crumb === 'object'\n\t\t\t\t&& (typeof crumb.label === 'string' || typeof crumb.icon === 'string')),\n\t\t},\n\n\t\t/**\n\t\t * Accessible name of the breadcrumb nav landmark. Defaults to the\n\t\t * lib's translation of \"Breadcrumbs\"; override per surface when a\n\t\t * page carries more than one trail.\n\t\t */\n\t\tariaLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Breadcrumbs'),\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Whether the crumb at `index` is the trail's last entry — the\n\t\t * current location, which renders unlinked with aria-current.\n\t\t *\n\t\t * @param {number} index Crumb position in `crumbs`.\n\t\t * @return {boolean}\n\t\t */\n\t\tisCurrent(index) {\n\t\t\treturn index === this.crumbs.length - 1\n\t\t},\n\t},\n}\n</script>\n"],"names":[
|
|
1
|
+
{"version":3,"file":"CnBreadcrumbs.vue3.js","sources":["../../../../src/components/CnBreadcrumbs/CnBreadcrumbs.vue?vue&type=template&id=296fde9b&lang.js"],"sourcesContent":["<!--\n CnBreadcrumbs — declarative breadcrumb trail wrapping NcBreadcrumbs.\n\n Renders a `crumbs` array as NcBreadcrumb entries: every crumb but the\n last navigates via `to` (router target) or `href` (plain anchor); the\n LAST crumb is the current location — rendered without a link target and\n carrying aria-current=\"page\" so assistive tech announces the position\n in the trail. Crumb icons resolve by PascalCase MDI name through the\n shared CnIcon registry, so a home crumb is `{ icon: 'Home', to: … }`\n without the consumer importing an icon component.\n\n NcBreadcrumbs supplies the nav landmark, the chevron separators and the\n responsive collapse of middle crumbs into an overflow menu; this wrapper\n only owns the array-in API and the last-crumb semantics, keeping fleet\n apps from hand-rolling the same v-for.\n-->\n<template>\n\t<NcBreadcrumbs\n\t\tv-if=\"crumbs.length > 0\"\n\t\t:aria-label=\"ariaLabel\"\n\t\t:rootIcon=\"rootText ? '' : undefined\"\n\t\tdata-testid=\"cn-breadcrumbs\">\n\t\t<!-- `name` falls back to '' because NcBreadcrumb declares it a REQUIRED\n\t\t String and warns per render on the label-less icon-only crumb. The\n\t\t empty string never shows: NcBreadcrumb prints `name` only for\n\t\t crumbs without an icon slot. -->\n\t\t<NcBreadcrumb\n\t\t\tv-for=\"(crumb, index) in crumbs\"\n\t\t\t:key=\"`${index}-${crumb.label ?? crumb.icon}`\"\n\t\t\t:name=\"crumb.label ?? ''\"\n\t\t\t:to=\"isCurrent(index) ? undefined : crumb.to\"\n\t\t\t:href=\"isCurrent(index) ? undefined : crumb.href\"\n\t\t\t:aria-current=\"isCurrent(index) ? 'page' : undefined\"\n\t\t\t:data-testid=\"`cn-breadcrumbs-crumb-${index}`\">\n\t\t\t<template v-if=\"crumb.icon\" #icon>\n\t\t\t\t<CnIcon :name=\"crumb.icon\" :size=\"20\" />\n\t\t\t</template>\n\t\t</NcBreadcrumb>\n\t</NcBreadcrumbs>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcBreadcrumb, NcBreadcrumbs } from '@nextcloud/vue'\nimport { CnIcon } from '../CnIcon/index.js'\n\n/**\n * CnBreadcrumbs — declarative breadcrumb trail wrapping NcBreadcrumbs.\n *\n * Feed it the whole trail as one `crumbs` array — first entry is the root\n * (typically a Home crumb), last entry is the CURRENT location. Every crumb\n * but the last links via its `to` (router) or `href` (anchor); the last one\n * is rendered unlinked with `aria-current=\"page\"`, per the WAI-ARIA\n * breadcrumb pattern.\n *\n * ```vue\n * <CnBreadcrumbs\n * :crumbs=\"[\n * { icon: 'Home', to: { name: 'SecretList' } },\n * { label: 'Team vault', to: { name: 'SecretListFolder', params: { folderId: '7' } } },\n * { label: 'Production' },\n * ]\" />\n * ```\n */\nexport default {\n\tname: 'CnBreadcrumbs',\n\n\tcomponents: {\n\t\tNcBreadcrumbs,\n\t\tNcBreadcrumb,\n\t\tCnIcon,\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The trail, root first, current location LAST. Each crumb:\n\t\t * `{ label, to?, href?, icon? }` — `label` is the visible (already\n\t\t * translated) text, `to` a vue-router target, `href` a plain URL\n\t\t * (use one or the other; both are ignored on the last crumb), and\n\t\t * `icon` a PascalCase MDI name resolved via the CnIcon registry\n\t\t * (register it with `registerIcons()` at boot).\n\t\t *\n\t\t * @type {Array<{label: string, to?: (object|string), href?: string, icon?: string}>}\n\t\t */\n\t\tcrumbs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t\tvalidator: (value) => value.every((crumb) => crumb && typeof crumb === 'object'\n\t\t\t\t&& (typeof crumb.label === 'string' || typeof crumb.icon === 'string')),\n\t\t},\n\n\t\t/**\n\t\t * Accessible name of the breadcrumb nav landmark. Defaults to the\n\t\t * lib's translation of \"Breadcrumbs\"; override per surface when a\n\t\t * page carries more than one trail.\n\t\t */\n\t\tariaLabel: {\n\t\t\ttype: String,\n\t\t\tdefault: () => t('nextcloud-vue', 'Breadcrumbs'),\n\t\t},\n\n\t\t/**\n\t\t * Draw the FIRST crumb's label as text. NcBreadcrumbs gives the root\n\t\t * crumb a home icon and prints its `label` only as the accessible\n\t\t * name, so \"All cases\" read as a house. Off by default, which keeps\n\t\t * the home icon. A first crumb with its own `icon` keeps that icon.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-declared-breadcrumb-label-shows-as-text\n\t\t */\n\t\trootText: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Whether the crumb at `index` is the trail's last entry — the\n\t\t * current location, which renders unlinked with aria-current.\n\t\t *\n\t\t * @param {number} index Crumb position in `crumbs`.\n\t\t * @return {boolean}\n\t\t */\n\t\tisCurrent(index) {\n\t\t\treturn index === this.crumbs.length - 1\n\t\t},\n\t},\n}\n</script>\n"],"names":[],"mappings":";;;;;;;AAkCQ,EAAA,OAAA,CAAA,MAAA,CAAA,MAAM,CAAC,MAAM,GAAA,CAAA;;;AACjB,QAAA,YAAS,EAAE,MAAS,CAAA,SAAA;QACrB,QAAQ,EAAE,MAAA,CAAA,QAAA,GAAA,EAAA,GAAA,SAAA;AACX,QAAA,aAAW,EAAC,gBAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -13,6 +13,7 @@ import __sfc_main$b from '../CnBuildiqEditButton/CnBuildiqEditButton.vue.js';
|
|
|
13
13
|
import __sfc_main$4 from '../CnChartWidget/CnChartWidget.vue.js';
|
|
14
14
|
import __sfc_main from '../CnDashboardGrid/CnDashboardGrid.vue.js';
|
|
15
15
|
import __sfc_main$8 from '../CnDateRangePicker/CnDateRangePicker.vue.js';
|
|
16
|
+
import __sfc_main$e from '../CnSegmentedControl/CnSegmentedControl.vue.js';
|
|
16
17
|
import __sfc_main$5 from '../CnStatsBlockWidget/CnStatsBlockWidget.vue.js';
|
|
17
18
|
import __sfc_main$3 from '../CnTileWidget/CnTileWidget.vue.js';
|
|
18
19
|
import __sfc_main$6 from '../CnWidgetRefItem/CnWidgetRefItem.vue.js';
|
|
@@ -20,6 +21,7 @@ import __sfc_main$2 from '../CnWidgetRenderer/CnWidgetRenderer.vue.js';
|
|
|
20
21
|
import __sfc_main$1 from '../CnWidgetWrapper/CnWidgetWrapper.vue.js';
|
|
21
22
|
import { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js';
|
|
22
23
|
import { readUserPreference, writeUserPreference } from '../../composables/useUserPreferences.js';
|
|
24
|
+
import { pageViews } from '../../mixins/pageViews.js';
|
|
23
25
|
import { mergeUserLayout, dashboardLayoutKey } from '../../store/plugins/dashboardLayouts.js';
|
|
24
26
|
import { isAppInstalled } from '../../utils/appInstalled.js';
|
|
25
27
|
import { readVisibleWhenValue, compareVisibleWhen } from '../../utils/visibleWhen.js';
|
|
@@ -175,8 +177,11 @@ var script = {
|
|
|
175
177
|
CnBuildiqEditButton: __sfc_main$b,
|
|
176
178
|
CnWidgetStyleEditorModal: __sfc_main$c,
|
|
177
179
|
CnLeafMountHost: __sfc_main$d,
|
|
180
|
+
CnSegmentedControl: __sfc_main$e,
|
|
178
181
|
},
|
|
179
182
|
|
|
183
|
+
mixins: [pageViews],
|
|
184
|
+
|
|
180
185
|
inject: {
|
|
181
186
|
/**
|
|
182
187
|
* Buildiq in-app edit state (ADR-041), provided by CnAppRoot as a ref.
|
|
@@ -249,6 +254,21 @@ var script = {
|
|
|
249
254
|
default: true,
|
|
250
255
|
},
|
|
251
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Whether a widget draws its overflow Actions menu when neither its
|
|
259
|
+
* placement nor its definition says (`showActions`). `false` (manifest
|
|
260
|
+
* `config.showWidgetActions: false`) drops the menu from every such
|
|
261
|
+
* widget, for a dashboard whose widgets carry a header link and
|
|
262
|
+
* nothing else. A widget that sets `showActions: true` keeps its menu.
|
|
263
|
+
* Card widgets have no menu either way.
|
|
264
|
+
*
|
|
265
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-dashboard-can-drop-the-widget-actions-menu
|
|
266
|
+
*/
|
|
267
|
+
showWidgetActions: {
|
|
268
|
+
type: Boolean,
|
|
269
|
+
default: true,
|
|
270
|
+
},
|
|
271
|
+
|
|
252
272
|
/**
|
|
253
273
|
* Widget definitions array. Each widget defines metadata for rendering.
|
|
254
274
|
*
|
|
@@ -1164,6 +1184,89 @@ var script = {
|
|
|
1164
1184
|
return this.layout.length > 0 || this.widgetRefItems.length > 0
|
|
1165
1185
|
},
|
|
1166
1186
|
|
|
1187
|
+
/**
|
|
1188
|
+
* Whether the grid sections render at all: not while loading, not
|
|
1189
|
+
* while the widget predicates settle, not on the empty page and not
|
|
1190
|
+
* on a widget-ref content page.
|
|
1191
|
+
*
|
|
1192
|
+
* @return {boolean}
|
|
1193
|
+
* @spec openspec/changes/view-switch-containers/specs/view-switch-containers/spec.md#requirement-a-page-declares-views-that-each-hold-a-widget-grid
|
|
1194
|
+
*/
|
|
1195
|
+
gridSectionsShown() {
|
|
1196
|
+
if (this.loading || (!this.widgetConditionsSettled && !this.gridEditable)) {
|
|
1197
|
+
return false
|
|
1198
|
+
}
|
|
1199
|
+
if (!this.hasWidgets && !this.hasBodyWidgets && !this.hasViews) {
|
|
1200
|
+
return false
|
|
1201
|
+
}
|
|
1202
|
+
return this.widgetRefItems.length === 0
|
|
1203
|
+
},
|
|
1204
|
+
|
|
1205
|
+
/**
|
|
1206
|
+
* The chosen view's layout as the grid draws it: in live mode the
|
|
1207
|
+
* widgets that would draw nothing leave and the rest close up, as
|
|
1208
|
+
* for the page's own layout.
|
|
1209
|
+
*
|
|
1210
|
+
* @return {Array<object>}
|
|
1211
|
+
* @spec openspec/changes/view-switch-containers/specs/view-switch-containers/spec.md#requirement-a-view-with-nothing-to-draw-says-so
|
|
1212
|
+
*/
|
|
1213
|
+
viewDisplayLayout() {
|
|
1214
|
+
const items = this.activeView ? this.activeView.layout : [];
|
|
1215
|
+
if (this.gridEditable) {
|
|
1216
|
+
return items
|
|
1217
|
+
}
|
|
1218
|
+
const visible = items.filter((item) => !this.isCollapsedWidget(item));
|
|
1219
|
+
return visible.length === items.length ? items : this.compactDisplayLayout(visible)
|
|
1220
|
+
},
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Whether the chosen view has nothing to draw.
|
|
1224
|
+
*
|
|
1225
|
+
* @return {boolean}
|
|
1226
|
+
* @spec openspec/changes/view-switch-containers/specs/view-switch-containers/spec.md#requirement-a-view-with-nothing-to-draw-says-so
|
|
1227
|
+
*/
|
|
1228
|
+
viewIsEmpty() {
|
|
1229
|
+
return this.hasViews && this.viewDisplayLayout.length === 0
|
|
1230
|
+
},
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* The grids this page draws. Without views: the page's own layout,
|
|
1234
|
+
* as it always was. With views: the page's own layout when it has
|
|
1235
|
+
* items, then the chosen view's layout in the region the switch
|
|
1236
|
+
* controls (left out when the view is empty; the empty state takes
|
|
1237
|
+
* the region then).
|
|
1238
|
+
*
|
|
1239
|
+
* @return {Array<{key: string, view: boolean, layout: Array<object>, editable: boolean, attrs: object}>}
|
|
1240
|
+
* @spec openspec/changes/view-switch-containers/specs/view-switch-containers/spec.md#requirement-a-page-declares-views-that-each-hold-a-widget-grid
|
|
1241
|
+
*/
|
|
1242
|
+
gridSections() {
|
|
1243
|
+
if (!this.gridSectionsShown) {
|
|
1244
|
+
return []
|
|
1245
|
+
}
|
|
1246
|
+
const page = { key: 'page', view: false, layout: this.displayLayout, editable: this.gridEditable, attrs: {} };
|
|
1247
|
+
if (!this.hasViews) {
|
|
1248
|
+
return [page]
|
|
1249
|
+
}
|
|
1250
|
+
const sections = this.displayLayout.length > 0 ? [page] : [];
|
|
1251
|
+
if (!this.viewIsEmpty) {
|
|
1252
|
+
sections.push({
|
|
1253
|
+
key: `view-${this.activeViewId}`,
|
|
1254
|
+
view: true,
|
|
1255
|
+
layout: this.viewDisplayLayout,
|
|
1256
|
+
// A user arrangement covers the page's own layout only.
|
|
1257
|
+
editable: this.gridEditable && !this.userLayout,
|
|
1258
|
+
attrs: {
|
|
1259
|
+
id: this.viewRegionId,
|
|
1260
|
+
role: 'region',
|
|
1261
|
+
'aria-label': this.activeView.label,
|
|
1262
|
+
class: 'cn-page-view-region',
|
|
1263
|
+
'data-testid': 'cn-dashboard-page-view-region',
|
|
1264
|
+
},
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
return sections
|
|
1268
|
+
},
|
|
1269
|
+
|
|
1167
1270
|
/**
|
|
1168
1271
|
* The widget settings object handed to CnWidgetStyleEditorModal,
|
|
1169
1272
|
* built from the widget definition currently being configured
|
|
@@ -1294,6 +1397,14 @@ var script = {
|
|
|
1294
1397
|
this.evaluateWidgetConditions();
|
|
1295
1398
|
},
|
|
1296
1399
|
},
|
|
1400
|
+
|
|
1401
|
+
/** A view's widgets carry predicates too. */
|
|
1402
|
+
views: {
|
|
1403
|
+
deep: true,
|
|
1404
|
+
handler() {
|
|
1405
|
+
this.evaluateWidgetConditions();
|
|
1406
|
+
},
|
|
1407
|
+
},
|
|
1297
1408
|
},
|
|
1298
1409
|
|
|
1299
1410
|
created() {
|
|
@@ -2158,7 +2269,8 @@ var script = {
|
|
|
2158
2269
|
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-an-attention-card-says-when-it-could-not-check
|
|
2159
2270
|
*/
|
|
2160
2271
|
async evaluateWidgetConditions() {
|
|
2161
|
-
const
|
|
2272
|
+
const defs = [...(this.widgets || []), ...this.normalizedViews.flatMap((view) => view.widgets)];
|
|
2273
|
+
const conditional = defs.filter((def) => def && def.id && def.type
|
|
2162
2274
|
&& this.widgetDisplayConfig(def).visibleWhen);
|
|
2163
2275
|
// Skip when the CONDITIONAL SET is unchanged: the deep `widgets`
|
|
2164
2276
|
// watch fires on any def edit, but only an added/removed/edited
|
|
@@ -2292,7 +2404,7 @@ var script = {
|
|
|
2292
2404
|
*/
|
|
2293
2405
|
getWidgetDef(widgetId) {
|
|
2294
2406
|
const list = Array.isArray(this.widgets) ? this.widgets : [];
|
|
2295
|
-
return list.find((w) => w && w.id === widgetId) ||
|
|
2407
|
+
return list.find((w) => w && w.id === widgetId) || this.findViewWidget(widgetId)
|
|
2296
2408
|
},
|
|
2297
2409
|
|
|
2298
2410
|
/**
|
|
@@ -2683,11 +2795,20 @@ var script = {
|
|
|
2683
2795
|
* exactly that reason; there is now one rule for every family, so a
|
|
2684
2796
|
* custom slot and a registered widget cannot disagree about it.
|
|
2685
2797
|
*
|
|
2798
|
+
* A greeting header that declares `content.ground: true` sits on the
|
|
2799
|
+
* page ground, so it asks for no card either: one key on the widget
|
|
2800
|
+
* instead of a second one on its placement.
|
|
2801
|
+
*
|
|
2802
|
+
* @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-greeting-can-sit-on-the-page-ground
|
|
2686
2803
|
* @param {object} item the layout placement.
|
|
2687
2804
|
* @return {boolean}
|
|
2688
2805
|
*/
|
|
2689
2806
|
widgetBorderless(item) {
|
|
2690
|
-
|
|
2807
|
+
if (item.borderless === true) {
|
|
2808
|
+
return true
|
|
2809
|
+
}
|
|
2810
|
+
const def = this.getWidgetDef(item.widgetId);
|
|
2811
|
+
return Boolean(def && def.type === 'header' && this.getWidgetContent(item).ground === true)
|
|
2691
2812
|
},
|
|
2692
2813
|
|
|
2693
2814
|
/**
|
|
@@ -2704,7 +2825,7 @@ var script = {
|
|
|
2704
2825
|
const def = this.getWidgetDef(item.widgetId);
|
|
2705
2826
|
const value = item.showActions !== undefined ? item.showActions : def?.showActions;
|
|
2706
2827
|
if (value === undefined || value === null) {
|
|
2707
|
-
return !this.isCardWidget(item)
|
|
2828
|
+
return this.showWidgetActions && !this.isCardWidget(item)
|
|
2708
2829
|
}
|
|
2709
2830
|
return value !== false
|
|
2710
2831
|
},
|