@conduction/nextcloud-vue 2.93.0 → 2.95.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/CnActionsMenu/CnActionsMenu.vue2.js +1 -1
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js +2 -1
- package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +28 -8
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +37 -2
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +46 -28
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +17 -10
- package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue2.js.map +1 -1
- package/dist/esm/components/CnBrandBar/CnBrandBar.vue3.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +139 -3
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js +60 -12
- package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +91 -36
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +115 -72
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +32 -3
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +7 -7
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +56 -16
- 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/CnDeviceFramesWidget/CnDeviceFramesWidget.vue.js +9 -0
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue.js.map +1 -0
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue2.js +240 -0
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue3.js +65 -0
- package/dist/esm/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnDeviceFramesWidget/index.js +30 -0
- package/dist/esm/components/CnDeviceFramesWidget/index.js.map +1 -0
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +17 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +30 -31
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderSearchLabel/CnHeaderSearchLabel.vue.js +6 -0
- package/dist/esm/components/CnHeaderSearchLabel/CnHeaderSearchLabel.vue.js.map +1 -0
- package/dist/esm/components/CnHeaderSearchLabel/CnHeaderSearchLabel.vue2.js +90 -0
- package/dist/esm/components/CnHeaderSearchLabel/CnHeaderSearchLabel.vue2.js.map +1 -0
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +141 -7
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +5 -2
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue.js +8 -0
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue.js.map +1 -0
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js +114 -0
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js.map +1 -0
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue3.js +45 -0
- package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue3.js.map +1 -0
- package/dist/esm/components/CnPageHeader/CnPageHeader.vue2.js +38 -2
- package/dist/esm/components/CnPageHeader/CnPageHeader.vue2.js.map +1 -1
- package/dist/esm/components/CnPageHeader/CnPageHeader.vue3.js +12 -2
- package/dist/esm/components/CnPageHeader/CnPageHeader.vue3.js.map +1 -1
- package/dist/esm/components/CnPagination/CnPagination.vue2.js.map +1 -1
- package/dist/esm/components/CnPagination/CnPagination.vue3.js +56 -51
- package/dist/esm/components/CnPagination/CnPagination.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +51 -4
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +20 -2
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +230 -25
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +447 -221
- package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +24 -0
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js +3 -1
- package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue2.js +39 -2
- package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +85 -8
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +37 -9
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -3
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +20 -0
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +31 -20
- package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +9 -0
- package/dist/esm/composables/indexSources.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 +18 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +18 -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 +712 -330
- package/dist/esm/utils/dueText.js +49 -8
- package/dist/esm/utils/dueText.js.map +1 -1
- package/dist/esm/utils/libraryWidgetKeys.js +1 -0
- package/dist/esm/utils/libraryWidgetKeys.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/nextcloud-vue.cjs.js +8275 -6302
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +712 -330
- package/l10n/en.json +18 -1
- package/l10n/nl.json +18 -1
- package/package.json +1 -1
- package/src/components/CnActionsMenu/CnActionsMenu.vue +3 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +39 -1
- package/src/components/CnAppRoot/CnAppRoot.vue +20 -0
- package/src/components/CnBrandBar/CnBrandBar.vue +5 -4
- package/src/components/CnCountdownWidget/CnCountdownWidget.vue +222 -6
- package/src/components/CnDashboardPage/CnDashboardPage.vue +96 -2
- package/src/components/CnDataTable/CnDataTable.md +1 -0
- package/src/components/CnDataTable/CnDataTable.vue +39 -10
- package/src/components/CnDetailPage/CnDetailPage.vue +55 -15
- package/src/components/CnDeviceFramesWidget/CnDeviceFramesWidget.vue +360 -0
- package/src/components/CnDeviceFramesWidget/index.js +29 -0
- package/src/components/CnFactsWidget/CnFactsWidget.vue +46 -2
- package/src/components/CnHeaderSearchLabel/CnHeaderSearchLabel.vue +107 -0
- package/src/components/CnIndexPage/CnIndexPage.vue +144 -7
- package/src/components/CnPageHeader/CnHeaderTrail.vue +140 -0
- package/src/components/CnPageHeader/CnPageHeader.md +11 -0
- package/src/components/CnPageHeader/CnPageHeader.vue +42 -0
- package/src/components/CnPagination/CnPagination.vue +10 -2
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +84 -4
- package/src/components/CnRegisterMapping/CnRegisterMapping.md +10 -0
- package/src/components/CnRegisterMapping/CnRegisterMapping.vue +511 -28
- package/src/components/CnSettingsPage/CnSettingsPage.vue +26 -0
- package/src/components/CnTabs/CnTabs.vue +39 -2
- package/src/components/CnTabsWidget/CnTabsWidget.vue +106 -13
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +4 -3
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +8 -0
- package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +31 -2
- package/src/components/index.js +1 -0
- package/src/composables/indexSources.js +9 -0
- package/src/css/dialog.css +14 -0
- package/src/css/look-board-index.css +27 -1
- package/src/css/look-board.css +27 -0
- package/src/css/page-header.css +16 -0
- package/src/index.js +1 -0
- package/src/schemas/app-manifest-v2.schema.json +27 -15
- package/src/utils/dueText.js +49 -8
- package/src/utils/libraryWidgetKeys.js +1 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
|
@@ -34,7 +34,29 @@
|
|
|
34
34
|
<!-- @slot title-meta Content on the title's row, right of the title (e.g. a page-wide picker). Fill it from a manifest with `page.slots: { "title-meta": "<RegistryName>" }`. -->
|
|
35
35
|
<slot name="title-meta" />
|
|
36
36
|
</div>
|
|
37
|
-
<
|
|
37
|
+
<CnHeaderTrail
|
|
38
|
+
:breadcrumb="breadcrumb"
|
|
39
|
+
:current="title ? resolvedTitle : ''"
|
|
40
|
+
:meta="headerMeta ? effectiveTranslate(headerMeta) : ''" />
|
|
41
|
+
<!-- `dateRange.placement: "description"`: the segmented period
|
|
42
|
+
group ends the description line ("Week 41 · alle teams ·
|
|
43
|
+
[Deze week | Dit kwartaal | Dit jaar]"). -->
|
|
44
|
+
<div
|
|
45
|
+
v-if="datePeriodInDescription"
|
|
46
|
+
class="cn-dashboard-page__description cn-dashboard-page__description--with-period"
|
|
47
|
+
data-testid="cn-dashboard-page-subtitle">
|
|
48
|
+
<span v-if="subtitleText">{{ subtitleText }}</span>
|
|
49
|
+
<span v-if="subtitleText" aria-hidden="true">·</span>
|
|
50
|
+
<CnSegmentedControl
|
|
51
|
+
size="compact"
|
|
52
|
+
mode="toggle"
|
|
53
|
+
:options="segmentedOptions"
|
|
54
|
+
:modelValue="segmentedValue"
|
|
55
|
+
:ariaLabel="datePeriodLabel"
|
|
56
|
+
data-testid="cn-dashboard-page-date-segmented"
|
|
57
|
+
@update:modelValue="onSegmentPick" />
|
|
58
|
+
</div>
|
|
59
|
+
<p v-else-if="subtitleText" class="cn-dashboard-page__description" data-testid="cn-dashboard-page-subtitle">
|
|
38
60
|
{{ subtitleText }}
|
|
39
61
|
</p>
|
|
40
62
|
</div>
|
|
@@ -185,7 +207,7 @@
|
|
|
185
207
|
handling, persistence, and event emission lives in
|
|
186
208
|
`onDateRangeChange`. -->
|
|
187
209
|
<div
|
|
188
|
-
v-if="showHeaderDateRange"
|
|
210
|
+
v-if="showHeaderDateRange && !datePeriodInDescription"
|
|
189
211
|
class="cn-dashboard-page__date-range"
|
|
190
212
|
:class="{
|
|
191
213
|
'cn-dashboard-page__date-range--pills': dateRangeControl === 'pills',
|
|
@@ -436,6 +458,7 @@
|
|
|
436
458
|
v-else
|
|
437
459
|
:title="getWidgetTitle(item)"
|
|
438
460
|
:eyebrow="getWidgetEyebrow(item)"
|
|
461
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
439
462
|
:showTitle="false"
|
|
440
463
|
:showRefresh="false">
|
|
441
464
|
<div class="cn-dashboard-page__unknown">
|
|
@@ -498,6 +521,7 @@
|
|
|
498
521
|
v-if="missingRequiredApp(item)"
|
|
499
522
|
:title="getWidgetTitle(item)"
|
|
500
523
|
:eyebrow="getWidgetEyebrow(item)"
|
|
524
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
501
525
|
:showTitle="widgetShowTitle(item)">
|
|
502
526
|
<!-- Compact on purpose: a two-row tile is about 150px, less
|
|
503
527
|
a title row. NcEmptyContent's 64px icon, 20px name,
|
|
@@ -537,6 +561,7 @@
|
|
|
537
561
|
:widgetId="item.widgetId"
|
|
538
562
|
:title="getWidgetTitle(item)"
|
|
539
563
|
:eyebrow="getWidgetEyebrow(item)"
|
|
564
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
540
565
|
:iconUrl="getWidgetIconUrl(item)"
|
|
541
566
|
:iconClass="getWidgetIconClass(item)"
|
|
542
567
|
:showTitle="widgetShowTitle(item)"
|
|
@@ -619,6 +644,7 @@
|
|
|
619
644
|
:class="{ 'cn-dashboard-page__chart-fit': isChartFitted(item) }"
|
|
620
645
|
:title="getWidgetTitle(item)"
|
|
621
646
|
:eyebrow="getWidgetEyebrow(item)"
|
|
647
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
622
648
|
:iconUrl="getWidgetIconUrl(item)"
|
|
623
649
|
:iconClass="getWidgetIconClass(item)"
|
|
624
650
|
:showTitle="widgetShowTitle(item)"
|
|
@@ -698,6 +724,7 @@
|
|
|
698
724
|
:widgetId="item.widgetId"
|
|
699
725
|
:title="getWidgetTitle(item)"
|
|
700
726
|
:eyebrow="getWidgetEyebrow(item)"
|
|
727
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
701
728
|
:iconUrl="getWidgetIconUrl(item)"
|
|
702
729
|
:iconClass="getWidgetIconClass(item)"
|
|
703
730
|
:showTitle="widgetShowTitle(item)"
|
|
@@ -726,6 +753,7 @@
|
|
|
726
753
|
:widgetId="item.widgetId"
|
|
727
754
|
:title="getWidgetTitle(item)"
|
|
728
755
|
:eyebrow="getWidgetEyebrow(item)"
|
|
756
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
729
757
|
:iconUrl="getWidgetIconUrl(item)"
|
|
730
758
|
:iconClass="getWidgetIconClass(item)"
|
|
731
759
|
:showTitle="widgetShowTitle(item)"
|
|
@@ -766,6 +794,7 @@
|
|
|
766
794
|
:widgetId="item.widgetId"
|
|
767
795
|
:title="getWidgetTitle(item)"
|
|
768
796
|
:eyebrow="getWidgetEyebrow(item)"
|
|
797
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
769
798
|
:iconUrl="getWidgetIconUrl(item)"
|
|
770
799
|
:iconClass="getWidgetIconClass(item)"
|
|
771
800
|
:showTitle="widgetShowTitle(item)"
|
|
@@ -792,6 +821,7 @@
|
|
|
792
821
|
:widgetId="item.widgetId"
|
|
793
822
|
:title="getWidgetTitle(item)"
|
|
794
823
|
:eyebrow="getWidgetEyebrow(item)"
|
|
824
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
795
825
|
:showTitle="widgetShowTitle(item)"
|
|
796
826
|
:showActions="widgetShowActions(item)"
|
|
797
827
|
:showRefresh="getWidgetShowRefresh(item)"
|
|
@@ -893,6 +923,7 @@
|
|
|
893
923
|
v-else
|
|
894
924
|
:title="getWidgetTitle(item)"
|
|
895
925
|
:eyebrow="getWidgetEyebrow(item)"
|
|
926
|
+
:subtitle="getWidgetSubtitle(item)"
|
|
896
927
|
:showTitle="widgetShowTitle(item)"
|
|
897
928
|
:showRefresh="false">
|
|
898
929
|
<div class="cn-dashboard-page__unknown">
|
|
@@ -972,6 +1003,7 @@ import CnDashboardGrid from '../CnDashboardGrid/CnDashboardGrid.vue'
|
|
|
972
1003
|
import CnDateRangePicker, { DEFAULT_DATE_RANGE_PRESETS, resolvePresetWindow, translatePresetLabel } from '../CnDateRangePicker/CnDateRangePicker.vue'
|
|
973
1004
|
import CnEmptyContent from '../CnEmptyContent/CnEmptyContent.vue'
|
|
974
1005
|
import CnKpiGrid from '../CnKpiGrid/CnKpiGrid.vue'
|
|
1006
|
+
import CnHeaderTrail from '../CnPageHeader/CnHeaderTrail.vue'
|
|
975
1007
|
import CnSegmentedControl from '../CnSegmentedControl/CnSegmentedControl.vue'
|
|
976
1008
|
import CnStatsBlockWidget from '../CnStatsBlockWidget/CnStatsBlockWidget.vue'
|
|
977
1009
|
import CnTileWidget from '../CnTileWidget/CnTileWidget.vue'
|
|
@@ -1115,6 +1147,7 @@ export default {
|
|
|
1115
1147
|
name: 'CnDashboardPage',
|
|
1116
1148
|
|
|
1117
1149
|
components: {
|
|
1150
|
+
CnHeaderTrail,
|
|
1118
1151
|
NcActions,
|
|
1119
1152
|
NcActionButton,
|
|
1120
1153
|
NcActionInput,
|
|
@@ -1214,6 +1247,30 @@ export default {
|
|
|
1214
1247
|
default: '',
|
|
1215
1248
|
},
|
|
1216
1249
|
|
|
1250
|
+
/**
|
|
1251
|
+
* A breadcrumb under the title (manifest `config.breadcrumb`): one
|
|
1252
|
+
* crumb `{ label, route?, params?, href?, icon?, separator? }` or a
|
|
1253
|
+
* list; the title follows as the current crumb. Drawn as the detail
|
|
1254
|
+
* header's breadcrumb row. Null (the default) draws none.
|
|
1255
|
+
*
|
|
1256
|
+
* @type {object|Array<object>|null}
|
|
1257
|
+
* @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-list-dashboard-or-settings-page-can-show-a-breadcrumb-and-a-meta-note
|
|
1258
|
+
*/
|
|
1259
|
+
breadcrumb: {
|
|
1260
|
+
type: [Object, Array],
|
|
1261
|
+
default: null,
|
|
1262
|
+
},
|
|
1263
|
+
|
|
1264
|
+
/**
|
|
1265
|
+
* A note after the breadcrumb and a middle dot (manifest `config.headerMeta`).
|
|
1266
|
+
*
|
|
1267
|
+
* @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-list-dashboard-or-settings-page-can-show-a-breadcrumb-and-a-meta-note
|
|
1268
|
+
*/
|
|
1269
|
+
headerMeta: {
|
|
1270
|
+
type: String,
|
|
1271
|
+
default: '',
|
|
1272
|
+
},
|
|
1273
|
+
|
|
1217
1274
|
/** Page description (shown below title) */
|
|
1218
1275
|
description: {
|
|
1219
1276
|
type: String,
|
|
@@ -2261,6 +2318,20 @@ export default {
|
|
|
2261
2318
|
return this.dateRangeEnabled && this.dateRange.showHeaderPicker !== false
|
|
2262
2319
|
},
|
|
2263
2320
|
|
|
2321
|
+
/**
|
|
2322
|
+
* Whether the segmented period group sits at the end of the
|
|
2323
|
+
* description line (`dateRange.placement: "description"`) instead of
|
|
2324
|
+
* in a row of its own. Only for the segmented control without a
|
|
2325
|
+
* custom range, whose from/to popover keeps the row of its own.
|
|
2326
|
+
*
|
|
2327
|
+
* @return {boolean}
|
|
2328
|
+
* @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-dashboard-can-show-its-period-on-the-description-line
|
|
2329
|
+
*/
|
|
2330
|
+
datePeriodInDescription() {
|
|
2331
|
+
return this.showHeaderDateRange && this.dateRangeControl === 'segmented'
|
|
2332
|
+
&& this.dateRange.placement === 'description' && !this.hasCustomPreset
|
|
2333
|
+
},
|
|
2334
|
+
|
|
2264
2335
|
/**
|
|
2265
2336
|
* The preset list passed to the picker. Falls back to the
|
|
2266
2337
|
* `DEFAULT_DATE_RANGE_PRESETS` constant when the consumer
|
|
@@ -2972,6 +3043,7 @@ export default {
|
|
|
2972
3043
|
widgetId: item.widgetId,
|
|
2973
3044
|
title: this.getWidgetTitle(item),
|
|
2974
3045
|
eyebrow: this.getWidgetEyebrow(item),
|
|
3046
|
+
subtitle: this.getWidgetSubtitle(item),
|
|
2975
3047
|
showTitle: this.widgetShowTitle(item),
|
|
2976
3048
|
showActions: this.widgetShowActions(item),
|
|
2977
3049
|
showRefresh: this.getWidgetShowRefresh(item),
|
|
@@ -4090,6 +4162,20 @@ export default {
|
|
|
4090
4162
|
this.showWidgetConfig = false
|
|
4091
4163
|
},
|
|
4092
4164
|
|
|
4165
|
+
/**
|
|
4166
|
+
* The line under a widget's title (`subtitle` on the widget
|
|
4167
|
+
* definition), translated; empty when it carries none.
|
|
4168
|
+
*
|
|
4169
|
+
* @param {object} item Layout item.
|
|
4170
|
+
* @return {string}
|
|
4171
|
+
* @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-dashboard-widget-card-can-carry-a-line-under-its-title
|
|
4172
|
+
*/
|
|
4173
|
+
getWidgetSubtitle(item) {
|
|
4174
|
+
const def = this.getWidgetDef(item.widgetId)
|
|
4175
|
+
const subtitle = def && typeof def.subtitle === 'string' ? def.subtitle : ''
|
|
4176
|
+
return subtitle ? this.effectiveTranslate(subtitle) : ''
|
|
4177
|
+
},
|
|
4178
|
+
|
|
4093
4179
|
/**
|
|
4094
4180
|
* The line above a widget's title (`eyebrow` on the widget
|
|
4095
4181
|
* definition: "Saldo per week" above "Prognose 13 weken"), through the
|
|
@@ -4903,6 +4989,14 @@ export default {
|
|
|
4903
4989
|
margin-bottom: 16px;
|
|
4904
4990
|
}
|
|
4905
4991
|
|
|
4992
|
+
/* The period group at the end of the description line. */
|
|
4993
|
+
.cn-dashboard-page__description--with-period {
|
|
4994
|
+
align-items: center;
|
|
4995
|
+
display: flex;
|
|
4996
|
+
flex-wrap: wrap;
|
|
4997
|
+
gap: 8px;
|
|
4998
|
+
}
|
|
4999
|
+
|
|
4906
5000
|
.cn-dashboard-page__date-segmented {
|
|
4907
5001
|
display: flex;
|
|
4908
5002
|
align-items: center;
|
|
@@ -198,6 +198,7 @@ export default {
|
|
|
198
198
|
| `rowIndicatorCap` | Number | `3` | How many declared indicators render on the row before the rest move into the row menu, reachable as `indicatorsFor(row).overflow`. |
|
|
199
199
|
| `selectAllLabel` | String | `'Select all rows'` | Accessible name (`aria-label`) for the header select-all checkbox, so screen readers announce a named control (WCAG 4.1.2) |
|
|
200
200
|
| `selectRowLabel` | String | `'Select row'` | Accessible name (`aria-label`) for each per-row select checkbox, so screen readers announce a named control (WCAG 4.1.2) |
|
|
201
|
+
| `showUnread` | Boolean | `true` | Draw an unread record (`@self.unread`) in bold with the unread dot. Off, every row reads alike. CnIndexPage turns it off under the board look unless the page offers the Unread lens. |
|
|
201
202
|
| `rowTitle` | String | `'link'` | Board look only: how the title column draws its title. `link` underlines the title (not its secondary line). `plain` draws it as 15px bold text without an underline over a 13px muted secondary line, as the PqTickets board does; the row stays clickable. The Nextcloud look ignores it. |
|
|
202
203
|
| `hideHeader` | Boolean | `false` | Hide the column-header row (`<thead>`) — for compact dashboard list widgets that want a plain bordered-row list without column labels |
|
|
203
204
|
| `pinnedCount` | Number | `0` | How many data columns are pinned to the start of the table. They, and the selection and icon columns, stay in view when the table scrolls sideways |
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
col.class || '',
|
|
131
131
|
pinClass(leadingCount + colIndex),
|
|
132
132
|
isGrowColumn(col) ? 'cn-table-col--grow' : '',
|
|
133
|
-
colIndex ===
|
|
133
|
+
colIndex === titleColumnIndex ? 'cn-table-head--title' : '',
|
|
134
134
|
]"
|
|
135
135
|
:style="{ ...(col.width ? { width: col.width } : {}), ...pinStyle(leadingCount + colIndex) }"
|
|
136
136
|
:aria-sort="ariaSortFor(col)"
|
|
@@ -259,7 +259,7 @@
|
|
|
259
259
|
<td
|
|
260
260
|
v-for="(col, colIndex) in effectiveColumns"
|
|
261
261
|
:key="col.key"
|
|
262
|
-
:class="[col.class || '', col.cellClass || '', cellClass ? cellClass(row, col) : '', pinClass(leadingCount + colIndex), colIndex ===
|
|
262
|
+
:class="[col.class || '', col.cellClass || '', cellClass ? cellClass(row, col) : '', pinClass(leadingCount + colIndex), colIndex === titleColumnIndex ? 'cn-table-col--title' : '', isGrowColumn(col) ? 'cn-table-col--grow' : '']"
|
|
263
263
|
:style="{ ...(col.width ? { maxWidth: col.width } : {}), ...pinStyle(leadingCount + colIndex) }"
|
|
264
264
|
@mouseenter="titleWhenClipped">
|
|
265
265
|
<!-- A row with a `rowClickRoute` is a real link: this anchor
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
the URL, a middle or ctrl click opens a new tab natively,
|
|
268
268
|
and the row is reachable with Tab. The row's own click
|
|
269
269
|
handlers treat it as a nested control and leave it be. -->
|
|
270
|
-
<a v-if="colIndex ===
|
|
270
|
+
<a v-if="colIndex === titleColumnIndex && rowLinks[String(row[rowKey])]"
|
|
271
271
|
class="cn-table-row__link"
|
|
272
272
|
:href="rowLinks[String(row[rowKey])].href"
|
|
273
273
|
:aria-label="rowLinkLabel(row, col)"
|
|
@@ -281,9 +281,9 @@
|
|
|
281
281
|
the record is locked. It renders nothing when unlocked,
|
|
282
282
|
so an unlocked table is byte-for-byte what it was. -->
|
|
283
283
|
<CnUnreadMarker
|
|
284
|
-
v-if="colIndex ===
|
|
284
|
+
v-if="colIndex === titleColumnIndex && isUnreadRow(row)" />
|
|
285
285
|
<CnLockIndicator
|
|
286
|
-
v-if="colIndex ===
|
|
286
|
+
v-if="colIndex === titleColumnIndex"
|
|
287
287
|
:object="row"
|
|
288
288
|
:size="16" />
|
|
289
289
|
<!-- Declared state indicators ride the first data cell
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
however the record is shaped. Past the cap the rest move
|
|
294
294
|
into the row menu, because a row of nine icons is not a
|
|
295
295
|
row anyone can triage at a glance. -->
|
|
296
|
-
<span v-if="colIndex ===
|
|
296
|
+
<span v-if="colIndex === titleColumnIndex && indicatorsFor(row).shown.length > 0"
|
|
297
297
|
class="cn-table-row-indicators"
|
|
298
298
|
data-testid="cn-row-indicators">
|
|
299
299
|
<span v-for="indicator in indicatorsFor(row).shown"
|
|
@@ -338,7 +338,7 @@
|
|
|
338
338
|
file names it (OpenRegister `@self.matchedFile`): plain text,
|
|
339
339
|
file name only, under the first cell. -->
|
|
340
340
|
<span
|
|
341
|
-
v-if="colIndex ===
|
|
341
|
+
v-if="colIndex === titleColumnIndex && matchedFileOf(row)"
|
|
342
342
|
class="cn-table-cell__secondary cn-table-cell__matched-file"
|
|
343
343
|
data-testid="cn-row-matched-file">{{ matchedFileLabel(row) }}</span>
|
|
344
344
|
</td>
|
|
@@ -532,7 +532,10 @@ export default {
|
|
|
532
532
|
* formats through `fillTemplate`), or a function of the row. Empty fields leave their placeholder blank; a line that
|
|
533
533
|
* resolves to nothing is not drawn.
|
|
534
534
|
*
|
|
535
|
-
*
|
|
535
|
+
* `link: true` makes that column the one that names the row: it carries
|
|
536
|
+
* the row link and the title look. Without it the first column does.
|
|
537
|
+
*
|
|
538
|
+
* @type {Array<{key: string, label: string, description: string, sortable: boolean, width: string, class: string, cellClass: string, link: boolean, secondary: (string|((row: object) => string))}|string>}
|
|
536
539
|
*/
|
|
537
540
|
columns: {
|
|
538
541
|
type: Array,
|
|
@@ -742,6 +745,17 @@ export default {
|
|
|
742
745
|
default: '',
|
|
743
746
|
},
|
|
744
747
|
|
|
748
|
+
/**
|
|
749
|
+
* Draw an unread record (`@self.unread`) in bold with the unread dot.
|
|
750
|
+
* Off, every row reads alike whatever its read state.
|
|
751
|
+
*
|
|
752
|
+
* @spec openspec/changes/screens-index-board-gaps/specs/index-list-board-look/spec.md#requirement-unread-rows-are-marked-only-where-the-reader-asked-for-them
|
|
753
|
+
*/
|
|
754
|
+
showUnread: {
|
|
755
|
+
type: Boolean,
|
|
756
|
+
default: true,
|
|
757
|
+
},
|
|
758
|
+
|
|
745
759
|
/**
|
|
746
760
|
* How the board look draws the title column: `link` (the default) is
|
|
747
761
|
* the 15px weight 600 underlined title of the DqZaken board; `plain` is
|
|
@@ -1045,6 +1059,20 @@ export default {
|
|
|
1045
1059
|
* @return {string|null} The column key, or null when not fitting.
|
|
1046
1060
|
* @spec openspec/changes/narrow-object-table-widgets/specs/narrow-object-table-widgets/spec.md#requirement-a-narrow-object-table-keeps-its-trailing-columns-in-view
|
|
1047
1061
|
*/
|
|
1062
|
+
/**
|
|
1063
|
+
* The column that names the row: it carries the row link, the title
|
|
1064
|
+
* look and the unread, lock and indicator marks. The first column with
|
|
1065
|
+
* `link: true`, else the first column (DqTeamwachtrij puts the waiting
|
|
1066
|
+
* time first and links the case title in the second).
|
|
1067
|
+
*
|
|
1068
|
+
* @return {number} The index in `effectiveColumns`.
|
|
1069
|
+
* @spec openspec/changes/screens-index-board-gaps/specs/index-list-board-look/spec.md#requirement-a-column-can-carry-the-row-link
|
|
1070
|
+
*/
|
|
1071
|
+
titleColumnIndex() {
|
|
1072
|
+
const index = this.effectiveColumns.findIndex((c) => c && c.link === true)
|
|
1073
|
+
return index === -1 ? 0 : index
|
|
1074
|
+
},
|
|
1075
|
+
|
|
1048
1076
|
growColumnKey() {
|
|
1049
1077
|
if (!this.fitWidth || this.effectiveColumns.length === 0) {
|
|
1050
1078
|
return null
|
|
@@ -1365,13 +1393,14 @@ export default {
|
|
|
1365
1393
|
|
|
1366
1394
|
/**
|
|
1367
1395
|
* Whether a row's record changed since the user last looked
|
|
1368
|
-
* (`@self.unread`). A row without the marker
|
|
1396
|
+
* (`@self.unread`), when `showUnread` is on. A row without the marker
|
|
1397
|
+
* renders as it always did.
|
|
1369
1398
|
*
|
|
1370
1399
|
* @param {object} row The row.
|
|
1371
1400
|
* @return {boolean} True when the row is unread.
|
|
1372
1401
|
*/
|
|
1373
1402
|
isUnreadRow(row) {
|
|
1374
|
-
return !!(row && row['@self'] && row['@self'].unread === true)
|
|
1403
|
+
return this.showUnread && !!(row && row['@self'] && row['@self'].unread === true)
|
|
1375
1404
|
},
|
|
1376
1405
|
|
|
1377
1406
|
/**
|
|
@@ -2101,7 +2101,7 @@ export default {
|
|
|
2101
2101
|
default: false,
|
|
2102
2102
|
},
|
|
2103
2103
|
|
|
2104
|
-
/** Label for the header Edit button. Defaults to a translated "Edit". */
|
|
2104
|
+
/** Label for the header Edit button, run through the host translate. Defaults to a translated "Edit". */
|
|
2105
2105
|
editLabel: {
|
|
2106
2106
|
type: String,
|
|
2107
2107
|
default: '',
|
|
@@ -3416,14 +3416,40 @@ export default {
|
|
|
3416
3416
|
|
|
3417
3417
|
/**
|
|
3418
3418
|
* The side column's widget definitions. A string names a widget
|
|
3419
|
-
* declared in `widgets`; an object is a definition of its own.
|
|
3419
|
+
* declared in `widgets`; an object is a definition of its own. A
|
|
3420
|
+
* definition whose `visibleWhen` does not hold for the record (or the
|
|
3421
|
+
* records `visibilityContext` names) is left out, exactly as in the
|
|
3422
|
+
* body grid; edit mode shows them all.
|
|
3420
3423
|
*
|
|
3421
3424
|
* @return {Array<object>} The definitions that resolve, each with an `id`.
|
|
3422
3425
|
* @spec openspec/changes/detail-action-model-and-case-surfaces/specs/detail-action-model/spec.md#requirement-side-column
|
|
3426
|
+
* @spec openspec/changes/detail-side-visible-when/specs/detail-page/spec.md#requirement-a-side-column-widget-shows-only-while-its-visiblewhen-holds
|
|
3423
3427
|
*/
|
|
3424
3428
|
sideColumnWidgets() {
|
|
3429
|
+
const resolved = this.declaredSideWidgets.filter((widget) => this.sideWidgetVisible(widget))
|
|
3430
|
+
if (!this.isBoard) {
|
|
3431
|
+
return resolved
|
|
3432
|
+
}
|
|
3433
|
+
// The board look: the notice first, the History card last.
|
|
3434
|
+
const rank = (widget) => (widget.type === 'banner' ? 0 : isActivityWidget(widget) ? 2 : 1)
|
|
3435
|
+
return resolved
|
|
3436
|
+
.map((widget, index) => ({ widget, index }))
|
|
3437
|
+
.sort((a, b) => (rank(a.widget) - rank(b.widget)) || (a.index - b.index))
|
|
3438
|
+
.map(({ widget }) => widget)
|
|
3439
|
+
},
|
|
3440
|
+
|
|
3441
|
+
/**
|
|
3442
|
+
* The side column's entries resolved to definitions, before any
|
|
3443
|
+
* `visibleWhen` is read: a string names a widget declared in
|
|
3444
|
+
* `widgets`, an object is a definition of its own (given an id when it
|
|
3445
|
+
* has none).
|
|
3446
|
+
*
|
|
3447
|
+
* @return {Array<object>}
|
|
3448
|
+
* @spec openspec/changes/detail-side-visible-when/specs/detail-page/spec.md#requirement-a-side-column-widget-shows-only-while-its-visiblewhen-holds
|
|
3449
|
+
*/
|
|
3450
|
+
declaredSideWidgets() {
|
|
3425
3451
|
const declared = Array.isArray(this.widgets) ? this.widgets : []
|
|
3426
|
-
|
|
3452
|
+
return (Array.isArray(this.sideColumn) ? this.sideColumn : [])
|
|
3427
3453
|
.map((entry, index) => {
|
|
3428
3454
|
if (typeof entry === 'string') {
|
|
3429
3455
|
return declared.find((widget) => widget && widget.id === entry) || null
|
|
@@ -3434,15 +3460,6 @@ export default {
|
|
|
3434
3460
|
return entry.id ? entry : { ...entry, id: `cn-side-${index}` }
|
|
3435
3461
|
})
|
|
3436
3462
|
.filter(Boolean)
|
|
3437
|
-
if (!this.isBoard) {
|
|
3438
|
-
return resolved
|
|
3439
|
-
}
|
|
3440
|
-
// The board look: the notice first, the History card last.
|
|
3441
|
-
const rank = (widget) => (widget.type === 'banner' ? 0 : isActivityWidget(widget) ? 2 : 1)
|
|
3442
|
-
return resolved
|
|
3443
|
-
.map((widget, index) => ({ widget, index }))
|
|
3444
|
-
.sort((a, b) => (rank(a.widget) - rank(b.widget)) || (a.index - b.index))
|
|
3445
|
-
.map(({ widget }) => widget)
|
|
3446
3463
|
},
|
|
3447
3464
|
|
|
3448
3465
|
/**
|
|
@@ -3763,12 +3780,14 @@ export default {
|
|
|
3763
3780
|
},
|
|
3764
3781
|
|
|
3765
3782
|
/**
|
|
3766
|
-
* Label for the header Edit button
|
|
3783
|
+
* Label for the header Edit button: the manifest's `editLabel` through
|
|
3784
|
+
* the host translate, else the library's translated "Edit".
|
|
3767
3785
|
*
|
|
3768
3786
|
* @return {string}
|
|
3787
|
+
* @spec openspec/changes/detail-edit-label-translate/specs/detail-page/spec.md#requirement-the-edit-button-label-follows-the-reader-s-language
|
|
3769
3788
|
*/
|
|
3770
3789
|
editActionLabel() {
|
|
3771
|
-
return this.editLabel
|
|
3790
|
+
return this.editLabel ? this.effectiveTranslate(this.editLabel) : t('nextcloud-vue', 'Edit')
|
|
3772
3791
|
},
|
|
3773
3792
|
|
|
3774
3793
|
/**
|
|
@@ -4022,7 +4041,7 @@ export default {
|
|
|
4022
4041
|
if (!this.widgetVisibilityData || this.visibilityRowsPending) {
|
|
4023
4042
|
return ''
|
|
4024
4043
|
}
|
|
4025
|
-
const defs = [...(this.bodyGridWidgets || []), ...((this.activeView && this.activeView.widgets) || [])]
|
|
4044
|
+
const defs = [...(this.bodyGridWidgets || []), ...((this.activeView && this.activeView.widgets) || []), ...this.declaredSideWidgets]
|
|
4026
4045
|
const remote = defs.filter((def) => def && def.visibleWhen && typeof def.visibleWhen === 'object'
|
|
4027
4046
|
&& !isLocallyDecidableVisibleWhen(def.visibleWhen))
|
|
4028
4047
|
if (remote.length === 0) {
|
|
@@ -5897,6 +5916,27 @@ export default {
|
|
|
5897
5916
|
return compactLayoutRows(drawable)
|
|
5898
5917
|
},
|
|
5899
5918
|
|
|
5919
|
+
/**
|
|
5920
|
+
* Whether a side column widget shows: always in edit mode or without a
|
|
5921
|
+
* `visibleWhen`, else while it holds for the record and the records
|
|
5922
|
+
* `visibilityContext` names, read by the same `detailWidgetVisible` the
|
|
5923
|
+
* body grid uses (local field conditions, `@context.<name>.*`, and the
|
|
5924
|
+
* answers of endpoint and source conditions).
|
|
5925
|
+
*
|
|
5926
|
+
* @param {object} widget A side column widget definition.
|
|
5927
|
+
* @return {boolean}
|
|
5928
|
+
* @spec openspec/changes/detail-side-visible-when/specs/detail-page/spec.md#requirement-a-side-column-widget-shows-only-while-its-visiblewhen-holds
|
|
5929
|
+
*/
|
|
5930
|
+
sideWidgetVisible(widget) {
|
|
5931
|
+
if (this.editingBody || widget.visibleWhen === undefined || widget.visibleWhen === null) {
|
|
5932
|
+
return true
|
|
5933
|
+
}
|
|
5934
|
+
return detailWidgetVisible(widget, this.widgetVisibilityData, {
|
|
5935
|
+
pending: this.visibilityRowsPending,
|
|
5936
|
+
answers: this.widgetConditionAnswers,
|
|
5937
|
+
})
|
|
5938
|
+
},
|
|
5939
|
+
|
|
5900
5940
|
/**
|
|
5901
5941
|
* Whether a layout item has anything to draw, so a grid cell is worth
|
|
5902
5942
|
* spending on it.
|