@rancher/shell 3.0.1 → 3.0.2-rc.1
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/assets/styles/base/_basic.scss +17 -5
- package/assets/styles/base/_mixins.scss +2 -1
- package/assets/styles/global/_button.scss +10 -0
- package/assets/styles/global/_form.scss +2 -2
- package/assets/translations/en-us.yaml +33 -5
- package/assets/translations/zh-hans.yaml +1 -1
- package/components/ActionMenu.vue +8 -0
- package/components/AsyncButton.vue +9 -3
- package/components/BannerGraphic.vue +10 -0
- package/components/ButtonGroup.vue +2 -0
- package/components/ButtonMultiAction.vue +6 -0
- package/components/ClusterIconMenu.vue +1 -1
- package/components/CodeMirror.vue +28 -1
- package/components/CommunityLinks.vue +13 -0
- package/components/CruResource.vue +6 -0
- package/components/GrowlManager.vue +14 -4
- package/components/LocaleSelector.vue +49 -5
- package/components/PaginatedResourceTable.vue +4 -3
- package/components/ResourceDetail/Masthead.vue +11 -4
- package/components/ResourceList/index.vue +5 -3
- package/components/ResourceTable.vue +1 -1
- package/components/SortableTable/THead.vue +19 -4
- package/components/SortableTable/index.vue +13 -9
- package/components/SortableTable/selection.js +19 -5
- package/components/YamlEditor.vue +2 -1
- package/components/auth/SelectPrincipal.vue +1 -1
- package/components/fleet/FleetBundles.vue +2 -1
- package/components/form/LabeledSelect.vue +20 -7
- package/components/form/NodeScheduling.vue +5 -1
- package/components/form/Password.vue +23 -13
- package/components/form/ResourceLabeledSelect.vue +1 -1
- package/components/form/Select.vue +28 -6
- package/components/form/SelectOrCreateAuthSecret.vue +39 -11
- package/components/form/__tests__/NodeScheduling.test.ts +44 -0
- package/components/formatter/Endpoints.vue +1 -1
- package/components/formatter/LiveExpiryDate.vue +5 -1
- package/components/formatter/ServiceTargets.vue +1 -1
- package/components/formatter/ServiceType.vue +19 -17
- package/components/nav/Pinned.vue +6 -1
- package/components/nav/TopLevelMenu.helper.ts +17 -1
- package/components/nav/TopLevelMenu.vue +154 -19
- package/config/pagination-table-headers.js +9 -1
- package/config/product/apps.js +63 -30
- package/config/product/explorer.js +182 -17
- package/config/product/settings.js +9 -1
- package/config/router/routes.js +0 -1
- package/config/settings.ts +20 -2
- package/config/table-headers.js +23 -15
- package/config/types.js +2 -1
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +12 -3
- package/edit/fleet.cattle.io.gitrepo.vue +40 -33
- package/edit/provisioning.cattle.io.cluster/rke2.vue +13 -2
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +10 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +8 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +6 -3
- package/edit/workload/mixins/workload.js +15 -7
- package/list/catalog.cattle.io.app.vue +4 -11
- package/list/catalog.cattle.io.clusterrepo.vue +59 -25
- package/list/fleet.cattle.io.bundle.vue +2 -2
- package/list/management.cattle.io.feature.vue +12 -5
- package/list/management.cattle.io.setting.vue +30 -19
- package/list/namespace.vue +4 -1
- package/list/networking.k8s.io.ingress.vue +14 -11
- package/list/node.vue +65 -63
- package/list/persistentvolume.vue +55 -20
- package/list/persistentvolumeclaim.vue +3 -15
- package/list/service.vue +16 -21
- package/list/workload.vue +35 -49
- package/mixins/resource-fetch.js +8 -1
- package/mixins/vue-select-overrides.js +10 -16
- package/models/management.cattle.io.cluster.js +6 -1
- package/models/persistentvolume.js +1 -3
- package/models/storage.k8s.io.storageclass.js +4 -0
- package/package.json +28 -29
- package/pages/c/_cluster/explorer/EventsTable.vue +58 -16
- package/pages/c/_cluster/explorer/index.vue +3 -16
- package/pages/c/_cluster/settings/performance.vue +49 -23
- package/pages/home.vue +24 -3
- package/pages/support/index.vue +1 -1
- package/plugins/floating-vue.js +1 -1
- package/plugins/steve/steve-pagination-utils.ts +85 -15
- package/rancher-components/Banner/Banner.vue +12 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -5
- package/rancher-components/Form/Radio/RadioButton.vue +0 -6
- package/rancher-components/Form/Radio/RadioGroup.vue +5 -1
- package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +2 -2
- package/scripts/test-plugins-build.sh +21 -6
- package/scripts/typegen.sh +1 -0
- package/store/index.js +16 -0
- package/store/type-map.utils.ts +14 -1
- package/types/shell/index.d.ts +467 -418
- package/types/store/vuex.d.ts +1 -1
- package/types/vue-shim.d.ts +2 -8
- package/utils/cluster.js +2 -2
- package/utils/string.js +6 -0
- package/vue.config.js +3 -4
|
@@ -12,6 +12,10 @@ export default {
|
|
|
12
12
|
type: Object,
|
|
13
13
|
default: () => {}
|
|
14
14
|
},
|
|
15
|
+
missingKey: {
|
|
16
|
+
type: String,
|
|
17
|
+
default: 'generic.never',
|
|
18
|
+
}
|
|
15
19
|
},
|
|
16
20
|
|
|
17
21
|
data() {
|
|
@@ -77,7 +81,7 @@ export default {
|
|
|
77
81
|
/>
|
|
78
82
|
<span
|
|
79
83
|
v-else
|
|
80
|
-
v-t="
|
|
84
|
+
v-t="missingKey"
|
|
81
85
|
class="text-muted"
|
|
82
86
|
/>
|
|
83
87
|
</template>
|
|
@@ -17,28 +17,30 @@ export default {
|
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
data() {
|
|
20
|
-
const
|
|
21
|
-
|
|
20
|
+
const cloned = this.getLabel(this.value.toLowerCase());
|
|
21
|
+
const headless = this.value === 'ClusterIP' && this.row?.spec?.clusterIP === 'None' ? this.getLabel('headless') : undefined;
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
23
|
+
return { translated: cloned, headless };
|
|
24
|
+
},
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
methods: {
|
|
27
|
+
getLabel(type) {
|
|
28
|
+
const match = DEFAULT_SERVICE_TYPES.find((s) => s.id.toLowerCase() === type);
|
|
29
|
+
const translationLabel = match?.label;
|
|
30
|
+
let translated;
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
if (translationLabel && this.$store.getters['i18n/exists'](translationLabel)) {
|
|
33
|
+
translated = this.$store.getters['i18n/t'](translationLabel);
|
|
34
|
+
} else {
|
|
35
|
+
translated = this.value;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
return translated;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
39
41
|
};
|
|
40
|
-
</script
|
|
42
|
+
</script>
|
|
41
43
|
|
|
42
44
|
<template>
|
|
43
|
-
<span>{{ translated }}</span>
|
|
45
|
+
<span>{{ translated }}{{ headless ? ` (${headless})` : '' }}</span>
|
|
44
46
|
</template>
|
|
@@ -5,6 +5,10 @@ export default {
|
|
|
5
5
|
cluster: {
|
|
6
6
|
type: Object,
|
|
7
7
|
required: true,
|
|
8
|
+
},
|
|
9
|
+
tabOrder: {
|
|
10
|
+
type: Number,
|
|
11
|
+
default: null,
|
|
8
12
|
}
|
|
9
13
|
},
|
|
10
14
|
|
|
@@ -28,11 +32,12 @@ export default {
|
|
|
28
32
|
|
|
29
33
|
<template>
|
|
30
34
|
<i
|
|
31
|
-
:tabindex="
|
|
35
|
+
:tabindex="tabOrder"
|
|
32
36
|
:aria-checked="!!pinned"
|
|
33
37
|
class="pin icon"
|
|
34
38
|
:class="{'icon-pin-outlined': !pinned, 'icon-pin': pinned}"
|
|
35
39
|
aria-role="button"
|
|
40
|
+
:aria-label="`${t('nav.ariaLabel.pinCluster')} ${ cluster.label }`"
|
|
36
41
|
@click.stop.prevent="toggle"
|
|
37
42
|
@keydown.enter.prevent="toggle"
|
|
38
43
|
@keydown.space.prevent="toggle"
|
|
@@ -13,6 +13,7 @@ interface TopLevelMenuCluster {
|
|
|
13
13
|
ready: boolean
|
|
14
14
|
providerNavLogo: string,
|
|
15
15
|
badge: string,
|
|
16
|
+
iconColor: string,
|
|
16
17
|
isLocal: boolean,
|
|
17
18
|
pinned: boolean,
|
|
18
19
|
description: string,
|
|
@@ -128,6 +129,12 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
128
129
|
this.$store = $store;
|
|
129
130
|
|
|
130
131
|
this.hasProvCluster = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);
|
|
132
|
+
|
|
133
|
+
// Reduce flicker when component is recreated on a different layout
|
|
134
|
+
const { clustersPinned = [], clustersOthers = [] } = this.$store.getters['sideNavCache'] || {};
|
|
135
|
+
|
|
136
|
+
this.clustersPinned.push(...clustersPinned);
|
|
137
|
+
this.clustersOthers.push(...clustersOthers);
|
|
131
138
|
}
|
|
132
139
|
|
|
133
140
|
protected convertToCluster(mgmtCluster: MgmtCluster, provCluster: ProvCluster): TopLevelMenuCluster {
|
|
@@ -137,6 +144,7 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
137
144
|
ready: mgmtCluster.isReady, // && !provCluster?.hasError,
|
|
138
145
|
providerNavLogo: mgmtCluster.providerMenuLogo,
|
|
139
146
|
badge: mgmtCluster.badge,
|
|
147
|
+
iconColor: mgmtCluster.iconColor,
|
|
140
148
|
isLocal: mgmtCluster.isLocal,
|
|
141
149
|
pinned: mgmtCluster.pinned,
|
|
142
150
|
description: provCluster?.description || mgmtCluster.description,
|
|
@@ -145,6 +153,10 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
145
153
|
clusterRoute: { name: 'c-cluster-explorer', params: { cluster: mgmtCluster.id } }
|
|
146
154
|
};
|
|
147
155
|
}
|
|
156
|
+
|
|
157
|
+
protected cacheClusters() {
|
|
158
|
+
this.$store.dispatch('setSideNavCache', { clustersPinned: this.clustersPinned, clustersOthers: this.clustersOthers });
|
|
159
|
+
}
|
|
148
160
|
}
|
|
149
161
|
|
|
150
162
|
/**
|
|
@@ -258,6 +270,8 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
258
270
|
|
|
259
271
|
this.clustersPinned.push(..._clustersPinned);
|
|
260
272
|
this.clustersOthers.push(..._clustersNotPinned);
|
|
273
|
+
|
|
274
|
+
this.cacheClusters();
|
|
261
275
|
}
|
|
262
276
|
|
|
263
277
|
private constructParams({
|
|
@@ -378,7 +392,7 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
|
|
|
378
392
|
}
|
|
379
393
|
|
|
380
394
|
/**
|
|
381
|
-
* Helper designed to supply non-
|
|
395
|
+
* Helper designed to supply non-paginated results for the top level menu cluster resources
|
|
382
396
|
*/
|
|
383
397
|
export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements TopLevelMenuHelper {
|
|
384
398
|
constructor({ $store }: {
|
|
@@ -401,6 +415,8 @@ export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements
|
|
|
401
415
|
|
|
402
416
|
this.clustersPinned.push(..._clustersPinned);
|
|
403
417
|
this.clustersOthers.push(..._clustersNotPinned);
|
|
418
|
+
|
|
419
|
+
this.cacheClusters();
|
|
404
420
|
}
|
|
405
421
|
|
|
406
422
|
/**
|
|
@@ -42,6 +42,17 @@ export default {
|
|
|
42
42
|
const provClusters = !canPagination && hasProvCluster ? this.$store.getters[`management/all`](CAPI.RANCHER_CLUSTER) : [];
|
|
43
43
|
const mgmtClusters = !canPagination ? this.$store.getters[`management/all`](MANAGEMENT.CLUSTER) : [];
|
|
44
44
|
|
|
45
|
+
if (!canPagination) {
|
|
46
|
+
// Reduce the impact of the initial load, but only if we're not making a request
|
|
47
|
+
const args = {
|
|
48
|
+
pinnedIds: this.pinnedIds,
|
|
49
|
+
searchTerm: this.search,
|
|
50
|
+
unPinnedMax: this.maxClustersToShow
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
helper.update(args);
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
return {
|
|
46
57
|
shown: false,
|
|
47
58
|
displayVersion,
|
|
@@ -54,8 +65,9 @@ export default {
|
|
|
54
65
|
|
|
55
66
|
canPagination,
|
|
56
67
|
helper,
|
|
57
|
-
debouncedHelperUpdateSlow:
|
|
58
|
-
|
|
68
|
+
debouncedHelperUpdateSlow: debounce((...args) => this.helper.update(...args), 1000),
|
|
69
|
+
debouncedHelperUpdateMedium: debounce((...args) => this.helper.update(...args), 750),
|
|
70
|
+
debouncedHelperUpdateQuick: debounce((...args) => this.helper.update(...args), 200),
|
|
59
71
|
provClusters,
|
|
60
72
|
mgmtClusters,
|
|
61
73
|
};
|
|
@@ -264,6 +276,14 @@ export default {
|
|
|
264
276
|
this.shown = false;
|
|
265
277
|
},
|
|
266
278
|
|
|
279
|
+
// Before SSP world all of these changes were kicked off given Vue change detection to properties in a computed method.
|
|
280
|
+
// Changes could come from two scenarios
|
|
281
|
+
// 1. Changes made by the user (pin / search). Could be tens per second
|
|
282
|
+
// 2. Changes made by rancher to clusters (state, label, etc change). Could be hundreds a second
|
|
283
|
+
// They can be restricted to help the churn caused from above
|
|
284
|
+
// 1. When SSP enabled reduce http spam
|
|
285
|
+
// 2. When SSP is disabled (legacy) reduce fn churn (this was a known performance customer issue)
|
|
286
|
+
|
|
267
287
|
pinnedIds: {
|
|
268
288
|
immediate: true,
|
|
269
289
|
handler(neu, old) {
|
|
@@ -271,27 +291,29 @@ export default {
|
|
|
271
291
|
return;
|
|
272
292
|
}
|
|
273
293
|
|
|
294
|
+
// Low throughput (user click). Changes should be shown quickly
|
|
274
295
|
this.updateClusters(neu, 'quick');
|
|
275
296
|
}
|
|
276
297
|
},
|
|
277
298
|
|
|
278
299
|
search() {
|
|
279
|
-
|
|
300
|
+
// Medium throughput. Changes should be shown quickly, unless we want to reduce http spam in SSP world
|
|
301
|
+
this.updateClusters(this.pinnedIds, this.canPagination ? 'medium' : 'quick');
|
|
280
302
|
},
|
|
281
303
|
|
|
282
304
|
provClusters: {
|
|
283
|
-
handler() {
|
|
284
|
-
// Shouldn't get here if SSP
|
|
285
|
-
this.updateClusters(this.pinnedIds, 'slow');
|
|
305
|
+
handler(neu, old) {
|
|
306
|
+
// Potentially incredibly high throughput. Changes should be at least limited (slow if state change, quick if added/removed). Shouldn't get here if SSP
|
|
307
|
+
this.updateClusters(this.pinnedIds, neu?.length === old?.length ? 'slow' : 'quick');
|
|
286
308
|
},
|
|
287
309
|
deep: true,
|
|
288
310
|
immediate: true,
|
|
289
311
|
},
|
|
290
312
|
|
|
291
313
|
mgmtClusters: {
|
|
292
|
-
handler() {
|
|
293
|
-
// Shouldn't get here if SSP
|
|
294
|
-
this.updateClusters(this.pinnedIds, 'slow');
|
|
314
|
+
handler(neu, old) {
|
|
315
|
+
// Potentially incredibly high throughput. Changes should be at least limited (slow if state change, quick if added/removed). Shouldn't get here if SSP
|
|
316
|
+
this.updateClusters(this.pinnedIds, neu?.length === old?.length ? 'slow' : 'quick');
|
|
295
317
|
},
|
|
296
318
|
deep: true,
|
|
297
319
|
immediate: true,
|
|
@@ -424,7 +446,7 @@ export default {
|
|
|
424
446
|
};
|
|
425
447
|
},
|
|
426
448
|
|
|
427
|
-
updateClusters(pinnedIds, speed = 'slow' | 'quick') {
|
|
449
|
+
updateClusters(pinnedIds, speed = 'slow' | 'medium' | 'quick') {
|
|
428
450
|
const args = {
|
|
429
451
|
pinnedIds,
|
|
430
452
|
searchTerm: this.search,
|
|
@@ -435,6 +457,9 @@ export default {
|
|
|
435
457
|
case 'slow':
|
|
436
458
|
this.debouncedHelperUpdateSlow(args);
|
|
437
459
|
break;
|
|
460
|
+
case 'medium':
|
|
461
|
+
this.debouncedHelperUpdateMedium(args);
|
|
462
|
+
break;
|
|
438
463
|
case 'quick':
|
|
439
464
|
this.debouncedHelperUpdateQuick(args);
|
|
440
465
|
break;
|
|
@@ -460,6 +485,8 @@ export default {
|
|
|
460
485
|
:class="{'menu-open': shown, 'menu-close':!shown}"
|
|
461
486
|
:style="sideMenuStyle"
|
|
462
487
|
tabindex="-1"
|
|
488
|
+
role="navigation"
|
|
489
|
+
:aria-label="t('nav.ariaLabel.topLevelMenu')"
|
|
463
490
|
>
|
|
464
491
|
<!-- Logo and name -->
|
|
465
492
|
<div class="title">
|
|
@@ -479,6 +506,7 @@ export default {
|
|
|
479
506
|
height="24"
|
|
480
507
|
viewBox="0 0 24 24"
|
|
481
508
|
width="24"
|
|
509
|
+
:alt="t('nav.alt.mainMenuIcon')"
|
|
482
510
|
><path
|
|
483
511
|
d="M0 0h24v24H0z"
|
|
484
512
|
fill="none"
|
|
@@ -487,6 +515,7 @@ export default {
|
|
|
487
515
|
<div class="side-menu-logo">
|
|
488
516
|
<BrandImage
|
|
489
517
|
data-testid="side-menu__brand-img"
|
|
518
|
+
:alt="t('nav.alt.mainMenuRancherLogo')"
|
|
490
519
|
file-name="rancher-logo.svg"
|
|
491
520
|
/>
|
|
492
521
|
</div>
|
|
@@ -500,9 +529,12 @@ export default {
|
|
|
500
529
|
<router-link
|
|
501
530
|
class="option cluster selector home"
|
|
502
531
|
:to="{ name: 'home' }"
|
|
532
|
+
role="link"
|
|
533
|
+
:aria-label="t('nav.ariaLabel.homePage')"
|
|
503
534
|
>
|
|
504
535
|
<svg
|
|
505
536
|
v-clean-tooltip="getTooltipConfig(t('nav.home'))"
|
|
537
|
+
class="top-menu-icon"
|
|
506
538
|
xmlns="http://www.w3.org/2000/svg"
|
|
507
539
|
height="24"
|
|
508
540
|
viewBox="0 0 24 24"
|
|
@@ -537,6 +569,8 @@ export default {
|
|
|
537
569
|
ref="clusterFilter"
|
|
538
570
|
v-model="clusterFilter"
|
|
539
571
|
:placeholder="t('nav.search.placeholder')"
|
|
572
|
+
:tabindex="!shown ? -1 : 0"
|
|
573
|
+
:aria-label="t('nav.search.ariaLabel')"
|
|
540
574
|
>
|
|
541
575
|
<i
|
|
542
576
|
class="magnifier icon icon-search"
|
|
@@ -558,10 +592,11 @@ export default {
|
|
|
558
592
|
<a
|
|
559
593
|
v-if="isRancherInHarvester"
|
|
560
594
|
class="option"
|
|
595
|
+
tabindex="0"
|
|
561
596
|
@click="goToHarvesterCluster()"
|
|
562
597
|
>
|
|
563
598
|
<i
|
|
564
|
-
class="icon icon-dashboard"
|
|
599
|
+
class="icon icon-dashboard app-icon"
|
|
565
600
|
/>
|
|
566
601
|
<div>
|
|
567
602
|
{{ t('nav.harvesterDashboard') }}
|
|
@@ -577,8 +612,11 @@ export default {
|
|
|
577
612
|
class="option"
|
|
578
613
|
:to="a.to"
|
|
579
614
|
:class="{'active-menu-link': a.isMenuActive }"
|
|
615
|
+
role="link"
|
|
616
|
+
:aria-label="`${t('nav.ariaLabel.harvesterCluster')} ${ a.label }`"
|
|
580
617
|
>
|
|
581
618
|
<IconOrSvg
|
|
619
|
+
class="app-icon"
|
|
582
620
|
:icon="a.icon"
|
|
583
621
|
:src="a.svg"
|
|
584
622
|
/>
|
|
@@ -612,6 +650,8 @@ export default {
|
|
|
612
650
|
class="cluster selector option"
|
|
613
651
|
:class="{'active-menu-link': c.isMenuActive }"
|
|
614
652
|
:to="c.clusterRoute"
|
|
653
|
+
role="button"
|
|
654
|
+
:aria-label="`${t('nav.ariaLabel.cluster')} ${ c.label }`"
|
|
615
655
|
@click.prevent="clusterMenuClick($event, c)"
|
|
616
656
|
@shortkey="handleKeyComboClick"
|
|
617
657
|
>
|
|
@@ -635,6 +675,7 @@ export default {
|
|
|
635
675
|
</div>
|
|
636
676
|
<Pinned
|
|
637
677
|
:cluster="c"
|
|
678
|
+
:tab-order="shown ? 0 : -1"
|
|
638
679
|
/>
|
|
639
680
|
</button>
|
|
640
681
|
<span
|
|
@@ -661,6 +702,7 @@ export default {
|
|
|
661
702
|
</div>
|
|
662
703
|
<Pinned
|
|
663
704
|
:cluster="c"
|
|
705
|
+
:tab-order="shown ? 0 : -1"
|
|
664
706
|
/>
|
|
665
707
|
</span>
|
|
666
708
|
</div>
|
|
@@ -687,6 +729,8 @@ export default {
|
|
|
687
729
|
class="cluster selector option"
|
|
688
730
|
:class="{'active-menu-link': c.isMenuActive }"
|
|
689
731
|
:to="c.clusterRoute"
|
|
732
|
+
role="button"
|
|
733
|
+
:aria-label="`${t('nav.ariaLabel.cluster')} ${ c.label }`"
|
|
690
734
|
@click="clusterMenuClick($event, c)"
|
|
691
735
|
@shortkey="handleKeyComboClick"
|
|
692
736
|
>
|
|
@@ -700,7 +744,6 @@ export default {
|
|
|
700
744
|
v-clean-tooltip="getTooltipConfig(c)"
|
|
701
745
|
class="cluster-name"
|
|
702
746
|
>
|
|
703
|
-
<!-- HERE LOCAL CLUSTER! -->
|
|
704
747
|
<p>{{ c.label }}</p>
|
|
705
748
|
<p
|
|
706
749
|
v-if="c.description"
|
|
@@ -711,6 +754,7 @@ export default {
|
|
|
711
754
|
</div>
|
|
712
755
|
<Pinned
|
|
713
756
|
:class="{'showPin': c.pinned}"
|
|
757
|
+
:tab-order="shown ? 0 : -1"
|
|
714
758
|
:cluster="c"
|
|
715
759
|
/>
|
|
716
760
|
</button>
|
|
@@ -738,6 +782,7 @@ export default {
|
|
|
738
782
|
</div>
|
|
739
783
|
<Pinned
|
|
740
784
|
:class="{'showPin': c.pinned}"
|
|
785
|
+
:tab-order="shown ? 0 : -1"
|
|
741
786
|
:cluster="c"
|
|
742
787
|
/>
|
|
743
788
|
</span>
|
|
@@ -763,6 +808,8 @@ export default {
|
|
|
763
808
|
product: 'manager',
|
|
764
809
|
resource: 'provisioning.cattle.io.cluster'
|
|
765
810
|
} }"
|
|
811
|
+
role="link"
|
|
812
|
+
:aria-label="t('nav.ariaLabel.seeAll')"
|
|
766
813
|
>
|
|
767
814
|
<span>
|
|
768
815
|
{{ shown ? t('nav.seeAllClusters') : t('nav.seeAllClustersCollapsed') }}
|
|
@@ -771,6 +818,7 @@ export default {
|
|
|
771
818
|
</router-link>
|
|
772
819
|
</template>
|
|
773
820
|
|
|
821
|
+
<!-- MULTI CLUSTER APPS -->
|
|
774
822
|
<div class="category">
|
|
775
823
|
<template v-if="multiClusterApps.length">
|
|
776
824
|
<div
|
|
@@ -790,9 +838,12 @@ export default {
|
|
|
790
838
|
class="option"
|
|
791
839
|
:class="{'active-menu-link': a.isMenuActive }"
|
|
792
840
|
:to="a.to"
|
|
841
|
+
role="link"
|
|
842
|
+
:aria-label="`${t('nav.ariaLabel.multiClusterApps')} ${ a.label }`"
|
|
793
843
|
>
|
|
794
844
|
<IconOrSvg
|
|
795
845
|
v-clean-tooltip="getTooltipConfig(a.label)"
|
|
846
|
+
class="app-icon"
|
|
796
847
|
:icon="a.icon"
|
|
797
848
|
:src="a.svg"
|
|
798
849
|
/>
|
|
@@ -801,7 +852,7 @@ export default {
|
|
|
801
852
|
</div>
|
|
802
853
|
</template>
|
|
803
854
|
|
|
804
|
-
<!--
|
|
855
|
+
<!-- Configuration apps menu -->
|
|
805
856
|
<template v-if="configurationApps.length">
|
|
806
857
|
<div
|
|
807
858
|
class="category-title"
|
|
@@ -820,9 +871,12 @@ export default {
|
|
|
820
871
|
class="option"
|
|
821
872
|
:class="{'active-menu-link': a.isMenuActive }"
|
|
822
873
|
:to="a.to"
|
|
874
|
+
role="link"
|
|
875
|
+
:aria-label="`${t('nav.ariaLabel.configurationApps')} ${ a.label }`"
|
|
823
876
|
>
|
|
824
877
|
<IconOrSvg
|
|
825
878
|
v-clean-tooltip="getTooltipConfig(a.label)"
|
|
879
|
+
class="app-icon"
|
|
826
880
|
:icon="a.icon"
|
|
827
881
|
:src="a.svg"
|
|
828
882
|
/>
|
|
@@ -844,6 +898,8 @@ export default {
|
|
|
844
898
|
>
|
|
845
899
|
<router-link
|
|
846
900
|
:to="{name: 'support'}"
|
|
901
|
+
role="link"
|
|
902
|
+
:aria-label="t('nav.ariaLabel.support')"
|
|
847
903
|
>
|
|
848
904
|
{{ t('nav.support', {hasSupport}) }}
|
|
849
905
|
</router-link>
|
|
@@ -855,6 +911,8 @@ export default {
|
|
|
855
911
|
>
|
|
856
912
|
<router-link
|
|
857
913
|
:to="{ name: 'about' }"
|
|
914
|
+
role="link"
|
|
915
|
+
:aria-label="t('nav.ariaLabel.about')"
|
|
858
916
|
>
|
|
859
917
|
{{ aboutText }}
|
|
860
918
|
</router-link>
|
|
@@ -958,13 +1016,27 @@ export default {
|
|
|
958
1016
|
overflow: hidden;
|
|
959
1017
|
transition: width 250ms;
|
|
960
1018
|
|
|
961
|
-
&:focus {
|
|
1019
|
+
&:focus, &:focus-visible {
|
|
1020
|
+
outline: 0;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
.option:focus-visible {
|
|
962
1024
|
outline: 0;
|
|
963
1025
|
}
|
|
964
1026
|
|
|
965
|
-
|
|
1027
|
+
&.menu-open {
|
|
966
1028
|
width: 300px;
|
|
967
1029
|
box-shadow: 3px 1px 3px var(--shadow);
|
|
1030
|
+
|
|
1031
|
+
// because of accessibility, we force pin action to be visible on menu open
|
|
1032
|
+
.pin {
|
|
1033
|
+
display: block !important;
|
|
1034
|
+
|
|
1035
|
+
&:focus-visible {
|
|
1036
|
+
@include focus-outline;
|
|
1037
|
+
outline-offset: 4px;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
968
1040
|
}
|
|
969
1041
|
|
|
970
1042
|
.title {
|
|
@@ -1074,10 +1146,6 @@ export default {
|
|
|
1074
1146
|
&:focus {
|
|
1075
1147
|
outline: 0;
|
|
1076
1148
|
box-shadow: none;
|
|
1077
|
-
|
|
1078
|
-
> div {
|
|
1079
|
-
text-decoration: underline;
|
|
1080
|
-
}
|
|
1081
1149
|
}
|
|
1082
1150
|
|
|
1083
1151
|
> i, > img {
|
|
@@ -1095,7 +1163,22 @@ export default {
|
|
|
1095
1163
|
fill: var(--link);
|
|
1096
1164
|
}
|
|
1097
1165
|
|
|
1166
|
+
.top-menu-icon {
|
|
1167
|
+
outline-offset: 4px;
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1098
1170
|
&.router-link-active, &.active-menu-link {
|
|
1171
|
+
&:focus-visible {
|
|
1172
|
+
.top-menu-icon, .app-icon {
|
|
1173
|
+
@include focus-outline;
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
&:focus-visible .rancher-provider-icon {
|
|
1178
|
+
@include focus-outline;
|
|
1179
|
+
outline-offset: -4px;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1099
1182
|
background: var(--primary-hover-bg);
|
|
1100
1183
|
color: var(--primary-hover-text);
|
|
1101
1184
|
|
|
@@ -1112,6 +1195,12 @@ export default {
|
|
|
1112
1195
|
}
|
|
1113
1196
|
}
|
|
1114
1197
|
|
|
1198
|
+
&:focus-visible {
|
|
1199
|
+
.top-menu-icon, .rancher-provider-icon, .app-icon {
|
|
1200
|
+
@include focus-outline;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1115
1204
|
&:hover {
|
|
1116
1205
|
color: var(--primary-hover-text);
|
|
1117
1206
|
background: var(--primary-hover-bg);
|
|
@@ -1188,10 +1277,19 @@ export default {
|
|
|
1188
1277
|
margin-right: 16px;
|
|
1189
1278
|
margin-top: 10px;
|
|
1190
1279
|
|
|
1280
|
+
&:focus-visible {
|
|
1281
|
+
outline: none;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1191
1284
|
span {
|
|
1192
1285
|
display: flex;
|
|
1193
1286
|
align-items: center;
|
|
1194
1287
|
}
|
|
1288
|
+
|
|
1289
|
+
&:focus-visible span {
|
|
1290
|
+
@include focus-outline;
|
|
1291
|
+
outline-offset: 4px;
|
|
1292
|
+
}
|
|
1195
1293
|
}
|
|
1196
1294
|
|
|
1197
1295
|
.clusters {
|
|
@@ -1314,6 +1412,33 @@ export default {
|
|
|
1314
1412
|
}
|
|
1315
1413
|
}
|
|
1316
1414
|
|
|
1415
|
+
&.menu-open {
|
|
1416
|
+
.option {
|
|
1417
|
+
&.router-link-active, &.active-menu-link {
|
|
1418
|
+
&:focus-visible {
|
|
1419
|
+
@include focus-outline;
|
|
1420
|
+
border-radius: 0;
|
|
1421
|
+
outline-offset: -4px;
|
|
1422
|
+
|
|
1423
|
+
.top-menu-icon, .app-icon, .rancher-provider-icon {
|
|
1424
|
+
outline: none;
|
|
1425
|
+
border-radius: 0;
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
&:focus-visible {
|
|
1431
|
+
@include focus-outline;
|
|
1432
|
+
outline-offset: -4px;
|
|
1433
|
+
|
|
1434
|
+
.top-menu-icon, .app-icon, .rancher-provider-icon {
|
|
1435
|
+
outline: none;
|
|
1436
|
+
border-radius: 0;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1317
1442
|
&.menu-close {
|
|
1318
1443
|
.side-menu-logo {
|
|
1319
1444
|
opacity: 0;
|
|
@@ -1387,8 +1512,18 @@ export default {
|
|
|
1387
1512
|
text-align: center;
|
|
1388
1513
|
}
|
|
1389
1514
|
|
|
1515
|
+
.support a:focus-visible {
|
|
1516
|
+
@include focus-outline;
|
|
1517
|
+
outline-offset: 4px;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1390
1520
|
.version {
|
|
1391
1521
|
cursor: pointer;
|
|
1522
|
+
|
|
1523
|
+
a:focus-visible {
|
|
1524
|
+
@include focus-outline;
|
|
1525
|
+
outline-offset: 4px;
|
|
1526
|
+
}
|
|
1392
1527
|
}
|
|
1393
1528
|
}
|
|
1394
1529
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
STATE, NAME as NAME_COL, NAMESPACE as NAMESPACE_COL, AGE, OBJECT
|
|
3
|
+
} from '@shell/config/table-headers';
|
|
2
4
|
|
|
3
5
|
// This file contains table headers
|
|
4
6
|
// These table headers are used for server side pagination
|
|
@@ -44,6 +46,12 @@ export const STEVE_NAMESPACE_COL = {
|
|
|
44
46
|
search: 'metadata.namespace',
|
|
45
47
|
};
|
|
46
48
|
|
|
49
|
+
export const STEVE_EVENT_OBJECT = {
|
|
50
|
+
...OBJECT,
|
|
51
|
+
sort: 'involvedObject.kind',
|
|
52
|
+
search: 'involvedObject.kind',
|
|
53
|
+
};
|
|
54
|
+
|
|
47
55
|
export const STEVE_LIST_GROUPS = [{
|
|
48
56
|
tooltipKey: 'resourceTable.groupBy.none',
|
|
49
57
|
icon: 'icon-list-flat',
|