@rancher/shell 0.1.4 → 0.2.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/brand/suse/favicon.png +0 -0
- package/assets/images/generic-plugin.svg +1 -7
- package/assets/styles/global/_button.scss +1 -0
- package/assets/translations/en-us.yaml +129 -53
- package/assets/translations/zh-hans.yaml +18 -0
- package/components/CommunityLinks.vue +40 -49
- package/components/ExplorerProjectsNamespaces.vue +20 -3
- package/components/HarvesterServiceAddOnConfig.vue +10 -10
- package/components/LazyImage.vue +21 -8
- package/components/PromptRemove.vue +2 -2
- package/components/ResourceList/Masthead.vue +21 -1
- package/components/ResourceList/ResourceLoadingIndicator.vue +0 -8
- package/components/ResourceList/index.vue +42 -36
- package/components/ResourceTable.vue +19 -0
- package/components/SortableTable/THead.vue +311 -70
- package/components/SortableTable/advanced-filtering.js +272 -0
- package/components/SortableTable/filtering.js +90 -29
- package/components/SortableTable/index.vue +486 -280
- package/components/Tabbed/index.vue +25 -7
- package/components/TypeDescription.vue +10 -1
- package/components/fleet/FleetClusters.vue +6 -0
- package/components/fleet/FleetRepos.vue +7 -1
- package/components/form/Command.vue +5 -0
- package/components/form/EnvVars.vue +5 -0
- package/components/form/NameNsDescription.vue +3 -1
- package/components/form/NodeScheduling.vue +6 -1
- package/components/form/PodAffinity.vue +5 -0
- package/components/form/ServiceNameSelect.vue +5 -0
- package/components/form/ValueFromResource.vue +7 -1
- package/components/form/WorkloadPorts.vue +2 -2
- package/components/nav/TopLevelMenu.vue +2 -1
- package/config/home-links.js +155 -0
- package/config/private-label.js +1 -1
- package/config/product/manager.js +0 -2
- package/config/product/settings.js +1 -0
- package/config/product/uiplugins.js +2 -1
- package/config/settings.js +3 -1
- package/config/uiplugins.js +76 -6
- package/config/version.js +17 -0
- package/core/plugin.ts +12 -0
- package/core/plugins.js +29 -5
- package/core/types.ts +6 -0
- package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
- package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
- package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
- package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
- package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
- package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
- package/creators/app/init +16 -17
- package/creators/app/package.json +7 -1
- package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
- package/creators/pkg/{index.ts → files/index.ts} +0 -0
- package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
- package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
- package/creators/pkg/init +1 -1
- package/creators/pkg/package.json +1 -1
- package/creators/update/init +54 -0
- package/creators/update/package.json +20 -0
- package/creators/update/upgrade +56 -0
- package/creators/update/yarn-error.log +54 -0
- package/detail/provisioning.cattle.io.cluster.vue +1 -1
- package/detail/workload/index.vue +1 -0
- package/edit/persistentvolume/index.vue +48 -13
- package/edit/persistentvolumeclaim.vue +31 -13
- package/edit/provisioning.cattle.io.cluster/ACE.vue +2 -1
- package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +0 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +52 -43
- package/edit/service.vue +1 -1
- package/edit/workload/index.vue +19 -9
- package/edit/workload/mixins/workload.js +109 -114
- package/edit/workload/storage/index.vue +11 -17
- package/edit/workload/storage/persistentVolumeClaim/index.vue +5 -0
- package/edit/workload/storage/secret.vue +6 -1
- package/list/catalog.cattle.io.app.vue +10 -9
- package/list/catalog.cattle.io.clusterrepo.vue +6 -61
- package/list/cis.cattle.io.clusterscan.vue +12 -12
- package/list/fleet.cattle.io.bundle.vue +33 -28
- package/list/fleet.cattle.io.cluster.vue +26 -22
- package/list/fleet.cattle.io.clustergroup.vue +6 -0
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +28 -24
- package/list/fleet.cattle.io.gitrepo.vue +25 -14
- package/list/helm.cattle.io.projecthelmchart.vue +52 -33
- package/list/logging.banzaicloud.io.clusterflow.vue +7 -12
- package/list/logging.banzaicloud.io.flow.vue +7 -14
- package/list/management.cattle.io.cluster.vue +26 -15
- package/list/management.cattle.io.feature.vue +13 -8
- package/list/management.cattle.io.user.vue +38 -19
- package/list/monitoring.coreos.com.alertmanagerconfig.vue +8 -15
- package/list/namespace.vue +14 -1
- package/list/node.vue +13 -16
- package/list/persistentvolume.vue +16 -9
- package/list/persistentvolumeclaim.vue +5 -8
- package/list/provisioning.cattle.io.cluster.vue +34 -8
- package/list/service.vue +24 -12
- package/list/ui.cattle.io.navlink.vue +6 -0
- package/list/workload.vue +2 -2
- package/middleware/authenticated.js +6 -0
- package/mixins/resource-fetch.js +12 -18
- package/mixins/resource-manager.js +126 -0
- package/models/catalog.cattle.io.uiplugin.js +4 -0
- package/models/management.cattle.io.cluster.js +9 -1
- package/models/pod.js +15 -5
- package/models/provisioning.cattle.io.cluster.js +4 -0
- package/models/workload.service.js +10 -0
- package/nuxt.config.js +2 -1
- package/package.json +1 -1
- package/pages/auth/login.vue +10 -0
- package/pages/auth/verify.vue +9 -0
- package/pages/c/_cluster/apps/charts/install.vue +119 -31
- package/pages/c/_cluster/settings/DefaultLinksEditor.vue +108 -0
- package/pages/c/_cluster/settings/links.vue +53 -101
- package/pages/c/_cluster/settings/performance.vue +90 -7
- package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +3 -3
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +72 -21
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +26 -7
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +2 -7
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +23 -15
- package/pages/c/_cluster/uiplugins/UninstallDialog.vue +12 -5
- package/pages/c/_cluster/uiplugins/index.vue +223 -72
- package/pages/support/index.vue +31 -142
- package/plugins/dashboard-store/actions.js +19 -0
- package/plugins/dashboard-store/getters.js +20 -3
- package/plugins/dashboard-store/mutations.js +13 -7
- package/plugins/plugin.js +18 -15
- package/plugins/steve/getters.js +12 -0
- package/plugins/version.js +21 -0
- package/promptRemove/mixin/roleDeletionCheck.js +15 -1
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -7
- package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
- package/rancher-components/components/BadgeState/BadgeState.vue +107 -0
- package/rancher-components/components/BadgeState/index.ts +1 -0
- package/rancher-components/components/Banner/Banner.test.ts +13 -0
- package/rancher-components/components/Banner/Banner.vue +163 -0
- package/rancher-components/components/Banner/index.ts +1 -0
- package/rancher-components/components/Card/Card.vue +150 -0
- package/rancher-components/components/Card/index.ts +1 -0
- package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +395 -0
- package/rancher-components/components/Form/Checkbox/index.ts +1 -0
- package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +29 -0
- package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +343 -0
- package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +270 -0
- package/rancher-components/components/Form/Radio/RadioGroup.vue +235 -0
- package/rancher-components/components/Form/Radio/index.ts +2 -0
- package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +168 -0
- package/rancher-components/components/Form/TextArea/index.ts +1 -0
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
- package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +137 -0
- package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
- package/rancher-components/components/Form/index.ts +5 -0
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +137 -0
- package/rancher-components/components/LabeledTooltip/index.ts +1 -0
- package/scripts/publish-shell.sh +39 -6
- package/scripts/record-deps.js +37 -0
- package/scripts/test-plugins-build.sh +8 -5
- package/scripts/typegen.sh +84 -0
- package/store/auth.js +3 -0
- package/store/index.js +12 -3
- package/store/type-map.js +2 -0
- package/types/shell/index.d.ts +3046 -0
- package/utils/favicon.js +8 -2
- package/utils/gc/gc-interval.ts +40 -0
- package/utils/gc/gc-root-store.js +76 -0
- package/utils/gc/gc-route-changed.ts +44 -0
- package/utils/gc/gc-types.ts +21 -0
- package/utils/gc/gc.ts +282 -0
- package/config/footer.js +0 -18
- package/creators/pkg/nuxt.config.js +0 -6
- package/yarn-error.log +0 -195
|
@@ -40,6 +40,12 @@ export default {
|
|
|
40
40
|
default: false,
|
|
41
41
|
},
|
|
42
42
|
|
|
43
|
+
// Remove padding and box-shadow
|
|
44
|
+
flat: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
|
|
43
49
|
tabsOnly: {
|
|
44
50
|
type: Boolean,
|
|
45
51
|
default: false,
|
|
@@ -257,7 +263,13 @@ export default {
|
|
|
257
263
|
</ul>
|
|
258
264
|
<slot name="tab-row-extras" />
|
|
259
265
|
</ul>
|
|
260
|
-
<div
|
|
266
|
+
<div
|
|
267
|
+
:class="{
|
|
268
|
+
'tab-container': !!tabs.length || !!sideTabs,
|
|
269
|
+
'no-content': noContent,
|
|
270
|
+
'tab-container--flat': !!flat,
|
|
271
|
+
}"
|
|
272
|
+
>
|
|
261
273
|
<slot />
|
|
262
274
|
</div>
|
|
263
275
|
</div>
|
|
@@ -350,6 +362,15 @@ export default {
|
|
|
350
362
|
&.no-content {
|
|
351
363
|
padding: 0 0 3px 0;
|
|
352
364
|
}
|
|
365
|
+
|
|
366
|
+
// Example case: Tabbed component within a tabbed component
|
|
367
|
+
&--flat {
|
|
368
|
+
padding: 0;
|
|
369
|
+
|
|
370
|
+
.side-tabs {
|
|
371
|
+
box-shadow: unset;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
353
374
|
}
|
|
354
375
|
|
|
355
376
|
.tabs-only {
|
|
@@ -375,11 +396,6 @@ export default {
|
|
|
375
396
|
padding: 20px;
|
|
376
397
|
}
|
|
377
398
|
|
|
378
|
-
// Tabbed component within a tabbed component
|
|
379
|
-
.tab-container & {
|
|
380
|
-
box-shadow: unset;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
399
|
& .tabs {
|
|
384
400
|
width: $sideways-tabs-width;
|
|
385
401
|
min-width: $sideways-tabs-width;
|
|
@@ -451,7 +467,9 @@ export default {
|
|
|
451
467
|
}
|
|
452
468
|
}
|
|
453
469
|
|
|
454
|
-
&
|
|
470
|
+
&
|
|
471
|
+
|
|
472
|
+
.tab-container {
|
|
455
473
|
width: calc(100% - #{$sideways-tabs-width});
|
|
456
474
|
flex-grow: 1;
|
|
457
475
|
background-color: var(--body-bg);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { mapGetters } from 'vuex';
|
|
2
3
|
import { Banner } from '@components/Banner';
|
|
3
4
|
import { HIDE_DESC, mapPref } from '@shell/store/prefs';
|
|
4
5
|
import { addObject } from '@shell/utils/array';
|
|
6
|
+
import { CATALOG } from '@shell/config/types';
|
|
5
7
|
|
|
6
8
|
export default {
|
|
7
9
|
components: { Banner },
|
|
@@ -14,10 +16,17 @@ export default {
|
|
|
14
16
|
},
|
|
15
17
|
|
|
16
18
|
computed: {
|
|
19
|
+
...mapGetters(['currentCluster']),
|
|
17
20
|
hideDescriptions: mapPref(HIDE_DESC),
|
|
18
21
|
|
|
19
22
|
typeDescriptionKey() {
|
|
20
|
-
|
|
23
|
+
let key;
|
|
24
|
+
|
|
25
|
+
if (this.resource === CATALOG.CLUSTER_REPO) {
|
|
26
|
+
key = !this.currentCluster || this.currentCluster.isLocal ? 'typeDescription."catalog.cattle.io.clusterrepo.local"' : 'typeDescription."catalog.cattle.io.clusterrepo"';
|
|
27
|
+
} else {
|
|
28
|
+
key = `typeDescription."${ this.resource }"`;
|
|
29
|
+
}
|
|
21
30
|
|
|
22
31
|
if ( this.hideDescriptions.includes(this.resource) || this.hideDescriptions.includes('ALL') ) {
|
|
23
32
|
return false;
|
|
@@ -16,6 +16,11 @@ export default {
|
|
|
16
16
|
type: Object,
|
|
17
17
|
default: null,
|
|
18
18
|
},
|
|
19
|
+
|
|
20
|
+
loading: {
|
|
21
|
+
type: Boolean,
|
|
22
|
+
default: false,
|
|
23
|
+
},
|
|
19
24
|
},
|
|
20
25
|
|
|
21
26
|
computed: {
|
|
@@ -80,6 +85,7 @@ export default {
|
|
|
80
85
|
:schema="schema"
|
|
81
86
|
:headers="headers"
|
|
82
87
|
:rows="rows"
|
|
88
|
+
:loading="loading"
|
|
83
89
|
key-field="_key"
|
|
84
90
|
v-on="$listeners"
|
|
85
91
|
>
|
|
@@ -28,6 +28,11 @@ export default {
|
|
|
28
28
|
type: Object,
|
|
29
29
|
required: true,
|
|
30
30
|
},
|
|
31
|
+
|
|
32
|
+
loading: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
required: false,
|
|
35
|
+
},
|
|
31
36
|
},
|
|
32
37
|
|
|
33
38
|
computed: {
|
|
@@ -89,13 +94,14 @@ export default {
|
|
|
89
94
|
|
|
90
95
|
<template>
|
|
91
96
|
<div>
|
|
92
|
-
<FleetIntro v-if="noRows" />
|
|
97
|
+
<FleetIntro v-if="noRows && !loading" />
|
|
93
98
|
<ResourceTable
|
|
94
99
|
v-if="!noRows"
|
|
95
100
|
v-bind="$attrs"
|
|
96
101
|
:schema="schema"
|
|
97
102
|
:headers="headers"
|
|
98
103
|
:rows="rows"
|
|
104
|
+
:loading="loading"
|
|
99
105
|
key-field="_key"
|
|
100
106
|
v-on="$listeners"
|
|
101
107
|
>
|
|
@@ -36,6 +36,10 @@ export default {
|
|
|
36
36
|
return {};
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
|
+
loading: {
|
|
40
|
+
default: false,
|
|
41
|
+
type: Boolean
|
|
42
|
+
},
|
|
39
43
|
},
|
|
40
44
|
|
|
41
45
|
data() {
|
|
@@ -200,6 +204,7 @@ export default {
|
|
|
200
204
|
:config-maps="configMaps"
|
|
201
205
|
:secrets="secrets"
|
|
202
206
|
:value="value"
|
|
207
|
+
:loading="loading"
|
|
203
208
|
/>
|
|
204
209
|
</div>
|
|
205
210
|
</template>
|
|
@@ -23,6 +23,10 @@ export default {
|
|
|
23
23
|
type: Array,
|
|
24
24
|
required: true
|
|
25
25
|
},
|
|
26
|
+
loading: {
|
|
27
|
+
default: false,
|
|
28
|
+
type: Boolean
|
|
29
|
+
},
|
|
26
30
|
/**
|
|
27
31
|
* Container spec
|
|
28
32
|
*/
|
|
@@ -107,6 +111,7 @@ export default {
|
|
|
107
111
|
:all-secrets="secrets"
|
|
108
112
|
:all-config-maps="configMaps"
|
|
109
113
|
:mode="mode"
|
|
114
|
+
:loading="loading"
|
|
110
115
|
@remove="removeRow(i)"
|
|
111
116
|
@input="updateRow"
|
|
112
117
|
/>
|
|
@@ -342,7 +342,7 @@ export default {
|
|
|
342
342
|
}
|
|
343
343
|
|
|
344
344
|
if (this.namespaced) {
|
|
345
|
-
this.$emit('isNamespaceNew', this.namespaces && !this.namespaces.find(n => n.value === val));
|
|
345
|
+
this.$emit('isNamespaceNew', !val || (this.namespaces && !this.namespaces.find(n => n.value === val)));
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
if (this.namespaceKey) {
|
|
@@ -361,10 +361,12 @@ export default {
|
|
|
361
361
|
if (!e || e.value === '') { // The blank value in the dropdown is labeled "Create a New Namespace"
|
|
362
362
|
this.createNamespace = true;
|
|
363
363
|
this.$parent.$emit('createNamespace', true);
|
|
364
|
+
this.$emit('isNamespaceNew', true);
|
|
364
365
|
Vue.nextTick(() => this.$refs.namespace.focus());
|
|
365
366
|
} else {
|
|
366
367
|
this.createNamespace = false;
|
|
367
368
|
this.$parent.$emit('createNamespace', false);
|
|
369
|
+
this.$emit('isNamespaceNew', false);
|
|
368
370
|
}
|
|
369
371
|
}
|
|
370
372
|
},
|
|
@@ -31,7 +31,11 @@ export default {
|
|
|
31
31
|
mode: {
|
|
32
32
|
type: String,
|
|
33
33
|
default: 'create'
|
|
34
|
-
}
|
|
34
|
+
},
|
|
35
|
+
loading: {
|
|
36
|
+
default: false,
|
|
37
|
+
type: Boolean
|
|
38
|
+
},
|
|
35
39
|
},
|
|
36
40
|
|
|
37
41
|
data() {
|
|
@@ -177,6 +181,7 @@ export default {
|
|
|
177
181
|
:options="nodes || []"
|
|
178
182
|
:mode="mode"
|
|
179
183
|
:multiple="false"
|
|
184
|
+
:loading="loading"
|
|
180
185
|
@input="update"
|
|
181
186
|
/>
|
|
182
187
|
</div>
|
|
@@ -40,6 +40,10 @@ export default {
|
|
|
40
40
|
type: Array,
|
|
41
41
|
default: null
|
|
42
42
|
},
|
|
43
|
+
loading: {
|
|
44
|
+
default: false,
|
|
45
|
+
type: Boolean
|
|
46
|
+
},
|
|
43
47
|
},
|
|
44
48
|
|
|
45
49
|
data() {
|
|
@@ -305,6 +309,7 @@ export default {
|
|
|
305
309
|
:placeholder="t('workload.scheduling.affinity.topologyKey.placeholder')"
|
|
306
310
|
:options="existingNodeLabels"
|
|
307
311
|
:disabled="mode==='view'"
|
|
312
|
+
:loading="loading"
|
|
308
313
|
@input="update"
|
|
309
314
|
/>
|
|
310
315
|
<LabeledInput
|
|
@@ -60,6 +60,10 @@ export default {
|
|
|
60
60
|
type: Boolean,
|
|
61
61
|
default: true,
|
|
62
62
|
},
|
|
63
|
+
loading: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
default: false,
|
|
66
|
+
},
|
|
63
67
|
},
|
|
64
68
|
|
|
65
69
|
data() {
|
|
@@ -134,6 +138,7 @@ export default {
|
|
|
134
138
|
:option-label="optionLabel"
|
|
135
139
|
:placement="$attrs.placement ? $attrs.placement : null"
|
|
136
140
|
:v-bind="$attrs"
|
|
141
|
+
:loading="loading"
|
|
137
142
|
@input="changeSelected"
|
|
138
143
|
/>
|
|
139
144
|
<button
|
|
@@ -34,7 +34,11 @@ export default {
|
|
|
34
34
|
namespaced: {
|
|
35
35
|
type: Boolean,
|
|
36
36
|
default: true
|
|
37
|
-
}
|
|
37
|
+
},
|
|
38
|
+
loading: {
|
|
39
|
+
default: false,
|
|
40
|
+
type: Boolean
|
|
41
|
+
},
|
|
38
42
|
},
|
|
39
43
|
|
|
40
44
|
data() {
|
|
@@ -300,6 +304,7 @@ export default {
|
|
|
300
304
|
:get-option-key="opt=>opt.id|| opt"
|
|
301
305
|
:mode="mode"
|
|
302
306
|
:label="sourceLabel"
|
|
307
|
+
:loading="loading"
|
|
303
308
|
/>
|
|
304
309
|
</div>
|
|
305
310
|
<div v-if="type!=='secretRef' && type!== 'configMapRef'">
|
|
@@ -310,6 +315,7 @@ export default {
|
|
|
310
315
|
:mode="mode"
|
|
311
316
|
option-label="label"
|
|
312
317
|
:label="t('workload.container.command.fromResource.key.label')"
|
|
318
|
+
:loading="loading"
|
|
313
319
|
@input="updateRow"
|
|
314
320
|
/>
|
|
315
321
|
</div>
|
|
@@ -366,7 +366,7 @@ export default {
|
|
|
366
366
|
v-model="row._ipam"
|
|
367
367
|
:mode="mode"
|
|
368
368
|
:options="ipamOptions"
|
|
369
|
-
:label="t('harvester.
|
|
369
|
+
:label="t('servicesPage.harvester.ipam.label')"
|
|
370
370
|
:disabled="mode === 'edit'"
|
|
371
371
|
@input="queueUpdate"
|
|
372
372
|
/>
|
|
@@ -376,7 +376,7 @@ export default {
|
|
|
376
376
|
v-model="rows[ipamIndex]._ipam"
|
|
377
377
|
:mode="mode"
|
|
378
378
|
:options="ipamOptions"
|
|
379
|
-
:label="t('harvester.
|
|
379
|
+
:label="t('servicesPage.harvester.ipam.label')"
|
|
380
380
|
:disabled="true"
|
|
381
381
|
@input="queueUpdate"
|
|
382
382
|
/>
|
|
@@ -12,6 +12,7 @@ import { getVersionInfo } from '@shell/utils/version';
|
|
|
12
12
|
import { LEGACY } from '@shell/store/features';
|
|
13
13
|
import { SETTING } from '@shell/config/settings';
|
|
14
14
|
import { filterOnlyKubernetesClusters, filterHiddenLocalCluster } from '@shell/utils/cluster';
|
|
15
|
+
import { isRancherPrime } from '@shell/config/version';
|
|
15
16
|
|
|
16
17
|
const UNKNOWN = 'unknown';
|
|
17
18
|
const UI_VERSION = process.env.VERSION || UNKNOWN;
|
|
@@ -162,7 +163,7 @@ export default {
|
|
|
162
163
|
},
|
|
163
164
|
|
|
164
165
|
hasSupport() {
|
|
165
|
-
return this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SUPPORTED )?.value === 'true';
|
|
166
|
+
return isRancherPrime() || this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SUPPORTED )?.value === 'true';
|
|
166
167
|
},
|
|
167
168
|
},
|
|
168
169
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { DOCS_BASE } from '@shell/config/private-label';
|
|
2
|
+
import { MANAGEMENT } from '@shell/config/types';
|
|
3
|
+
import { SETTING } from '@shell/config/settings';
|
|
4
|
+
import { allHash } from '@shell/utils/promise';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_LINKS = [
|
|
7
|
+
{
|
|
8
|
+
key: 'docs',
|
|
9
|
+
value: DOCS_BASE,
|
|
10
|
+
enabled: true,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
key: 'forums',
|
|
14
|
+
value: 'https://forums.rancher.com/',
|
|
15
|
+
enabled: true,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
key: 'slack',
|
|
19
|
+
value: 'https://slack.rancher.io/',
|
|
20
|
+
enabled: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
key: 'issues',
|
|
24
|
+
value: 'https://github.com/rancher/dashboard/issues/new/choose',
|
|
25
|
+
enabled: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: 'getStarted',
|
|
29
|
+
value: '/docs/getting-started',
|
|
30
|
+
enabled: true,
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const SUPPORT_LINK = {
|
|
35
|
+
key: 'commercialSupport',
|
|
36
|
+
value: '/support',
|
|
37
|
+
enabled: true,
|
|
38
|
+
readonly: true
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// We add a version attribute to the setting so we know what has been migrated and which version of the setting we have
|
|
42
|
+
export const CUSTOM_LINKS_VERSION = 'v1';
|
|
43
|
+
|
|
44
|
+
// Fetch the settings required for the links, taking into account legacy settings if we have not migrated
|
|
45
|
+
export async function fetchLinks(store, hasSupport, isSupportPage, t) {
|
|
46
|
+
let uiLinks = {};
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const uiLinksSetting = await store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.UI_CUSTOM_LINKS });
|
|
50
|
+
|
|
51
|
+
uiLinks = JSON.parse(uiLinksSetting.value);
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.warn('Could not parse custom link settings', e); // eslint-disable-line no-console
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If uiLinks is set and has the correct version, then we are okay, otherwise we need to migrate from the old settings
|
|
57
|
+
if (uiLinks?.version === CUSTOM_LINKS_VERSION) {
|
|
58
|
+
// Map out the default settings, as we only store keys of the ones to show
|
|
59
|
+
if (uiLinks.defaults) {
|
|
60
|
+
const defaults = [...DEFAULT_LINKS];
|
|
61
|
+
|
|
62
|
+
// Map the link name stored to the default link, if it exists
|
|
63
|
+
defaults.forEach((link) => {
|
|
64
|
+
const enabled = uiLinks.defaults.find(linkName => linkName === link.key);
|
|
65
|
+
|
|
66
|
+
link.enabled = !!enabled;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
uiLinks.defaults = defaults;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return ensureSupportLink(uiLinks, hasSupport, isSupportPage, t);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// No new setting, so return the required structure
|
|
76
|
+
// We don't migrate here, as we may not have permissions to create the setting
|
|
77
|
+
const links = {
|
|
78
|
+
version: CUSTOM_LINKS_VERSION,
|
|
79
|
+
defaults: [...DEFAULT_LINKS],
|
|
80
|
+
custom: []
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// There are two legacy settings:
|
|
84
|
+
// SETTING.ISSUES - can specify a custom link to use for 'File an issue'
|
|
85
|
+
// SETTING.COMMUNITY_LINKS - can specify whether to hide all of the default links (other than 'File an issue')
|
|
86
|
+
try {
|
|
87
|
+
const { uiIssuesSetting, uiCommunitySetting } = await allHash({
|
|
88
|
+
uiIssuesSetting: store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES }),
|
|
89
|
+
uiCommunitySetting: store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.COMMUNITY_LINKS })
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Should we show the default set of links?
|
|
93
|
+
if (uiCommunitySetting?.value === 'false') {
|
|
94
|
+
// Hide all of the default links
|
|
95
|
+
links.defaults.forEach(link => (link.enabled = false));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Do we have a custom 'File an issue' link ?
|
|
99
|
+
if (uiIssuesSetting?.value) {
|
|
100
|
+
links.custom.push({
|
|
101
|
+
label: t ? t('customLinks.defaults.issues') : 'Issues',
|
|
102
|
+
value: uiIssuesSetting.value
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Hide the default 'File an issue' link
|
|
106
|
+
const issueLink = links.defaults?.find(link => link.key === 'issues');
|
|
107
|
+
|
|
108
|
+
if (issueLink) {
|
|
109
|
+
issueLink.enabled = false;
|
|
110
|
+
issueLink.readOnly = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch (e) {
|
|
114
|
+
console.warn('Could not parse legacy link settings', e); // eslint-disable-line no-console
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return ensureSupportLink(links, hasSupport, isSupportPage, t);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Ensure the support link is added if needed
|
|
121
|
+
function ensureSupportLink(links, hasSupport, isSupportPage, t) {
|
|
122
|
+
if (!hasSupport && !isSupportPage) {
|
|
123
|
+
const supportLink = links.defaults?.find(link => link.key === 'commercialSupport');
|
|
124
|
+
|
|
125
|
+
if (!supportLink) {
|
|
126
|
+
links.defaults.push(SUPPORT_LINK);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Localise the default links
|
|
131
|
+
links.defaults = links.defaults.map((link) => {
|
|
132
|
+
return {
|
|
133
|
+
...link,
|
|
134
|
+
label: t(`'customLinks.defaults.${ link.key }`)
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Ensure that if any custom links have the same name as a default link, we use the custom link
|
|
139
|
+
const customNamesMap = links.custom.reduce((linkMap, link) => {
|
|
140
|
+
linkMap[link.label] = link;
|
|
141
|
+
|
|
142
|
+
return linkMap;
|
|
143
|
+
}, {});
|
|
144
|
+
|
|
145
|
+
// If any custom links have the same name as a default link, then hide and mark readonly the default link
|
|
146
|
+
// Main use case if the 'File an Issue' link when migrating the old settings
|
|
147
|
+
links.defaults.forEach((link) => {
|
|
148
|
+
if (customNamesMap[link.label]) {
|
|
149
|
+
link.enabled = false;
|
|
150
|
+
link.readonly = true;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
return links;
|
|
155
|
+
}
|
package/config/private-label.js
CHANGED
|
@@ -7,7 +7,7 @@ export const DOCS_BASE = 'https://rancher.com/docs/rancher/v2.6/en';
|
|
|
7
7
|
|
|
8
8
|
const STANDARD_VENDOR = 'Rancher';
|
|
9
9
|
const STANDARD_PRODUCT = 'Explorer';
|
|
10
|
-
const CUSTOM_VENDOR = { suse: '
|
|
10
|
+
const CUSTOM_VENDOR = { suse: 'Rancher Prime' };
|
|
11
11
|
|
|
12
12
|
let mode = STANDARD;
|
|
13
13
|
let vendor = STANDARD_VENDOR;
|
|
@@ -120,8 +120,6 @@ export function init(store) {
|
|
|
120
120
|
weightType(CAPI.MACHINE, 1, true);
|
|
121
121
|
weightType(CATALOG.CLUSTER_REPO, 0, true);
|
|
122
122
|
|
|
123
|
-
configureType(CATALOG.CLUSTER_REPO, { showListMasthead: false });
|
|
124
|
-
|
|
125
123
|
basicType([
|
|
126
124
|
CAPI.MACHINE_DEPLOYMENT,
|
|
127
125
|
CAPI.MACHINE_SET,
|
|
@@ -9,9 +9,10 @@ export function init(store) {
|
|
|
9
9
|
product({
|
|
10
10
|
ifHave: IF_HAVE.ADMIN, // Only admins can see the UI Plugin Custom Resource by default
|
|
11
11
|
inStore: 'management',
|
|
12
|
-
icon: '
|
|
12
|
+
icon: 'extension',
|
|
13
13
|
removable: false,
|
|
14
14
|
showClusterSwitcher: false,
|
|
15
15
|
category: 'configuration',
|
|
16
|
+
weight: 50,
|
|
16
17
|
});
|
|
17
18
|
}
|
package/config/settings.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Settings
|
|
2
|
+
import { GC_DEFAULTS } from '../utils/gc/gc-types';
|
|
2
3
|
import { MANAGEMENT } from './types';
|
|
3
4
|
|
|
4
5
|
// Adapted from: https://github.com/rancher/ui/blob/08c379a9529f740666a704b52522a468986c3520/lib/shared/addon/utils/constants.js#L564
|
|
@@ -105,7 +106,8 @@ export const DEFAULT_PERF_SETTING = {
|
|
|
105
106
|
enabled: false,
|
|
106
107
|
threshold: 1500,
|
|
107
108
|
},
|
|
108
|
-
disableWebsocketNotification: true
|
|
109
|
+
disableWebsocketNotification: true,
|
|
110
|
+
garbageCollection: GC_DEFAULTS
|
|
109
111
|
};
|
|
110
112
|
|
|
111
113
|
export const fetchOrCreateSetting = async(store, id, val, save = true) => {
|
package/config/uiplugins.js
CHANGED
|
@@ -2,6 +2,7 @@ import semver from 'semver';
|
|
|
2
2
|
|
|
3
3
|
// Version of the plugin API supported
|
|
4
4
|
export const UI_PLUGIN_API_VERSION = '1.0.0';
|
|
5
|
+
export const UI_PLUGIN_HOST_APP = 'rancher-manager';
|
|
5
6
|
|
|
6
7
|
export const UI_PLUGIN_BASE_URL = '/api/v1/namespaces/cattle-ui-plugin-system/services/http:ui-plugin-operator:80/proxy';
|
|
7
8
|
|
|
@@ -28,8 +29,21 @@ export const UI_PLUGINS_REPO_NAME = 'rancher-ui-plugins';
|
|
|
28
29
|
export const UI_PLUGINS_REPO_URL = 'https://github.com/rancher/ui-plugin-charts';
|
|
29
30
|
export const UI_PLUGINS_REPO_BRANCH = 'main';
|
|
30
31
|
|
|
32
|
+
// Chart annotations
|
|
33
|
+
export const UI_PLUGIN_CHART_ANNOTATIONS = {
|
|
34
|
+
RANCHER_VERSION: 'catalog.cattle.io/rancher-version',
|
|
35
|
+
EXTENSIONS_VERSION: 'catalog.cattle.io/ui-extenstions-version',
|
|
36
|
+
EXTENSIONS_HOST: 'catalog.cattle.io/ui-extenstions-host',
|
|
37
|
+
DISPLAY_NAME: 'catalog.cattle.io/display-name',
|
|
38
|
+
};
|
|
39
|
+
|
|
31
40
|
// Plugin Metadata properties
|
|
32
|
-
const
|
|
41
|
+
export const UI_PLUGIN_METADATA = {
|
|
42
|
+
RANCHER_VERSION: 'rancherVersion',
|
|
43
|
+
EXTENSION_VERSION: 'extVersion',
|
|
44
|
+
EXTENSIONS_HOST: 'host',
|
|
45
|
+
DISPLAY_NAME: 'displayName',
|
|
46
|
+
};
|
|
33
47
|
|
|
34
48
|
export function isUIPlugin(chart) {
|
|
35
49
|
return !!chart?.versions.find((v) => {
|
|
@@ -43,17 +57,73 @@ export function uiPluginHasAnnotation(chart, name, value) {
|
|
|
43
57
|
});
|
|
44
58
|
}
|
|
45
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Get value of the annotation from teh latest version for a chart
|
|
62
|
+
*/
|
|
63
|
+
export function uiPluginAnnotation(chart, name) {
|
|
64
|
+
if (chart?.versions?.length > 0) {
|
|
65
|
+
return chart.versions[0].annotations?.[name];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
46
71
|
// Should we load a plugin, based on the metadata returned by the backend?
|
|
47
|
-
|
|
72
|
+
// Returns error key string or false
|
|
73
|
+
export function shouldNotLoadPlugin(plugin, rancherVersion) {
|
|
48
74
|
if (!plugin.name || !plugin.version || !plugin.endpoint) {
|
|
75
|
+
return 'plugins.error.generic';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Plugin specified a required extension API version
|
|
79
|
+
const requiredAPI = plugin.metadata?.[UI_PLUGIN_METADATA.EXTENSION_VERSION];
|
|
80
|
+
|
|
81
|
+
if (requiredAPI && !semver.satisfies(UI_PLUGIN_API_VERSION, requiredAPI)) {
|
|
82
|
+
return 'plugins.error.api';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Host application
|
|
86
|
+
const requiredHost = plugin.metadata?.[UI_PLUGIN_METADATA.EXTENSIONS_HOST];
|
|
87
|
+
|
|
88
|
+
if (requiredHost && requiredHost !== UI_PLUGIN_HOST_APP) {
|
|
89
|
+
return 'plugins.error.host';
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Rancher version
|
|
93
|
+
if (rancherVersion) {
|
|
94
|
+
const requiredRancherVersion = plugin.metadata?.[UI_PLUGIN_METADATA.RANCHER_VERSION];
|
|
95
|
+
|
|
96
|
+
if (requiredRancherVersion && !semver.satisfies(rancherVersion, requiredRancherVersion)) {
|
|
97
|
+
return 'plugins.error.version';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Can a chart version be used for this Rancher (based on the annotations on the chart)?
|
|
105
|
+
export function isSupportedChartVersion(chartVersion, rancherVersion) {
|
|
106
|
+
// Plugin specified a required extension API version
|
|
107
|
+
const requiredAPI = chartVersion.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_VERSION];
|
|
108
|
+
|
|
109
|
+
if (requiredAPI && !semver.satisfies(UI_PLUGIN_API_VERSION, requiredAPI)) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Host application
|
|
114
|
+
const requiredHost = chartVersion.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.EXTENSIONS_HOST];
|
|
115
|
+
|
|
116
|
+
if (requiredHost && requiredHost !== UI_PLUGIN_HOST_APP) {
|
|
49
117
|
return false;
|
|
50
118
|
}
|
|
51
119
|
|
|
52
|
-
//
|
|
53
|
-
|
|
120
|
+
// Rancher version
|
|
121
|
+
if (rancherVersion) {
|
|
122
|
+
const requiredRancherVersion = chartVersion.annotations?.[UI_PLUGIN_CHART_ANNOTATIONS.RANCHER_VERSION];
|
|
54
123
|
|
|
55
|
-
|
|
56
|
-
|
|
124
|
+
if (requiredRancherVersion && !semver.satisfies(rancherVersion, requiredRancherVersion)) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
57
127
|
}
|
|
58
128
|
|
|
59
129
|
return true;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store version data retrieved from the backend /rancherversion API
|
|
3
|
+
*/
|
|
4
|
+
let _versionData = { RancherPrime: 'false' };
|
|
5
|
+
|
|
6
|
+
export function isRancherPrime() {
|
|
7
|
+
return _versionData.RancherPrime?.toLowerCase() === 'true';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function getVersionData() {
|
|
11
|
+
return _versionData;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function setVersionData(v) {
|
|
15
|
+
// Remove any properties on 'v' we don't want
|
|
16
|
+
_versionData = JSON.parse(JSON.stringify(v));
|
|
17
|
+
}
|