@rancher/shell 3.0.5 → 3.0.7
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/images/pl/dark/rancher-logo.svg +131 -44
- package/assets/images/pl/rancher-logo.svg +120 -44
- package/assets/styles/base/_basic.scss +2 -2
- package/assets/styles/base/_color-classic.scss +51 -0
- package/assets/styles/base/_color.scss +3 -3
- package/assets/styles/base/_mixins.scss +1 -1
- package/assets/styles/base/_variables-classic.scss +47 -0
- package/assets/styles/global/_button.scss +49 -17
- package/assets/styles/global/_form.scss +1 -1
- package/assets/styles/themes/_dark.scss +4 -0
- package/assets/styles/themes/_light.scss +3 -69
- package/assets/styles/themes/_modern.scss +194 -50
- package/assets/styles/vendor/vue-select.scss +1 -2
- package/assets/translations/en-us.yaml +33 -21
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/CodeMirror.vue +1 -1
- package/components/FilterPanel.vue +8 -1
- package/components/IconOrSvg.vue +40 -29
- package/components/PaginatedResourceTable.vue +7 -2
- package/components/PromptRemove.vue +5 -0
- package/components/ResourceDetail/index.vue +1 -0
- package/components/ResourceTable.vue +30 -20
- package/components/SortableTable/sorting.js +3 -1
- package/components/Tabbed/index.vue +5 -5
- package/components/form/ResourceTabs/index.vue +37 -18
- package/components/form/SecretSelector.vue +6 -2
- package/components/nav/Group.vue +29 -9
- package/components/nav/Header.vue +6 -8
- package/components/nav/NamespaceFilter.vue +1 -1
- package/components/nav/TopLevelMenu.helper.ts +47 -20
- package/components/nav/TopLevelMenu.vue +44 -14
- package/components/nav/Type.vue +0 -5
- package/components/nav/__tests__/TopLevelMenu.test.ts +2 -0
- package/config/pagination-table-headers.js +10 -2
- package/config/product/explorer.js +9 -8
- package/config/table-headers.js +9 -0
- package/config/uiplugins.js +1 -1
- package/core/plugin.ts +33 -9
- package/core/types.ts +37 -6
- package/detail/provisioning.cattle.io.cluster.vue +1 -0
- package/dialog/InstallExtensionDialog.vue +71 -45
- package/dialog/UninstallExtensionDialog.vue +2 -1
- package/dialog/__tests__/InstallExtensionDialog.test.ts +111 -0
- package/edit/auth/oidc.vue +86 -16
- package/list/catalog.cattle.io.clusterrepo.vue +2 -2
- package/mixins/__tests__/chart.test.ts +1 -1
- package/mixins/chart.js +1 -1
- package/models/event.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +9 -0
- package/package.json +2 -2
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +6 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +4 -3
- package/pages/c/_cluster/apps/charts/index.vue +12 -11
- package/pages/c/_cluster/explorer/EventsTable.vue +3 -6
- package/pages/c/_cluster/settings/performance.vue +1 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +159 -62
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +102 -0
- package/pages/c/_cluster/uiplugins/__tests__/{index.spec.ts → index.test.ts} +121 -55
- package/pages/c/_cluster/uiplugins/index.vue +110 -94
- package/plugins/__tests__/subscribe.events.test.ts +194 -0
- package/plugins/dashboard-store/actions.js +3 -0
- package/plugins/dashboard-store/getters.js +1 -1
- package/plugins/dashboard-store/resource-class.js +15 -4
- package/plugins/steve/__tests__/subscribe.spec.ts +27 -24
- package/plugins/steve/index.js +18 -10
- package/plugins/steve/mutations.js +2 -2
- package/plugins/steve/resourceWatcher.js +2 -2
- package/plugins/steve/steve-pagination-utils.ts +26 -31
- package/plugins/steve/subscribe.js +113 -85
- package/plugins/subscribe-events.ts +211 -0
- package/rancher-components/BadgeState/BadgeState.vue +8 -6
- package/rancher-components/Banner/Banner.vue +2 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
- package/rancher-components/Form/Radio/RadioButton.vue +3 -3
- package/scripts/test-plugins-build.sh +4 -5
- package/scripts/typegen.sh +2 -0
- package/store/auth.js +2 -2
- package/store/index.js +12 -22
- package/types/extension-manager.ts +8 -1
- package/types/resources/settings.d.ts +24 -17
- package/types/shell/index.d.ts +534 -336
- package/types/store/subscribe-events.types.ts +70 -0
- package/types/store/subscribe.types.ts +6 -22
- package/types/store/vuex.d.ts +2 -1
- package/types/vue-shim.d.ts +2 -5
- package/utils/pagination-utils.ts +98 -30
- package/utils/pagination-wrapper.ts +6 -8
- package/utils/sort.js +5 -0
- package/utils/unit-tests/pagination-utils.spec.ts +283 -0
- package/utils/validators/formRules/__tests__/index.test.ts +7 -0
- package/utils/validators/formRules/index.ts +2 -2
package/core/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ProductFunction } from './plugin';
|
|
2
2
|
import { RouteRecordRaw } from 'vue-router';
|
|
3
3
|
import type { ExtensionManager } from '@shell/types/extension-manager';
|
|
4
|
+
import { PaginationSettingsStores } from '@shell/types/resources/settings';
|
|
4
5
|
|
|
5
6
|
// Cluster Provisioning types
|
|
6
7
|
export * from './types-provisioning';
|
|
@@ -130,9 +131,6 @@ export type Card = {
|
|
|
130
131
|
component: Function;
|
|
131
132
|
};
|
|
132
133
|
|
|
133
|
-
// Duplication of HeaderOptions?
|
|
134
|
-
export type TableColumn = any;
|
|
135
|
-
|
|
136
134
|
/** Definition of a tab (options that can be passed when defining an extension tab enhancement) */
|
|
137
135
|
export type Tab = {
|
|
138
136
|
name: string;
|
|
@@ -281,6 +279,9 @@ export interface ProductOptions {
|
|
|
281
279
|
// typeStoreMap: string;
|
|
282
280
|
}
|
|
283
281
|
|
|
282
|
+
/**
|
|
283
|
+
* Configuration required to show a header in a ResourceTable
|
|
284
|
+
*/
|
|
284
285
|
export interface HeaderOptions {
|
|
285
286
|
/**
|
|
286
287
|
* Name of the header. This should be unique.
|
|
@@ -305,7 +306,7 @@ export interface HeaderOptions {
|
|
|
305
306
|
/**
|
|
306
307
|
* A string which represents the path to access the value from the row object which we'll use to sort i.e. `row.meta.value`
|
|
307
308
|
*/
|
|
308
|
-
sort?: string | string[];
|
|
309
|
+
sort?: string | string[] | boolean;
|
|
309
310
|
|
|
310
311
|
/**
|
|
311
312
|
* A string which represents the path to access the value from the row object which we'll use to search i.e. `row.meta.value`.
|
|
@@ -336,6 +337,26 @@ export interface HeaderOptions {
|
|
|
336
337
|
getValue?: (row: any) => string | number | null | undefined;
|
|
337
338
|
}
|
|
338
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Configuration required to show a header in a ResourceTable when server-side pagination is enable
|
|
342
|
+
*/
|
|
343
|
+
export type PaginationHeaderOptions = Omit<HeaderOptions, 'getValue'>
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* External extension configuration for @HeaderOptions
|
|
347
|
+
*/
|
|
348
|
+
export type TableColumn = HeaderOptions;
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* External extension configuration for @PaginationHeaderOptions
|
|
352
|
+
*/
|
|
353
|
+
export type PaginationTableColumn = PaginationHeaderOptions;
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* External extension configuration for @PaginationSettingsStores
|
|
357
|
+
*/
|
|
358
|
+
export type ServerSidePaginationExtensionConfig = PaginationSettingsStores;
|
|
359
|
+
|
|
339
360
|
export interface ConfigureTypeOptions {
|
|
340
361
|
/**
|
|
341
362
|
* Override for the create button string on a list view
|
|
@@ -621,9 +642,17 @@ export interface IPlugin {
|
|
|
621
642
|
addCard(where: CardLocation | string, when: LocationConfig | string, action: Card): void;
|
|
622
643
|
|
|
623
644
|
/**
|
|
624
|
-
* Adds a new column to
|
|
645
|
+
* Adds a new column to a ResourceTable
|
|
646
|
+
*
|
|
647
|
+
* @param where
|
|
648
|
+
* @param when
|
|
649
|
+
* @param action
|
|
650
|
+
* @param column
|
|
651
|
+
* The information required to show a header and values for a column in a table
|
|
652
|
+
* @param paginationColumn
|
|
653
|
+
* As per `column`, but is used where server-side pagination is enabled
|
|
625
654
|
*/
|
|
626
|
-
addTableColumn(where: TableColumnLocation | string, when: LocationConfig | string,
|
|
655
|
+
addTableColumn(where: TableColumnLocation | string, when: LocationConfig | string, column: TableColumn, paginationColumn?: TableColumn): void;
|
|
627
656
|
|
|
628
657
|
/**
|
|
629
658
|
* Set the component to use for the landing home page
|
|
@@ -670,6 +699,8 @@ export interface IPlugin {
|
|
|
670
699
|
): void;
|
|
671
700
|
addNavHooks(hooks: NavHooks): void;
|
|
672
701
|
|
|
702
|
+
enableServerSidePagination(config: ServerSidePaginationExtensionConfig): void;
|
|
703
|
+
|
|
673
704
|
/**
|
|
674
705
|
* Adds a model extension
|
|
675
706
|
* @experimental May change or be removed in the future
|
|
@@ -3,12 +3,12 @@ import AsyncButton from '@shell/components/AsyncButton';
|
|
|
3
3
|
import LabeledSelect from '@shell/components/form/LabeledSelect';
|
|
4
4
|
import { CATALOG, MANAGEMENT } from '@shell/config/types';
|
|
5
5
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
6
|
-
import { UI_PLUGIN_NAMESPACE } from '@shell/config/uiplugins';
|
|
6
|
+
import { UI_PLUGIN_NAMESPACE, isChartVersionHigher } from '@shell/config/uiplugins';
|
|
7
7
|
import Banner from '@components/Banner/Banner.vue';
|
|
8
8
|
import { SETTING } from '@shell/config/settings';
|
|
9
|
-
import {
|
|
9
|
+
import { getPluginChartVersionLabel } from '@shell/utils/uiplugins';
|
|
10
10
|
|
|
11
|
-
// Note: This dialog handles installation and
|
|
11
|
+
// Note: This dialog handles installation, upgrade and downgrade of a plugin
|
|
12
12
|
|
|
13
13
|
export default {
|
|
14
14
|
emits: ['close'],
|
|
@@ -29,7 +29,14 @@ export default {
|
|
|
29
29
|
required: true
|
|
30
30
|
},
|
|
31
31
|
/**
|
|
32
|
-
* The
|
|
32
|
+
* The pre-selected version in the dropdown
|
|
33
|
+
*/
|
|
34
|
+
initialVersion: {
|
|
35
|
+
type: String,
|
|
36
|
+
default: null
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* The action to perform (install, upgrade, downgrade)
|
|
33
40
|
*/
|
|
34
41
|
action: {
|
|
35
42
|
type: String,
|
|
@@ -63,33 +70,32 @@ export default {
|
|
|
63
70
|
},
|
|
64
71
|
|
|
65
72
|
async fetch() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (this.action === 'update') {
|
|
72
|
-
this.currentVersion = chartVersion;
|
|
73
|
-
|
|
74
|
-
// Update to latest version, so take the first version
|
|
75
|
-
if (this.plugin?.installableVersions?.length > 0) {
|
|
76
|
-
this.version = this.plugin?.installableVersions?.[0]?.version;
|
|
77
|
-
}
|
|
78
|
-
} else if (this.action === 'rollback') {
|
|
79
|
-
// Find the newest version once we remove the current version
|
|
80
|
-
const versionNames = this.plugin.installableVersions.filter((v) => v.version !== chartVersion);
|
|
73
|
+
// Determine the currently installed version, if any
|
|
74
|
+
if (this.plugin.installed) {
|
|
75
|
+
this.currentVersion = this.plugin.installedVersion;
|
|
76
|
+
}
|
|
81
77
|
|
|
82
|
-
|
|
78
|
+
// Determine the initial version to select in the dropdown
|
|
79
|
+
if (this.initialVersion) {
|
|
80
|
+
this.version = this.initialVersion;
|
|
81
|
+
} else if (this.action === 'upgrade') {
|
|
82
|
+
// Upgrade to the latest version, so take the first version
|
|
83
|
+
this.version = this.plugin?.installableVersions?.[0]?.version;
|
|
84
|
+
} else if (this.action === 'downgrade') {
|
|
85
|
+
const versions = this.plugin.installableVersions;
|
|
86
|
+
const currentIndex = versions.findIndex((v) => v.version === this.currentVersion);
|
|
83
87
|
|
|
84
|
-
if (
|
|
85
|
-
|
|
88
|
+
if (currentIndex !== -1 && currentIndex < versions.length - 1) {
|
|
89
|
+
// Select the version just below the current version
|
|
90
|
+
this.version = versions[currentIndex + 1].version;
|
|
86
91
|
}
|
|
92
|
+
} else {
|
|
93
|
+
// Default to the latest installable version for new installs
|
|
94
|
+
this.version = this.plugin?.installableVersions?.[0]?.version;
|
|
87
95
|
}
|
|
88
96
|
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (!versionChart) {
|
|
97
|
+
// Fallback if no version could be determined
|
|
98
|
+
if (!this.version) {
|
|
93
99
|
this.version = this.plugin?.installableVersions?.[0]?.version;
|
|
94
100
|
}
|
|
95
101
|
|
|
@@ -119,37 +125,39 @@ export default {
|
|
|
119
125
|
},
|
|
120
126
|
|
|
121
127
|
versionOptions() {
|
|
122
|
-
if (!this.plugin) {
|
|
128
|
+
if (!this.plugin?.installableVersions) {
|
|
123
129
|
return [];
|
|
124
130
|
}
|
|
125
131
|
|
|
126
|
-
// Don't allow
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return v.version !== this.currentVersion;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return true;
|
|
133
|
-
});
|
|
132
|
+
// Don't allow upgrade/downgrade to current version by disabling the option
|
|
133
|
+
return this.plugin.installableVersions.map((v) => {
|
|
134
|
+
const isCurrent = v.version === this.currentVersion;
|
|
134
135
|
|
|
135
|
-
return versions.map((version) => {
|
|
136
136
|
return {
|
|
137
|
-
label:
|
|
138
|
-
value:
|
|
137
|
+
label: getPluginChartVersionLabel(v) + (isCurrent ? ` (${ this.t('plugins.labels.current') })` : ''),
|
|
138
|
+
value: v.version,
|
|
139
|
+
disabled: isCurrent,
|
|
139
140
|
};
|
|
140
141
|
});
|
|
141
142
|
},
|
|
142
143
|
|
|
143
144
|
buttonMode() {
|
|
144
|
-
if (this.action === '
|
|
145
|
-
return '
|
|
145
|
+
if (this.action === 'install') {
|
|
146
|
+
return 'install';
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
if (this.
|
|
149
|
-
|
|
149
|
+
if (this.currentVersion && this.version) {
|
|
150
|
+
if (isChartVersionHigher(this.version, this.currentVersion)) {
|
|
151
|
+
return 'upgrade';
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (isChartVersionHigher(this.currentVersion, this.version)) {
|
|
155
|
+
return 'downgrade';
|
|
156
|
+
}
|
|
150
157
|
}
|
|
151
158
|
|
|
152
|
-
|
|
159
|
+
// Fallback for safety, though should not be reached if version is selected
|
|
160
|
+
return this.action;
|
|
153
161
|
},
|
|
154
162
|
|
|
155
163
|
chartVersionLoadsWithoutAuth() {
|
|
@@ -158,6 +166,23 @@ export default {
|
|
|
158
166
|
|
|
159
167
|
returnFocusSelector() {
|
|
160
168
|
return `[data-testid="extension-card-${ this.action }-btn-${ this.plugin?.name }"]`;
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
buttonIcon() {
|
|
172
|
+
if (this.busy) {
|
|
173
|
+
return '';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
switch (this.buttonMode) {
|
|
177
|
+
case 'install':
|
|
178
|
+
return 'icon-plus';
|
|
179
|
+
case 'upgrade':
|
|
180
|
+
return 'icon-upgrade-alt';
|
|
181
|
+
case 'downgrade':
|
|
182
|
+
return 'icon-downgrade-alt';
|
|
183
|
+
default:
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
161
186
|
}
|
|
162
187
|
},
|
|
163
188
|
|
|
@@ -295,12 +320,12 @@ export default {
|
|
|
295
320
|
<template>
|
|
296
321
|
<div class="plugin-install-dialog">
|
|
297
322
|
<h4 class="mt-10">
|
|
298
|
-
{{ t(`plugins.${
|
|
323
|
+
{{ t(`plugins.${ buttonMode }.title`, { name: `"${plugin?.label}"` }, true) }}
|
|
299
324
|
</h4>
|
|
300
325
|
<div class="custom mt-10">
|
|
301
326
|
<div class="dialog-panel">
|
|
302
327
|
<p>
|
|
303
|
-
{{ t(`plugins.${
|
|
328
|
+
{{ t(`plugins.${ buttonMode }.prompt`) }}
|
|
304
329
|
</p>
|
|
305
330
|
<Banner
|
|
306
331
|
v-if="chartVersionLoadsWithoutAuth"
|
|
@@ -335,6 +360,7 @@ export default {
|
|
|
335
360
|
</button>
|
|
336
361
|
<AsyncButton
|
|
337
362
|
:mode="buttonMode"
|
|
363
|
+
:icon="buttonIcon"
|
|
338
364
|
data-testid="install-ext-modal-install-btn"
|
|
339
365
|
@click="install"
|
|
340
366
|
/>
|
|
@@ -103,7 +103,7 @@ export default {
|
|
|
103
103
|
<template>
|
|
104
104
|
<div class="plugin-install-dialog">
|
|
105
105
|
<h4 class="mt-10">
|
|
106
|
-
{{ t('plugins.uninstall.title', { name: plugin?.label }) }}
|
|
106
|
+
{{ t('plugins.uninstall.title', { name: `"${plugin?.label}"` }, true) }}
|
|
107
107
|
</h4>
|
|
108
108
|
<div class="mt-10 dialog-panel">
|
|
109
109
|
<div class="dialog-info">
|
|
@@ -122,6 +122,7 @@ export default {
|
|
|
122
122
|
</button>
|
|
123
123
|
<AsyncButton
|
|
124
124
|
mode="uninstall"
|
|
125
|
+
:icon="busy ? '' : 'icon-delete'"
|
|
125
126
|
data-testid="uninstall-ext-modal-uninstall-btn"
|
|
126
127
|
@click="uninstall()"
|
|
127
128
|
/>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { shallowMount, VueWrapper } from '@vue/test-utils';
|
|
2
|
+
import InstallExtensionDialog from '@shell/dialog/InstallExtensionDialog.vue';
|
|
3
|
+
|
|
4
|
+
jest.mock('@shell/config/uiplugins', () => ({
|
|
5
|
+
...jest.requireActual('@shell/config/uiplugins'),
|
|
6
|
+
isChartVersionHigher: jest.fn((v1: string, v2: string) => v1 > v2),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
const t = (key: string): string => key;
|
|
10
|
+
|
|
11
|
+
describe('component: InstallExtensionDialog', () => {
|
|
12
|
+
let wrapper: VueWrapper<any>;
|
|
13
|
+
|
|
14
|
+
const mountComponent = (propsData = {}) => {
|
|
15
|
+
const store = { dispatch: () => Promise.resolve() };
|
|
16
|
+
|
|
17
|
+
const defaultProps = {
|
|
18
|
+
plugin: { installableVersions: [] },
|
|
19
|
+
action: 'install',
|
|
20
|
+
updateStatus: jest.fn(),
|
|
21
|
+
closed: jest.fn(),
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return shallowMount(InstallExtensionDialog, {
|
|
25
|
+
propsData: {
|
|
26
|
+
...defaultProps,
|
|
27
|
+
...propsData,
|
|
28
|
+
},
|
|
29
|
+
global: {
|
|
30
|
+
mocks: {
|
|
31
|
+
$store: store,
|
|
32
|
+
t,
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
describe('fetch', () => {
|
|
39
|
+
it('should set currentVersion if plugin is installed', async() => {
|
|
40
|
+
wrapper = mountComponent({ plugin: { installed: true, installedVersion: '1.0.0' } });
|
|
41
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
42
|
+
expect(wrapper.vm.currentVersion).toBe('1.0.0');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should set version from initialVersion if provided', async() => {
|
|
46
|
+
wrapper = mountComponent({ initialVersion: '1.2.3', plugin: { installed: false } });
|
|
47
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
48
|
+
expect(wrapper.vm.version).toBe('1.2.3');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should set version to latest for upgrade action', async() => {
|
|
52
|
+
const plugin = { installableVersions: [{ version: '1.1.0' }, { version: '1.0.0' }] };
|
|
53
|
+
|
|
54
|
+
wrapper = mountComponent({ plugin, action: 'upgrade' });
|
|
55
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
56
|
+
expect(wrapper.vm.version).toBe('1.1.0');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should set version to next oldest for downgrade action', async() => {
|
|
60
|
+
const plugin = {
|
|
61
|
+
installed: true,
|
|
62
|
+
installedVersion: '1.1.0',
|
|
63
|
+
installableVersions: [{ version: '1.1.0' }, { version: '1.0.0' }]
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
wrapper = mountComponent({ plugin, action: 'downgrade' });
|
|
67
|
+
await wrapper.vm.$options.fetch.call(wrapper.vm);
|
|
68
|
+
expect(wrapper.vm.version).toBe('1.0.0');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('versionOptions', () => {
|
|
73
|
+
it('should include and disable the current version', () => {
|
|
74
|
+
const plugin = {
|
|
75
|
+
installableVersions: [
|
|
76
|
+
{ version: '1.1.0' },
|
|
77
|
+
{ version: '1.0.0' },
|
|
78
|
+
]
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
wrapper = mountComponent({ plugin });
|
|
82
|
+
wrapper.vm.currentVersion = '1.0.0';
|
|
83
|
+
|
|
84
|
+
const options = wrapper.vm.versionOptions;
|
|
85
|
+
const currentOption = options.find((o: any) => o.value === '1.0.0');
|
|
86
|
+
|
|
87
|
+
expect(currentOption).toBeDefined();
|
|
88
|
+
expect(currentOption.disabled).toBe(true);
|
|
89
|
+
expect(currentOption.label).toContain('(plugins.labels.current)');
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe('buttonMode', () => {
|
|
94
|
+
beforeEach(() => {
|
|
95
|
+
wrapper = mountComponent({ action: 'upgrade' });
|
|
96
|
+
wrapper.vm.currentVersion = '1.0.0';
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should be "upgrade" if selected version is higher', async() => {
|
|
100
|
+
wrapper.vm.version = '1.1.0';
|
|
101
|
+
await wrapper.vm.$nextTick();
|
|
102
|
+
expect(wrapper.vm.buttonMode).toBe('upgrade');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('should be "downgrade" if selected version is lower', async() => {
|
|
106
|
+
wrapper.vm.version = '0.9.0';
|
|
107
|
+
await wrapper.vm.$nextTick();
|
|
108
|
+
expect(wrapper.vm.buttonMode).toBe('downgrade');
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
package/edit/auth/oidc.vue
CHANGED
|
@@ -59,11 +59,16 @@ export default {
|
|
|
59
59
|
userInfoEndpoint: null,
|
|
60
60
|
},
|
|
61
61
|
// TODO #13457: this is duplicated due wrong format
|
|
62
|
-
oidcScope:
|
|
63
|
-
SLO_OPTION_VALUES
|
|
62
|
+
oidcScope: [],
|
|
63
|
+
SLO_OPTION_VALUES,
|
|
64
|
+
addCustomClaims: false,
|
|
64
65
|
};
|
|
65
66
|
},
|
|
66
67
|
|
|
68
|
+
created() {
|
|
69
|
+
this.registerBeforeHook(this.willSave, 'willSave');
|
|
70
|
+
},
|
|
71
|
+
|
|
67
72
|
computed: {
|
|
68
73
|
tArgs() {
|
|
69
74
|
return {
|
|
@@ -140,6 +145,10 @@ export default {
|
|
|
140
145
|
return this.model?.id === 'cognito';
|
|
141
146
|
},
|
|
142
147
|
|
|
148
|
+
isGenericOidc() {
|
|
149
|
+
return this.model?.id === 'genericoidc';
|
|
150
|
+
},
|
|
151
|
+
|
|
143
152
|
isLogoutAllSupported() {
|
|
144
153
|
return this.model?.logoutAllSupported;
|
|
145
154
|
},
|
|
@@ -220,6 +229,15 @@ export default {
|
|
|
220
229
|
this.model.logoutAllForced = false;
|
|
221
230
|
break;
|
|
222
231
|
}
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
model: {
|
|
235
|
+
handler(newVal) {
|
|
236
|
+
if (newVal?.nameClaim || newVal?.groupsClaim || newVal?.emailClaim) {
|
|
237
|
+
this.addCustomClaims = true;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
once: true
|
|
223
241
|
}
|
|
224
242
|
},
|
|
225
243
|
|
|
@@ -248,6 +266,14 @@ export default {
|
|
|
248
266
|
|
|
249
267
|
updateScope() {
|
|
250
268
|
this.model.scope = this.oidcScope.join(' ');
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
willSave() {
|
|
272
|
+
if (this.isGenericOidc && !this.addCustomClaims) {
|
|
273
|
+
this.model.nameClaim = undefined;
|
|
274
|
+
this.model.groupsClaim = undefined;
|
|
275
|
+
this.model.emailClaim = undefined;
|
|
276
|
+
}
|
|
251
277
|
}
|
|
252
278
|
}
|
|
253
279
|
};
|
|
@@ -390,21 +416,60 @@ export default {
|
|
|
390
416
|
</div>
|
|
391
417
|
</div>
|
|
392
418
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
419
|
+
<template v-if="isGenericOidc || supportsGroupSearch">
|
|
420
|
+
<div
|
|
421
|
+
class="row mb-20"
|
|
422
|
+
>
|
|
423
|
+
<div class="col span-6 checkbox-flex">
|
|
424
|
+
<!-- Allow group search -->
|
|
425
|
+
<Checkbox
|
|
426
|
+
v-if="supportsGroupSearch"
|
|
427
|
+
v-model:value="model.groupSearchEnabled"
|
|
428
|
+
data-testid="input-group-search"
|
|
429
|
+
:label="t('authConfig.oidc.groupSearch.label')"
|
|
430
|
+
:tooltip="t('authConfig.oidc.groupSearch.tooltip')"
|
|
431
|
+
:mode="mode"
|
|
432
|
+
/>
|
|
433
|
+
<Checkbox
|
|
434
|
+
v-if="isGenericOidc"
|
|
435
|
+
v-model:value="addCustomClaims"
|
|
436
|
+
data-testid="input-add-custom-claims"
|
|
437
|
+
:label="t('authConfig.oidc.customClaims.enable.label')"
|
|
438
|
+
:tooltip="t('authConfig.oidc.customClaims.enable.tooltip')"
|
|
439
|
+
:mode="mode"
|
|
440
|
+
/>
|
|
441
|
+
</div>
|
|
406
442
|
</div>
|
|
407
|
-
</
|
|
443
|
+
</template>
|
|
444
|
+
|
|
445
|
+
<template v-if="addCustomClaims">
|
|
446
|
+
<h4>{{ t('authConfig.oidc.customClaims.label') }}</h4>
|
|
447
|
+
<div class="row mb-20">
|
|
448
|
+
<div class="col span-6">
|
|
449
|
+
<LabeledInput
|
|
450
|
+
v-model:value="model.nameClaim"
|
|
451
|
+
:label="t(`authConfig.oidc.customClaims.nameClaim.label`)"
|
|
452
|
+
:mode="mode"
|
|
453
|
+
/>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="col span-6">
|
|
456
|
+
<LabeledInput
|
|
457
|
+
v-model:value="model.groupsClaim"
|
|
458
|
+
:label="t(`authConfig.oidc.customClaims.groupsClaim.label`)"
|
|
459
|
+
:mode="mode"
|
|
460
|
+
/>
|
|
461
|
+
</div>
|
|
462
|
+
</div>
|
|
463
|
+
<div class="row mb-20">
|
|
464
|
+
<div class="col span-6">
|
|
465
|
+
<LabeledInput
|
|
466
|
+
v-model:value="model.emailClaim"
|
|
467
|
+
:label="t(`authConfig.oidc.customClaims.emailClaim.label`)"
|
|
468
|
+
:mode="mode"
|
|
469
|
+
/>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
</template>
|
|
408
473
|
|
|
409
474
|
<!-- Scopes -->
|
|
410
475
|
<div class="row mb-20">
|
|
@@ -608,4 +673,9 @@ export default {
|
|
|
608
673
|
margin: 0 3px;
|
|
609
674
|
}
|
|
610
675
|
}
|
|
676
|
+
|
|
677
|
+
.checkbox-flex {
|
|
678
|
+
display: flex;
|
|
679
|
+
flex-direction: column;
|
|
680
|
+
}
|
|
611
681
|
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
|
|
3
3
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
4
|
-
import
|
|
4
|
+
import { RancherKubeMetadata } from '@shell/types/kube/kube-api';
|
|
5
5
|
import { PaginationArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
|
|
6
6
|
import { defineComponent } from 'vue';
|
|
7
7
|
|
|
@@ -25,7 +25,7 @@ export default defineComponent({
|
|
|
25
25
|
/**
|
|
26
26
|
* Filter out hidden repos from list of all repos
|
|
27
27
|
*/
|
|
28
|
-
filterRowsLocal(rows:
|
|
28
|
+
filterRowsLocal(rows: { metadata: RancherKubeMetadata}[]) {
|
|
29
29
|
return rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
|
|
30
30
|
},
|
|
31
31
|
|
package/mixins/chart.js
CHANGED
package/models/event.js
CHANGED
|
@@ -25,6 +25,13 @@ export default class K8sEvent extends SteveModel {
|
|
|
25
25
|
return this._type;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
get firstSeen() {
|
|
29
|
+
const schema = this.$getters['schemaFor'](this.type);
|
|
30
|
+
const rowValueGetter = this.$rootGetters['type-map/rowValueGetter'];
|
|
31
|
+
|
|
32
|
+
return schema && rowValueGetter ? rowValueGetter(schema, 'First Seen')(this) : null;
|
|
33
|
+
}
|
|
34
|
+
|
|
28
35
|
get lastSeen() {
|
|
29
36
|
const schema = this.$getters['schemaFor'](this.type);
|
|
30
37
|
const rowValueGetter = this.$rootGetters['type-map/rowValueGetter'];
|
|
@@ -391,6 +391,15 @@ export default class ProvCluster extends SteveModel {
|
|
|
391
391
|
const pCluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, this.id);
|
|
392
392
|
const name = this.status?.clusterName || pCluster?.status?.clusterName;
|
|
393
393
|
|
|
394
|
+
try {
|
|
395
|
+
if (name) {
|
|
396
|
+
// Just in case we're not generically watching all mgmt clusters and...
|
|
397
|
+
// thus won't receive new mgmt cluster over socket...
|
|
398
|
+
// fire and forget a request to fetch it (this won't make multiple requests if one is already running)
|
|
399
|
+
this.$dispatch('find', { type: MANAGEMENT.CLUSTER, id: name });
|
|
400
|
+
}
|
|
401
|
+
} catch {}
|
|
402
|
+
|
|
394
403
|
return name && !!this.$rootGetters['management/byId'](MANAGEMENT.CLUSTER, name);
|
|
395
404
|
}, this.$rootGetters['i18n/t']('cluster.managementTimeout'), timeout, interval);
|
|
396
405
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.7",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"express": "4.17.1",
|
|
94
94
|
"file-saver": "2.0.2",
|
|
95
95
|
"floating-vue": "5.2.2",
|
|
96
|
-
"focus-trap": "7.6.
|
|
96
|
+
"focus-trap": "7.6.5",
|
|
97
97
|
"frontmatter-markdown-loader": "3.7.0",
|
|
98
98
|
"identicon.js": "2.3.3",
|
|
99
99
|
"intl-messageformat": "7.8.4",
|
|
@@ -80,6 +80,12 @@ function onClickItem(type: string, label: string) {
|
|
|
80
80
|
&-text {
|
|
81
81
|
text-transform: capitalize;
|
|
82
82
|
margin-right: 8px;
|
|
83
|
+
display: -webkit-box;
|
|
84
|
+
-webkit-line-clamp: 1;
|
|
85
|
+
-webkit-box-orient: vertical;
|
|
86
|
+
overflow: hidden;
|
|
87
|
+
text-overflow: ellipsis;
|
|
88
|
+
word-break: break-all;
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
&-icon {
|