@rancher/shell 3.0.8-rc.5 → 3.0.8-rc.6
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/metadata.json +5 -2
- package/assets/styles/themes/_suse.scss +10 -0
- package/components/ResourceDetail/index.vue +1 -1
- package/directives/ui-context.ts +6 -6
- package/models/__tests__/chart.test.ts +33 -4
- package/models/chart.js +25 -13
- package/models/provisioning.cattle.io.cluster.js +0 -21
- package/package.json +1 -1
- package/pages/auth/login.vue +26 -3
- package/pages/c/_cluster/apps/charts/index.vue +11 -13
- package/types/shell/index.d.ts +13 -0
- package/utils/chart.js +18 -0
|
@@ -97,6 +97,16 @@
|
|
|
97
97
|
.suse-login-banner-graphic {
|
|
98
98
|
object-position: left;
|
|
99
99
|
}
|
|
100
|
+
|
|
101
|
+
// Styling for logo image on the login screen
|
|
102
|
+
.suse-logo-login {
|
|
103
|
+
$suse-logo-width: 280px;
|
|
104
|
+
|
|
105
|
+
width: $suse-logo-width;
|
|
106
|
+
max-width: $suse-logo-width;
|
|
107
|
+
align-self: center;
|
|
108
|
+
margin-bottom: 30px;
|
|
109
|
+
}
|
|
100
110
|
}
|
|
101
111
|
|
|
102
112
|
// Ensure that with a small window size, the banner centers, so that the text does not overlay
|
package/directives/ui-context.ts
CHANGED
|
@@ -89,15 +89,15 @@ export default {
|
|
|
89
89
|
|
|
90
90
|
if (store) {
|
|
91
91
|
delete context.store;
|
|
92
|
-
|
|
92
|
+
const id = await store.dispatch('ui-context/add', context);
|
|
93
|
+
|
|
94
|
+
el._uiContextRemove = async() => await store.dispatch('ui-context/remove', id);
|
|
93
95
|
}
|
|
94
96
|
},
|
|
95
97
|
|
|
96
|
-
async beforeUnmount(el: any
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (store && el._uiContextId) {
|
|
100
|
-
await store.dispatch('ui-context/remove', el._uiContextId);
|
|
98
|
+
async beforeUnmount(el: any) {
|
|
99
|
+
if (el._uiContextRemove) {
|
|
100
|
+
await el._uiContextRemove();
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
};
|
|
@@ -2,11 +2,16 @@ import Chart from '@shell/models/chart';
|
|
|
2
2
|
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';
|
|
3
3
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
4
4
|
import { ZERO_TIME } from '@shell/config/types';
|
|
5
|
+
import { getLatestCompatibleVersion } from '@shell/utils/chart';
|
|
6
|
+
|
|
7
|
+
jest.mock('@shell/utils/chart', () => ({ getLatestCompatibleVersion: jest.fn() }));
|
|
5
8
|
|
|
6
9
|
type MockChartContext = {
|
|
7
10
|
rootGetters: {
|
|
8
11
|
'cluster/all': () => any[];
|
|
9
12
|
'i18n/t': (key: string) => string;
|
|
13
|
+
currentCluster: { workerOSs: string[] };
|
|
14
|
+
'prefs/get': (key: string) => boolean;
|
|
10
15
|
};
|
|
11
16
|
dispatch?: jest.Mock;
|
|
12
17
|
};
|
|
@@ -58,11 +63,32 @@ describe('class Chart', () => {
|
|
|
58
63
|
beforeEach(() => {
|
|
59
64
|
ctx = {
|
|
60
65
|
rootGetters: {
|
|
61
|
-
'cluster/all':
|
|
62
|
-
'i18n/t':
|
|
66
|
+
'cluster/all': () => [],
|
|
67
|
+
'i18n/t': t,
|
|
68
|
+
currentCluster: { workerOSs: [] },
|
|
69
|
+
'prefs/get': () => false,
|
|
63
70
|
},
|
|
64
71
|
dispatch
|
|
65
72
|
};
|
|
73
|
+
(getLatestCompatibleVersion as jest.Mock).mockImplementation((chart) => chart.versions[0]);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe('queryParams', () => {
|
|
77
|
+
it('should return query params with the latest compatible version', () => {
|
|
78
|
+
const chart = new Chart(base, ctx);
|
|
79
|
+
const query = chart.queryParams();
|
|
80
|
+
|
|
81
|
+
expect(getLatestCompatibleVersion).toHaveBeenCalledWith(chart, [], false);
|
|
82
|
+
expect(query).toHaveProperty('version', '1.3.0');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should reflect a different latest version from the mock', () => {
|
|
86
|
+
(getLatestCompatibleVersion as jest.Mock).mockImplementation((chart) => chart.versions[1]);
|
|
87
|
+
const chart = new Chart(base, ctx);
|
|
88
|
+
const query = chart.queryParams();
|
|
89
|
+
|
|
90
|
+
expect(query).toHaveProperty('version', '1.2.3');
|
|
91
|
+
});
|
|
66
92
|
});
|
|
67
93
|
|
|
68
94
|
describe('matchingInstalledApps', () => {
|
|
@@ -188,6 +214,7 @@ describe('class Chart', () => {
|
|
|
188
214
|
|
|
189
215
|
const result = chart.cardContent as CardContent;
|
|
190
216
|
|
|
217
|
+
expect(getLatestCompatibleVersion).toHaveBeenCalledWith(chart, [], false);
|
|
191
218
|
expect(result.subHeaderItems).toHaveLength(2);
|
|
192
219
|
expect(result.subHeaderItems[0].label).toBe('1.3.0');
|
|
193
220
|
expect(result.subHeaderItems[1].label).toBe('Mar 10, 2024');
|
|
@@ -297,8 +324,10 @@ describe('class Chart', () => {
|
|
|
297
324
|
};
|
|
298
325
|
const chart = new Chart(chartWithZeroTime, {
|
|
299
326
|
rootGetters: {
|
|
300
|
-
'cluster/all':
|
|
301
|
-
'i18n/t':
|
|
327
|
+
'cluster/all': () => [],
|
|
328
|
+
'i18n/t': (key: string) => key,
|
|
329
|
+
currentCluster: { workerOSs: [] },
|
|
330
|
+
'prefs/get': () => false,
|
|
302
331
|
},
|
|
303
332
|
});
|
|
304
333
|
|
package/models/chart.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';
|
|
2
2
|
import {
|
|
3
3
|
REPO_TYPE, REPO, CHART, VERSION, _FLAGGED, HIDE_SIDE_NAV, CATEGORY, TAG, DEPRECATED as DEPRECATED_QUERY
|
|
4
4
|
} from '@shell/config/query-params';
|
|
5
5
|
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
6
|
+
import { SHOW_PRE_RELEASE } from '@shell/store/prefs';
|
|
7
|
+
import { getLatestCompatibleVersion } from '@shell/utils/chart';
|
|
6
8
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
7
9
|
import { CATALOG, ZERO_TIME } from '@shell/config/types';
|
|
8
10
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
@@ -10,17 +12,7 @@ import day from 'dayjs';
|
|
|
10
12
|
|
|
11
13
|
export default class Chart extends SteveModel {
|
|
12
14
|
queryParams(from, hideSideNav) {
|
|
13
|
-
|
|
14
|
-
const chartVersions = this.versions;
|
|
15
|
-
const currentCluster = this.$rootGetters['currentCluster'];
|
|
16
|
-
const workerOSs = currentCluster?.workerOSs;
|
|
17
|
-
const compatibleVersions = compatibleVersionsFor(this, workerOSs);
|
|
18
|
-
|
|
19
|
-
if (compatibleVersions.length) {
|
|
20
|
-
version = compatibleVersions[0].version;
|
|
21
|
-
} else {
|
|
22
|
-
version = chartVersions[0].version;
|
|
23
|
-
}
|
|
15
|
+
const version = this.latestCompatibleVersion.version;
|
|
24
16
|
|
|
25
17
|
const out = {
|
|
26
18
|
[REPO_TYPE]: this.repoType,
|
|
@@ -115,6 +107,26 @@ export default class Chart extends SteveModel {
|
|
|
115
107
|
return this.isInstalled && this.matchingInstalledApps[0].upgradeAvailable === APP_UPGRADE_STATUS.SINGLE_UPGRADE;
|
|
116
108
|
}
|
|
117
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Retrieves the latest chart version that is compatible with the current cluster's OS and user's pre-release preference.
|
|
112
|
+
* It caches the result for efficiency.
|
|
113
|
+
*
|
|
114
|
+
* @returns {Object} The latest compatible chart version object.
|
|
115
|
+
*/
|
|
116
|
+
get latestCompatibleVersion() {
|
|
117
|
+
if (this._latestCompatibleVersion) {
|
|
118
|
+
return this._latestCompatibleVersion;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const currentCluster = this.$rootGetters['currentCluster'];
|
|
122
|
+
const workerOSs = currentCluster?.workerOSs;
|
|
123
|
+
const showPrerelease = this.$rootGetters['prefs/get'](SHOW_PRE_RELEASE);
|
|
124
|
+
|
|
125
|
+
this._latestCompatibleVersion = getLatestCompatibleVersion(this, workerOSs, showPrerelease);
|
|
126
|
+
|
|
127
|
+
return this._latestCompatibleVersion;
|
|
128
|
+
}
|
|
129
|
+
|
|
118
130
|
/**
|
|
119
131
|
* Builds structured metadata for display in RcItemCard.vue:
|
|
120
132
|
* - Sub-header (version and last updated)
|
|
@@ -125,7 +137,7 @@ export default class Chart extends SteveModel {
|
|
|
125
137
|
*/
|
|
126
138
|
get cardContent() {
|
|
127
139
|
if (!this._cardContent) {
|
|
128
|
-
const latestVersion = this.
|
|
140
|
+
const latestVersion = this.latestCompatibleVersion;
|
|
129
141
|
const subHeaderItems = [];
|
|
130
142
|
|
|
131
143
|
if (latestVersion) {
|
|
@@ -9,7 +9,6 @@ import { get, set } from '@shell/utils/object';
|
|
|
9
9
|
import { sortBy } from '@shell/utils/sort';
|
|
10
10
|
import { ucFirst } from '@shell/utils/string';
|
|
11
11
|
import { compare } from '@shell/utils/version';
|
|
12
|
-
import { AS, MODE, _VIEW, _YAML } from '@shell/config/query-params';
|
|
13
12
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
14
13
|
import { CAPI as CAPI_ANNOTATIONS, NODE_ARCHITECTURE } from '@shell/config/labels-annotations';
|
|
15
14
|
import { KEV1 } from '@shell/models/management.cattle.io.kontainerdriver';
|
|
@@ -260,26 +259,6 @@ export default class ProvCluster extends SteveModel {
|
|
|
260
259
|
}
|
|
261
260
|
}
|
|
262
261
|
|
|
263
|
-
goToViewYaml() {
|
|
264
|
-
let location;
|
|
265
|
-
|
|
266
|
-
if ( !this.isRke2 ) {
|
|
267
|
-
location = this.mgmt?.detailLocation;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if ( !location ) {
|
|
271
|
-
location = this.detailLocation;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
location.query = {
|
|
275
|
-
...location.query,
|
|
276
|
-
[MODE]: _VIEW,
|
|
277
|
-
[AS]: _YAML
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
this.currentRouter().push(location);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
262
|
get canDelete() {
|
|
284
263
|
return super.canDelete && this.stateObj?.name !== 'removing';
|
|
285
264
|
}
|
package/package.json
CHANGED
package/pages/auth/login.vue
CHANGED
|
@@ -142,11 +142,19 @@ export default {
|
|
|
142
142
|
const brandMeta = getBrandMeta(setting?.value);
|
|
143
143
|
const login = brandMeta?.login || {};
|
|
144
144
|
|
|
145
|
-
return
|
|
145
|
+
return {
|
|
146
|
+
welcomeLabelKey: 'login.welcome',
|
|
147
|
+
logoClass: 'login-logo',
|
|
148
|
+
...login,
|
|
149
|
+
};
|
|
146
150
|
},
|
|
147
151
|
|
|
148
152
|
bannerClass() {
|
|
149
153
|
return this.customizations.bannerClass;
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
brandLogo() {
|
|
157
|
+
return this.customizations.logo;
|
|
150
158
|
}
|
|
151
159
|
},
|
|
152
160
|
|
|
@@ -349,11 +357,20 @@ export default {
|
|
|
349
357
|
</TabTitle>
|
|
350
358
|
<div class="row gutless mb-20">
|
|
351
359
|
<div class="col span-6 p-20">
|
|
352
|
-
<p
|
|
360
|
+
<p
|
|
361
|
+
v-if="!brandLogo"
|
|
362
|
+
class="text-center"
|
|
363
|
+
>
|
|
353
364
|
{{ t('login.howdy') }}
|
|
354
365
|
</p>
|
|
366
|
+
<BrandImage
|
|
367
|
+
v-else
|
|
368
|
+
:class="{[customizations.logoClass]: !!customizations.logoClass}"
|
|
369
|
+
:file-name="brandLogo"
|
|
370
|
+
:alt="t('login.landscapeAlt')"
|
|
371
|
+
/>
|
|
355
372
|
<h1 class="text-center login-welcome">
|
|
356
|
-
{{ t(
|
|
373
|
+
{{ t(customizations.welcomeLabelKey, {vendor}) }}
|
|
357
374
|
</h1>
|
|
358
375
|
<div
|
|
359
376
|
class="login-messages"
|
|
@@ -567,6 +584,12 @@ export default {
|
|
|
567
584
|
margin: 0
|
|
568
585
|
}
|
|
569
586
|
|
|
587
|
+
.login-logo {
|
|
588
|
+
align-self: center;
|
|
589
|
+
max-width: 260px;
|
|
590
|
+
margin-bottom: 20px;
|
|
591
|
+
}
|
|
592
|
+
|
|
570
593
|
.login-messages {
|
|
571
594
|
display: flex;
|
|
572
595
|
justify-content: center;
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
REPO_TYPE, REPO, CHART, VERSION, SEARCH_QUERY, SORT_BY, _FLAGGED, CATEGORY, DEPRECATED, HIDDEN, TAG, STATUS
|
|
8
8
|
} from '@shell/config/query-params';
|
|
9
9
|
import { DOCS_BASE } from '@shell/config/private-label';
|
|
10
|
-
import { APP_STATUS,
|
|
10
|
+
import { APP_STATUS, filterAndArrangeCharts, normalizeFilterQuery } from '@shell/store/catalog';
|
|
11
11
|
import { lcFirst } from '@shell/utils/string';
|
|
12
12
|
import { sortBy } from '@shell/utils/sort';
|
|
13
13
|
import debounce from 'lodash/debounce';
|
|
@@ -24,6 +24,7 @@ import AppChartCardFooter from '@shell/pages/c/_cluster/apps/charts/AppChartCard
|
|
|
24
24
|
import AddRepoLink from '@shell/pages/c/_cluster/apps/charts/AddRepoLink';
|
|
25
25
|
import StatusLabel from '@shell/pages/c/_cluster/apps/charts/StatusLabel';
|
|
26
26
|
import RichTranslation from '@shell/components/RichTranslation.vue';
|
|
27
|
+
import { getLatestCompatibleVersion } from '@shell/utils/chart';
|
|
27
28
|
import Select from '@shell/components/form/Select';
|
|
28
29
|
|
|
29
30
|
const createInitialFilters = () => ({
|
|
@@ -190,6 +191,13 @@ export default {
|
|
|
190
191
|
sort: this.selectedSortOption
|
|
191
192
|
});
|
|
192
193
|
|
|
194
|
+
const OSs = this.currentCluster.workerOSs;
|
|
195
|
+
const showPrerelease = this.$store.getters['prefs/get'](SHOW_PRE_RELEASE);
|
|
196
|
+
|
|
197
|
+
res.forEach((chart) => {
|
|
198
|
+
chart._latestCompatibleVersion = getLatestCompatibleVersion(chart, OSs, showPrerelease);
|
|
199
|
+
});
|
|
200
|
+
|
|
193
201
|
// status filtering is separated from other filters because "isInstalled" and "upgradeable" statuses are already calculated in models/chart.js
|
|
194
202
|
// by doing this we won't need to re-calculate it in filterAndArrangeCharts
|
|
195
203
|
if (!statuses.length) {
|
|
@@ -265,7 +273,7 @@ export default {
|
|
|
265
273
|
statuses: chart.cardContent.statuses
|
|
266
274
|
},
|
|
267
275
|
subHeaderItems: chart.cardContent.subHeaderItems,
|
|
268
|
-
image: { src: chart.
|
|
276
|
+
image: { src: chart.latestCompatibleVersion.icon, alt: { text: this.t('catalog.charts.iconAlt', { app: get(chart, 'chartNameDisplay') }) } },
|
|
269
277
|
content: { text: chart.chartDescription },
|
|
270
278
|
footerItems: chart.cardContent.footerItems,
|
|
271
279
|
rawChart: chart
|
|
@@ -343,17 +351,7 @@ export default {
|
|
|
343
351
|
}, 100),
|
|
344
352
|
|
|
345
353
|
selectChart(chart) {
|
|
346
|
-
|
|
347
|
-
const OSs = this.currentCluster.workerOSs;
|
|
348
|
-
const showPrerelease = this.$store.getters['prefs/get'](SHOW_PRE_RELEASE);
|
|
349
|
-
const compatibleVersions = compatibleVersionsFor(chart, OSs, showPrerelease);
|
|
350
|
-
const versions = chart.versions;
|
|
351
|
-
|
|
352
|
-
if (compatibleVersions.length > 0) {
|
|
353
|
-
version = compatibleVersions[0].version;
|
|
354
|
-
} else {
|
|
355
|
-
version = versions[0].version;
|
|
356
|
-
}
|
|
354
|
+
const version = chart.latestCompatibleVersion.version;
|
|
357
355
|
|
|
358
356
|
const query = {
|
|
359
357
|
[REPO_TYPE]: chart.repoType,
|
package/types/shell/index.d.ts
CHANGED
|
@@ -3950,6 +3950,19 @@ export function getIndividualBanners(store: any): {};
|
|
|
3950
3950
|
export function overlayIndividualBanners(parsedBanner: any, banners: any): void;
|
|
3951
3951
|
}
|
|
3952
3952
|
|
|
3953
|
+
// @shell/utils/chart
|
|
3954
|
+
|
|
3955
|
+
declare module '@shell/utils/chart' {
|
|
3956
|
+
/**
|
|
3957
|
+
* Get the latest chart version that is compatible with the cluster's OS and user's pre-release preference.
|
|
3958
|
+
* @param {Object} chart - The chart object.
|
|
3959
|
+
* @param {Array<string>} workerOSs - The list of worker OSs for the cluster.
|
|
3960
|
+
* @param {boolean} showPrerelease - Whether to include pre-release versions.
|
|
3961
|
+
* @returns {Object} The latest compatible chart version object.
|
|
3962
|
+
*/
|
|
3963
|
+
export function getLatestCompatibleVersion(chart: any, workerOSs: Array<string>, showPrerelease: boolean): any;
|
|
3964
|
+
}
|
|
3965
|
+
|
|
3953
3966
|
// @shell/utils/clipboard
|
|
3954
3967
|
|
|
3955
3968
|
declare module '@shell/utils/clipboard' {
|
package/utils/chart.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { compatibleVersionsFor } from '@shell/store/catalog';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get the latest chart version that is compatible with the cluster's OS and user's pre-release preference.
|
|
5
|
+
* @param {Object} chart - The chart object.
|
|
6
|
+
* @param {Array<string>} workerOSs - The list of worker OSs for the cluster.
|
|
7
|
+
* @param {boolean} showPrerelease - Whether to include pre-release versions.
|
|
8
|
+
* @returns {Object} The latest compatible chart version object.
|
|
9
|
+
*/
|
|
10
|
+
export function getLatestCompatibleVersion(chart, workerOSs, showPrerelease) {
|
|
11
|
+
if (!chart?.versions?.length) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const compatible = compatibleVersionsFor(chart, workerOSs, showPrerelease);
|
|
16
|
+
|
|
17
|
+
return (compatible.length ? compatible[0] : chart.versions[0]) || {};
|
|
18
|
+
}
|