dashboard-shell-shell 1.0.113 → 1.0.114
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 +19 -60
- package/components/SideNav.vue +12 -32
- package/components/SortableTable/THead.vue +5 -34
- package/components/SortableTable/actions.js +1 -1
- package/components/SortableTable/index.vue +142 -649
- package/components/SortableTable/paging.js +28 -36
- 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 +27 -60
- 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 +35 -32
- 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/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
|
}
|
|
@@ -245,11 +231,8 @@ export default {
|
|
|
245
231
|
</router-link>
|
|
246
232
|
<h6
|
|
247
233
|
v-else
|
|
248
|
-
@click="peek($event, true)"
|
|
249
234
|
>
|
|
250
|
-
|
|
251
|
-
{{ group.labelDisplay || group.label }}
|
|
252
|
-
<!-- <span v-clean-html="group.labelDisplay || group.label" /> -->
|
|
235
|
+
<span v-clean-html="group.labelDisplay || group.label" />
|
|
253
236
|
</h6>
|
|
254
237
|
</slot>
|
|
255
238
|
<i
|
|
@@ -277,7 +260,7 @@ export default {
|
|
|
277
260
|
v-if="child.divider"
|
|
278
261
|
:key="idx"
|
|
279
262
|
>
|
|
280
|
-
<hr
|
|
263
|
+
<hr>
|
|
281
264
|
</li>
|
|
282
265
|
<!-- <div v-else-if="child[childrenKey] && hideGroup(child[childrenKey])" :key="child.name">
|
|
283
266
|
HIDDEN
|
|
@@ -359,28 +342,21 @@ export default {
|
|
|
359
342
|
}
|
|
360
343
|
|
|
361
344
|
&.active {
|
|
362
|
-
color: var(--
|
|
363
|
-
background-color: var(--
|
|
345
|
+
color: var(--primary-hover-text);
|
|
346
|
+
background-color: var(--primary-hover-bg);
|
|
364
347
|
|
|
365
348
|
h6 {
|
|
366
|
-
|
|
367
|
-
font-weight: bold;
|
|
368
|
-
color: var(--
|
|
369
|
-
}
|
|
370
|
-
I{
|
|
371
|
-
color: var(--nav-hover-color);
|
|
349
|
+
padding: 8px 0 8px 16px;
|
|
350
|
+
font-weight: bold;
|
|
351
|
+
color: var(--primary-hover-text);
|
|
372
352
|
}
|
|
373
353
|
|
|
374
|
-
|
|
354
|
+
&:hover {
|
|
375
355
|
background-color: var(--primary-hover-bg);
|
|
376
|
-
}
|
|
356
|
+
}
|
|
377
357
|
}
|
|
378
358
|
&:hover:not(.active) {
|
|
379
|
-
background-color: var(--nav-
|
|
380
|
-
color: var(--nav-hover-color);
|
|
381
|
-
h6{
|
|
382
|
-
color: var(--nav-hover-color);
|
|
383
|
-
}
|
|
359
|
+
background-color: var(--nav-hover);
|
|
384
360
|
}
|
|
385
361
|
}
|
|
386
362
|
}
|
|
@@ -388,53 +364,49 @@ export default {
|
|
|
388
364
|
.accordion {
|
|
389
365
|
&.depth-0 {
|
|
390
366
|
> .header {
|
|
391
|
-
/* padding: 8px 0; */
|
|
392
|
-
padding: 0px 0px 0px 20px;
|
|
393
|
-
height: 50px;
|
|
394
367
|
|
|
395
368
|
&.noHover {
|
|
396
369
|
cursor: default;
|
|
397
370
|
}
|
|
398
371
|
|
|
399
372
|
> H6 {
|
|
400
|
-
font-size: 14px;
|
|
401
373
|
text-transform: none;
|
|
402
|
-
|
|
403
|
-
display: flex;
|
|
404
|
-
align-items: center;
|
|
374
|
+
padding: 8px 0 8px 16px;
|
|
405
375
|
}
|
|
406
376
|
|
|
407
377
|
> I {
|
|
408
378
|
position: absolute;
|
|
409
379
|
right: 0;
|
|
410
380
|
top: 0;
|
|
411
|
-
padding:
|
|
381
|
+
padding: 10px 10px 9px 7px;
|
|
412
382
|
user-select: none;
|
|
413
|
-
line-height: 50px;
|
|
414
383
|
}
|
|
415
384
|
}
|
|
416
385
|
|
|
417
386
|
> .body {
|
|
418
387
|
margin-left: 0;
|
|
419
388
|
}
|
|
389
|
+
|
|
390
|
+
&.group-highlight {
|
|
391
|
+
background: var(--nav-active);
|
|
392
|
+
}
|
|
420
393
|
}
|
|
421
394
|
|
|
422
395
|
&.depth-1 {
|
|
423
396
|
> .header {
|
|
397
|
+
padding-left: 20px;
|
|
424
398
|
> H6 {
|
|
425
|
-
|
|
426
|
-
line-height: 16px;
|
|
399
|
+
line-height: 18px;
|
|
427
400
|
padding: 8px 0 7px 5px !important;
|
|
428
401
|
}
|
|
429
402
|
> I {
|
|
430
|
-
padding:
|
|
403
|
+
padding: 10px 7px 9px 7px !important;
|
|
431
404
|
}
|
|
432
405
|
}
|
|
433
406
|
}
|
|
434
407
|
|
|
435
408
|
&:not(.depth-0) {
|
|
436
409
|
> .header {
|
|
437
|
-
padding-left: 10px;
|
|
438
410
|
> H6 {
|
|
439
411
|
// Child groups that aren't linked themselves
|
|
440
412
|
display: inline-block;
|
|
@@ -456,16 +428,13 @@ export default {
|
|
|
456
428
|
padding: 0;
|
|
457
429
|
|
|
458
430
|
A, A I {
|
|
459
|
-
|
|
460
|
-
color: var(--nav-hover-color);
|
|
431
|
+
color: var(--primary-hover-text);
|
|
461
432
|
}
|
|
462
433
|
|
|
463
434
|
A {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
color: var(--nav-hover-color);
|
|
468
|
-
}
|
|
435
|
+
color: var(--primary-hover-text);
|
|
436
|
+
background-color: var(--primary-hover-bg);
|
|
437
|
+
font-weight: bold;
|
|
469
438
|
}
|
|
470
439
|
}
|
|
471
440
|
|
|
@@ -474,6 +443,9 @@ export default {
|
|
|
474
443
|
border-left: solid 5px transparent;
|
|
475
444
|
line-height: 16px;
|
|
476
445
|
font-size: 14px;
|
|
446
|
+
padding-left: 24px;
|
|
447
|
+
display: flex;
|
|
448
|
+
justify-content: space-between;
|
|
477
449
|
}
|
|
478
450
|
|
|
479
451
|
A:focus {
|
|
@@ -487,9 +459,4 @@ export default {
|
|
|
487
459
|
}
|
|
488
460
|
}
|
|
489
461
|
}
|
|
490
|
-
.nav-icon{
|
|
491
|
-
font-size: 32px;
|
|
492
|
-
margin-top: -11px;
|
|
493
|
-
color: #a8abb2;
|
|
494
|
-
}
|
|
495
462
|
</style>
|