dashboard-shell-shell 1.0.113 → 1.0.115
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/components/ActionDropdown.vue +1 -1
- package/components/ActionMenu.vue +2 -2
- package/components/ActionMenuShell.vue +0 -1
- package/components/AppModal.vue +6 -78
- package/components/AssignTo.vue +11 -25
- package/components/AsyncButton.vue +7 -24
- package/components/BannerGraphic.vue +0 -1
- package/components/ButtonDropdown.vue +4 -26
- package/components/ButtonGroup.vue +0 -4
- package/components/ButtonMultiAction.vue +0 -1
- package/components/CommunityLinks.vue +3 -3
- package/components/ConsumptionGauge.vue +5 -24
- package/components/CopyToClipboardText.vue +1 -2
- package/components/CruResource.vue +7 -12
- package/components/CruResourceFooter.vue +2 -2
- package/components/DashboardOptions.vue +15 -21
- package/components/DetailText.vue +0 -5
- package/components/DisableAuthProviderModal.vue +0 -1
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +14 -56
- package/components/FixedBanner.vue +12 -19
- package/components/GlobalRoleBindings.vue +1 -5
- package/components/GrafanaDashboard.vue +4 -4
- package/components/GrowlManager.vue +1 -4
- package/components/HardwareResourceGauge.vue +3 -39
- package/components/InfoBox.vue +3 -3
- package/components/InputOrDisplay.vue +2 -28
- package/components/LabelValue.vue +1 -16
- package/components/LandingPagePreference.vue +3 -5
- package/components/LocaleSelector.vue +93 -39
- package/components/ModalWithCard.vue +0 -2
- package/components/MoveModal.vue +0 -1
- package/components/PromptChangePassword.vue +1 -1
- package/components/PromptModal.vue +2 -15
- package/components/PromptRemove.vue +8 -28
- package/components/PromptRestore.vue +0 -1
- package/components/ResourceCancelModal.vue +0 -1
- package/components/ResourceDetail/Masthead.vue +43 -188
- package/components/ResourceDetail/__tests__/Masthead.test.ts +1 -5
- package/components/ResourceDetail/index.vue +14 -49
- package/components/ResourceList/Masthead.vue +18 -80
- package/components/ResourceTable.vue +8 -3
- package/components/SideNav.vue +3 -2
- package/components/SortableTable/THead.vue +4 -10
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +537 -637
- package/components/SortableTable/selection.js +11 -0
- package/components/Tabbed/Tab.vue +3 -3
- package/components/Tabbed/index.vue +26 -44
- package/components/Wizard.vue +2 -2
- package/components/__tests__/AsyncButton.test.ts +2 -2
- package/components/__tests__/FixedBanner.test.ts +3 -3
- package/components/auth/Principal.vue +3 -10
- package/components/auth/__tests__/RoleDetailEdit.test.ts +2 -3
- package/components/form/ArrayList.vue +85 -123
- package/components/form/ArrayListGrouped.vue +2 -10
- package/components/form/Command.vue +15 -6
- package/components/form/EnvVars.vue +8 -16
- package/components/form/Footer.vue +5 -8
- package/components/form/HealthCheck.vue +3 -3
- package/components/form/HookOption.vue +16 -11
- package/components/form/KeyValue.vue +7 -16
- package/components/form/LabeledSelect.vue +76 -59
- package/components/form/LifecycleHooks.vue +3 -3
- package/components/form/MatchExpressions.vue +12 -35
- package/components/form/NameNsDescription.vue +115 -147
- package/components/form/Networking.vue +12 -20
- package/components/form/NodeAffinity.vue +23 -31
- package/components/form/NodeScheduling.vue +3 -13
- package/components/form/Password.vue +5 -11
- package/components/form/PodAffinity.vue +44 -43
- package/components/form/Probe.vue +66 -68
- package/components/form/ResourceQuota/Project.vue +1 -5
- package/components/form/ResourceSelector.vue +9 -7
- package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +3 -6
- package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +1 -12
- package/components/form/SSHKnownHosts/index.vue +2 -16
- package/components/form/Security.vue +56 -54
- package/components/form/Select.vue +7 -41
- package/components/form/ShellInput.vue +1 -5
- package/components/form/Tolerations.vue +1 -5
- package/components/form/UnitInput.vue +2 -2
- package/components/form/ValueFromResource.vue +121 -134
- package/components/form/WorkloadPorts.vue +18 -18
- package/components/form/__tests__/ArrayList.test.ts +2 -5
- package/components/form/__tests__/MatchExpressions.test.ts +12 -12
- package/components/form/__tests__/NameNsDescription.test.ts +14 -115
- package/components/form/__tests__/Probe.test.ts +8 -12
- package/components/form/__tests__/SSHKnownHosts.test.ts +0 -11
- package/components/form/__tests__/Select.test.ts +0 -37
- package/components/form/__tests__/UnitInput.test.ts +5 -4
- package/components/formatter/BadgeStateFormatter.vue +5 -8
- package/components/formatter/ExtensionCache.vue +74 -0
- package/components/formatter/InternalExternalIP.vue +0 -2
- package/components/formatter/Port.vue +24 -0
- package/components/formatter/SecretData.vue +7 -20
- package/components/formatter/SecretType.vue +41 -0
- package/components/nav/Favorite.vue +1 -5
- package/components/nav/Group.vue +3 -16
- package/components/nav/Header.vue +13 -39
- package/components/nav/Jump.vue +0 -7
- package/components/nav/NamespaceFilter.vue +8 -14
- package/components/nav/Pinned.vue +1 -1
- package/components/nav/TopLevelMenu.vue +17 -5
- package/components/nav/Type.vue +1 -14
- package/components/nav/__tests__/TopLevelMenu.test.ts +40 -0
- package/components/templates/blank.vue +1 -4
- package/components/templates/default.vue +0 -8
- package/components/templates/home.vue +1 -10
- package/components/templates/plain.vue +1 -10
- package/package.json +1 -1
- package/public/index.html +3 -3
- package/components/ActionDropdownShell.vue +0 -71
- package/components/DotState.vue +0 -84
- package/components/ModalManager.vue +0 -55
- package/components/SlideInPanelManager.vue +0 -126
- package/components/StatusBadge.vue +0 -77
- package/components/__tests__/ModalManager.spec.ts +0 -176
- package/components/__tests__/SlideInPanelManager.spec.ts +0 -166
|
@@ -6,20 +6,18 @@ 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
|
+
['HTTPS', ['port', 'path']],
|
|
10
|
+
['tcp', ['socket']],
|
|
11
|
+
['exec', ['command']],
|
|
12
|
+
])('given kind %p', (kind, 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
|
-
|
|
21
|
-
value,
|
|
22
|
-
},
|
|
19
|
+
props: { mode: _EDIT },
|
|
20
|
+
data: () => ({ kind })
|
|
23
21
|
});
|
|
24
22
|
const input = wrapper.find(`[data-testid="input-probe-${ field }"]`).find('input');
|
|
25
23
|
const newValue = 123;
|
|
@@ -35,10 +33,8 @@ describe('component: Probe', () => {
|
|
|
35
33
|
'timeoutSeconds',
|
|
36
34
|
])('should emit an update on %p input and blur', (field) => {
|
|
37
35
|
const wrapper = mount(Probe as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
|
|
38
|
-
props: {
|
|
39
|
-
|
|
40
|
-
value
|
|
41
|
-
},
|
|
36
|
+
props: { mode: _EDIT },
|
|
37
|
+
data: () => ({ kind })
|
|
42
38
|
});
|
|
43
39
|
const input = wrapper.find(`[data-testid="input-probe-${ field }"]`).find('input');
|
|
44
40
|
const newValue = 123;
|
|
@@ -2,17 +2,6 @@ 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
|
-
|
|
16
5
|
describe('component: SSHKnownHosts', () => {
|
|
17
6
|
it.each([
|
|
18
7
|
['0 entities', '', 0],
|
|
@@ -27,41 +27,4 @@ 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
|
-
});
|
|
67
30
|
});
|
|
@@ -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', 'change'])('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')[2]).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')[3][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(['input', '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,6 +248,7 @@ describe('component: UnitInput', () => {
|
|
|
248
248
|
const input = wrapper.find('input');
|
|
249
249
|
|
|
250
250
|
await input.trigger('update:value');
|
|
251
|
+
await input.trigger('input');
|
|
251
252
|
|
|
252
253
|
expect(input.element.value).toBe('123');
|
|
253
254
|
});
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import { BadgeState } from '@components/BadgeState';
|
|
3
|
-
import DotState from '@shell/components/DotState'
|
|
4
3
|
import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
5
4
|
export default {
|
|
6
|
-
components: { BadgeState
|
|
5
|
+
components: { BadgeState },
|
|
7
6
|
props: {
|
|
8
7
|
value: {
|
|
9
8
|
type: String,
|
|
@@ -50,17 +49,15 @@ export default {
|
|
|
50
49
|
<template>
|
|
51
50
|
<div>
|
|
52
51
|
<div v-if="arbitrary">
|
|
53
|
-
|
|
52
|
+
<BadgeState
|
|
54
53
|
v-if="value"
|
|
55
54
|
:color="stateBackground"
|
|
56
55
|
:label="stateDisplay"
|
|
57
|
-
/>
|
|
58
|
-
<DotState v-if="value" :color="stateBackground" :label="stateDisplay" />
|
|
56
|
+
/>
|
|
59
57
|
</div>
|
|
60
|
-
|
|
58
|
+
<BadgeState
|
|
61
59
|
v-else
|
|
62
60
|
:value="row"
|
|
63
|
-
/>
|
|
64
|
-
<DotState v-else :value="row" />
|
|
61
|
+
/>
|
|
65
62
|
</div>
|
|
66
63
|
</template>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { BadgeState } from '@components/BadgeState';
|
|
3
|
+
import { stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
props: {
|
|
7
|
+
value: {
|
|
8
|
+
type: String,
|
|
9
|
+
default: ''
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
components: { BadgeState },
|
|
14
|
+
|
|
15
|
+
data() {
|
|
16
|
+
const STATES = {
|
|
17
|
+
cached: {
|
|
18
|
+
color: 'info', icon: 'dot-open', label: 'Cached', compoundIcon: 'checkmark'
|
|
19
|
+
},
|
|
20
|
+
pending: {
|
|
21
|
+
color: 'warning', icon: 'tag', label: 'In Progress', compoundIcon: 'info'
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
color: 'error', icon: 'dot-half', label: 'Cache Disabled', compoundIcon: 'info'
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
STATES,
|
|
30
|
+
stateDisplay: '',
|
|
31
|
+
stateBackground: ''
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
watch: {
|
|
36
|
+
value: {
|
|
37
|
+
handler() {
|
|
38
|
+
const out = this.value || 'pending';
|
|
39
|
+
const color = this.colorForState(out);
|
|
40
|
+
|
|
41
|
+
this.stateDisplay = stateDisplay(out);
|
|
42
|
+
this.stateBackground = color.replace('text-', 'bg-');
|
|
43
|
+
},
|
|
44
|
+
immediate: true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
methods: {
|
|
49
|
+
colorForState(state) {
|
|
50
|
+
const key = (state).toLowerCase();
|
|
51
|
+
let color;
|
|
52
|
+
|
|
53
|
+
if ( this.STATES[key] && this.STATES[key].color ) {
|
|
54
|
+
color = this.STATES[key].color;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if ( !color ) {
|
|
58
|
+
color = 'info';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return `text-${ color }`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<div>
|
|
69
|
+
<BadgeState
|
|
70
|
+
:color="stateBackground"
|
|
71
|
+
:label="stateDisplay"
|
|
72
|
+
/>
|
|
73
|
+
</div>
|
|
74
|
+
</template>
|
|
@@ -28,7 +28,6 @@ export default {
|
|
|
28
28
|
<span>
|
|
29
29
|
<template v-if="isIp(row.externalIp)">
|
|
30
30
|
{{ row.externalIp }} <CopyToClipboard
|
|
31
|
-
:aria-label="t('internalExternalIP.copyExternalIp')"
|
|
32
31
|
label-as="tooltip"
|
|
33
32
|
:text="row.externalIp"
|
|
34
33
|
class="icon-btn"
|
|
@@ -44,7 +43,6 @@ export default {
|
|
|
44
43
|
</template>
|
|
45
44
|
<template v-else-if="isIp(row.internalIp)">
|
|
46
45
|
{{ row.internalIp }}<CopyToClipboard
|
|
47
|
-
:aria-label="t('internalExternalIP.copyInternalIp')"
|
|
48
46
|
label-as="tooltip"
|
|
49
47
|
:text="row.internalIp"
|
|
50
48
|
class="icon-btn"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export default {
|
|
3
|
+
props: {
|
|
4
|
+
value: {
|
|
5
|
+
type: Array,
|
|
6
|
+
default: () => []
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
data() {
|
|
10
|
+
const { hostPort = '', protocol = '' } = this.value[0] || {};
|
|
11
|
+
|
|
12
|
+
return { hostPort, protocol };
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<div v-if="hostPort">
|
|
19
|
+
{{ hostPort+'/'+protocol }}
|
|
20
|
+
</div>
|
|
21
|
+
<div v-else>
|
|
22
|
+
—
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
@@ -13,25 +13,17 @@ export default {
|
|
|
13
13
|
},
|
|
14
14
|
},
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
data() {
|
|
17
17
|
if (this.value.issuer) {
|
|
18
18
|
const { cn, notAfter, sans = [] } = this.value;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
return {
|
|
21
|
+
cn, expiration: notAfter, sans, isTLS: true
|
|
22
|
+
};
|
|
23
|
+
} else {
|
|
24
|
+
return { isTLS: false };
|
|
24
25
|
}
|
|
25
26
|
},
|
|
26
|
-
|
|
27
|
-
data() {
|
|
28
|
-
return {
|
|
29
|
-
isTLS: false,
|
|
30
|
-
cn: null,
|
|
31
|
-
sans: [],
|
|
32
|
-
expiration: null,
|
|
33
|
-
};
|
|
34
|
-
},
|
|
35
27
|
computed: {
|
|
36
28
|
// use 'text-warning' or 'text-error' classes if the cert is <8 days from expiring or expired respectively
|
|
37
29
|
dateClass() {
|
|
@@ -51,12 +43,7 @@ export default {
|
|
|
51
43
|
|
|
52
44
|
<template>
|
|
53
45
|
<div v-if="isTLS">
|
|
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>
|
|
46
|
+
<t k="secret.certificate.cn" /> {{ cn }} <span v-if="row.unrepeatedSans && row.unrepeatedSans.length">{{ t('secret.certificate.plusMore', {n:row.unrepeatedSans.length}) }}</span><br>
|
|
60
47
|
<t k="secret.certificate.expires" />: <DateComponent
|
|
61
48
|
:class="dateClass"
|
|
62
49
|
:value="expiration"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { SERVICE_ACCOUNT } from '@shell/config/types';
|
|
3
|
+
export default {
|
|
4
|
+
props: {
|
|
5
|
+
value: {
|
|
6
|
+
type: [String, Object],
|
|
7
|
+
default: 'Opaque'
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
data() {
|
|
11
|
+
if (this.value.typeDisplay) {
|
|
12
|
+
this.findServiceAccount();
|
|
13
|
+
|
|
14
|
+
return { typeDisplay: this.value.typeDisplay, serviceAccountLink: null };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return { typeDisplay: this.value, serviceAccountLink: null };
|
|
18
|
+
},
|
|
19
|
+
methods: {
|
|
20
|
+
async findServiceAccount() {
|
|
21
|
+
const serviceAccount = await this.$store.dispatch('cluster/find', { type: SERVICE_ACCOUNT, id: this.value.serviceAccountID });
|
|
22
|
+
|
|
23
|
+
if (serviceAccount) {
|
|
24
|
+
this.serviceAccountLink = serviceAccount.detailLocation;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
</script>>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<router-link
|
|
33
|
+
v-if="serviceAccountLink"
|
|
34
|
+
:to="serviceAccountLink"
|
|
35
|
+
>
|
|
36
|
+
{{ typeDisplay }}
|
|
37
|
+
</router-link>
|
|
38
|
+
<div v-else>
|
|
39
|
+
{{ typeDisplay }}
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
@@ -10,9 +10,6 @@ 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 });
|
|
16
13
|
}
|
|
17
14
|
},
|
|
18
15
|
|
|
@@ -31,11 +28,10 @@ export default {
|
|
|
31
28
|
<template>
|
|
32
29
|
<i
|
|
33
30
|
:tabindex="0"
|
|
34
|
-
:aria-
|
|
31
|
+
:aria-checked="!!isFavorite"
|
|
35
32
|
class="favorite icon"
|
|
36
33
|
:class="{'icon-star-open': !isFavorite, 'icon-star': isFavorite}"
|
|
37
34
|
aria-role="button"
|
|
38
|
-
:aria-label="ariaLabel"
|
|
39
35
|
@click.stop.prevent="toggle"
|
|
40
36
|
@keydown.enter.prevent="toggle"
|
|
41
37
|
@keydown.space.prevent="toggle"
|
package/components/nav/Group.vue
CHANGED
|
@@ -158,17 +158,6 @@ 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
|
-
|
|
172
161
|
for (const item of items.children) {
|
|
173
162
|
if (item.children && this.hasActiveRoute(item)) {
|
|
174
163
|
return true;
|
|
@@ -177,11 +166,8 @@ export default {
|
|
|
177
166
|
const matchesNavLevel = navLevels.filter((param) => !this.$route.params[param] || this.$route.params[param] !== item.route.params[param]).length === 0;
|
|
178
167
|
const withoutHash = this.$route.hash ? this.$route.fullPath.slice(0, this.$route.fullPath.indexOf(this.$route.hash)) : this.$route.fullPath;
|
|
179
168
|
const withoutQuery = withoutHash.split('?')[0];
|
|
180
|
-
const itemFullPath = this.$router.resolve(item.route).fullPath;
|
|
181
169
|
|
|
182
|
-
if (matchesNavLevel ||
|
|
183
|
-
return true;
|
|
184
|
-
} else if (parentPath && itemFullPath === parentPath) {
|
|
170
|
+
if (matchesNavLevel || this.$router.resolve(item.route).fullPath === withoutQuery) {
|
|
185
171
|
return true;
|
|
186
172
|
}
|
|
187
173
|
}
|
|
@@ -277,7 +263,7 @@ export default {
|
|
|
277
263
|
v-if="child.divider"
|
|
278
264
|
:key="idx"
|
|
279
265
|
>
|
|
280
|
-
<hr
|
|
266
|
+
<hr>
|
|
281
267
|
</li>
|
|
282
268
|
<!-- <div v-else-if="child[childrenKey] && hideGroup(child[childrenKey])" :key="child.name">
|
|
283
269
|
HIDDEN
|
|
@@ -493,3 +479,4 @@ export default {
|
|
|
493
479
|
color: #a8abb2;
|
|
494
480
|
}
|
|
495
481
|
</style>
|
|
482
|
+
|
|
@@ -81,8 +81,7 @@ export default {
|
|
|
81
81
|
extensionHeaderActions: getApplicableExtensionEnhancements(this, ExtensionPoint.ACTION, ActionLocation.HEADER, this.$route),
|
|
82
82
|
ctx: this,
|
|
83
83
|
showImportModal: false,
|
|
84
|
-
showSearchModal: false
|
|
85
|
-
userIcon: require('~shell/assets/images/logo.png'),
|
|
84
|
+
showSearchModal: false
|
|
86
85
|
};
|
|
87
86
|
},
|
|
88
87
|
|
|
@@ -405,7 +404,7 @@ export default {
|
|
|
405
404
|
<TopLevelMenu v-if="isRancherInHarvester || isMultiCluster || !isSingleProduct" />
|
|
406
405
|
</div>
|
|
407
406
|
|
|
408
|
-
|
|
407
|
+
<div
|
|
409
408
|
class="menu-spacer"
|
|
410
409
|
:class="{'isSingleProduct': isSingleProduct }"
|
|
411
410
|
>
|
|
@@ -524,20 +523,8 @@ export default {
|
|
|
524
523
|
:alt="t('branding.logos.label')"
|
|
525
524
|
/>
|
|
526
525
|
</div>
|
|
527
|
-
</div> -->
|
|
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
526
|
</div>
|
|
540
|
-
|
|
527
|
+
|
|
541
528
|
<div class="spacer" />
|
|
542
529
|
|
|
543
530
|
<div class="rd-header-right">
|
|
@@ -709,23 +696,20 @@ export default {
|
|
|
709
696
|
data-testid="nav_header_showUserMenu"
|
|
710
697
|
:aria-label="t('nav.userMenu.button.label')"
|
|
711
698
|
>
|
|
712
|
-
|
|
699
|
+
<img
|
|
713
700
|
v-if="principal && principal.avatarSrc"
|
|
714
701
|
:src="principal.avatarSrc"
|
|
715
702
|
:class="{'avatar-round': principal.roundAvatar}"
|
|
716
703
|
width="36"
|
|
717
704
|
height="36"
|
|
718
|
-
:alt="t('nav.alt.userAvatar')"
|
|
719
705
|
>
|
|
720
706
|
<i
|
|
721
707
|
v-else
|
|
722
708
|
class="icon icon-user icon-3x avatar"
|
|
723
|
-
/>
|
|
724
|
-
<i class="icon icon-usericon" />
|
|
725
|
-
<span class="login-name">{{ principal.loginName }}</span>
|
|
709
|
+
/>
|
|
726
710
|
</rc-dropdown-trigger>
|
|
727
711
|
<template #dropdownCollection>
|
|
728
|
-
|
|
712
|
+
<template v-if="authEnabled">
|
|
729
713
|
<div class="user-info">
|
|
730
714
|
<div class="user-name">
|
|
731
715
|
<i class="icon icon-lg icon-user" /> {{ principal.loginName }}
|
|
@@ -737,13 +721,13 @@ export default {
|
|
|
737
721
|
</div>
|
|
738
722
|
</div>
|
|
739
723
|
<rc-dropdown-separator />
|
|
740
|
-
</template>
|
|
741
|
-
|
|
724
|
+
</template>
|
|
725
|
+
<rc-dropdown-item
|
|
742
726
|
v-if="showPreferencesLink"
|
|
743
727
|
@click="$router.push({ name: 'prefs'})"
|
|
744
728
|
>
|
|
745
729
|
{{ t('nav.userMenu.preferences') }}
|
|
746
|
-
</rc-dropdown-item>
|
|
730
|
+
</rc-dropdown-item>
|
|
747
731
|
<rc-dropdown-item
|
|
748
732
|
v-if="showAccountAndApiKeyLink"
|
|
749
733
|
@click="$router.push({ name: 'account'})"
|
|
@@ -776,7 +760,6 @@ export default {
|
|
|
776
760
|
HEADER {
|
|
777
761
|
display: flex;
|
|
778
762
|
z-index: z-index('mainHeader');
|
|
779
|
-
box-shadow: 0px 3px 3px 1px rgba(0,0,0,0.12);
|
|
780
763
|
|
|
781
764
|
> .spacer {
|
|
782
765
|
flex: 1;
|
|
@@ -894,7 +877,7 @@ export default {
|
|
|
894
877
|
|
|
895
878
|
> * {
|
|
896
879
|
background-color: var(--header-bg);
|
|
897
|
-
|
|
880
|
+
border-bottom: var(--header-border-size) solid var(--header-border);
|
|
898
881
|
}
|
|
899
882
|
|
|
900
883
|
.rd-header-right {
|
|
@@ -907,7 +890,7 @@ export default {
|
|
|
907
890
|
}
|
|
908
891
|
|
|
909
892
|
> .top {
|
|
910
|
-
padding-top:
|
|
893
|
+
padding-top: 6px;
|
|
911
894
|
|
|
912
895
|
INPUT[type='search']::placeholder,
|
|
913
896
|
.vs__open-indicator,
|
|
@@ -1027,7 +1010,7 @@ export default {
|
|
|
1027
1010
|
|
|
1028
1011
|
> .user {
|
|
1029
1012
|
outline: none;
|
|
1030
|
-
|
|
1013
|
+
width: var(--header-height);
|
|
1031
1014
|
|
|
1032
1015
|
.v-popper {
|
|
1033
1016
|
display: flex;
|
|
@@ -1041,10 +1024,6 @@ export default {
|
|
|
1041
1024
|
.user-image {
|
|
1042
1025
|
display: flex;
|
|
1043
1026
|
align-items: center;
|
|
1044
|
-
&:hover{
|
|
1045
|
-
color: var(--primary);
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
1027
|
}
|
|
1049
1028
|
|
|
1050
1029
|
&:focus {
|
|
@@ -1173,10 +1152,5 @@ export default {
|
|
|
1173
1152
|
}
|
|
1174
1153
|
}
|
|
1175
1154
|
}
|
|
1176
|
-
|
|
1177
|
-
font-size: 14px;
|
|
1178
|
-
margin-left: 5px;
|
|
1179
|
-
margin-top: 5px;
|
|
1180
|
-
line-height: 20px;
|
|
1181
|
-
}
|
|
1155
|
+
|
|
1182
1156
|
</style>
|
package/components/nav/Jump.vue
CHANGED
|
@@ -71,12 +71,6 @@ 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>
|
|
80
74
|
<input
|
|
81
75
|
ref="input"
|
|
82
76
|
v-model="value"
|
|
@@ -84,7 +78,6 @@ export default {
|
|
|
84
78
|
class="search"
|
|
85
79
|
role="textbox"
|
|
86
80
|
:aria-label="t('nav.resourceSearch.label')"
|
|
87
|
-
aria-describedby="describe-filter-resource-search"
|
|
88
81
|
@keyup.esc="$emit('closeSearch')"
|
|
89
82
|
>
|
|
90
83
|
<div class="results">
|