dashboard-shell-shell 1.0.111 → 1.0.113
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/.DS_Store +0 -0
- package/assets/icons/demo.css +539 -0
- package/assets/icons/demo_index.html +1131 -0
- package/assets/icons/iconfont.css +200 -0
- package/assets/icons/iconfont.js +1 -0
- package/assets/icons/iconfont.json +296 -0
- package/assets/icons/iconfont.ttf +0 -0
- package/assets/icons/iconfont.woff +0 -0
- package/assets/icons/iconfont.woff2 +0 -0
- package/assets/images/API.svg +3 -0
- package/assets/images/login/password.svg +20 -0
- package/assets/images/login/user.svg +6 -0
- package/assets/images/login-bg.png +0 -0
- package/assets/images/login-left.png +0 -0
- package/assets/images/login-logo.svg +19 -0
- package/assets/images/logo.png +0 -0
- package/assets/images/pl/harvester.png +0 -0
- package/assets/images/promp-yellow.svg +5 -0
- package/assets/images/user.png +0 -0
- package/assets/styles/all.scss +63 -0
- package/assets/styles/app.scss +2 -0
- package/assets/styles/base/_basic.scss +8 -2
- package/assets/styles/base/_helpers.scss +4 -0
- package/assets/styles/base/_typography.scss +2 -1
- package/assets/styles/base/_variables.scss +10 -2
- package/assets/styles/global/_button.scss +37 -25
- package/assets/styles/global/_columns.scss +3 -1
- package/assets/styles/global/_form.scss +45 -13
- package/assets/styles/global/_labeled-input.scss +50 -25
- package/assets/styles/global/_layout.scss +9 -3
- package/assets/styles/global/_select.scss +20 -13
- package/assets/styles/global/_table.scss +1 -1
- package/assets/styles/global/_tooltip.scss +47 -6
- package/assets/styles/themes/_dark.scss +1 -0
- package/assets/styles/themes/_light.scss +59 -46
- package/assets/styles/themes/_suse.scss +1 -0
- package/assets/styles/vendor/vue-select.scss +18 -7
- package/assets/translations/en-us.yaml +93 -12
- package/assets/translations/zh-hans.yaml +278 -141
- package/components/ActionDropdown.vue +1 -1
- package/components/ActionDropdownShell.vue +71 -0
- package/components/ActionMenu.vue +2 -2
- package/components/ActionMenuShell.vue +1 -0
- package/components/AppModal.vue +78 -6
- package/components/AssignTo.vue +25 -11
- package/components/AsyncButton.vue +24 -7
- package/components/BannerGraphic.vue +1 -0
- package/components/ButtonDropdown.vue +26 -4
- package/components/ButtonGroup.vue +4 -0
- package/components/ButtonMultiAction.vue +1 -0
- package/components/CommunityLinks.vue +3 -3
- package/components/ConsumptionGauge.vue +24 -5
- package/components/CopyToClipboardText.vue +2 -1
- package/components/CruResource.vue +12 -7
- package/components/CruResourceFooter.vue +2 -2
- package/components/DashboardOptions.vue +21 -15
- package/components/DetailText.vue +5 -0
- package/components/DisableAuthProviderModal.vue +1 -0
- package/components/DotState.vue +84 -0
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +56 -14
- package/components/FixedBanner.vue +19 -12
- package/components/GlobalRoleBindings.vue +5 -1
- package/components/GrafanaDashboard.vue +4 -4
- package/components/GrowlManager.vue +4 -1
- package/components/HardwareResourceGauge.vue +39 -3
- package/components/InfoBox.vue +3 -3
- package/components/InputOrDisplay.vue +28 -2
- package/components/LabelValue.vue +16 -1
- package/components/LandingPagePreference.vue +5 -3
- package/components/LocaleSelector.vue +39 -93
- package/components/ModalManager.vue +55 -0
- package/components/ModalWithCard.vue +2 -0
- package/components/MoveModal.vue +1 -0
- package/components/PromptChangePassword.vue +1 -1
- package/components/PromptModal.vue +15 -2
- package/components/PromptRemove.vue +28 -8
- package/components/PromptRestore.vue +1 -0
- package/components/ResourceCancelModal.vue +1 -0
- package/components/ResourceDetail/Masthead.vue +188 -43
- package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
- package/components/ResourceDetail/index.vue +49 -14
- package/components/ResourceList/Masthead.vue +80 -18
- package/components/ResourceTable.vue +60 -19
- package/components/SideNav.vue +32 -12
- package/components/SlideInPanelManager.vue +126 -0
- package/components/SortableTable/THead.vue +34 -5
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +649 -142
- package/components/SortableTable/paging.js +36 -28
- package/components/SortableTable/selection.js +0 -11
- package/components/StatusBadge.vue +77 -0
- package/components/Tabbed/Tab.vue +3 -3
- package/components/Tabbed/index.vue +44 -26
- package/components/Wizard.vue +2 -2
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/__tests__/FixedBanner.test.ts +3 -3
- package/components/__tests__/ModalManager.spec.ts +176 -0
- package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
- package/components/auth/Principal.vue +10 -3
- package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
- package/components/form/ArrayList.vue +123 -85
- package/components/form/ArrayListGrouped.vue +10 -2
- package/components/form/Command.vue +6 -15
- package/components/form/EnvVars.vue +16 -8
- package/components/form/Footer.vue +8 -5
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +11 -16
- package/components/form/KeyValue.vue +16 -7
- package/components/form/LabeledSelect.vue +59 -76
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +35 -12
- package/components/form/NameNsDescription.vue +147 -115
- package/components/form/Networking.vue +20 -12
- package/components/form/NodeAffinity.vue +31 -23
- package/components/form/NodeScheduling.vue +13 -3
- package/components/form/Password.vue +11 -5
- package/components/form/PodAffinity.vue +43 -44
- package/components/form/Probe.vue +68 -66
- package/components/form/ResourceQuota/Project.vue +5 -1
- package/components/form/ResourceSelector.vue +7 -9
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
- package/components/form/SSHKnownHosts/index.vue +16 -2
- package/components/form/Security.vue +54 -56
- package/components/form/Select.vue +41 -7
- package/components/form/ShellInput.vue +5 -1
- package/components/form/Tolerations.vue +5 -1
- package/components/form/UnitInput.vue +2 -2
- package/components/form/ValueFromResource.vue +134 -121
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +5 -2
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +115 -14
- package/components/form/__tests__/Probe.test.ts +12 -8
- package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
- package/components/form/__tests__/Select.test.ts +37 -0
- package/components/form/__tests__/UnitInput.test.ts +4 -5
- package/components/formatter/BadgeStateFormatter.vue +8 -5
- package/components/formatter/InternalExternalIP.vue +2 -0
- package/components/formatter/SecretData.vue +20 -7
- package/components/nav/Favorite.vue +5 -1
- package/components/nav/Group.vue +60 -27
- package/components/nav/Header.vue +39 -13
- package/components/nav/Jump.vue +7 -0
- package/components/nav/NamespaceFilter.vue +14 -8
- package/components/nav/Pinned.vue +1 -1
- package/components/nav/TopLevelMenu.vue +5 -17
- package/components/nav/Type.vue +32 -35
- package/components/nav/__tests__/TopLevelMenu.test.ts +0 -40
- package/components/templates/blank.vue +4 -1
- package/components/templates/default.vue +8 -0
- package/components/templates/home.vue +10 -1
- package/components/templates/plain.vue +10 -1
- package/package.json +1 -1
- package/rancher-components/Banner/Banner.vue +6 -4
- package/rancher-components/Card/Card.vue +6 -4
- package/rancher-components/Form/Checkbox/Checkbox.vue +20 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +46 -5
- package/rancher-components/Form/Radio/RadioButton.vue +32 -8
- package/rancher-components/Form/Radio/RadioGroup.vue +31 -24
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +8 -3
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +15 -3
- package/rancher-components/RcButton/RcButton.vue +1 -0
- package/rancher-components/RcButton/types.ts +1 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +54 -15
- package/rancher-components/RcDropdown/RcDropdownItem.vue +5 -4
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +11 -7
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +12 -2
- package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
- package/rancher-components/StringList/StringList.vue +1 -1
- package/store/type-map.js +29 -2
- package/utils/error.js +30 -8
- package/utils/errorTranslate.json +916 -0
- package/vue.config.js +1 -1
- package/components/formatter/ExtensionCache.vue +0 -74
- package/components/formatter/Port.vue +0 -24
- package/components/formatter/SecretType.vue +0 -41
|
@@ -6,18 +6,20 @@ import { DefaultProps } from 'vue/types/options';
|
|
|
6
6
|
|
|
7
7
|
describe('component: Probe', () => {
|
|
8
8
|
describe.each([
|
|
9
|
-
['
|
|
10
|
-
[
|
|
11
|
-
[
|
|
12
|
-
])('given kind %p', (
|
|
9
|
+
[{ httpGet: { scheme: 'https' } }, ['port', 'path']],
|
|
10
|
+
[{ tcpSocket: {} }, ['socket']],
|
|
11
|
+
[{ exec: {} }, ['command']],
|
|
12
|
+
])('given kind %p', (value, extraFields) => {
|
|
13
13
|
it.each([
|
|
14
14
|
...extraFields,
|
|
15
15
|
'successThreshold',
|
|
16
16
|
'failureThreshold',
|
|
17
17
|
])('should emit an update on %p input', (field) => {
|
|
18
18
|
const wrapper = mount(Probe as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
19
|
-
props: {
|
|
20
|
-
|
|
19
|
+
props: {
|
|
20
|
+
mode: _EDIT,
|
|
21
|
+
value,
|
|
22
|
+
},
|
|
21
23
|
});
|
|
22
24
|
const input = wrapper.find(`[data-testid="input-probe-${ field }"]`).find('input');
|
|
23
25
|
const newValue = 123;
|
|
@@ -33,8 +35,10 @@ describe('component: Probe', () => {
|
|
|
33
35
|
'timeoutSeconds',
|
|
34
36
|
])('should emit an update on %p input and blur', (field) => {
|
|
35
37
|
const wrapper = mount(Probe as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
36
|
-
props: {
|
|
37
|
-
|
|
38
|
+
props: {
|
|
39
|
+
mode: _EDIT,
|
|
40
|
+
value
|
|
41
|
+
},
|
|
38
42
|
});
|
|
39
43
|
const input = wrapper.find(`[data-testid="input-probe-${ field }"]`).find('input');
|
|
40
44
|
const newValue = 123;
|
|
@@ -2,6 +2,17 @@ import { mount } from '@vue/test-utils';
|
|
|
2
2
|
import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
3
3
|
import SSHKnownHosts from '@shell/components/form/SSHKnownHosts/index.vue';
|
|
4
4
|
|
|
5
|
+
jest.mock('focus-trap', () => {
|
|
6
|
+
return {
|
|
7
|
+
createFocusTrap: jest.fn().mockImplementation(() => {
|
|
8
|
+
return {
|
|
9
|
+
activate: jest.fn(),
|
|
10
|
+
deactivate: jest.fn(),
|
|
11
|
+
};
|
|
12
|
+
}),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
5
16
|
describe('component: SSHKnownHosts', () => {
|
|
6
17
|
it.each([
|
|
7
18
|
['0 entities', '', 0],
|
|
@@ -27,4 +27,41 @@ describe('select.vue', () => {
|
|
|
27
27
|
// eslint-disable-next-line no-console
|
|
28
28
|
expect(console.warn).not.toHaveBeenCalled();
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
it('a11y: adding ARIA props should correctly fill out the appropriate fields on the component', async() => {
|
|
32
|
+
const label = 'Foo';
|
|
33
|
+
const value = 'foo';
|
|
34
|
+
const ariaDescribedById = 'some-described-by-id';
|
|
35
|
+
const ariaLabelText = 'some-aria-label';
|
|
36
|
+
|
|
37
|
+
const wrapper = shallowMount(SelectComponent, {
|
|
38
|
+
props: {
|
|
39
|
+
value,
|
|
40
|
+
options: [
|
|
41
|
+
{ label, value },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
attrs: {
|
|
45
|
+
'aria-describedby': ariaDescribedById,
|
|
46
|
+
'aria-label': ariaLabelText,
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const labeledSelectContainer = wrapper.find('.unlabeled-select');
|
|
51
|
+
const ariaExpanded = labeledSelectContainer.attributes('aria-expanded');
|
|
52
|
+
const ariaDescribedBy = labeledSelectContainer.attributes('aria-describedby');
|
|
53
|
+
const ariaLabel = labeledSelectContainer.attributes('aria-label');
|
|
54
|
+
|
|
55
|
+
const vSelectInput = wrapper.find('.inline');
|
|
56
|
+
|
|
57
|
+
expect(ariaExpanded).toBe('false');
|
|
58
|
+
expect(ariaDescribedBy).toBe(ariaDescribedById);
|
|
59
|
+
expect(ariaLabel).toBe(ariaLabelText);
|
|
60
|
+
|
|
61
|
+
// make sure it's hardcoded to a "neutral" value so that
|
|
62
|
+
// in the current architecture of the component
|
|
63
|
+
// screen readers won't pick up the default "Select option" aria-label
|
|
64
|
+
// from the library
|
|
65
|
+
expect(vSelectInput.attributes('aria-label')).toBe('-');
|
|
66
|
+
});
|
|
30
67
|
});
|
|
@@ -11,7 +11,7 @@ describe('component: UnitInput', () => {
|
|
|
11
11
|
expect(wrapper.isVisible()).toBe(true);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
it.each(['blur', '
|
|
14
|
+
it.each(['blur', 'update:value'])('should emit input event when "%p" is fired', async(event) => {
|
|
15
15
|
const wrapper = mount(UnitInput, { props: { value: 1, delay: 0 } });
|
|
16
16
|
const input = wrapper.find('input');
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ describe('component: UnitInput', () => {
|
|
|
20
20
|
input.trigger(event);
|
|
21
21
|
|
|
22
22
|
expect(wrapper.emitted('update:value')).toBeTruthy();
|
|
23
|
-
expect(wrapper.emitted('update:value')[
|
|
23
|
+
expect(wrapper.emitted('update:value')[1]).toStrictEqual([4]);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
it.each([
|
|
@@ -184,7 +184,7 @@ describe('component: UnitInput', () => {
|
|
|
184
184
|
input.trigger('blur');
|
|
185
185
|
|
|
186
186
|
expect(wrapper.emitted('update:value')).toBeTruthy();
|
|
187
|
-
expect(wrapper.emitted('update:value')[
|
|
187
|
+
expect(wrapper.emitted('update:value')[0][0]).toBe(value);
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
describe.each([
|
|
@@ -207,7 +207,7 @@ describe('component: UnitInput', () => {
|
|
|
207
207
|
expect(inputElement.value).toBe('123');
|
|
208
208
|
});
|
|
209
209
|
|
|
210
|
-
it.each(['
|
|
210
|
+
it.each(['update:value', 'blur'])('on %p 123 should display input value 123', async(trigger) => {
|
|
211
211
|
const wrapper = mount(UnitInput, {
|
|
212
212
|
props: {
|
|
213
213
|
value: '0',
|
|
@@ -248,7 +248,6 @@ describe('component: UnitInput', () => {
|
|
|
248
248
|
const input = wrapper.find('input');
|
|
249
249
|
|
|
250
250
|
await input.trigger('update:value');
|
|
251
|
-
await input.trigger('input');
|
|
252
251
|
|
|
253
252
|
expect(input.element.value).toBe('123');
|
|
254
253
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { BadgeState } from '@components/BadgeState';
|
|
3
|
+
import DotState from '@shell/components/DotState'
|
|
3
4
|
import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
4
5
|
export default {
|
|
5
|
-
components: { BadgeState },
|
|
6
|
+
components: { BadgeState, DotState },
|
|
6
7
|
props: {
|
|
7
8
|
value: {
|
|
8
9
|
type: String,
|
|
@@ -49,15 +50,17 @@ export default {
|
|
|
49
50
|
<template>
|
|
50
51
|
<div>
|
|
51
52
|
<div v-if="arbitrary">
|
|
52
|
-
<BadgeState
|
|
53
|
+
<!-- <BadgeState
|
|
53
54
|
v-if="value"
|
|
54
55
|
:color="stateBackground"
|
|
55
56
|
:label="stateDisplay"
|
|
56
|
-
/>
|
|
57
|
+
/> -->
|
|
58
|
+
<DotState v-if="value" :color="stateBackground" :label="stateDisplay" />
|
|
57
59
|
</div>
|
|
58
|
-
<BadgeState
|
|
60
|
+
<!-- <BadgeState
|
|
59
61
|
v-else
|
|
60
62
|
:value="row"
|
|
61
|
-
/>
|
|
63
|
+
/> -->
|
|
64
|
+
<DotState v-else :value="row" />
|
|
62
65
|
</div>
|
|
63
66
|
</template>
|
|
@@ -28,6 +28,7 @@ export default {
|
|
|
28
28
|
<span>
|
|
29
29
|
<template v-if="isIp(row.externalIp)">
|
|
30
30
|
{{ row.externalIp }} <CopyToClipboard
|
|
31
|
+
:aria-label="t('internalExternalIP.copyExternalIp')"
|
|
31
32
|
label-as="tooltip"
|
|
32
33
|
:text="row.externalIp"
|
|
33
34
|
class="icon-btn"
|
|
@@ -43,6 +44,7 @@ export default {
|
|
|
43
44
|
</template>
|
|
44
45
|
<template v-else-if="isIp(row.internalIp)">
|
|
45
46
|
{{ row.internalIp }}<CopyToClipboard
|
|
47
|
+
:aria-label="t('internalExternalIP.copyInternalIp')"
|
|
46
48
|
label-as="tooltip"
|
|
47
49
|
:text="row.internalIp"
|
|
48
50
|
class="icon-btn"
|
|
@@ -13,17 +13,25 @@ export default {
|
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
beforeMount() {
|
|
17
17
|
if (this.value.issuer) {
|
|
18
18
|
const { cn, notAfter, sans = [] } = this.value;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return { isTLS: false };
|
|
20
|
+
this.expiration = notAfter;
|
|
21
|
+
this.sans = sans;
|
|
22
|
+
this.cn = cn;
|
|
23
|
+
this.isTLS = true;
|
|
25
24
|
}
|
|
26
25
|
},
|
|
26
|
+
|
|
27
|
+
data() {
|
|
28
|
+
return {
|
|
29
|
+
isTLS: false,
|
|
30
|
+
cn: null,
|
|
31
|
+
sans: [],
|
|
32
|
+
expiration: null,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
27
35
|
computed: {
|
|
28
36
|
// use 'text-warning' or 'text-error' classes if the cert is <8 days from expiring or expired respectively
|
|
29
37
|
dateClass() {
|
|
@@ -43,7 +51,12 @@ export default {
|
|
|
43
51
|
|
|
44
52
|
<template>
|
|
45
53
|
<div v-if="isTLS">
|
|
46
|
-
<t k="secret.certificate.cn" />
|
|
54
|
+
<t k="secret.certificate.cn" />
|
|
55
|
+
{{ cn }}
|
|
56
|
+
<span v-if="row.unrepeatedSans && row.unrepeatedSans.length">
|
|
57
|
+
{{ t('secret.certificate.plusMore', {n:row.unrepeatedSans.length}) }}
|
|
58
|
+
</span>
|
|
59
|
+
<br>
|
|
47
60
|
<t k="secret.certificate.expires" />: <DateComponent
|
|
48
61
|
:class="dateClass"
|
|
49
62
|
:value="expiration"
|
|
@@ -10,6 +10,9 @@ export default {
|
|
|
10
10
|
computed: {
|
|
11
11
|
isFavorite() {
|
|
12
12
|
return this.$store.getters['type-map/isFavorite'](this.resource);
|
|
13
|
+
},
|
|
14
|
+
ariaLabel() {
|
|
15
|
+
return this.t(`resourceDetail.masthead.ariaLabel.${ this.isFavorite ? 'unfavoriteAction' : 'favoriteAction' }`, { resource: this.resource });
|
|
13
16
|
}
|
|
14
17
|
},
|
|
15
18
|
|
|
@@ -28,10 +31,11 @@ export default {
|
|
|
28
31
|
<template>
|
|
29
32
|
<i
|
|
30
33
|
:tabindex="0"
|
|
31
|
-
:aria-
|
|
34
|
+
:aria-pressed="!!isFavorite"
|
|
32
35
|
class="favorite icon"
|
|
33
36
|
:class="{'icon-star-open': !isFavorite, 'icon-star': isFavorite}"
|
|
34
37
|
aria-role="button"
|
|
38
|
+
:aria-label="ariaLabel"
|
|
35
39
|
@click.stop.prevent="toggle"
|
|
36
40
|
@keydown.enter.prevent="toggle"
|
|
37
41
|
@keydown.space.prevent="toggle"
|
package/components/nav/Group.vue
CHANGED
|
@@ -158,6 +158,17 @@ export default {
|
|
|
158
158
|
items = this.group;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
let parentPath = '';
|
|
162
|
+
const cluster = this.$route.params?.cluster;
|
|
163
|
+
|
|
164
|
+
// Where we use nested route configuration, consider the parent route when trying to identify the nav location
|
|
165
|
+
if (this.$route.matched.length > 1) {
|
|
166
|
+
const parentRoute = this.$route.matched[this.$route.matched.length - 2];
|
|
167
|
+
|
|
168
|
+
parentPath = parentRoute.path.replace(':cluster', cluster);
|
|
169
|
+
parentPath = parentPath === '/' ? undefined : parentPath;
|
|
170
|
+
}
|
|
171
|
+
|
|
161
172
|
for (const item of items.children) {
|
|
162
173
|
if (item.children && this.hasActiveRoute(item)) {
|
|
163
174
|
return true;
|
|
@@ -166,8 +177,11 @@ export default {
|
|
|
166
177
|
const matchesNavLevel = navLevels.filter((param) => !this.$route.params[param] || this.$route.params[param] !== item.route.params[param]).length === 0;
|
|
167
178
|
const withoutHash = this.$route.hash ? this.$route.fullPath.slice(0, this.$route.fullPath.indexOf(this.$route.hash)) : this.$route.fullPath;
|
|
168
179
|
const withoutQuery = withoutHash.split('?')[0];
|
|
180
|
+
const itemFullPath = this.$router.resolve(item.route).fullPath;
|
|
169
181
|
|
|
170
|
-
if (matchesNavLevel ||
|
|
182
|
+
if (matchesNavLevel || itemFullPath === withoutQuery) {
|
|
183
|
+
return true;
|
|
184
|
+
} else if (parentPath && itemFullPath === parentPath) {
|
|
171
185
|
return true;
|
|
172
186
|
}
|
|
173
187
|
}
|
|
@@ -231,8 +245,11 @@ export default {
|
|
|
231
245
|
</router-link>
|
|
232
246
|
<h6
|
|
233
247
|
v-else
|
|
248
|
+
@click="peek($event, true)"
|
|
234
249
|
>
|
|
235
|
-
|
|
250
|
+
<i :class="'nav-icon icon-'+group.name.replace(/\s+/g, '').toLowerCase()" />
|
|
251
|
+
{{ group.labelDisplay || group.label }}
|
|
252
|
+
<!-- <span v-clean-html="group.labelDisplay || group.label" /> -->
|
|
236
253
|
</h6>
|
|
237
254
|
</slot>
|
|
238
255
|
<i
|
|
@@ -260,7 +277,7 @@ export default {
|
|
|
260
277
|
v-if="child.divider"
|
|
261
278
|
:key="idx"
|
|
262
279
|
>
|
|
263
|
-
<hr>
|
|
280
|
+
<hr role="none">
|
|
264
281
|
</li>
|
|
265
282
|
<!-- <div v-else-if="child[childrenKey] && hideGroup(child[childrenKey])" :key="child.name">
|
|
266
283
|
HIDDEN
|
|
@@ -342,21 +359,28 @@ export default {
|
|
|
342
359
|
}
|
|
343
360
|
|
|
344
361
|
&.active {
|
|
345
|
-
color: var(--
|
|
346
|
-
background-color: var(--
|
|
362
|
+
color: var(--nav-hover-color);
|
|
363
|
+
background-color: var(--nav-active);
|
|
347
364
|
|
|
348
365
|
h6 {
|
|
349
|
-
padding: 8px 0 8px 16px;
|
|
350
|
-
font-weight: bold;
|
|
351
|
-
color: var(--
|
|
366
|
+
/* padding: 8px 0 8px 16px;
|
|
367
|
+
font-weight: bold; */
|
|
368
|
+
color: var(--nav-hover-color);
|
|
369
|
+
}
|
|
370
|
+
I{
|
|
371
|
+
color: var(--nav-hover-color);
|
|
352
372
|
}
|
|
353
373
|
|
|
354
|
-
&:hover {
|
|
374
|
+
/* &:hover {
|
|
355
375
|
background-color: var(--primary-hover-bg);
|
|
356
|
-
}
|
|
376
|
+
} */
|
|
357
377
|
}
|
|
358
378
|
&:hover:not(.active) {
|
|
359
|
-
background-color: var(--nav-
|
|
379
|
+
background-color: var(--nav-active);
|
|
380
|
+
color: var(--nav-hover-color);
|
|
381
|
+
h6{
|
|
382
|
+
color: var(--nav-hover-color);
|
|
383
|
+
}
|
|
360
384
|
}
|
|
361
385
|
}
|
|
362
386
|
}
|
|
@@ -364,49 +388,53 @@ export default {
|
|
|
364
388
|
.accordion {
|
|
365
389
|
&.depth-0 {
|
|
366
390
|
> .header {
|
|
391
|
+
/* padding: 8px 0; */
|
|
392
|
+
padding: 0px 0px 0px 20px;
|
|
393
|
+
height: 50px;
|
|
367
394
|
|
|
368
395
|
&.noHover {
|
|
369
396
|
cursor: default;
|
|
370
397
|
}
|
|
371
398
|
|
|
372
399
|
> H6 {
|
|
400
|
+
font-size: 14px;
|
|
373
401
|
text-transform: none;
|
|
374
|
-
|
|
402
|
+
line-height: 50px;
|
|
403
|
+
display: flex;
|
|
404
|
+
align-items: center;
|
|
375
405
|
}
|
|
376
406
|
|
|
377
407
|
> I {
|
|
378
408
|
position: absolute;
|
|
379
409
|
right: 0;
|
|
380
410
|
top: 0;
|
|
381
|
-
padding:
|
|
411
|
+
padding: 0px 20px 0px 0px;
|
|
382
412
|
user-select: none;
|
|
413
|
+
line-height: 50px;
|
|
383
414
|
}
|
|
384
415
|
}
|
|
385
416
|
|
|
386
417
|
> .body {
|
|
387
418
|
margin-left: 0;
|
|
388
419
|
}
|
|
389
|
-
|
|
390
|
-
&.group-highlight {
|
|
391
|
-
background: var(--nav-active);
|
|
392
|
-
}
|
|
393
420
|
}
|
|
394
421
|
|
|
395
422
|
&.depth-1 {
|
|
396
423
|
> .header {
|
|
397
|
-
padding-left: 20px;
|
|
398
424
|
> H6 {
|
|
399
|
-
|
|
425
|
+
font-size: 13px;
|
|
426
|
+
line-height: 16px;
|
|
400
427
|
padding: 8px 0 7px 5px !important;
|
|
401
428
|
}
|
|
402
429
|
> I {
|
|
403
|
-
padding:
|
|
430
|
+
padding: 9px 7px 8px 7px !important;
|
|
404
431
|
}
|
|
405
432
|
}
|
|
406
433
|
}
|
|
407
434
|
|
|
408
435
|
&:not(.depth-0) {
|
|
409
436
|
> .header {
|
|
437
|
+
padding-left: 10px;
|
|
410
438
|
> H6 {
|
|
411
439
|
// Child groups that aren't linked themselves
|
|
412
440
|
display: inline-block;
|
|
@@ -428,13 +456,16 @@ export default {
|
|
|
428
456
|
padding: 0;
|
|
429
457
|
|
|
430
458
|
A, A I {
|
|
431
|
-
color: var(--primary-hover-text);
|
|
459
|
+
/* color: var(--primary-hover-text); */
|
|
460
|
+
color: var(--nav-hover-color);
|
|
432
461
|
}
|
|
433
462
|
|
|
434
463
|
A {
|
|
435
|
-
color: var(--
|
|
436
|
-
|
|
437
|
-
|
|
464
|
+
background-color: var(--nav-active);
|
|
465
|
+
::v-deep .icon {
|
|
466
|
+
/* color: var(--body-text); */
|
|
467
|
+
color: var(--nav-hover-color);
|
|
468
|
+
}
|
|
438
469
|
}
|
|
439
470
|
}
|
|
440
471
|
|
|
@@ -443,9 +474,6 @@ export default {
|
|
|
443
474
|
border-left: solid 5px transparent;
|
|
444
475
|
line-height: 16px;
|
|
445
476
|
font-size: 14px;
|
|
446
|
-
padding-left: 24px;
|
|
447
|
-
display: flex;
|
|
448
|
-
justify-content: space-between;
|
|
449
477
|
}
|
|
450
478
|
|
|
451
479
|
A:focus {
|
|
@@ -459,4 +487,9 @@ export default {
|
|
|
459
487
|
}
|
|
460
488
|
}
|
|
461
489
|
}
|
|
490
|
+
.nav-icon{
|
|
491
|
+
font-size: 32px;
|
|
492
|
+
margin-top: -11px;
|
|
493
|
+
color: #a8abb2;
|
|
494
|
+
}
|
|
462
495
|
</style>
|
|
@@ -81,7 +81,8 @@ export default {
|
|
|
81
81
|
extensionHeaderActions: getApplicableExtensionEnhancements(this, ExtensionPoint.ACTION, ActionLocation.HEADER, this.$route),
|
|
82
82
|
ctx: this,
|
|
83
83
|
showImportModal: false,
|
|
84
|
-
showSearchModal: false
|
|
84
|
+
showSearchModal: false,
|
|
85
|
+
userIcon: require('~shell/assets/images/logo.png'),
|
|
85
86
|
};
|
|
86
87
|
},
|
|
87
88
|
|
|
@@ -404,7 +405,7 @@ export default {
|
|
|
404
405
|
<TopLevelMenu v-if="isRancherInHarvester || isMultiCluster || !isSingleProduct" />
|
|
405
406
|
</div>
|
|
406
407
|
|
|
407
|
-
<div
|
|
408
|
+
<!-- <div
|
|
408
409
|
class="menu-spacer"
|
|
409
410
|
:class="{'isSingleProduct': isSingleProduct }"
|
|
410
411
|
>
|
|
@@ -523,8 +524,20 @@ export default {
|
|
|
523
524
|
:alt="t('branding.logos.label')"
|
|
524
525
|
/>
|
|
525
526
|
</div>
|
|
526
|
-
</div>
|
|
527
|
+
</div> -->
|
|
527
528
|
|
|
529
|
+
<!-- logo -->
|
|
530
|
+
<div class="menu-spacer">
|
|
531
|
+
<router-link
|
|
532
|
+
v-if="isSingleProduct && !isRancherInHarvester"
|
|
533
|
+
:to="singleProductLogoRoute"
|
|
534
|
+
>
|
|
535
|
+
<img
|
|
536
|
+
:src="userIcon"
|
|
537
|
+
>
|
|
538
|
+
</router-link>
|
|
539
|
+
</div>
|
|
540
|
+
<!-- 中间 -->
|
|
528
541
|
<div class="spacer" />
|
|
529
542
|
|
|
530
543
|
<div class="rd-header-right">
|
|
@@ -696,20 +709,23 @@ export default {
|
|
|
696
709
|
data-testid="nav_header_showUserMenu"
|
|
697
710
|
:aria-label="t('nav.userMenu.button.label')"
|
|
698
711
|
>
|
|
699
|
-
<img
|
|
712
|
+
<!-- <img
|
|
700
713
|
v-if="principal && principal.avatarSrc"
|
|
701
714
|
:src="principal.avatarSrc"
|
|
702
715
|
:class="{'avatar-round': principal.roundAvatar}"
|
|
703
716
|
width="36"
|
|
704
717
|
height="36"
|
|
718
|
+
:alt="t('nav.alt.userAvatar')"
|
|
705
719
|
>
|
|
706
720
|
<i
|
|
707
721
|
v-else
|
|
708
722
|
class="icon icon-user icon-3x avatar"
|
|
709
|
-
/>
|
|
723
|
+
/> -->
|
|
724
|
+
<i class="icon icon-usericon" />
|
|
725
|
+
<span class="login-name">{{ principal.loginName }}</span>
|
|
710
726
|
</rc-dropdown-trigger>
|
|
711
727
|
<template #dropdownCollection>
|
|
712
|
-
<template v-if="authEnabled">
|
|
728
|
+
<!-- <template v-if="authEnabled">
|
|
713
729
|
<div class="user-info">
|
|
714
730
|
<div class="user-name">
|
|
715
731
|
<i class="icon icon-lg icon-user" /> {{ principal.loginName }}
|
|
@@ -721,13 +737,13 @@ export default {
|
|
|
721
737
|
</div>
|
|
722
738
|
</div>
|
|
723
739
|
<rc-dropdown-separator />
|
|
724
|
-
</template>
|
|
725
|
-
<rc-dropdown-item
|
|
740
|
+
</template> -->
|
|
741
|
+
<!-- <rc-dropdown-item
|
|
726
742
|
v-if="showPreferencesLink"
|
|
727
743
|
@click="$router.push({ name: 'prefs'})"
|
|
728
744
|
>
|
|
729
745
|
{{ t('nav.userMenu.preferences') }}
|
|
730
|
-
</rc-dropdown-item>
|
|
746
|
+
</rc-dropdown-item> -->
|
|
731
747
|
<rc-dropdown-item
|
|
732
748
|
v-if="showAccountAndApiKeyLink"
|
|
733
749
|
@click="$router.push({ name: 'account'})"
|
|
@@ -760,6 +776,7 @@ export default {
|
|
|
760
776
|
HEADER {
|
|
761
777
|
display: flex;
|
|
762
778
|
z-index: z-index('mainHeader');
|
|
779
|
+
box-shadow: 0px 3px 3px 1px rgba(0,0,0,0.12);
|
|
763
780
|
|
|
764
781
|
> .spacer {
|
|
765
782
|
flex: 1;
|
|
@@ -877,7 +894,7 @@ export default {
|
|
|
877
894
|
|
|
878
895
|
> * {
|
|
879
896
|
background-color: var(--header-bg);
|
|
880
|
-
border-bottom: var(--header-border-size) solid var(--header-border);
|
|
897
|
+
/* border-bottom: var(--header-border-size) solid var(--header-border); */
|
|
881
898
|
}
|
|
882
899
|
|
|
883
900
|
.rd-header-right {
|
|
@@ -890,7 +907,7 @@ export default {
|
|
|
890
907
|
}
|
|
891
908
|
|
|
892
909
|
> .top {
|
|
893
|
-
padding-top:
|
|
910
|
+
padding-top: 10px;
|
|
894
911
|
|
|
895
912
|
INPUT[type='search']::placeholder,
|
|
896
913
|
.vs__open-indicator,
|
|
@@ -1010,7 +1027,7 @@ export default {
|
|
|
1010
1027
|
|
|
1011
1028
|
> .user {
|
|
1012
1029
|
outline: none;
|
|
1013
|
-
width: var(--header-height);
|
|
1030
|
+
/* width: var(--header-height); */
|
|
1014
1031
|
|
|
1015
1032
|
.v-popper {
|
|
1016
1033
|
display: flex;
|
|
@@ -1024,6 +1041,10 @@ export default {
|
|
|
1024
1041
|
.user-image {
|
|
1025
1042
|
display: flex;
|
|
1026
1043
|
align-items: center;
|
|
1044
|
+
&:hover{
|
|
1045
|
+
color: var(--primary);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1027
1048
|
}
|
|
1028
1049
|
|
|
1029
1050
|
&:focus {
|
|
@@ -1152,5 +1173,10 @@ export default {
|
|
|
1152
1173
|
}
|
|
1153
1174
|
}
|
|
1154
1175
|
}
|
|
1155
|
-
|
|
1176
|
+
.login-name{
|
|
1177
|
+
font-size: 14px;
|
|
1178
|
+
margin-left: 5px;
|
|
1179
|
+
margin-top: 5px;
|
|
1180
|
+
line-height: 20px;
|
|
1181
|
+
}
|
|
1156
1182
|
</style>
|
package/components/nav/Jump.vue
CHANGED
|
@@ -71,6 +71,12 @@ export default {
|
|
|
71
71
|
|
|
72
72
|
<template>
|
|
73
73
|
<div>
|
|
74
|
+
<p
|
|
75
|
+
id="describe-filter-resource-search"
|
|
76
|
+
hidden
|
|
77
|
+
>
|
|
78
|
+
{{ t('nav.resourceSearch.filteringDescription') }}
|
|
79
|
+
</p>
|
|
74
80
|
<input
|
|
75
81
|
ref="input"
|
|
76
82
|
v-model="value"
|
|
@@ -78,6 +84,7 @@ export default {
|
|
|
78
84
|
class="search"
|
|
79
85
|
role="textbox"
|
|
80
86
|
:aria-label="t('nav.resourceSearch.label')"
|
|
87
|
+
aria-describedby="describe-filter-resource-search"
|
|
81
88
|
@keyup.esc="$emit('closeSearch')"
|
|
82
89
|
>
|
|
83
90
|
<div class="results">
|