@conduction/nextcloud-vue 2.56.0-beta.7 → 2.56.0-beta.9
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 +169 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
- package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +88 -4
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +38 -25
- package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js +21 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js.map +1 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js +4 -1
- package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +40 -8
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +40 -15
- package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +2 -2
- package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +6 -5
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +3 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js +10 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js.map +1 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js +316 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js.map +1 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js +105 -0
- package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +53 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +22 -5
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnPageRenderer/pageTypes.js +1 -0
- package/dist/esm/components/CnPageRenderer/pageTypes.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
- package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue2.js.map +1 -1
- package/dist/esm/components/CnStorePage/CnStorePage.vue3.js.map +1 -1
- package/dist/esm/components/CnWikiPage/CnWikiPage.vue2.js.map +1 -1
- package/dist/esm/components/CnWikiPage/CnWikiPage.vue3.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +6 -0
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +6 -0
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/nextcloud-vue.css +198 -9
- package/dist/esm/utils/headers.js +28 -2
- package/dist/esm/utils/headers.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 +9162 -8283
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +198 -9
- package/l10n/en.json +6 -0
- package/l10n/nl.json +6 -0
- package/package.json +3 -2
- package/scripts/.jsdoc-baselines.json +1 -0
- package/scripts/manifest-schema-hash.js +41 -0
- package/scripts/record-manifest-schema-hash.js +52 -0
- package/src/components/CnAppNav/CnAppNav.vue +169 -1
- package/src/components/CnBannerWidget/CnBannerWidget.vue +122 -4
- package/src/components/CnBrandStripe/CnBrandStripe.md +16 -0
- package/src/components/CnBrandStripe/CnBrandStripe.vue +58 -5
- package/src/components/CnDashboardPage/CnDashboardPage.vue +40 -8
- package/src/components/CnDataTable/CnDataTable.md +1 -1
- package/src/components/CnDataTable/CnDataTable.vue +42 -17
- package/src/components/CnDetailPage/CnDetailPage.vue +4 -1
- package/src/components/CnHeaderWidget/CnHeaderWidget.vue +3 -1
- package/src/components/CnLinkCardsPage/CnLinkCardsPage.vue +517 -0
- package/src/components/CnLinkCardsPage/index.js +4 -0
- package/src/components/CnObjectSidebar/CnFilesTab.vue +65 -0
- package/src/components/CnPageRenderer/pageTypes.js +1 -0
- package/src/components/CnReportsPage/CnReportsPage.vue +7 -0
- package/src/components/CnStorePage/CnStorePage.vue +7 -0
- package/src/components/CnWikiPage/CnWikiPage.vue +7 -0
- package/src/components/index.js +1 -0
- package/src/css/detail-page.css +10 -2
- package/src/css/table.css +1 -2
- package/src/index.js +7 -0
- package/src/public/index.js +5 -0
- package/src/schemas/app-manifest-v2.schema.json +45 -3
- package/src/types/manifest.d.ts +1 -1
- package/src/utils/headers.js +28 -2
- package/src/utils/validateManifestV2.compiled.js +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/dist/nextcloud-vue.cjs.js.map
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 34658160 bytes
|
|
4
|
+
sha256: 39b2808fa6e91c4a4c4e4dce5008a2efbcbb57754f60422fbac1771331bc070e
|
package/dist/nextcloud-vue.css
CHANGED
|
@@ -325,8 +325,7 @@
|
|
|
325
325
|
outline-offset: -2px;
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
/* Multi-column sort priority badge (1, 2, 3)
|
|
329
|
-
one sort key is active; a single active sort shows the arrow alone. */
|
|
328
|
+
/* Multi-column sort priority badge (1, 2, 3), rendered only when two or more rendered, sortable columns are sorted. */
|
|
330
329
|
.cn-table-sort-badge {
|
|
331
330
|
display: inline-flex;
|
|
332
331
|
align-items: center;
|
|
@@ -2660,9 +2659,17 @@
|
|
|
2660
2659
|
font-weight: 700;
|
|
2661
2660
|
line-height: 1.3;
|
|
2662
2661
|
color: var(--color-main-text);
|
|
2663
|
-
|
|
2662
|
+
/* Two lines, then an ellipsis. One line cut a long case title short on a
|
|
2663
|
+
page with room to spare, and the title is the one thing that says which
|
|
2664
|
+
record this is. The element carries the full text as its `title`, so a
|
|
2665
|
+
title cut after two lines is still reachable. `overflow-wrap` breaks a
|
|
2666
|
+
word longer than the line, which nowrap used to hide. */
|
|
2667
|
+
display: -webkit-box;
|
|
2668
|
+
-webkit-box-orient: vertical;
|
|
2669
|
+
-webkit-line-clamp: 2;
|
|
2670
|
+
line-clamp: 2;
|
|
2664
2671
|
overflow: hidden;
|
|
2665
|
-
|
|
2672
|
+
overflow-wrap: anywhere;
|
|
2666
2673
|
}
|
|
2667
2674
|
|
|
2668
2675
|
.cn-detail-page__subtitle {
|
|
@@ -6352,8 +6359,7 @@ svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
6352
6359
|
outline-offset: -2px;
|
|
6353
6360
|
}
|
|
6354
6361
|
|
|
6355
|
-
/* Multi-column sort priority badge (1, 2, 3)
|
|
6356
|
-
one sort key is active; a single active sort shows the arrow alone. */
|
|
6362
|
+
/* Multi-column sort priority badge (1, 2, 3), rendered only when two or more rendered, sortable columns are sorted. */
|
|
6357
6363
|
.cn-table-sort-badge {
|
|
6358
6364
|
display: inline-flex;
|
|
6359
6365
|
align-items: center;
|
|
@@ -17505,6 +17511,30 @@ to { background-position: -200% 0;
|
|
|
17505
17511
|
color: inherit;
|
|
17506
17512
|
}
|
|
17507
17513
|
|
|
17514
|
+
/* The check failed. Muted text, no fill, no severity colour: it is a note
|
|
17515
|
+
that something is not known, not a warning. */
|
|
17516
|
+
.cn-banner-widget--unchecked[data-v-3531692f] {
|
|
17517
|
+
box-sizing: border-box;
|
|
17518
|
+
margin: 0;
|
|
17519
|
+
padding: 8px 12px;
|
|
17520
|
+
color: var(--color-text-maxcontrast);
|
|
17521
|
+
font-size: 0.9em;
|
|
17522
|
+
cursor: help;
|
|
17523
|
+
}
|
|
17524
|
+
|
|
17525
|
+
/* The reason, for assistive technology; sighted readers get the tooltip. */
|
|
17526
|
+
.cn-banner-widget__unchecked-reason[data-v-3531692f] {
|
|
17527
|
+
position: absolute;
|
|
17528
|
+
width: 1px;
|
|
17529
|
+
height: 1px;
|
|
17530
|
+
margin: -1px;
|
|
17531
|
+
padding: 0;
|
|
17532
|
+
overflow: hidden;
|
|
17533
|
+
clip-path: inset(50%);
|
|
17534
|
+
white-space: nowrap;
|
|
17535
|
+
border: 0;
|
|
17536
|
+
}
|
|
17537
|
+
|
|
17508
17538
|
/* Attention card. The severity edge is an inset shadow, so it takes no width. */
|
|
17509
17539
|
.cn-banner-widget--attention[data-v-3531692f] {
|
|
17510
17540
|
--cn-banner-accent: var(--color-primary-element);
|
|
@@ -31807,6 +31837,13 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
31807
31837
|
.cn-wiki-page__header[data-v-25a3d3cf] {
|
|
31808
31838
|
margin-bottom: 16px;
|
|
31809
31839
|
}
|
|
31840
|
+
|
|
31841
|
+
/* Without a sidebar the title starts at the left edge of the content, under
|
|
31842
|
+
the Nextcloud navigation toggle button (44px wide). Clear it as CnPageHeader
|
|
31843
|
+
does. With a sidebar the tree sits there instead and the title is clear. */
|
|
31844
|
+
.cn-wiki-page:not(.cn-wiki-page--has-sidebar) .cn-wiki-page__header[data-v-25a3d3cf] {
|
|
31845
|
+
padding-inline-start: 56px;
|
|
31846
|
+
}
|
|
31810
31847
|
.cn-wiki-page__title[data-v-25a3d3cf] {
|
|
31811
31848
|
font-size: 1.6em;
|
|
31812
31849
|
margin: 0;
|
|
@@ -31866,6 +31903,13 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
31866
31903
|
.cn-reports-page[data-v-41525752] {
|
|
31867
31904
|
padding: 16px;
|
|
31868
31905
|
}
|
|
31906
|
+
|
|
31907
|
+
/* Clear the Nextcloud navigation toggle button (44px wide, absolutely
|
|
31908
|
+
positioned at the left edge of .app-content) plus 12px breathing room, as
|
|
31909
|
+
CnPageHeader does. Only the header shifts; the body keeps the full width. */
|
|
31910
|
+
.cn-reports-page__header[data-v-41525752] {
|
|
31911
|
+
padding-inline-start: 56px;
|
|
31912
|
+
}
|
|
31869
31913
|
.cn-reports-page__title[data-v-41525752] {
|
|
31870
31914
|
margin: 0 0 4px;
|
|
31871
31915
|
}
|
|
@@ -31922,6 +31966,13 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
31922
31966
|
padding: 16px;
|
|
31923
31967
|
max-width: 1200px;
|
|
31924
31968
|
}
|
|
31969
|
+
|
|
31970
|
+
/* Clear the Nextcloud navigation toggle button (44px wide, absolutely
|
|
31971
|
+
positioned at the left edge of .app-content) plus 12px breathing room, as
|
|
31972
|
+
CnPageHeader does. Only the header shifts; the body keeps the full width. */
|
|
31973
|
+
.cn-store-page__header[data-v-25c8171b] {
|
|
31974
|
+
padding-inline-start: 56px;
|
|
31975
|
+
}
|
|
31925
31976
|
.cn-store-page__heading[data-v-25c8171b] {
|
|
31926
31977
|
display: flex;
|
|
31927
31978
|
flex-wrap: wrap;
|
|
@@ -32005,6 +32056,122 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
32005
32056
|
}
|
|
32006
32057
|
|
|
32007
32058
|
|
|
32059
|
+
.cn-link-cards-page[data-v-2f9a546b] {
|
|
32060
|
+
display: flex;
|
|
32061
|
+
flex-direction: column;
|
|
32062
|
+
gap: calc(6 * var(--default-grid-baseline));
|
|
32063
|
+
padding: calc(5 * var(--default-grid-baseline));
|
|
32064
|
+
}
|
|
32065
|
+
|
|
32066
|
+
/* Clear the Nextcloud navigation toggle button (44px wide, absolutely
|
|
32067
|
+
positioned at the left edge of .app-content) plus 12px breathing room, as
|
|
32068
|
+
CnPageHeader does. Only the header shifts; the cards keep the full width. */
|
|
32069
|
+
.cn-link-cards-page__header[data-v-2f9a546b] {
|
|
32070
|
+
padding-inline-start: 56px;
|
|
32071
|
+
}
|
|
32072
|
+
.cn-link-cards-page__title[data-v-2f9a546b] {
|
|
32073
|
+
margin: 0 0 var(--default-grid-baseline);
|
|
32074
|
+
}
|
|
32075
|
+
.cn-link-cards-page__description[data-v-2f9a546b],
|
|
32076
|
+
.cn-link-cards-page__empty[data-v-2f9a546b] {
|
|
32077
|
+
color: var(--color-text-maxcontrast);
|
|
32078
|
+
margin: 0;
|
|
32079
|
+
max-width: 70ch;
|
|
32080
|
+
}
|
|
32081
|
+
.cn-link-cards-page__group[data-v-2f9a546b] {
|
|
32082
|
+
display: flex;
|
|
32083
|
+
flex-direction: column;
|
|
32084
|
+
gap: calc(3 * var(--default-grid-baseline));
|
|
32085
|
+
}
|
|
32086
|
+
.cn-link-cards-page__caption[data-v-2f9a546b] {
|
|
32087
|
+
color: var(--color-text-maxcontrast);
|
|
32088
|
+
font-size: 0.85em;
|
|
32089
|
+
font-weight: 600;
|
|
32090
|
+
letter-spacing: 0.06em;
|
|
32091
|
+
margin: 0;
|
|
32092
|
+
text-transform: uppercase;
|
|
32093
|
+
}
|
|
32094
|
+
.cn-link-cards-page__grid[data-v-2f9a546b] {
|
|
32095
|
+
display: grid;
|
|
32096
|
+
gap: calc(3 * var(--default-grid-baseline));
|
|
32097
|
+
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
|
32098
|
+
list-style: none;
|
|
32099
|
+
margin: 0;
|
|
32100
|
+
padding: 0;
|
|
32101
|
+
}
|
|
32102
|
+
.cn-link-cards-page__cell[data-v-2f9a546b] {
|
|
32103
|
+
display: flex;
|
|
32104
|
+
}
|
|
32105
|
+
.cn-link-cards-page__card[data-v-2f9a546b] {
|
|
32106
|
+
align-items: flex-start;
|
|
32107
|
+
background: var(--color-main-background);
|
|
32108
|
+
border: 1px solid var(--color-border-dark);
|
|
32109
|
+
border-radius: var(--border-radius-large);
|
|
32110
|
+
color: var(--color-main-text);
|
|
32111
|
+
display: flex;
|
|
32112
|
+
flex: 1;
|
|
32113
|
+
gap: calc(3 * var(--default-grid-baseline));
|
|
32114
|
+
min-width: 0;
|
|
32115
|
+
padding: calc(4 * var(--default-grid-baseline));
|
|
32116
|
+
transition: background-color var(--animation-quick, 100ms) ease, border-color var(--animation-quick, 100ms) ease, box-shadow var(--animation-quick, 100ms) ease;
|
|
32117
|
+
}
|
|
32118
|
+
|
|
32119
|
+
/* A card is a link, and it must not look like a line of prose. A theme may
|
|
32120
|
+
underline every link with `!important` (thematiq: `a { text-decoration:
|
|
32121
|
+
underline !important }`, specificity 0,0,1). Among `!important` rules the
|
|
32122
|
+
higher specificity wins, so this class rule has to carry it too; without it
|
|
32123
|
+
the label and the description both rendered underlined on a live Nextcloud. */
|
|
32124
|
+
.cn-link-cards-page__card[data-v-2f9a546b],
|
|
32125
|
+
.cn-link-cards-page__card[data-v-2f9a546b]:hover,
|
|
32126
|
+
.cn-link-cards-page__card[data-v-2f9a546b]:focus,
|
|
32127
|
+
.cn-link-cards-page__card[data-v-2f9a546b]:active {
|
|
32128
|
+
text-decoration: none !important;
|
|
32129
|
+
}
|
|
32130
|
+
|
|
32131
|
+
/* Hover moves the whole card: border, background and a soft lift. */
|
|
32132
|
+
.cn-link-cards-page__card[data-v-2f9a546b]:hover {
|
|
32133
|
+
background: var(--color-background-hover);
|
|
32134
|
+
border-color: var(--color-primary-element);
|
|
32135
|
+
box-shadow: 0 2px 6px var(--color-box-shadow);
|
|
32136
|
+
}
|
|
32137
|
+
@media (prefers-reduced-motion: reduce) {
|
|
32138
|
+
.cn-link-cards-page__card[data-v-2f9a546b] {
|
|
32139
|
+
transition: none;
|
|
32140
|
+
}
|
|
32141
|
+
}
|
|
32142
|
+
.cn-link-cards-page__card[data-v-2f9a546b]:focus-visible {
|
|
32143
|
+
border-color: var(--color-primary-element);
|
|
32144
|
+
outline: 2px solid var(--color-primary-element);
|
|
32145
|
+
outline-offset: 2px;
|
|
32146
|
+
}
|
|
32147
|
+
.cn-link-cards-page__icon[data-v-2f9a546b] {
|
|
32148
|
+
color: var(--color-primary-element);
|
|
32149
|
+
flex: none;
|
|
32150
|
+
}
|
|
32151
|
+
.cn-link-cards-page__body[data-v-2f9a546b] {
|
|
32152
|
+
display: flex;
|
|
32153
|
+
flex-direction: column;
|
|
32154
|
+
gap: var(--default-grid-baseline);
|
|
32155
|
+
min-width: 0;
|
|
32156
|
+
}
|
|
32157
|
+
|
|
32158
|
+
/* The label is the card's title. Its colour is set here, on the span, because
|
|
32159
|
+
a theme may force its link colour on the `a` itself; an inherited link
|
|
32160
|
+
colour made the title read as a hyperlink. */
|
|
32161
|
+
.cn-link-cards-page__label[data-v-2f9a546b] {
|
|
32162
|
+
color: var(--color-main-text);
|
|
32163
|
+
font-size: 1.05em;
|
|
32164
|
+
font-weight: 700;
|
|
32165
|
+
line-height: 1.3;
|
|
32166
|
+
overflow-wrap: anywhere;
|
|
32167
|
+
}
|
|
32168
|
+
.cn-link-cards-page__card-description[data-v-2f9a546b] {
|
|
32169
|
+
color: var(--color-text-maxcontrast);
|
|
32170
|
+
font-size: 0.9em;
|
|
32171
|
+
line-height: 1.4;
|
|
32172
|
+
}
|
|
32173
|
+
|
|
32174
|
+
|
|
32008
32175
|
/* NcDialog supplies the padding and the heading (via `name`); this div keeps only
|
|
32009
32176
|
the body's own column layout. */
|
|
32010
32177
|
.cn-page-config[data-v-9e9a9cf8] {
|
|
@@ -34218,15 +34385,40 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
34218
34385
|
|
|
34219
34386
|
|
|
34220
34387
|
.cn-brand-stripe[data-v-6fdfa763] {
|
|
34388
|
+
--cn-brand-stripe-first: var(--cn-brand-stripe-ratio-1, 1);
|
|
34389
|
+
--cn-brand-stripe-second: var(--cn-brand-stripe-ratio-2, 1);
|
|
34390
|
+
--cn-brand-stripe-total: calc(
|
|
34391
|
+
var(--cn-brand-stripe-first) + var(--cn-brand-stripe-second) + var(--cn-brand-stripe-ratio-3, 1)
|
|
34392
|
+
);
|
|
34393
|
+
--cn-brand-stripe-stop-1: calc(var(--cn-brand-stripe-first) / var(--cn-brand-stripe-total) * 100%);
|
|
34394
|
+
--cn-brand-stripe-stop-2: calc(
|
|
34395
|
+
(var(--cn-brand-stripe-first) + var(--cn-brand-stripe-second)) / var(--cn-brand-stripe-total) * 100%
|
|
34396
|
+
);
|
|
34397
|
+
--cn-brand-stripe-direction: to right;
|
|
34398
|
+
--cn-brand-stripe-bands: linear-gradient(
|
|
34399
|
+
var(--cn-brand-stripe-direction),
|
|
34400
|
+
var(--cn-brand-stripe-color-1, var(--color-primary-element)) 0 var(--cn-brand-stripe-stop-1),
|
|
34401
|
+
var(--cn-brand-stripe-color-2, var(--color-primary-element)) var(--cn-brand-stripe-stop-1) var(--cn-brand-stripe-stop-2),
|
|
34402
|
+
var(--cn-brand-stripe-color-3, var(--color-primary-element)) var(--cn-brand-stripe-stop-2) 100%
|
|
34403
|
+
);
|
|
34221
34404
|
display: flex;
|
|
34222
34405
|
flex: none;
|
|
34223
34406
|
width: 100%;
|
|
34224
34407
|
height: var(--cn-brand-stripe-height, 4px);
|
|
34408
|
+
background-image: var(--cn-brand-stripe-image, var(--cn-brand-stripe-bands));
|
|
34409
|
+
background-repeat: repeat-x;
|
|
34410
|
+
background-size: auto 100%;
|
|
34411
|
+
}
|
|
34412
|
+
.cn-brand-stripe--inverse[data-v-6fdfa763] {
|
|
34413
|
+
background-image: var(--cn-brand-stripe-image-inverse, var(--cn-brand-stripe-image, var(--cn-brand-stripe-bands)));
|
|
34225
34414
|
}
|
|
34226
34415
|
.cn-brand-stripe--vertical[data-v-6fdfa763] {
|
|
34416
|
+
--cn-brand-stripe-direction: to bottom;
|
|
34227
34417
|
flex-direction: column;
|
|
34228
34418
|
width: var(--cn-brand-stripe-height, 4px);
|
|
34229
34419
|
height: 100%;
|
|
34420
|
+
background-repeat: repeat-y;
|
|
34421
|
+
background-size: 100% auto;
|
|
34230
34422
|
}
|
|
34231
34423
|
.cn-brand-stripe__band[data-v-6fdfa763] {
|
|
34232
34424
|
flex-basis: 0;
|
|
@@ -34234,15 +34426,12 @@ a.cn-integration-card__title[data-v-f7e9bbfa]:hover {
|
|
|
34234
34426
|
}
|
|
34235
34427
|
.cn-brand-stripe__band--1[data-v-6fdfa763] {
|
|
34236
34428
|
flex-grow: var(--cn-brand-stripe-ratio-1, 1);
|
|
34237
|
-
background-color: var(--cn-brand-stripe-color-1, var(--color-primary-element));
|
|
34238
34429
|
}
|
|
34239
34430
|
.cn-brand-stripe__band--2[data-v-6fdfa763] {
|
|
34240
34431
|
flex-grow: var(--cn-brand-stripe-ratio-2, 1);
|
|
34241
|
-
background-color: var(--cn-brand-stripe-color-2, var(--color-primary-element));
|
|
34242
34432
|
}
|
|
34243
34433
|
.cn-brand-stripe__band--3[data-v-6fdfa763] {
|
|
34244
34434
|
flex-grow: var(--cn-brand-stripe-ratio-3, 1);
|
|
34245
|
-
background-color: var(--cn-brand-stripe-color-3, var(--color-primary-element));
|
|
34246
34435
|
}
|
|
34247
34436
|
@media print {
|
|
34248
34437
|
.cn-brand-stripe[data-v-6fdfa763] {
|
package/l10n/en.json
CHANGED
|
@@ -294,6 +294,11 @@
|
|
|
294
294
|
"JSON pointer": "JSON pointer",
|
|
295
295
|
"Last": "Last",
|
|
296
296
|
"Load more": "Load more",
|
|
297
|
+
"Nothing to open here.": "Nothing to open here.",
|
|
298
|
+
"Could not check": "Could not check",
|
|
299
|
+
"Could not check: {subject}": "Could not check: {subject}",
|
|
300
|
+
"The check failed.": "The check failed.",
|
|
301
|
+
"The check failed: {reason}": "The check failed: {reason}",
|
|
297
302
|
"To do": "To do",
|
|
298
303
|
"Next step": "Next step",
|
|
299
304
|
"Review": "Review",
|
|
@@ -621,6 +626,7 @@
|
|
|
621
626
|
"No linked emails yet": "No linked emails yet",
|
|
622
627
|
"Could not load emails": "Could not load emails",
|
|
623
628
|
"Open in Mail": "Open in Mail",
|
|
629
|
+
"Open in Office": "Open in Office",
|
|
624
630
|
"(no subject)": "(no subject)",
|
|
625
631
|
"Unknown sender": "Unknown sender",
|
|
626
632
|
"No conversations linked yet": "No conversations linked yet",
|
package/l10n/nl.json
CHANGED
|
@@ -294,6 +294,11 @@
|
|
|
294
294
|
"JSON pointer": "JSON-aanwijzer",
|
|
295
295
|
"Last": "Laatste",
|
|
296
296
|
"Load more": "Meer laden",
|
|
297
|
+
"Nothing to open here.": "Hier is niets te openen.",
|
|
298
|
+
"Could not check": "Kon niet controleren",
|
|
299
|
+
"Could not check: {subject}": "Kon niet controleren: {subject}",
|
|
300
|
+
"The check failed.": "De controle is mislukt.",
|
|
301
|
+
"The check failed: {reason}": "De controle is mislukt: {reason}",
|
|
297
302
|
"To do": "Nog doen",
|
|
298
303
|
"Next step": "Volgende stap",
|
|
299
304
|
"Review": "Beoordelen",
|
|
@@ -613,6 +618,7 @@
|
|
|
613
618
|
"No linked emails yet": "Nog geen gekoppelde e-mails",
|
|
614
619
|
"Could not load emails": "Kon e-mails niet laden",
|
|
615
620
|
"Open in Mail": "Openen in Mail",
|
|
621
|
+
"Open in Office": "Openen in Office",
|
|
616
622
|
"(no subject)": "(geen onderwerp)",
|
|
617
623
|
"Unknown sender": "Onbekende afzender",
|
|
618
624
|
"No conversations linked yet": "Nog geen gesprekken gekoppeld",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.56.0-beta.
|
|
3
|
+
"version": "2.56.0-beta.9",
|
|
4
4
|
"description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
|
|
5
5
|
"homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -94,7 +94,8 @@
|
|
|
94
94
|
"test": "jest",
|
|
95
95
|
"test:e2e": "playwright test",
|
|
96
96
|
"test:types": "tsd",
|
|
97
|
-
"update:manifest-fixtures": "node scripts/update-fleet-manifest-fixtures.js"
|
|
97
|
+
"update:manifest-fixtures": "node scripts/update-fleet-manifest-fixtures.js",
|
|
98
|
+
"update:manifest-schema-hash": "node scripts/record-manifest-schema-hash.js"
|
|
98
99
|
},
|
|
99
100
|
"overrides": {
|
|
100
101
|
"@vue/vue3-jest": {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
3
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
4
|
+
*
|
|
5
|
+
* The content hash of the v2 manifest schema, shared by the recording script
|
|
6
|
+
* (`record-manifest-schema-hash.js`) and the test that checks it
|
|
7
|
+
* (`tests/schemas/app-manifest-v2.schema-version.spec.js`).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const crypto = require('crypto')
|
|
11
|
+
const fs = require('fs')
|
|
12
|
+
const path = require('path')
|
|
13
|
+
|
|
14
|
+
const ROOT = path.resolve(__dirname, '..')
|
|
15
|
+
const SCHEMA_PATH = path.join(ROOT, 'src/schemas/app-manifest-v2.schema.json')
|
|
16
|
+
const LEDGER_PATH = path.join(ROOT, 'tests/schemas/app-manifest-v2.schema.hashes.json')
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Hash a parsed schema. The hash is over the parsed document written back
|
|
20
|
+
* without whitespace, so reformatting the file is not a content change while
|
|
21
|
+
* any key, value or ordering change is. `version` is part of the content.
|
|
22
|
+
*
|
|
23
|
+
* @param {object} schema The parsed schema.
|
|
24
|
+
* @return {string} `sha256:<hex>`.
|
|
25
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-the-manifest-schema-version-moves-with-its-content
|
|
26
|
+
*/
|
|
27
|
+
function hashSchema(schema) {
|
|
28
|
+
return 'sha256:' + crypto.createHash('sha256').update(JSON.stringify(schema)).digest('hex')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Read the ledger of recorded versions.
|
|
33
|
+
*
|
|
34
|
+
* @return {{versions: Record<string, string>}} The ledger.
|
|
35
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-the-manifest-schema-version-moves-with-its-content
|
|
36
|
+
*/
|
|
37
|
+
function readLedger() {
|
|
38
|
+
return JSON.parse(fs.readFileSync(LEDGER_PATH, 'utf8'))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = { SCHEMA_PATH, LEDGER_PATH, hashSchema, readLedger }
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SPDX-License-Identifier: EUPL-1.2
|
|
3
|
+
* SPDX-FileCopyrightText: 2026 Conduction B.V.
|
|
4
|
+
*
|
|
5
|
+
* Records the content hash of `src/schemas/app-manifest-v2.schema.json` under
|
|
6
|
+
* its current `version` in `tests/schemas/app-manifest-v2.schema.hashes.json`
|
|
7
|
+
* (`npm run update:manifest-schema-hash`).
|
|
8
|
+
*
|
|
9
|
+
* Why a ledger. The schema's `version` is the only machine-readable signal a
|
|
10
|
+
* consumer gets that the vocabulary moved: ConductionNL/.github vendors this
|
|
11
|
+
* file into the gate tooling and compares versions to decide whether its copy
|
|
12
|
+
* is stale. 2.61.0 shipped a new page type under an unchanged 2.42.0, so that
|
|
13
|
+
* comparison read "already current" against a schema that had moved. The
|
|
14
|
+
* ledger makes that state fail a test here instead: a version has one content
|
|
15
|
+
* hash, so changing the content means taking a new version.
|
|
16
|
+
*
|
|
17
|
+
* This script therefore REFUSES to replace the hash of a version that is
|
|
18
|
+
* already recorded. Bump `version` in the schema first, then run it.
|
|
19
|
+
*
|
|
20
|
+
* The hash and the ledger shape live in `manifest-schema-hash.js`, which the
|
|
21
|
+
* test requires too, so the two cannot disagree about what "content" means.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
const fs = require('fs')
|
|
25
|
+
const { SCHEMA_PATH, LEDGER_PATH, hashSchema, readLedger } = require('./manifest-schema-hash.js')
|
|
26
|
+
|
|
27
|
+
const schema = JSON.parse(fs.readFileSync(SCHEMA_PATH, 'utf8'))
|
|
28
|
+
const version = schema.version
|
|
29
|
+
if (typeof version !== 'string' || version === '') {
|
|
30
|
+
console.error(`${SCHEMA_PATH} has no "version". Nothing to record.`)
|
|
31
|
+
process.exit(1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const ledger = readLedger()
|
|
35
|
+
const hash = hashSchema(schema)
|
|
36
|
+
const recorded = ledger.versions[version]
|
|
37
|
+
|
|
38
|
+
if (recorded === hash) {
|
|
39
|
+
console.log(`Version ${version} is already recorded with this content. Nothing to do.`)
|
|
40
|
+
process.exit(0)
|
|
41
|
+
}
|
|
42
|
+
if (recorded !== undefined) {
|
|
43
|
+
const message = `Version ${version} is already recorded with different content.\n`
|
|
44
|
+
+ 'A version has one content. Bump "version" in the schema (minor for an\n'
|
|
45
|
+
+ 'additive change), then run this script again.'
|
|
46
|
+
console.error(message)
|
|
47
|
+
process.exit(1)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ledger.versions[version] = hash
|
|
51
|
+
fs.writeFileSync(LEDGER_PATH, JSON.stringify(ledger, null, '\t') + '\n')
|
|
52
|
+
console.log(`Recorded ${version} = ${hash}`)
|
|
@@ -346,6 +346,7 @@
|
|
|
346
346
|
import { translate as t } from '@nextcloud/l10n'
|
|
347
347
|
import { generateUrl } from '@nextcloud/router'
|
|
348
348
|
import { NcAppNavigation, NcAppNavigationCaption, NcAppNavigationItem, NcAppNavigationList, NcAppNavigationNew, NcAppNavigationSettings, NcButton, NcCounterBubble } from '@nextcloud/vue'
|
|
349
|
+
import { toRaw } from 'vue'
|
|
349
350
|
import BookOpenVariant from 'vue-material-design-icons/BookOpenVariant.vue'
|
|
350
351
|
import Cog from 'vue-material-design-icons/Cog.vue'
|
|
351
352
|
// ADR-077 rule 4: visible fallback for an unresolvable icon name.
|
|
@@ -576,6 +577,13 @@ export default {
|
|
|
576
577
|
|
|
577
578
|
emits: ['primary-action', 'primary-action-click'],
|
|
578
579
|
|
|
580
|
+
/**
|
|
581
|
+
* The navigation's own state: which groups are open, and which entry
|
|
582
|
+
* of a route the reader last used.
|
|
583
|
+
*
|
|
584
|
+
* @return {object} The state.
|
|
585
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
586
|
+
*/
|
|
579
587
|
data() {
|
|
580
588
|
return {
|
|
581
589
|
/**
|
|
@@ -589,6 +597,15 @@ export default {
|
|
|
589
597
|
*/
|
|
590
598
|
openState: {},
|
|
591
599
|
|
|
600
|
+
/**
|
|
601
|
+
* Per route name, the key of the entry that was last active on
|
|
602
|
+
* that route in this session. Read by `subRouteParent` to keep
|
|
603
|
+
* "the list I came from" marked on a page below it. In memory
|
|
604
|
+
* only: a reload starts empty and falls back to menu order.
|
|
605
|
+
*
|
|
606
|
+
* @type {Record<string, string>}
|
|
607
|
+
*/
|
|
608
|
+
lastActiveEntryByRoute: {},
|
|
592
609
|
}
|
|
593
610
|
},
|
|
594
611
|
|
|
@@ -946,6 +963,67 @@ export default {
|
|
|
946
963
|
}
|
|
947
964
|
return best ?? routeName ?? null
|
|
948
965
|
},
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Every visible entry and child, flat, in menu order.
|
|
969
|
+
*
|
|
970
|
+
* @return {Array<object>} The entries.
|
|
971
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
972
|
+
*/
|
|
973
|
+
flatEntries() {
|
|
974
|
+
const flat = []
|
|
975
|
+
for (const item of this.visibleItems) {
|
|
976
|
+
flat.push(item, ...this.visibleChildren(item))
|
|
977
|
+
}
|
|
978
|
+
return flat
|
|
979
|
+
},
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* The entry the query rule marks while the reader is on a menu
|
|
983
|
+
* route itself (not on a page below it). Watched, so the nav can
|
|
984
|
+
* remember which entry of a route the reader last used.
|
|
985
|
+
*
|
|
986
|
+
* @return {object|null} The entry, or null on a page below a route.
|
|
987
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
988
|
+
*/
|
|
989
|
+
entryActiveOnOwnRoute() {
|
|
990
|
+
const routeName = this.$route?.name
|
|
991
|
+
if (!routeName || routeName !== this.activeRouteName) {
|
|
992
|
+
return null
|
|
993
|
+
}
|
|
994
|
+
return this.flatEntries.find((entry) => this.isActiveByRule(entry)) ?? null
|
|
995
|
+
},
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* The one entry to mark on a page BELOW a menu route when the query
|
|
999
|
+
* rule marks none.
|
|
1000
|
+
*
|
|
1001
|
+
* On a detail page (`/cases/123`) the active route is found by path
|
|
1002
|
+
* prefix, and the address carries the detail page's query, not the
|
|
1003
|
+
* list's. When every entry on that list has a `query` ("My work",
|
|
1004
|
+
* "Queue"), none of them matched and the menu showed no place at
|
|
1005
|
+
* all. Marking all of them is the defect the query rule ended, so
|
|
1006
|
+
* this picks exactly one: the entry the reader last had active on
|
|
1007
|
+
* that route, else the first in menu order.
|
|
1008
|
+
*
|
|
1009
|
+
* Null whenever the existing rule already marks an entry, so a list
|
|
1010
|
+
* with an entry without a `query` behaves as it did.
|
|
1011
|
+
*
|
|
1012
|
+
* @return {object|null} The entry to mark, or null.
|
|
1013
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
1014
|
+
*/
|
|
1015
|
+
subRouteParent() {
|
|
1016
|
+
const active = this.activeRouteName
|
|
1017
|
+
if (!active || this.$route?.name === active) {
|
|
1018
|
+
return null
|
|
1019
|
+
}
|
|
1020
|
+
const entries = this.flatEntries.filter((entry) => !entry.href && entry.route === active)
|
|
1021
|
+
if (entries.length === 0 || entries.some((entry) => this.isActiveByRule(entry))) {
|
|
1022
|
+
return null
|
|
1023
|
+
}
|
|
1024
|
+
const remembered = this.lastActiveEntryByRoute[active]
|
|
1025
|
+
return entries.find((entry) => this.entryKey(entry) === remembered) ?? entries[0]
|
|
1026
|
+
},
|
|
949
1027
|
},
|
|
950
1028
|
|
|
951
1029
|
watch: {
|
|
@@ -960,6 +1038,23 @@ export default {
|
|
|
960
1038
|
visibleItems() {
|
|
961
1039
|
this.pinGroupsEntered(this.activeRouteName)
|
|
962
1040
|
},
|
|
1041
|
+
|
|
1042
|
+
entryActiveOnOwnRoute: {
|
|
1043
|
+
immediate: true,
|
|
1044
|
+
/**
|
|
1045
|
+
* Remember which entry of a route the reader used, for
|
|
1046
|
+
* `subRouteParent`.
|
|
1047
|
+
*
|
|
1048
|
+
* @param {object|null} entry The entry active on its own route.
|
|
1049
|
+
* @return {void}
|
|
1050
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
1051
|
+
*/
|
|
1052
|
+
handler(entry) {
|
|
1053
|
+
if (entry && entry.route) {
|
|
1054
|
+
this.lastActiveEntryByRoute[entry.route] = this.entryKey(entry)
|
|
1055
|
+
}
|
|
1056
|
+
},
|
|
1057
|
+
},
|
|
963
1058
|
},
|
|
964
1059
|
|
|
965
1060
|
created() {
|
|
@@ -1184,11 +1279,84 @@ export default {
|
|
|
1184
1279
|
return this.effectiveTranslate(item.label)
|
|
1185
1280
|
},
|
|
1186
1281
|
|
|
1282
|
+
/**
|
|
1283
|
+
* Whether a menu entry is the page the reader is on.
|
|
1284
|
+
*
|
|
1285
|
+
* Two entries may share a route and differ only in `query` ("My
|
|
1286
|
+
* work" and "Queue" on one list). The route name alone lit both. An
|
|
1287
|
+
* entry with a `query` is active only when the address carries that
|
|
1288
|
+
* query; an entry without one steps back when a sibling's query
|
|
1289
|
+
* matches, so exactly one of them is marked.
|
|
1290
|
+
*
|
|
1291
|
+
* On a page below a list where that rule marks nothing, the one
|
|
1292
|
+
* entry `subRouteParent` picks is active instead.
|
|
1293
|
+
*
|
|
1294
|
+
* @param {object} item Menu entry.
|
|
1295
|
+
* @return {boolean} True when the entry is the current page.
|
|
1296
|
+
* @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query
|
|
1297
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
1298
|
+
*/
|
|
1187
1299
|
isActive(item) {
|
|
1300
|
+
if (this.isActiveByRule(item)) {
|
|
1301
|
+
return true
|
|
1302
|
+
}
|
|
1303
|
+
const parent = this.subRouteParent
|
|
1304
|
+
return parent !== null && toRaw(parent) === toRaw(item)
|
|
1305
|
+
},
|
|
1306
|
+
|
|
1307
|
+
/**
|
|
1308
|
+
* The route and query rule on its own, without the fallback for a
|
|
1309
|
+
* page below a list. `subRouteParent` asks this to see whether the
|
|
1310
|
+
* rule already marks an entry.
|
|
1311
|
+
*
|
|
1312
|
+
* @param {object} item Menu entry.
|
|
1313
|
+
* @return {boolean} True when the rule marks the entry.
|
|
1314
|
+
* @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query
|
|
1315
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
1316
|
+
*/
|
|
1317
|
+
isActiveByRule(item) {
|
|
1188
1318
|
if (item.href || !item.route) {
|
|
1189
1319
|
return false
|
|
1190
1320
|
}
|
|
1191
|
-
|
|
1321
|
+
if (item.route !== this.activeRouteName) {
|
|
1322
|
+
return false
|
|
1323
|
+
}
|
|
1324
|
+
if (item.query && typeof item.query === 'object') {
|
|
1325
|
+
return this.queryMatches(item)
|
|
1326
|
+
}
|
|
1327
|
+
const siblings = []
|
|
1328
|
+
for (const entry of this.visibleItems) {
|
|
1329
|
+
siblings.push(entry, ...this.visibleChildren(entry))
|
|
1330
|
+
}
|
|
1331
|
+
return !siblings.some((entry) => entry !== item
|
|
1332
|
+
&& entry.route === item.route
|
|
1333
|
+
&& entry.query && typeof entry.query === 'object'
|
|
1334
|
+
&& this.queryMatches(entry))
|
|
1335
|
+
},
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* What an entry is remembered by: its `id`, else its label.
|
|
1339
|
+
*
|
|
1340
|
+
* @param {object} item Menu entry.
|
|
1341
|
+
* @return {string} The key.
|
|
1342
|
+
* @spec openspec/changes/live-check-follow-ups/specs/live-check-follow-ups/spec.md#requirement-a-page-below-a-list-marks-one-menu-entry
|
|
1343
|
+
*/
|
|
1344
|
+
entryKey(item) {
|
|
1345
|
+
return String(item.id ?? item.label ?? '')
|
|
1346
|
+
},
|
|
1347
|
+
|
|
1348
|
+
/**
|
|
1349
|
+
* Whether the address carries every key of an entry's `query`.
|
|
1350
|
+
* Values are compared as strings, since an address has no numbers.
|
|
1351
|
+
*
|
|
1352
|
+
* @param {object} item Menu entry with a `query`.
|
|
1353
|
+
* @return {boolean} True when every declared key matches.
|
|
1354
|
+
* @spec openspec/changes/link-cards-page/specs/link-cards-page/spec.md#requirement-menu-entries-that-differ-in-query
|
|
1355
|
+
*/
|
|
1356
|
+
queryMatches(item) {
|
|
1357
|
+
const current = this.$route?.query ?? {}
|
|
1358
|
+
const keys = Object.keys(item.query)
|
|
1359
|
+
return keys.length > 0 && keys.every((key) => String(current[key] ?? '') === String(item.query[key]))
|
|
1192
1360
|
},
|
|
1193
1361
|
|
|
1194
1362
|
/**
|