@rancher/shell 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/translations/en-us.yaml +18 -3
- package/components/AlertTable.vue +17 -7
- package/components/GrafanaDashboard.vue +6 -4
- package/components/PromptRemove.vue +1 -0
- package/components/form/KeyValue.vue +1 -0
- package/components/form/Taints.vue +13 -7
- package/components/form/__tests__/Taints.test.ts +70 -0
- package/components/nav/Header.vue +1 -1
- package/components/nav/TopLevelMenu.vue +1 -4
- package/config/product/auth.js +1 -1
- package/config/router/navigation-guards/i18n.js +13 -0
- package/config/router/navigation-guards/index.js +2 -1
- package/creators/app/app.package.json +2 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +42 -0
- package/detail/provisioning.cattle.io.cluster.vue +4 -4
- package/dialog/DeactivateDriverDialog.vue +30 -11
- package/edit/auth/__tests__/oidc.test.ts +2 -2
- package/edit/token.vue +2 -1
- package/initialize/entry-helpers.js +10 -13
- package/list/management.cattle.io.feature.vue +4 -2
- package/middleware/authenticated.js +0 -19
- package/mixins/auth-config.js +1 -1
- package/models/driver.js +3 -2
- package/models/kontainerdriver.js +30 -13
- package/models/management.cattle.io.authconfig.js +2 -2
- package/models/nodedriver.js +30 -13
- package/package.json +3 -2
- package/pages/c/_cluster/apps/charts/install.vue +3 -2
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +0 -3
- package/pages/c/_cluster/manager/drivers/nodeDriver/index.vue +1 -4
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +2 -1
- package/promptRemove/pod.vue +15 -7
- package/scripts/publish-shell.sh +1 -0
- package/store/auth.js +1 -1
- package/store/index.js +1 -1
- package/utils/__tests__/kontainer.test.ts +89 -1
- package/utils/auth.js +1 -1
- package/utils/kontainer.ts +5 -1
- package/utils/version.js +2 -1
- package/rancher-components/components/Accordion/Accordion.test.ts +0 -45
- package/rancher-components/components/Accordion/Accordion.vue +0 -86
- package/rancher-components/components/Accordion/index.ts +0 -1
- package/rancher-components/components/BadgeState/BadgeState.test.ts +0 -12
- package/rancher-components/components/BadgeState/BadgeState.vue +0 -111
- package/rancher-components/components/BadgeState/index.ts +0 -1
- package/rancher-components/components/Banner/Banner.test.ts +0 -59
- package/rancher-components/components/Banner/Banner.vue +0 -244
- package/rancher-components/components/Banner/index.ts +0 -1
- package/rancher-components/components/Card/Card.test.ts +0 -37
- package/rancher-components/components/Card/Card.vue +0 -167
- package/rancher-components/components/Card/index.ts +0 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +0 -68
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +0 -421
- package/rancher-components/components/Form/Checkbox/index.ts +0 -1
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +0 -40
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +0 -402
- package/rancher-components/components/Form/LabeledInput/index.ts +0 -1
- package/rancher-components/components/Form/Radio/RadioButton.test.ts +0 -33
- package/rancher-components/components/Form/Radio/RadioButton.vue +0 -293
- package/rancher-components/components/Form/Radio/RadioGroup.test.ts +0 -30
- package/rancher-components/components/Form/Radio/RadioGroup.vue +0 -259
- package/rancher-components/components/Form/Radio/index.ts +0 -2
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +0 -172
- package/rancher-components/components/Form/TextArea/index.ts +0 -1
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +0 -94
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +0 -152
- package/rancher-components/components/Form/ToggleSwitch/index.ts +0 -1
- package/rancher-components/components/Form/index.ts +0 -5
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -156
- package/rancher-components/components/LabeledTooltip/index.ts +0 -1
- package/rancher-components/components/StringList/StringList.test.ts +0 -754
- package/rancher-components/components/StringList/StringList.vue +0 -650
- package/rancher-components/components/StringList/index.ts +0 -1
|
@@ -8,19 +8,21 @@ export default class KontainerDriver extends Driver {
|
|
|
8
8
|
get _availableActions() {
|
|
9
9
|
const out = [
|
|
10
10
|
{
|
|
11
|
-
action:
|
|
12
|
-
label:
|
|
13
|
-
icon:
|
|
14
|
-
bulkable:
|
|
15
|
-
|
|
11
|
+
action: 'activate',
|
|
12
|
+
label: this.t('action.activate'),
|
|
13
|
+
icon: 'icon icon-play',
|
|
14
|
+
bulkable: true,
|
|
15
|
+
bulkAction: 'activateBulk',
|
|
16
|
+
enabled: !!this.links.update && !this.active
|
|
16
17
|
},
|
|
17
18
|
{
|
|
18
|
-
action:
|
|
19
|
-
label:
|
|
20
|
-
icon:
|
|
21
|
-
bulkable:
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
action: 'deactivate',
|
|
20
|
+
label: this.t('action.deactivate'),
|
|
21
|
+
icon: 'icon icon-pause',
|
|
22
|
+
bulkable: true,
|
|
23
|
+
bulkAction: 'deactivateBulk',
|
|
24
|
+
enabled: !!this.links.update && !!this.active,
|
|
25
|
+
weight: -1
|
|
24
26
|
},
|
|
25
27
|
{ divider: true },
|
|
26
28
|
{
|
|
@@ -52,9 +54,16 @@ export default class KontainerDriver extends Driver {
|
|
|
52
54
|
return out;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
deactivate() {
|
|
57
|
+
deactivate(resources = [this]) {
|
|
58
|
+
this.$dispatch('promptModal', {
|
|
59
|
+
componentProps: { drivers: resources, driverType: 'kontainerDrivers' },
|
|
60
|
+
component: 'DeactivateDriverDialog'
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
deactivateBulk(resources) {
|
|
56
65
|
this.$dispatch('promptModal', {
|
|
57
|
-
componentProps: {
|
|
66
|
+
componentProps: { drivers: resources, driverType: 'kontainerDrivers' },
|
|
58
67
|
component: 'DeactivateDriverDialog'
|
|
59
68
|
});
|
|
60
69
|
}
|
|
@@ -65,4 +74,12 @@ export default class KontainerDriver extends Driver {
|
|
|
65
74
|
method: 'post',
|
|
66
75
|
}, { root: true });
|
|
67
76
|
}
|
|
77
|
+
|
|
78
|
+
async activateBulk(resources) {
|
|
79
|
+
await Promise.all(resources.map((resource) => this.$dispatch('rancher/request', {
|
|
80
|
+
url: `v3/kontainerDrivers/${ escape(resource.id) }?action=activate`,
|
|
81
|
+
method: 'post',
|
|
82
|
+
}, { root: true }
|
|
83
|
+
)));
|
|
84
|
+
}
|
|
68
85
|
}
|
|
@@ -15,10 +15,10 @@ export const configType = {
|
|
|
15
15
|
local: '',
|
|
16
16
|
github: 'oauth',
|
|
17
17
|
keycloakoidc: 'oidc',
|
|
18
|
-
|
|
18
|
+
genericoidc: 'oidc',
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
const imageOverrides = { keycloakoidc: 'keycloak',
|
|
21
|
+
const imageOverrides = { keycloakoidc: 'keycloak', genericoidc: 'openid' };
|
|
22
22
|
|
|
23
23
|
export default class AuthConfig extends SteveModel {
|
|
24
24
|
get _availableActions() {
|
package/models/nodedriver.js
CHANGED
|
@@ -8,19 +8,21 @@ export default class NodeDriver extends Driver {
|
|
|
8
8
|
get _availableActions() {
|
|
9
9
|
const out = [
|
|
10
10
|
{
|
|
11
|
-
action:
|
|
12
|
-
label:
|
|
13
|
-
icon:
|
|
14
|
-
bulkable:
|
|
15
|
-
|
|
11
|
+
action: 'activate',
|
|
12
|
+
label: this.t('action.activate'),
|
|
13
|
+
icon: 'icon icon-play',
|
|
14
|
+
bulkable: true,
|
|
15
|
+
bulkAction: 'activateBulk',
|
|
16
|
+
enabled: !!this.actions.activate && this.state === 'inactive',
|
|
16
17
|
},
|
|
17
18
|
{
|
|
18
|
-
action:
|
|
19
|
-
label:
|
|
20
|
-
icon:
|
|
21
|
-
bulkable:
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
action: 'deactivate',
|
|
20
|
+
label: this.t('action.deactivate'),
|
|
21
|
+
icon: 'icon icon-pause',
|
|
22
|
+
bulkable: true,
|
|
23
|
+
bulkAction: 'deactivateBulk',
|
|
24
|
+
enabled: !!this.actions.deactivate && this.state === 'active',
|
|
25
|
+
weight: -1,
|
|
24
26
|
},
|
|
25
27
|
{ divider: true },
|
|
26
28
|
{
|
|
@@ -52,9 +54,16 @@ export default class NodeDriver extends Driver {
|
|
|
52
54
|
return out;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
deactivate() {
|
|
57
|
+
deactivate(resources = [this]) {
|
|
58
|
+
this.$dispatch('promptModal', {
|
|
59
|
+
componentProps: { drivers: resources, driverType: 'nodeDrivers' },
|
|
60
|
+
component: 'DeactivateDriverDialog'
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
deactivateBulk(resources) {
|
|
56
65
|
this.$dispatch('promptModal', {
|
|
57
|
-
componentProps: {
|
|
66
|
+
componentProps: { drivers: resources, driverType: 'nodeDrivers' },
|
|
58
67
|
component: 'DeactivateDriverDialog'
|
|
59
68
|
});
|
|
60
69
|
}
|
|
@@ -65,4 +74,12 @@ export default class NodeDriver extends Driver {
|
|
|
65
74
|
method: 'post',
|
|
66
75
|
}, { root: true });
|
|
67
76
|
}
|
|
77
|
+
|
|
78
|
+
async activateBulk(resources) {
|
|
79
|
+
await Promise.all(resources.map((resource) => this.$dispatch('rancher/request', {
|
|
80
|
+
url: `v3/nodeDrivers/${ escape(resource.id) }?action=activate`,
|
|
81
|
+
method: 'post',
|
|
82
|
+
}, { root: true }
|
|
83
|
+
)));
|
|
84
|
+
}
|
|
68
85
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -153,7 +153,8 @@
|
|
|
153
153
|
"nth-check": ">=2.0.1",
|
|
154
154
|
"follow-redirects": ">=1.14.7",
|
|
155
155
|
"merge": ">=2.1.1",
|
|
156
|
-
"semver": ">=7.5.2"
|
|
156
|
+
"semver": ">=7.5.2",
|
|
157
|
+
"glob": "7.2.3"
|
|
157
158
|
},
|
|
158
159
|
"nyc": {
|
|
159
160
|
"extension": [
|
|
@@ -37,6 +37,7 @@ import { findBy, insertAt } from '@shell/utils/array';
|
|
|
37
37
|
import Vue from 'vue';
|
|
38
38
|
import { saferDump } from '@shell/utils/create-yaml';
|
|
39
39
|
import { LINUX, WINDOWS } from '@shell/store/catalog';
|
|
40
|
+
import { SETTING } from '@shell/config/settings';
|
|
40
41
|
|
|
41
42
|
const VALUES_STATE = {
|
|
42
43
|
FORM: 'FORM',
|
|
@@ -126,7 +127,7 @@ export default {
|
|
|
126
127
|
try {
|
|
127
128
|
this.serverUrlSetting = await this.$store.dispatch('management/find', {
|
|
128
129
|
type: MANAGEMENT.SETTING,
|
|
129
|
-
id:
|
|
130
|
+
id: SETTING.SERVER_URL,
|
|
130
131
|
});
|
|
131
132
|
} catch (e) {
|
|
132
133
|
console.error('Unable to fetch `server-url` setting: ', e); // eslint-disable-line no-console
|
|
@@ -888,7 +889,7 @@ export default {
|
|
|
888
889
|
// runtime will pull images from docker.io.
|
|
889
890
|
const globalRegistry = await this.$store.dispatch('management/find', {
|
|
890
891
|
type: MANAGEMENT.SETTING,
|
|
891
|
-
id:
|
|
892
|
+
id: SETTING.SYSTEM_DEFAULT_REGISTRY,
|
|
892
893
|
});
|
|
893
894
|
|
|
894
895
|
return globalRegistry.value;
|
|
@@ -6,6 +6,7 @@ import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
|
|
6
6
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
7
7
|
import { UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
|
|
8
8
|
import Banner from '@components/Banner/Banner.vue';
|
|
9
|
+
import { SETTING } from '@shell/config/settings';
|
|
9
10
|
|
|
10
11
|
// Note: This dialog handles installation and update of a plugin
|
|
11
12
|
|
|
@@ -20,7 +21,7 @@ export default {
|
|
|
20
21
|
async fetch() {
|
|
21
22
|
this.defaultRegistrySetting = await this.$store.dispatch('management/find', {
|
|
22
23
|
type: MANAGEMENT.SETTING,
|
|
23
|
-
id:
|
|
24
|
+
id: SETTING.SYSTEM_DEFAULT_REGISTRY,
|
|
24
25
|
});
|
|
25
26
|
},
|
|
26
27
|
|
package/promptRemove/pod.vue
CHANGED
|
@@ -30,6 +30,16 @@ export default {
|
|
|
30
30
|
type: {
|
|
31
31
|
type: String,
|
|
32
32
|
required: true
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
close: {
|
|
36
|
+
type: Function,
|
|
37
|
+
required: true
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
doneLocation: {
|
|
41
|
+
type: Object,
|
|
42
|
+
default: () => {}
|
|
33
43
|
}
|
|
34
44
|
},
|
|
35
45
|
|
|
@@ -69,23 +79,21 @@ export default {
|
|
|
69
79
|
|
|
70
80
|
methods: {
|
|
71
81
|
async remove(confirm) {
|
|
72
|
-
const parentComponent = this.$parent.$parent.$parent;
|
|
73
|
-
|
|
74
82
|
let goTo;
|
|
75
83
|
|
|
76
|
-
if (
|
|
84
|
+
if (this.doneLocation) {
|
|
77
85
|
// doneLocation will recompute to undefined when delete request completes
|
|
78
|
-
goTo = { ...
|
|
86
|
+
goTo = { ...this.doneLocation };
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
try {
|
|
82
90
|
await Promise.all(this.value.map((resource) => this.removePod(resource)));
|
|
83
91
|
if ( goTo && !isEmpty(goTo) ) {
|
|
84
|
-
|
|
92
|
+
this.value?.[0]?.currentRouter().push(goTo);
|
|
85
93
|
}
|
|
86
|
-
|
|
94
|
+
this.close();
|
|
87
95
|
} catch (err) {
|
|
88
|
-
|
|
96
|
+
this.$emit('errors', err);
|
|
89
97
|
confirm(false);
|
|
90
98
|
}
|
|
91
99
|
},
|
package/scripts/publish-shell.sh
CHANGED
|
@@ -67,6 +67,7 @@ function publish() {
|
|
|
67
67
|
# For now, copy the rancher components into the shell and ship them with it
|
|
68
68
|
if [ "$NAME" == "Shell" ]; then
|
|
69
69
|
echo "Adding Rancher Components"
|
|
70
|
+
rm -rf ./rancher-components
|
|
70
71
|
cp -R ${BASE_DIR}/pkg/rancher-components/src/components ./rancher-components/
|
|
71
72
|
fi
|
|
72
73
|
|
package/store/auth.js
CHANGED
package/store/index.js
CHANGED
|
@@ -594,7 +594,7 @@ export const getters = {
|
|
|
594
594
|
},
|
|
595
595
|
|
|
596
596
|
releaseNotesUrl(state, getters) {
|
|
597
|
-
const version = getters['management/byId'](MANAGEMENT.SETTING,
|
|
597
|
+
const version = getters['management/byId'](MANAGEMENT.SETTING, SETTING.VERSION_RANCHER)?.value;
|
|
598
598
|
|
|
599
599
|
const base = 'https://github.com/rancher/rancher/releases';
|
|
600
600
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { diffUpstreamSpec } from '@shell/utils/kontainer';
|
|
1
|
+
import { diffUpstreamSpec, syncUpstreamConfig } from '@shell/utils/kontainer';
|
|
2
2
|
|
|
3
3
|
describe('fx: diffUpstreamSpec', () => {
|
|
4
4
|
it.each([
|
|
@@ -90,3 +90,91 @@ describe('fx: diffUpstreamSpec', () => {
|
|
|
90
90
|
expect(diffUpstreamSpec(upstream, local)).toStrictEqual(diff);
|
|
91
91
|
});
|
|
92
92
|
});
|
|
93
|
+
|
|
94
|
+
describe('fx: syncUpstreamSpec', () => {
|
|
95
|
+
it('should set any fields defined in upstream spec and not local spec', () => {
|
|
96
|
+
const upstream = {
|
|
97
|
+
string: 'def',
|
|
98
|
+
'other-string': '123',
|
|
99
|
+
alreadySet: 'abc',
|
|
100
|
+
alreadySetArray: [2, 3, 4],
|
|
101
|
+
alreadySetBooleanFalse: false,
|
|
102
|
+
alreadySetBooleanTrue: true
|
|
103
|
+
};
|
|
104
|
+
const local = {
|
|
105
|
+
alreadySet: 'def',
|
|
106
|
+
alreadySetArray: [1, 2, 3],
|
|
107
|
+
alreadySetBooleanFalse: false,
|
|
108
|
+
alreadySetBooleanTrue: true
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const expected = {
|
|
112
|
+
string: 'def',
|
|
113
|
+
'other-string': '123',
|
|
114
|
+
alreadySet: 'def',
|
|
115
|
+
alreadySetArray: [1, 2, 3],
|
|
116
|
+
alreadySetBooleanFalse: false,
|
|
117
|
+
alreadySetBooleanTrue: true
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const testCluster = { eksConfig: local, eksStatus: { upstreamSpec: upstream } };
|
|
121
|
+
|
|
122
|
+
syncUpstreamConfig( 'eks', testCluster);
|
|
123
|
+
|
|
124
|
+
expect(testCluster.eksConfig).toStrictEqual(expected);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should not set empty objects or arrays from upstream spec', () => {
|
|
128
|
+
const upstream = {
|
|
129
|
+
emptyArray: [],
|
|
130
|
+
emptyObject: {},
|
|
131
|
+
nonEmptyArray: [1, 2, 3],
|
|
132
|
+
nonEmptyObject: { foo: 'bar' },
|
|
133
|
+
alreadySet: 'abc',
|
|
134
|
+
alreadySetArray: [2, 3, 4],
|
|
135
|
+
};
|
|
136
|
+
const local = {
|
|
137
|
+
alreadySet: 'def',
|
|
138
|
+
alreadySetArray: [1, 2, 3],
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const expected = {
|
|
142
|
+
nonEmptyArray: [1, 2, 3],
|
|
143
|
+
nonEmptyObject: { foo: 'bar' },
|
|
144
|
+
alreadySet: 'def',
|
|
145
|
+
alreadySetArray: [1, 2, 3],
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const testCluster = { eksConfig: local, eksStatus: { upstreamSpec: upstream } };
|
|
149
|
+
|
|
150
|
+
syncUpstreamConfig( 'eks', testCluster);
|
|
151
|
+
|
|
152
|
+
expect(testCluster.eksConfig).toStrictEqual(expected);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should not overwrite boolean values explicitly set false', () => {
|
|
156
|
+
const upstream = {
|
|
157
|
+
falseBoolean: false,
|
|
158
|
+
trueBoolean: true,
|
|
159
|
+
alreadySetBooleanFalse: true,
|
|
160
|
+
alreadySetBooleanTrue: false
|
|
161
|
+
};
|
|
162
|
+
const local = {
|
|
163
|
+
alreadySetBooleanFalse: false,
|
|
164
|
+
alreadySetBooleanTrue: true
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const expected = {
|
|
168
|
+
falseBoolean: false,
|
|
169
|
+
trueBoolean: true,
|
|
170
|
+
alreadySetBooleanFalse: false,
|
|
171
|
+
alreadySetBooleanTrue: true
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const testCluster = { eksConfig: local, eksStatus: { upstreamSpec: upstream } };
|
|
175
|
+
|
|
176
|
+
syncUpstreamConfig( 'eks', testCluster);
|
|
177
|
+
|
|
178
|
+
expect(testCluster.eksConfig).toStrictEqual(expected);
|
|
179
|
+
});
|
|
180
|
+
});
|
package/utils/auth.js
CHANGED
|
@@ -71,7 +71,7 @@ export const authProvidersInfo = async(store) => {
|
|
|
71
71
|
const nonLocal = rows.filter((x) => x.name !== 'local');
|
|
72
72
|
const enabled = nonLocal.filter((x) => x.enabled === true );
|
|
73
73
|
|
|
74
|
-
const supportedNonLocal = nonLocal.filter((x) => x.id !== '
|
|
74
|
+
const supportedNonLocal = nonLocal.filter((x) => x.id !== 'oidc');
|
|
75
75
|
|
|
76
76
|
const enabledLocation = enabled.length === 1 ? {
|
|
77
77
|
name: 'c-cluster-auth-config-id',
|
package/utils/kontainer.ts
CHANGED
|
@@ -17,7 +17,11 @@ export function syncUpstreamConfig(configPrefix: string, normanCluster: {[key: s
|
|
|
17
17
|
|
|
18
18
|
if (!isEmpty(upstreamConfig)) {
|
|
19
19
|
Object.keys(upstreamConfig).forEach((key) => {
|
|
20
|
-
if (
|
|
20
|
+
if (typeof upstreamConfig[key] === 'object') {
|
|
21
|
+
if (isEmpty(rancherConfig[key]) && !isEmpty(upstreamConfig[key])) {
|
|
22
|
+
set(rancherConfig, key, upstreamConfig[key]);
|
|
23
|
+
}
|
|
24
|
+
} else if ((rancherConfig[key] === null || rancherConfig[key] === undefined) && upstreamConfig[key] !== null && upstreamConfig[key] !== undefined) {
|
|
21
25
|
set(rancherConfig, key, upstreamConfig[key]);
|
|
22
26
|
}
|
|
23
27
|
});
|
package/utils/version.js
CHANGED
|
@@ -2,6 +2,7 @@ import { sortableNumericSuffix } from '@shell/utils/sort';
|
|
|
2
2
|
import semver from 'semver';
|
|
3
3
|
import { MANAGEMENT } from '@shell/config/types';
|
|
4
4
|
import { READ_WHATS_NEW, SEEN_WHATS_NEW } from '@shell/store/prefs';
|
|
5
|
+
import { SETTING } from '@shell/config/settings';
|
|
5
6
|
|
|
6
7
|
export function parse(str) {
|
|
7
8
|
str = `${ str }`;
|
|
@@ -82,7 +83,7 @@ export function isDevBuild(version) {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
export function getVersionInfo(store) {
|
|
85
|
-
const setting = store.getters['management/byId'](MANAGEMENT.SETTING,
|
|
86
|
+
const setting = store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.VERSION_RANCHER);
|
|
86
87
|
const fullVersion = setting?.value || 'unknown';
|
|
87
88
|
let displayVersion = fullVersion;
|
|
88
89
|
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { Accordion } from './index';
|
|
3
|
-
|
|
4
|
-
describe('component: Accordion', () => {
|
|
5
|
-
it('is closed initially by default', () => {
|
|
6
|
-
const title = 'Test Title';
|
|
7
|
-
|
|
8
|
-
const wrapper = shallowMount(Accordion, { propsData: { title } });
|
|
9
|
-
|
|
10
|
-
expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(false);
|
|
11
|
-
expect(wrapper.find('[data-testid="accordion-header"]').text()).toBe(title);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('is opened initially when openInitially prop is true', () => {
|
|
15
|
-
const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
|
|
16
|
-
|
|
17
|
-
expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(true);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('when closed, opens when the header is clicked', async() => {
|
|
21
|
-
const wrapper = shallowMount(Accordion, { });
|
|
22
|
-
|
|
23
|
-
await wrapper.find('[data-testid="accordion-header"]').trigger('click');
|
|
24
|
-
expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(true);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('when open, closes when the header is clicked', async() => {
|
|
28
|
-
const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
|
|
29
|
-
|
|
30
|
-
await wrapper.find('[data-testid="accordion-header"]').trigger('click');
|
|
31
|
-
expect(wrapper.find('[data-testid="accordion-body"]').isVisible()).toBe(false);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('displays a chevron when closed', async() => {
|
|
35
|
-
const wrapper = shallowMount(Accordion, { propsData: { } });
|
|
36
|
-
|
|
37
|
-
expect(wrapper.find('[data-testid="accordion-header"] .icon-chevron-up').exists()).toBe(true);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('displays an inverted chevron when open', async() => {
|
|
41
|
-
const wrapper = shallowMount(Accordion, { propsData: { openInitially: true } });
|
|
42
|
-
|
|
43
|
-
expect(wrapper.find('[data-testid="accordion-header"] .icon-chevron-down').exists()).toBe(true);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { defineComponent } from 'vue';
|
|
3
|
-
import { mapGetters } from 'vuex';
|
|
4
|
-
|
|
5
|
-
export default defineComponent({
|
|
6
|
-
props: {
|
|
7
|
-
title: {
|
|
8
|
-
type: String,
|
|
9
|
-
default: ''
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
titleKey: {
|
|
13
|
-
type: String,
|
|
14
|
-
default: null
|
|
15
|
-
},
|
|
16
|
-
|
|
17
|
-
openInitially: {
|
|
18
|
-
type: Boolean,
|
|
19
|
-
default: false
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
data() {
|
|
24
|
-
return { isOpen: this.openInitially };
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
computed: { ...mapGetters({ t: 'i18n/t' }) },
|
|
28
|
-
|
|
29
|
-
methods: {
|
|
30
|
-
toggle() {
|
|
31
|
-
this.isOpen = !this.isOpen;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
</script>
|
|
36
|
-
|
|
37
|
-
<template>
|
|
38
|
-
<div class="accordion-container">
|
|
39
|
-
<div
|
|
40
|
-
class="accordion-header"
|
|
41
|
-
data-testid="accordion-header"
|
|
42
|
-
@click="toggle"
|
|
43
|
-
>
|
|
44
|
-
<i
|
|
45
|
-
class="icon text-primary"
|
|
46
|
-
:class="{'icon-chevron-down':isOpen, 'icon-chevron-up':!isOpen}"
|
|
47
|
-
data-testid="accordion-chevron"
|
|
48
|
-
/>
|
|
49
|
-
<slot name="header">
|
|
50
|
-
<h4
|
|
51
|
-
data-testid="accordion-title-slot-content"
|
|
52
|
-
class="mb-0"
|
|
53
|
-
>
|
|
54
|
-
{{ titleKey ? t(titleKey) : title }}
|
|
55
|
-
</h4>
|
|
56
|
-
</slot>
|
|
57
|
-
</div>
|
|
58
|
-
<div
|
|
59
|
-
v-show="isOpen"
|
|
60
|
-
class="accordion-body"
|
|
61
|
-
data-testid="accordion-body"
|
|
62
|
-
>
|
|
63
|
-
<slot />
|
|
64
|
-
</div>
|
|
65
|
-
</div>
|
|
66
|
-
</template>
|
|
67
|
-
|
|
68
|
-
<style lang="scss" scoped>
|
|
69
|
-
.accordion-container {
|
|
70
|
-
border: 1px solid var(--border)
|
|
71
|
-
}
|
|
72
|
-
.accordion-header {
|
|
73
|
-
padding: 5px;
|
|
74
|
-
display: flex;
|
|
75
|
-
align-items: center;
|
|
76
|
-
&>*{
|
|
77
|
-
padding: 5px 0px 5px 0px;
|
|
78
|
-
}
|
|
79
|
-
I {
|
|
80
|
-
margin: 0px 10px 0px 10px;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
.accordion-body {
|
|
84
|
-
padding: 10px;
|
|
85
|
-
}
|
|
86
|
-
</style>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default as Accordion } from './Accordion.vue';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { BadgeState } from './index';
|
|
3
|
-
|
|
4
|
-
describe('BadgeState.vue', () => {
|
|
5
|
-
it('renders props.msg when passed', () => {
|
|
6
|
-
const label = 'Hello, World!';
|
|
7
|
-
|
|
8
|
-
const wrapper = shallowMount(BadgeState, { propsData: { label } });
|
|
9
|
-
|
|
10
|
-
expect(wrapper.find('span').text()).toMatch(label);
|
|
11
|
-
});
|
|
12
|
-
});
|