@rancher/shell 3.0.2-rc.2 → 3.0.2-rc.3
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 +5 -7
- package/assets/styles/global/_button.scss +10 -0
- package/assets/styles/global/_tooltip.scss +2 -2
- package/assets/styles/themes/_dark.scss +14 -2
- package/assets/styles/themes/_light.scss +7 -2
- package/assets/styles/vendor/vue-select.scss +4 -0
- package/assets/translations/en-us.yaml +44 -5
- package/components/BannerGraphic.vue +0 -42
- package/components/ButtonMultiAction.vue +1 -1
- package/components/Carousel.vue +36 -29
- package/components/CommunityLinks.vue +6 -1
- package/components/GrowlManager.vue +9 -2
- package/components/LocaleSelector.vue +8 -1
- package/components/PaginatedResourceTable.vue +4 -7
- package/components/ProgressBarMulti.vue +14 -0
- package/components/Questions/Reference.vue +57 -28
- package/components/SelectIconGrid.vue +12 -1
- package/components/SideNav.vue +12 -38
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/index.vue +12 -1
- package/components/YamlEditor.vue +1 -0
- package/components/auth/Principal.vue +5 -3
- package/components/fleet/FleetClusters.vue +82 -1
- package/components/fleet/FleetRepos.vue +13 -30
- package/components/fleet/ForceDirectedTreeChart/index.vue +2 -2
- package/components/form/ChangePassword.vue +2 -0
- package/components/form/ColorInput.vue +24 -1
- package/components/form/FileSelector.vue +2 -0
- package/components/form/KeyValue.vue +230 -160
- package/components/form/LabeledSelect.vue +1 -1
- package/components/form/PlusMinus.vue +14 -2
- package/components/form/ResourceLabeledSelect.vue +13 -53
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +79 -36
- package/components/form/SecretSelector.vue +2 -2
- package/components/form/__tests__/KeyValue.test.ts +1 -1
- package/components/formatter/FleetClusterSummaryGraph.vue +2 -2
- package/components/formatter/FleetSummaryGraph.vue +6 -7
- package/components/formatter/WorkloadHealthScale.vue +7 -0
- package/components/nav/Group.vue +30 -4
- package/components/nav/Header.vue +82 -114
- package/components/nav/HeaderPageActionMenu.vue +27 -131
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/Type.vue +15 -0
- package/config/home-links.js +21 -13
- package/config/labels-annotations.js +2 -0
- package/config/page-actions.js +1 -0
- package/config/pagination-table-headers.js +15 -1
- package/config/product/explorer.js +7 -17
- package/config/table-headers.js +6 -0
- package/config/version.js +5 -1
- package/core/plugin.ts +41 -1
- package/core/plugins.js +125 -72
- package/core/types-provisioning.ts +91 -2
- package/core/types.ts +55 -0
- package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +12 -3
- package/detail/catalog.cattle.io.app.vue +1 -1
- package/detail/fleet.cattle.io.cluster.vue +3 -3
- package/detail/namespace.vue +13 -19
- package/detail/networking.k8s.io.ingress.vue +13 -53
- package/detail/provisioning.cattle.io.cluster.vue +12 -1
- package/detail/workload/index.vue +3 -3
- package/dialog/AddCustomBadgeDialog.vue +5 -1
- package/edit/auth/ldap/__tests__/config.test.ts +18 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/auth/saml.vue +8 -6
- package/edit/fleet.cattle.io.gitrepo.vue +7 -1
- package/edit/logging-flow/index.vue +4 -19
- package/edit/networking.k8s.io.ingress/index.vue +18 -65
- package/edit/networking.k8s.io.networkpolicy/index.vue +4 -5
- package/edit/provisioning.cattle.io.cluster/index.vue +13 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +31 -115
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue +14 -28
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +25 -12
- package/edit/service.vue +1 -2
- package/list/networking.k8s.io.ingress.vue +1 -1
- package/list/node.vue +15 -8
- package/list/persistentvolume.vue +12 -4
- package/list/service.vue +1 -1
- package/list/workload.vue +4 -0
- package/mixins/chart.js +4 -1
- package/models/catalog.cattle.io.app.js +3 -1
- package/models/catalog.cattle.io.clusterrepo.js +56 -7
- package/models/fleet.cattle.io.bundle.js +0 -11
- package/models/fleet.cattle.io.cluster.js +17 -1
- package/models/fleet.cattle.io.gitrepo.js +86 -50
- package/models/provisioning.cattle.io.cluster.js +47 -2
- package/models/service.js +1 -0
- package/models/workload.js +19 -1
- package/package.json +5 -4
- package/pages/c/_cluster/apps/charts/index.vue +4 -0
- package/pages/c/_cluster/explorer/ConfigBadge.vue +8 -7
- package/pages/c/_cluster/explorer/index.vue +13 -6
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +3 -3
- package/pages/c/_cluster/fleet/index.vue +75 -89
- package/pages/c/_cluster/settings/links.vue +2 -2
- package/pages/diagnostic.vue +17 -15
- package/pages/home.vue +32 -6
- package/plugins/clean-html.js +50 -0
- package/plugins/dashboard-store/resource-class.js +4 -0
- package/plugins/plugin.js +54 -49
- package/plugins/steve/mutations.js +1 -1
- package/plugins/steve/steve-class.js +8 -0
- package/plugins/steve/steve-pagination-utils.ts +3 -1
- package/rancher-components/Accordion/Accordion.vue +4 -4
- package/rancher-components/BadgeState/BadgeState.vue +7 -0
- package/rancher-components/Card/Card.vue +27 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +9 -2
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +18 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +18 -1
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +39 -2
- package/rancher-components/RcButton/RcButton.vue +90 -0
- package/rancher-components/RcButton/index.ts +2 -0
- package/rancher-components/RcButton/types.ts +17 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +111 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +127 -0
- package/rancher-components/RcDropdown/RcDropdownSeparator.vue +6 -0
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +43 -0
- package/rancher-components/RcDropdown/index.ts +4 -0
- package/rancher-components/RcDropdown/types.ts +22 -0
- package/rancher-components/RcDropdown/useDropdownCollection.ts +45 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +83 -0
- package/scripts/test-plugins-build.sh +2 -0
- package/scripts/typegen.sh +2 -0
- package/store/catalog.js +1 -1
- package/tsconfig.json +2 -1
- package/types/components/paginatedResourceTable.ts +25 -0
- package/types/components/resourceLabeledSelect.ts +48 -0
- package/types/resources/fleet.d.ts +17 -0
- package/types/shell/index.d.ts +61 -0
- package/utils/auth.js +5 -1
- package/utils/cluster.js +106 -0
- package/utils/fleet.ts +35 -3
- package/utils/ingress.ts +64 -0
- package/utils/uiplugins.ts +56 -44
- package/utils/validators/cron-schedule.js +7 -2
- package/utils/validators/formRules/__tests__/index.test.ts +53 -17
- package/utils/validators/formRules/index.ts +20 -5
- package/vue.config.js +1 -1
- package/components/RelatedWorkloadsTable.vue +0 -50
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import ResourceLabeledSelect from '@shell/components/form/ResourceLabeledSelect.vue';
|
|
4
|
+
import { PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
5
|
+
|
|
5
6
|
import { PVC, STORAGE_CLASS } from '@shell/config/types';
|
|
6
7
|
import Question from './Question';
|
|
7
8
|
|
|
@@ -14,7 +15,7 @@ const LEGACY_MAP = {
|
|
|
14
15
|
export default {
|
|
15
16
|
emits: ['update:value'],
|
|
16
17
|
|
|
17
|
-
components: { LabeledInput,
|
|
18
|
+
components: { LabeledInput, ResourceLabeledSelect },
|
|
18
19
|
mixins: [Question],
|
|
19
20
|
|
|
20
21
|
props: {
|
|
@@ -29,12 +30,6 @@ export default {
|
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
32
|
|
|
32
|
-
async fetch() {
|
|
33
|
-
if ( this.typeSchema ) {
|
|
34
|
-
this.all = await this.$store.dispatch(`${ this.inStore }/findAll`, { type: this.typeName });
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
|
|
38
33
|
data() {
|
|
39
34
|
const t = this.question.type;
|
|
40
35
|
|
|
@@ -57,29 +52,61 @@ export default {
|
|
|
57
52
|
return {
|
|
58
53
|
typeName,
|
|
59
54
|
typeSchema,
|
|
60
|
-
all:
|
|
55
|
+
all: [],
|
|
56
|
+
allResourceSettings: {
|
|
57
|
+
updateResources: (all) => {
|
|
58
|
+
// Filter to only include required namespaced resources
|
|
59
|
+
const resources = this.isNamespaced ? all.filter((r) => r.metadata.namespace === this.targetNamespace) : all;
|
|
60
|
+
|
|
61
|
+
return this.mapResourcesToOptions(resources);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
paginateResourceSetting: {
|
|
65
|
+
updateResources: (resources) => {
|
|
66
|
+
return this.mapResourcesToOptions(resources);
|
|
67
|
+
},
|
|
68
|
+
/**
|
|
69
|
+
* of type PaginateTypeOverridesFn
|
|
70
|
+
* @param [LabelSelectPaginationFunctionOptions] opts
|
|
71
|
+
* @returns LabelSelectPaginationFunctionOptions
|
|
72
|
+
*/
|
|
73
|
+
requestSettings: (opts) => {
|
|
74
|
+
// Filter to only include required namespaced resources
|
|
75
|
+
const filters = this.isNamespaced ? [
|
|
76
|
+
PaginationParamFilter.createSingleField({ field: 'metadata.namespace', value: this.targetNamespace }),
|
|
77
|
+
] : [];
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
...opts,
|
|
81
|
+
filters,
|
|
82
|
+
groupByNamespace: false,
|
|
83
|
+
classify: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
},
|
|
61
87
|
};
|
|
62
88
|
},
|
|
63
89
|
|
|
90
|
+
methods: {
|
|
91
|
+
mapResourcesToOptions(resources) {
|
|
92
|
+
return resources.map((r) => {
|
|
93
|
+
if (r.id) {
|
|
94
|
+
return {
|
|
95
|
+
label: r.nameDisplay || r.metadata.name,
|
|
96
|
+
value: r.metadata.name
|
|
97
|
+
};
|
|
98
|
+
} else {
|
|
99
|
+
return r;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
},
|
|
105
|
+
|
|
64
106
|
computed: {
|
|
65
107
|
isNamespaced() {
|
|
66
108
|
return !!this.typeSchema?.attributes?.namespaced;
|
|
67
109
|
},
|
|
68
|
-
|
|
69
|
-
options() {
|
|
70
|
-
let out = this.all;
|
|
71
|
-
|
|
72
|
-
if ( this.isNamespaced ) {
|
|
73
|
-
out = filterBy(this.all, 'metadata.namespace', this.targetNamespace);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return out.map((x) => {
|
|
77
|
-
return {
|
|
78
|
-
label: x.nameDisplay || x.metadata.name,
|
|
79
|
-
value: x.metadata.name
|
|
80
|
-
};
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
110
|
},
|
|
84
111
|
};
|
|
85
112
|
</script>
|
|
@@ -90,15 +117,17 @@ export default {
|
|
|
90
117
|
class="row"
|
|
91
118
|
>
|
|
92
119
|
<div class="col span-6">
|
|
93
|
-
<
|
|
94
|
-
:
|
|
95
|
-
:
|
|
120
|
+
<ResourceLabeledSelect
|
|
121
|
+
:resource-type="typeName"
|
|
122
|
+
:in-store="inStore"
|
|
96
123
|
:disabled="$fetchState.pending || disabled"
|
|
97
124
|
:label="displayLabel"
|
|
98
125
|
:placeholder="question.description"
|
|
99
126
|
:required="question.required"
|
|
100
127
|
:value="value"
|
|
101
128
|
:tooltip="displayTooltip"
|
|
129
|
+
:paginated-resource-settings="paginateResourceSetting"
|
|
130
|
+
:all-resources-settings="allResourceSettings"
|
|
102
131
|
@update:value="!$fetchState.pending && $emit('update:value', $event)"
|
|
103
132
|
/>
|
|
104
133
|
</div>
|
|
@@ -104,6 +104,10 @@ export default {
|
|
|
104
104
|
:is="asLink ? 'a' : 'div'"
|
|
105
105
|
v-for="(r, idx) in rows"
|
|
106
106
|
:key="get(r, keyField)"
|
|
107
|
+
:role="asLink ? 'link' : null"
|
|
108
|
+
:aria-disabled="asLink && get(r, disabledField) === true ? true : null"
|
|
109
|
+
:aria-label="get(r, nameField)"
|
|
110
|
+
:tabindex="get(r, disabledField) === true ? -1 : 0"
|
|
107
111
|
:href="asLink ? get(r, linkField) : null"
|
|
108
112
|
:target="get(r, targetField)"
|
|
109
113
|
:rel="rel"
|
|
@@ -111,9 +115,12 @@ export default {
|
|
|
111
115
|
:data-testid="componentTestid + '-' + get(r, nameField)"
|
|
112
116
|
:class="{
|
|
113
117
|
'has-description': !!get(r, descriptionField),
|
|
114
|
-
'has-side-label': !!get(r, sideLabelField),
|
|
118
|
+
'has-side-label': !!get(r, sideLabelField),
|
|
119
|
+
[colorFor(r, idx)]: true,
|
|
120
|
+
disabled: get(r, disabledField) === true
|
|
115
121
|
}"
|
|
116
122
|
@click="select(r, idx)"
|
|
123
|
+
@keyup.enter.space="select(r, idx)"
|
|
117
124
|
>
|
|
118
125
|
<div
|
|
119
126
|
class="side-label"
|
|
@@ -212,6 +219,10 @@ export default {
|
|
|
212
219
|
text-decoration: none !important;
|
|
213
220
|
color: $color;
|
|
214
221
|
|
|
222
|
+
&:focus-visible {
|
|
223
|
+
@include focus-outline;
|
|
224
|
+
}
|
|
225
|
+
|
|
215
226
|
&:hover:not(.disabled) {
|
|
216
227
|
box-shadow: 0 0 30px var(--shadow);
|
|
217
228
|
transition: box-shadow 0.1s ease-in-out;
|
package/components/SideNav.vue
CHANGED
|
@@ -19,10 +19,11 @@ import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
|
19
19
|
import { TYPE_MODES } from '@shell/store/type-map';
|
|
20
20
|
import { NAME as NAVLINKS } from '@shell/config/product/navlinks';
|
|
21
21
|
import Group from '@shell/components/nav/Group';
|
|
22
|
+
import LocaleSelector from '@shell/components/LocaleSelector';
|
|
22
23
|
|
|
23
24
|
export default {
|
|
24
25
|
name: 'SideNav',
|
|
25
|
-
components: { Group },
|
|
26
|
+
components: { Group, LocaleSelector },
|
|
26
27
|
data() {
|
|
27
28
|
return {
|
|
28
29
|
groups: [],
|
|
@@ -112,9 +113,7 @@ export default {
|
|
|
112
113
|
computed: {
|
|
113
114
|
...mapState(['managementReady', 'clusterReady']),
|
|
114
115
|
...mapGetters(['isStandaloneHarvester', 'productId', 'clusterId', 'currentProduct', 'rootProduct', 'isSingleProduct', 'namespaceMode', 'isExplorer', 'isVirtualCluster']),
|
|
115
|
-
...mapGetters({
|
|
116
|
-
locale: 'i18n/selectedLocaleLabel', availableLocales: 'i18n/availableLocales', hasMultipleLocales: 'i18n/hasMultipleLocales'
|
|
117
|
-
}),
|
|
116
|
+
...mapGetters({ locale: 'i18n/selectedLocaleLabel', hasMultipleLocales: 'i18n/hasMultipleLocales' }),
|
|
118
117
|
...mapGetters('type-map', ['activeProducts']),
|
|
119
118
|
|
|
120
119
|
favoriteTypes: mapPref(FAVORITE_TYPES),
|
|
@@ -360,10 +359,6 @@ export default {
|
|
|
360
359
|
});
|
|
361
360
|
},
|
|
362
361
|
|
|
363
|
-
switchLocale(locale) {
|
|
364
|
-
this.$store.dispatch('i18n/switchTo', locale);
|
|
365
|
-
},
|
|
366
|
-
|
|
367
362
|
syncNav() {
|
|
368
363
|
const refs = this.$refs.groups;
|
|
369
364
|
|
|
@@ -427,6 +422,8 @@ export default {
|
|
|
427
422
|
<router-link
|
|
428
423
|
:to="supportLink"
|
|
429
424
|
class="pull-right"
|
|
425
|
+
role="link"
|
|
426
|
+
:aria-label="t('nav.support', {hasSupport: true})"
|
|
430
427
|
>
|
|
431
428
|
{{ t('nav.support', {hasSupport: true}) }}
|
|
432
429
|
</router-link>
|
|
@@ -439,36 +436,11 @@ export default {
|
|
|
439
436
|
</span>
|
|
440
437
|
|
|
441
438
|
<!-- locale selector -->
|
|
442
|
-
<
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
>
|
|
448
|
-
<a
|
|
449
|
-
data-testid="locale-selector"
|
|
450
|
-
class="locale-chooser"
|
|
451
|
-
>
|
|
452
|
-
{{ locale }}
|
|
453
|
-
</a>
|
|
454
|
-
|
|
455
|
-
<template #popper>
|
|
456
|
-
<ul
|
|
457
|
-
class="list-unstyled dropdown"
|
|
458
|
-
style="margin: -1px;"
|
|
459
|
-
>
|
|
460
|
-
<li
|
|
461
|
-
v-for="(label, name) in availableLocales"
|
|
462
|
-
:key="name"
|
|
463
|
-
class="hand"
|
|
464
|
-
@click="switchLocale(name)"
|
|
465
|
-
>
|
|
466
|
-
{{ label }}
|
|
467
|
-
</li>
|
|
468
|
-
</ul>
|
|
469
|
-
</template>
|
|
470
|
-
</v-dropdown>
|
|
471
|
-
</span>
|
|
439
|
+
<LocaleSelector
|
|
440
|
+
v-if="isSingleProduct && hasMultipleLocales && !isStandaloneHarvester"
|
|
441
|
+
mode="login"
|
|
442
|
+
:show-icon="false"
|
|
443
|
+
/>
|
|
472
444
|
</div>
|
|
473
445
|
<!-- SideNav footer alternative -->
|
|
474
446
|
<div
|
|
@@ -478,6 +450,8 @@ export default {
|
|
|
478
450
|
<router-link
|
|
479
451
|
v-if="singleProductAbout"
|
|
480
452
|
:to="singleProductAbout"
|
|
453
|
+
role="link"
|
|
454
|
+
:aria-label="t('nav.ariaLabel.productAboutPage')"
|
|
481
455
|
>
|
|
482
456
|
{{ displayVersion }}
|
|
483
457
|
</router-link>
|
|
@@ -258,7 +258,6 @@ export default {
|
|
|
258
258
|
role="tablist"
|
|
259
259
|
class="tabs"
|
|
260
260
|
:class="{'clearfix':!sideTabs, 'vertical': sideTabs, 'horizontal': !sideTabs}"
|
|
261
|
-
tabindex="0"
|
|
262
261
|
data-testid="tabbed-block"
|
|
263
262
|
@keydown.right.prevent="selectNext(1)"
|
|
264
263
|
@keydown.left.prevent="selectNext(-1)"
|
|
@@ -277,8 +276,12 @@ export default {
|
|
|
277
276
|
:data-testid="`btn-${tab.name}`"
|
|
278
277
|
:aria-controls="'#' + tab.name"
|
|
279
278
|
:aria-selected="tab.active"
|
|
279
|
+
:aria-label="tab.labelDisplay"
|
|
280
280
|
role="tab"
|
|
281
|
+
tabindex="0"
|
|
281
282
|
@click.prevent="select(tab.name, $event)"
|
|
283
|
+
@keyup.enter="select(tab.name, $event)"
|
|
284
|
+
@keyup.space="select(tab.name, $event)"
|
|
282
285
|
>
|
|
283
286
|
<span>{{ tab.labelDisplay }}</span>
|
|
284
287
|
<span
|
|
@@ -403,6 +406,14 @@ export default {
|
|
|
403
406
|
text-decoration: underline;
|
|
404
407
|
}
|
|
405
408
|
}
|
|
409
|
+
|
|
410
|
+
&:focus-visible {
|
|
411
|
+
@include focus-outline;
|
|
412
|
+
|
|
413
|
+
span {
|
|
414
|
+
text-decoration: underline;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
406
417
|
}
|
|
407
418
|
|
|
408
419
|
.conditions-alert-icon {
|
|
@@ -85,9 +85,11 @@ export default {
|
|
|
85
85
|
class="name"
|
|
86
86
|
>
|
|
87
87
|
<table>
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
<tbody>
|
|
89
|
+
<tr><td>{{ t('principal.name') }}: </td><td>{{ principal.name || principal.loginName }}</td></tr>
|
|
90
|
+
<tr><td>{{ t('principal.loginName') }}: </td><td>{{ principal.loginName }}</td></tr>
|
|
91
|
+
<tr><td>{{ t('principal.type') }}: </td><td>{{ principal.displayType }}</td></tr>
|
|
92
|
+
</tbody>
|
|
91
93
|
</table>
|
|
92
94
|
</div>
|
|
93
95
|
<template v-else>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import ResourceTable from '@shell/components/ResourceTable';
|
|
3
|
+
import Tag from '@shell/components/Tag.vue';
|
|
3
4
|
import { STATE, NAME, AGE, FLEET_SUMMARY } from '@shell/config/table-headers';
|
|
4
5
|
import { FLEET, MANAGEMENT } from '@shell/config/types';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
7
|
-
components: { ResourceTable },
|
|
8
|
+
components: { ResourceTable, Tag },
|
|
8
9
|
|
|
9
10
|
props: {
|
|
10
11
|
rows: {
|
|
@@ -75,6 +76,12 @@ export default {
|
|
|
75
76
|
pluralLabel: this.$store.getters['type-map/labelFor'](schema, 99),
|
|
76
77
|
};
|
|
77
78
|
},
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
methods: {
|
|
82
|
+
toggleCustomLabels(row) {
|
|
83
|
+
row['displayCustomLabels'] = !row.displayCustomLabels;
|
|
84
|
+
}
|
|
78
85
|
}
|
|
79
86
|
};
|
|
80
87
|
</script>
|
|
@@ -85,6 +92,7 @@ export default {
|
|
|
85
92
|
:schema="schema"
|
|
86
93
|
:headers="headers"
|
|
87
94
|
:rows="rows"
|
|
95
|
+
:sub-rows="true"
|
|
88
96
|
:loading="loading"
|
|
89
97
|
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
90
98
|
key-field="_key"
|
|
@@ -123,5 +131,78 @@ export default {
|
|
|
123
131
|
:class="{'text-error': !row.bundleInfo.total}"
|
|
124
132
|
>{{ row.bundleInfo.total }}</span>
|
|
125
133
|
</template>
|
|
134
|
+
|
|
135
|
+
<template #sub-row="{fullColspan, row, onRowMouseEnter, onRowMouseLeave}">
|
|
136
|
+
<tr
|
|
137
|
+
class="labels-row sub-row"
|
|
138
|
+
@mouseenter="onRowMouseEnter"
|
|
139
|
+
@mouseleave="onRowMouseLeave"
|
|
140
|
+
>
|
|
141
|
+
<template v-if="row.customLabels.length">
|
|
142
|
+
<td> </td>
|
|
143
|
+
<td> </td>
|
|
144
|
+
<td :colspan="fullColspan-2">
|
|
145
|
+
<span
|
|
146
|
+
v-if="row.customLabels.length"
|
|
147
|
+
class="mt-5"
|
|
148
|
+
> {{ t('fleet.cluster.labels') }}:
|
|
149
|
+
<span
|
|
150
|
+
v-for="(label, i) in row.customLabels"
|
|
151
|
+
:key="i"
|
|
152
|
+
class="mt-5 labels"
|
|
153
|
+
>
|
|
154
|
+
<Tag
|
|
155
|
+
v-if="i < 7"
|
|
156
|
+
class="mr-5 label"
|
|
157
|
+
>
|
|
158
|
+
{{ label }}
|
|
159
|
+
</Tag>
|
|
160
|
+
<Tag
|
|
161
|
+
v-else-if="i > 6 && row.displayCustomLabels"
|
|
162
|
+
class="mr-5 label"
|
|
163
|
+
>
|
|
164
|
+
{{ label }}
|
|
165
|
+
</Tag>
|
|
166
|
+
</span>
|
|
167
|
+
<a
|
|
168
|
+
v-if="row.customLabels.length > 7"
|
|
169
|
+
href="#"
|
|
170
|
+
@click.prevent="toggleCustomLabels(row)"
|
|
171
|
+
>
|
|
172
|
+
{{ t(`fleet.cluster.${row.displayCustomLabels? 'hideLabels' : 'showLabels'}`) }}
|
|
173
|
+
</a>
|
|
174
|
+
</span>
|
|
175
|
+
</td>
|
|
176
|
+
</template>
|
|
177
|
+
<td
|
|
178
|
+
v-else
|
|
179
|
+
:colspan="fullColspan"
|
|
180
|
+
>
|
|
181
|
+
|
|
182
|
+
</td>
|
|
183
|
+
</tr>
|
|
184
|
+
</template>
|
|
126
185
|
</ResourceTable>
|
|
127
186
|
</template>
|
|
187
|
+
|
|
188
|
+
<style lang='scss' scoped>
|
|
189
|
+
.labels-row {
|
|
190
|
+
td {
|
|
191
|
+
padding-top:0;
|
|
192
|
+
.tag {
|
|
193
|
+
margin-right: 5px;
|
|
194
|
+
display: inline-block;
|
|
195
|
+
margin-top: 2px;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
.labels {
|
|
200
|
+
display: inline;
|
|
201
|
+
flex-wrap: wrap;
|
|
202
|
+
|
|
203
|
+
.label {
|
|
204
|
+
display: inline-block;
|
|
205
|
+
margin-top: 2px;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
</style>
|
|
@@ -6,17 +6,15 @@ import FleetIntro from '@shell/components/fleet/FleetIntro';
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
AGE,
|
|
9
|
-
STATE,
|
|
10
|
-
NAME,
|
|
11
|
-
FLEET_SUMMARY,
|
|
12
9
|
FLEET_REPO,
|
|
13
|
-
FLEET_REPO_TARGET,
|
|
14
|
-
FLEET_REPO_CLUSTERS_READY,
|
|
15
10
|
FLEET_REPO_CLUSTER_SUMMARY,
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
FLEET_REPO_CLUSTERS_READY,
|
|
12
|
+
FLEET_REPO_PER_CLUSTER_STATE,
|
|
13
|
+
FLEET_REPO_TARGET,
|
|
14
|
+
FLEET_SUMMARY,
|
|
15
|
+
NAME,
|
|
16
|
+
STATE,
|
|
18
17
|
} from '@shell/config/table-headers';
|
|
19
|
-
import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
20
18
|
|
|
21
19
|
// i18n-ignore repoDisplay
|
|
22
20
|
export default {
|
|
@@ -77,31 +75,18 @@ export default {
|
|
|
77
75
|
|
|
78
76
|
headers() {
|
|
79
77
|
// Cluster summary is only shown in the cluster view
|
|
80
|
-
const
|
|
78
|
+
const summary = this.isClusterView ? [{
|
|
81
79
|
...FLEET_REPO_CLUSTER_SUMMARY,
|
|
82
|
-
formatterOpts: {
|
|
83
|
-
|
|
84
|
-
clusterLabel: this.clusterId
|
|
85
|
-
},
|
|
86
|
-
};
|
|
80
|
+
formatterOpts: { clusterId: this.clusterId },
|
|
81
|
+
}] : [FLEET_REPO_CLUSTERS_READY, FLEET_SUMMARY];
|
|
87
82
|
|
|
88
83
|
// if hasPerClusterState then use the repo state
|
|
89
|
-
const
|
|
84
|
+
const state = this.isClusterView ? {
|
|
90
85
|
...FLEET_REPO_PER_CLUSTER_STATE,
|
|
91
|
-
value: (
|
|
92
|
-
|
|
93
|
-
return c.clusterLabel === this.clusterId;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
return statePerCluster ? statePerCluster?.status?.displayStatus : STATES_ENUM.ACTIVE;
|
|
97
|
-
},
|
|
98
|
-
};
|
|
86
|
+
value: (repo) => repo.clusterState(this.clusterId),
|
|
87
|
+
} : STATE;
|
|
99
88
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const state = this.isClusterView ? fleetPerClusterState : STATE;
|
|
103
|
-
|
|
104
|
-
const out = [
|
|
89
|
+
return [
|
|
105
90
|
state,
|
|
106
91
|
NAME,
|
|
107
92
|
FLEET_REPO,
|
|
@@ -109,8 +94,6 @@ export default {
|
|
|
109
94
|
...summary,
|
|
110
95
|
AGE
|
|
111
96
|
];
|
|
112
|
-
|
|
113
|
-
return out;
|
|
114
97
|
},
|
|
115
98
|
},
|
|
116
99
|
methods: {
|
|
@@ -386,10 +386,10 @@ export default {
|
|
|
386
386
|
<router-link
|
|
387
387
|
:to="item.valueObj.detailLocation"
|
|
388
388
|
>
|
|
389
|
-
{{ item.valueObj.
|
|
389
|
+
{{ item.valueObj.label }}
|
|
390
390
|
</router-link>
|
|
391
391
|
</span>
|
|
392
|
-
<span v-else>{{ item.valueObj.
|
|
392
|
+
<span v-else>{{ item.valueObj.label }}</span>
|
|
393
393
|
</td>
|
|
394
394
|
<!-- state-badge template -->
|
|
395
395
|
<td
|
|
@@ -73,7 +73,21 @@ export default {
|
|
|
73
73
|
mounted() {
|
|
74
74
|
// Ensures that if the default value is used, the model is updated with it
|
|
75
75
|
this.$emit('update:value', this.inputValue);
|
|
76
|
-
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
methods: {
|
|
79
|
+
handleKeyup(ev) {
|
|
80
|
+
if (this.isDisabled) {
|
|
81
|
+
return '';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return this.$refs.input.click(ev);
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// according to https://www.w3.org/TR/html-aria/
|
|
89
|
+
// input type="color" has no applicable role
|
|
90
|
+
// and only aria-label and aria-disabled
|
|
77
91
|
};
|
|
78
92
|
</script>
|
|
79
93
|
|
|
@@ -82,6 +96,8 @@ export default {
|
|
|
82
96
|
class="color-input"
|
|
83
97
|
:class="{[mode]:mode, disabled: isDisabled}"
|
|
84
98
|
:data-testid="componentTestid + '-color-input'"
|
|
99
|
+
:tabindex="isDisabled ? -1 : 0"
|
|
100
|
+
@keyup.enter.space.stop="handleKeyup($event)"
|
|
85
101
|
>
|
|
86
102
|
<label class="text-label"><t
|
|
87
103
|
v-if="labelKey"
|
|
@@ -99,8 +115,11 @@ export default {
|
|
|
99
115
|
>
|
|
100
116
|
<input
|
|
101
117
|
ref="input"
|
|
118
|
+
:aria-disabled="isDisabled ? 'true' : 'false'"
|
|
119
|
+
:aria-label="t('generic.colorPicker')"
|
|
102
120
|
type="color"
|
|
103
121
|
:disabled="isDisabled"
|
|
122
|
+
tabindex="-1"
|
|
104
123
|
:value="inputValue"
|
|
105
124
|
@input="$emit('update:value', $event.target.value)"
|
|
106
125
|
>
|
|
@@ -116,6 +135,10 @@ export default {
|
|
|
116
135
|
border-radius: var(--border-radius);
|
|
117
136
|
padding: 10px;
|
|
118
137
|
|
|
138
|
+
&:focus-visible {
|
|
139
|
+
@include focus-outline;
|
|
140
|
+
}
|
|
141
|
+
|
|
119
142
|
&.disabled, &.disabled .selected, &[disabled], &[disabled]:hover {
|
|
120
143
|
color: var(--input-disabled-text);
|
|
121
144
|
background-color: var(--input-disabled-bg);
|