@rancher/shell 3.0.7 → 3.0.8-rc.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/images/vendor/githubapp.svg +13 -0
- package/assets/styles/base/_typography.scss +1 -1
- package/assets/styles/themes/_modern.scss +5 -5
- package/assets/translations/en-us.yaml +91 -11
- package/assets/translations/zh-hans.yaml +0 -4
- package/components/Inactivity.vue +222 -106
- package/components/InstallHelmCharts.vue +2 -2
- package/components/ResourceDetail/index.vue +1 -1
- package/components/SortableTable/index.vue +17 -2
- package/components/fleet/FleetConfigMapSelector.vue +117 -0
- package/components/fleet/FleetSecretSelector.vue +127 -0
- package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
- package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
- package/components/form/FileImageSelector.vue +13 -4
- package/components/form/FileSelector.vue +11 -2
- package/components/form/ResourceLabeledSelect.vue +1 -0
- package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
- package/components/nav/Header.vue +1 -0
- package/config/product/auth.js +1 -0
- package/config/query-params.js +1 -0
- package/config/settings.ts +8 -1
- package/config/types.js +2 -0
- package/dialog/AddonConfigConfirmationDialog.vue +45 -1
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
- package/edit/auth/AuthProviderWarningBanners.vue +14 -1
- package/edit/auth/github-app-steps.vue +97 -0
- package/edit/auth/github-steps.vue +75 -0
- package/edit/auth/github.vue +94 -65
- package/edit/fleet.cattle.io.helmop.vue +51 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
- package/edit/provisioning.cattle.io.cluster/rke2.vue +56 -9
- package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
- package/list/projectsecret.vue +1 -1
- package/machine-config/azure.vue +1 -1
- package/mixins/chart.js +1 -1
- package/models/__tests__/chart.test.ts +17 -9
- package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/chart.js +3 -1
- package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
- package/models/management.cattle.io.authconfig.js +1 -0
- package/package.json +2 -2
- package/pages/auth/login.vue +5 -2
- package/pages/auth/verify.vue +1 -1
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
- package/pages/c/_cluster/apps/charts/chart.vue +2 -2
- package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
- package/pages/c/_cluster/explorer/tools/index.vue +3 -3
- package/pages/c/_cluster/settings/performance.vue +12 -25
- package/pages/home.vue +313 -12
- package/plugins/axios.js +2 -1
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/resource-class.js +17 -2
- package/plugins/steve/steve-pagination-utils.ts +2 -2
- package/scripts/extension/publish +1 -1
- package/store/auth.js +8 -3
- package/store/aws.js +8 -6
- package/store/features.js +1 -0
- package/store/index.js +9 -3
- package/store/prefs.js +6 -0
- package/types/kube/kube-api.ts +2 -1
- package/types/rancher/index.d.ts +1 -0
- package/types/resources/settings.d.ts +29 -7
- package/types/shell/index.d.ts +59 -0
- package/utils/__tests__/cluster.test.ts +379 -1
- package/utils/cluster.js +157 -3
- package/utils/dynamic-content/__tests__/config.test.ts +187 -0
- package/utils/dynamic-content/__tests__/index.test.ts +390 -0
- package/utils/dynamic-content/__tests__/info.test.ts +263 -0
- package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
- package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
- package/utils/dynamic-content/__tests__/util.test.ts +235 -0
- package/utils/dynamic-content/config.ts +55 -0
- package/utils/dynamic-content/index.ts +273 -0
- package/utils/dynamic-content/info.ts +219 -0
- package/utils/dynamic-content/new-release.ts +126 -0
- package/utils/dynamic-content/support-notice.ts +169 -0
- package/utils/dynamic-content/types.d.ts +101 -0
- package/utils/dynamic-content/util.ts +122 -0
- package/utils/inactivity.ts +104 -0
- package/utils/pagination-utils.ts +19 -4
- package/utils/release-notes.ts +1 -1
|
@@ -475,16 +475,17 @@ describe('component: rke2', () => {
|
|
|
475
475
|
},
|
|
476
476
|
provider: 'custom'
|
|
477
477
|
},
|
|
478
|
-
|
|
479
|
-
|
|
478
|
+
computed: {
|
|
479
|
+
...rke2.computed,
|
|
480
|
+
agentArgs: () => ({
|
|
480
481
|
'cloud-provider-name': {
|
|
481
482
|
options: [
|
|
482
483
|
'azure',
|
|
483
484
|
'amazon'
|
|
484
485
|
]
|
|
485
486
|
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
487
|
+
})
|
|
488
|
+
},
|
|
488
489
|
global: {
|
|
489
490
|
mocks: {
|
|
490
491
|
...defaultMocks,
|
|
@@ -519,9 +520,10 @@ describe('component: rke2', () => {
|
|
|
519
520
|
},
|
|
520
521
|
provider: 'custom'
|
|
521
522
|
},
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
523
|
+
computed: {
|
|
524
|
+
...rke2.computed,
|
|
525
|
+
canAzureMigrateOnEdit: () => true,
|
|
526
|
+
agentArgs: () => ({
|
|
525
527
|
'cloud-provider-name': {
|
|
526
528
|
options: [
|
|
527
529
|
'azure',
|
|
@@ -529,8 +531,8 @@ describe('component: rke2', () => {
|
|
|
529
531
|
'external'
|
|
530
532
|
]
|
|
531
533
|
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
+
})
|
|
535
|
+
},
|
|
534
536
|
global: {
|
|
535
537
|
mocks: {
|
|
536
538
|
...defaultMocks,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
} from '@shell/utils/object';
|
|
29
29
|
import { allHash } from '@shell/utils/promise';
|
|
30
30
|
import {
|
|
31
|
-
getAllOptionsAfterCurrentVersion, filterOutDeprecatedPatchVersions, isHarvesterSatisfiesVersion, labelForAddon, initSchedulingCustomization
|
|
31
|
+
getAllOptionsAfterCurrentVersion, filterOutDeprecatedPatchVersions, isHarvesterSatisfiesVersion, labelForAddon, initSchedulingCustomization, addonConfigPreserve
|
|
32
32
|
} from '@shell/utils/cluster';
|
|
33
33
|
|
|
34
34
|
import { BadgeState } from '@components/BadgeState';
|
|
@@ -162,6 +162,10 @@ export default {
|
|
|
162
162
|
this.schedulingCustomizationOriginallyEnabled = sc.schedulingCustomizationOriginallyEnabled;
|
|
163
163
|
this.errors = this.errors.concat(sc.errors);
|
|
164
164
|
|
|
165
|
+
if (this.isEdit) {
|
|
166
|
+
this.originalKubeVersion = this.versionOptions.find((v) => v.value === this.liveValue.spec.kubernetesVersion);
|
|
167
|
+
}
|
|
168
|
+
|
|
165
169
|
Object.entries(this.chartValues).forEach(([name, value]) => {
|
|
166
170
|
const key = this.chartVersionKey(name);
|
|
167
171
|
|
|
@@ -278,6 +282,9 @@ export default {
|
|
|
278
282
|
REGISTRIES_TAB_NAME,
|
|
279
283
|
labelForAddon,
|
|
280
284
|
etcdConfigValid: true,
|
|
285
|
+
addonConfigDiffs: {},
|
|
286
|
+
originalKubeVersion: null,
|
|
287
|
+
isEmpty,
|
|
281
288
|
};
|
|
282
289
|
},
|
|
283
290
|
|
|
@@ -921,8 +928,22 @@ export default {
|
|
|
921
928
|
}
|
|
922
929
|
},
|
|
923
930
|
|
|
924
|
-
selectedVersion() {
|
|
925
|
-
this.
|
|
931
|
+
async selectedVersion(neu) {
|
|
932
|
+
if (this.isEdit) {
|
|
933
|
+
const {
|
|
934
|
+
addonConfigDiffs, addonNames, userChartValues, $store
|
|
935
|
+
} = this;
|
|
936
|
+
|
|
937
|
+
await addonConfigPreserve(
|
|
938
|
+
{
|
|
939
|
+
addonConfigDiffs, addonNames, userChartValues, $store
|
|
940
|
+
},
|
|
941
|
+
this.originalKubeVersion?.charts,
|
|
942
|
+
neu?.charts
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
this.versionInfo = {}; // Invalidate cache such that version info relevant to selected kube version is updated
|
|
926
947
|
|
|
927
948
|
// Allow time for addonNames to update... then fetch any missing addons
|
|
928
949
|
this.$nextTick(() => this.initAddons());
|
|
@@ -1511,10 +1532,15 @@ export default {
|
|
|
1511
1532
|
});
|
|
1512
1533
|
},
|
|
1513
1534
|
|
|
1514
|
-
showAddonConfirmation() {
|
|
1515
|
-
return new Promise((resolve
|
|
1535
|
+
showAddonConfirmation(addonNames, previousKubeVersion, newKubeVersion) {
|
|
1536
|
+
return new Promise((resolve) => {
|
|
1516
1537
|
this.$store.dispatch('cluster/promptModal', {
|
|
1517
|
-
component:
|
|
1538
|
+
component: 'AddonConfigConfirmationDialog',
|
|
1539
|
+
componentProps: {
|
|
1540
|
+
addonNames,
|
|
1541
|
+
previousKubeVersion,
|
|
1542
|
+
newKubeVersion
|
|
1543
|
+
},
|
|
1518
1544
|
resources: [(value) => resolve(value)]
|
|
1519
1545
|
});
|
|
1520
1546
|
});
|
|
@@ -1555,10 +1581,28 @@ export default {
|
|
|
1555
1581
|
const isEditVersion = this.isEdit && this.liveValue?.spec?.kubernetesVersion !== this.value?.spec?.kubernetesVersion;
|
|
1556
1582
|
|
|
1557
1583
|
if (isEditVersion) {
|
|
1558
|
-
const
|
|
1584
|
+
const hasDiffs = Object.values(this.addonConfigDiffs).some((d) => !isEmpty(d));
|
|
1585
|
+
|
|
1586
|
+
if (hasDiffs) {
|
|
1587
|
+
const addonNamesWithDiffs = [];
|
|
1588
|
+
|
|
1589
|
+
for (const name in this.addonConfigDiffs) {
|
|
1590
|
+
const diff = this.addonConfigDiffs[name];
|
|
1591
|
+
|
|
1592
|
+
if (!isEmpty(diff)) {
|
|
1593
|
+
addonNamesWithDiffs.push(name);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1559
1596
|
|
|
1560
|
-
|
|
1561
|
-
|
|
1597
|
+
const shouldContinue = await this.showAddonConfirmation(
|
|
1598
|
+
addonNamesWithDiffs,
|
|
1599
|
+
this.liveValue.spec.kubernetesVersion,
|
|
1600
|
+
this.value.spec.kubernetesVersion
|
|
1601
|
+
);
|
|
1602
|
+
|
|
1603
|
+
if (!shouldContinue) {
|
|
1604
|
+
return btnCb('cancelled');
|
|
1605
|
+
}
|
|
1562
1606
|
}
|
|
1563
1607
|
}
|
|
1564
1608
|
|
|
@@ -2521,6 +2565,9 @@ export default {
|
|
|
2521
2565
|
:addons-rev="addonsRev"
|
|
2522
2566
|
:user-chart-values-temp="userChartValuesTemp"
|
|
2523
2567
|
:init-yaml-editor="initYamlEditor"
|
|
2568
|
+
:has-diff="!isEmpty(addonConfigDiffs[v.name])"
|
|
2569
|
+
:previous-kube-version="liveValue?.spec?.kubernetesVersion"
|
|
2570
|
+
:new-kube-version="value.spec.kubernetesVersion"
|
|
2524
2571
|
@update:value="$emit('input', $event)"
|
|
2525
2572
|
@update-questions="syncChartValues"
|
|
2526
2573
|
@update-values="updateValues"
|
|
@@ -48,6 +48,27 @@ export default {
|
|
|
48
48
|
initYamlEditor: {
|
|
49
49
|
type: Function,
|
|
50
50
|
required: true,
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Indicates if a configuration conflict was detected for this addon.
|
|
54
|
+
*/
|
|
55
|
+
hasDiff: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: false
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* The Kubernetes version the user is upgrading from.
|
|
61
|
+
*/
|
|
62
|
+
previousKubeVersion: {
|
|
63
|
+
type: String,
|
|
64
|
+
default: ''
|
|
65
|
+
},
|
|
66
|
+
/**
|
|
67
|
+
* The Kubernetes version the user is upgrading to.
|
|
68
|
+
*/
|
|
69
|
+
newKubeVersion: {
|
|
70
|
+
type: String,
|
|
71
|
+
default: ''
|
|
51
72
|
}
|
|
52
73
|
|
|
53
74
|
},
|
|
@@ -73,10 +94,15 @@ export default {
|
|
|
73
94
|
<template>
|
|
74
95
|
<div>
|
|
75
96
|
<Banner
|
|
76
|
-
v-if="isEdit"
|
|
97
|
+
v-if="isEdit && hasDiff"
|
|
77
98
|
color="warning"
|
|
78
99
|
>
|
|
79
|
-
|
|
100
|
+
<span
|
|
101
|
+
v-clean-html="t('cluster.addOns.dependencyBanner', {
|
|
102
|
+
previousKubeVersion,
|
|
103
|
+
newKubeVersion
|
|
104
|
+
}, true)"
|
|
105
|
+
/>
|
|
80
106
|
</Banner>
|
|
81
107
|
<div
|
|
82
108
|
v-if="versionInfo && addonVersion"
|
package/list/projectsecret.vue
CHANGED
package/machine-config/azure.vue
CHANGED
|
@@ -35,7 +35,7 @@ const defaultConfig = {
|
|
|
35
35
|
dns: '',
|
|
36
36
|
environment: 'AzurePublicCloud',
|
|
37
37
|
faultDomainCount: '3',
|
|
38
|
-
image: 'canonical:
|
|
38
|
+
image: 'canonical:ubuntu-24_04-lts:server-gen1:latest',
|
|
39
39
|
location: 'westus',
|
|
40
40
|
managedDisks: false,
|
|
41
41
|
noPublicIp: false,
|
package/mixins/chart.js
CHANGED
|
@@ -12,9 +12,9 @@ type MockChartContext = {
|
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
interface CardContent {
|
|
15
|
-
subHeaderItems: { label: string }[];
|
|
15
|
+
subHeaderItems: { label: string, labelTooltip?: string}[];
|
|
16
16
|
footerItems: { labels: string[]; icon?: string }[];
|
|
17
|
-
statuses: { tooltip: { key
|
|
17
|
+
statuses: { tooltip: { key?: string; text?: string }; color: string }[];
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const t = jest.fn((key) => key); // mock translation function
|
|
@@ -225,7 +225,7 @@ describe('class Chart', () => {
|
|
|
225
225
|
|
|
226
226
|
const result = chart.cardContent as CardContent;
|
|
227
227
|
|
|
228
|
-
const deprecatedStatus = result.statuses.find((s) => s.tooltip
|
|
228
|
+
const deprecatedStatus = result.statuses.find((s) => s.tooltip?.key === 'generic.deprecated');
|
|
229
229
|
|
|
230
230
|
expect(deprecatedStatus).toBeDefined();
|
|
231
231
|
expect(deprecatedStatus?.color).toBe('error');
|
|
@@ -240,10 +240,11 @@ describe('class Chart', () => {
|
|
|
240
240
|
|
|
241
241
|
const result = chart.cardContent as CardContent;
|
|
242
242
|
|
|
243
|
-
const installedStatus = result.statuses.find((s) => s.tooltip
|
|
243
|
+
const installedStatus = result.statuses.find((s) => s.tooltip?.text?.startsWith('generic.installed'));
|
|
244
244
|
|
|
245
245
|
expect(installedStatus).toBeDefined();
|
|
246
246
|
expect(installedStatus?.color).toBe('success');
|
|
247
|
+
expect(installedStatus?.tooltip?.text).toContain(installedApp.spec.chart.metadata.version);
|
|
247
248
|
});
|
|
248
249
|
|
|
249
250
|
it('includes upgradeable status when upgrade is available', () => {
|
|
@@ -255,7 +256,7 @@ describe('class Chart', () => {
|
|
|
255
256
|
|
|
256
257
|
const result = chart.cardContent as CardContent;
|
|
257
258
|
|
|
258
|
-
const upgradeableStatus = result.statuses.find((s) => s.tooltip
|
|
259
|
+
const upgradeableStatus = result.statuses.find((s) => s.tooltip?.key === 'generic.upgradeable');
|
|
259
260
|
|
|
260
261
|
expect(upgradeableStatus).toBeDefined();
|
|
261
262
|
expect(upgradeableStatus?.color).toBe('info');
|
|
@@ -270,9 +271,16 @@ describe('class Chart', () => {
|
|
|
270
271
|
|
|
271
272
|
const result = chart.cardContent as CardContent;
|
|
272
273
|
|
|
273
|
-
const
|
|
274
|
+
const statuses = result.statuses.map((s) => {
|
|
275
|
+
if (s.tooltip?.key) {
|
|
276
|
+
return s.tooltip.key;
|
|
277
|
+
}
|
|
278
|
+
if (s.tooltip?.text?.startsWith('generic.installed')) {
|
|
279
|
+
return 'generic.installed';
|
|
280
|
+
}
|
|
281
|
+
});
|
|
274
282
|
|
|
275
|
-
expect(
|
|
283
|
+
expect(statuses).toStrictEqual(expect.arrayContaining([
|
|
276
284
|
'generic.deprecated',
|
|
277
285
|
'generic.upgradeable',
|
|
278
286
|
'generic.installed'
|
|
@@ -290,11 +298,11 @@ describe('class Chart', () => {
|
|
|
290
298
|
const chart = new Chart(chartWithZeroTime, {
|
|
291
299
|
rootGetters: {
|
|
292
300
|
'cluster/all': () => [],
|
|
293
|
-
'i18n/t': (key) => key
|
|
301
|
+
'i18n/t': (key: string) => key
|
|
294
302
|
},
|
|
295
303
|
});
|
|
296
304
|
|
|
297
|
-
const result = chart.cardContent;
|
|
305
|
+
const result = chart.cardContent as CardContent;
|
|
298
306
|
const lastUpdatedItem = result.subHeaderItems[1];
|
|
299
307
|
|
|
300
308
|
expect(lastUpdatedItem.label).toBe('generic.na');
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import ComplianceProfile from '@shell/models/compliance.cattle.io.clusterscanprofile';
|
|
2
|
+
|
|
3
|
+
describe('class: ComplianceProfile', () => {
|
|
4
|
+
describe('getter: numberTestsSkipped', () => {
|
|
5
|
+
it('should return 0 if skipTests is not present in spec', () => {
|
|
6
|
+
const complianceProfile = new ComplianceProfile({ spec: {} });
|
|
7
|
+
|
|
8
|
+
expect(complianceProfile.numberTestsSkipped).toBe(0);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should return 0 if skipTests is null', () => {
|
|
12
|
+
const complianceProfile = new ComplianceProfile({ spec: { skipTests: null } });
|
|
13
|
+
|
|
14
|
+
expect(complianceProfile.numberTestsSkipped).toBe(0);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return 0 if skipTests is an empty array', () => {
|
|
18
|
+
const complianceProfile = new ComplianceProfile({ spec: { skipTests: [] } });
|
|
19
|
+
|
|
20
|
+
expect(complianceProfile.numberTestsSkipped).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return the correct number of skipped tests', () => {
|
|
24
|
+
const tests = ['test-1', 'test-2', 'test-3'];
|
|
25
|
+
const complianceProfile = new ComplianceProfile({ spec: { skipTests: tests } });
|
|
26
|
+
|
|
27
|
+
expect(complianceProfile.numberTestsSkipped).toBe(tests.length);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -323,7 +323,7 @@ export default class CatalogApp extends SteveModel {
|
|
|
323
323
|
|
|
324
324
|
get relatedResourcesToRemove() {
|
|
325
325
|
return async() => {
|
|
326
|
-
const crd = this.spec
|
|
326
|
+
const crd = this.spec?.chart?.metadata?.annotations?.[CATALOG_ANNOTATIONS.AUTO_INSTALL]?.replace('=match', '');
|
|
327
327
|
|
|
328
328
|
return await this.$dispatch('find', {
|
|
329
329
|
type: CATALOG.APP,
|
package/models/chart.js
CHANGED
|
@@ -195,8 +195,10 @@ export default class Chart extends SteveModel {
|
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
if (this.isInstalled) {
|
|
198
|
+
const installedVersion = this.matchingInstalledApps[0]?.spec?.chart?.metadata?.version;
|
|
199
|
+
|
|
198
200
|
statuses.push({
|
|
199
|
-
icon: 'icon-confirmation-alt', color: 'success', tooltip: {
|
|
201
|
+
icon: 'icon-confirmation-alt', color: 'success', tooltip: { text: `${ this.t('generic.installed') } (${ installedVersion })` }
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
204
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.8-rc.1",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@babel/preset-typescript": "7.16.7",
|
|
39
39
|
"@novnc/novnc": "1.2.0",
|
|
40
40
|
"@popperjs/core": "2.11.8",
|
|
41
|
-
"@rancher/icons": "2.0.
|
|
41
|
+
"@rancher/icons": "2.0.49",
|
|
42
42
|
"@types/is-url": "1.2.30",
|
|
43
43
|
"@types/node": "20.10.8",
|
|
44
44
|
"@types/semver": "^7.5.8",
|
package/pages/auth/login.vue
CHANGED
|
@@ -10,7 +10,7 @@ import CopyCode from '@shell/components/CopyCode';
|
|
|
10
10
|
import { Banner } from '@components/Banner';
|
|
11
11
|
import {
|
|
12
12
|
LOCAL, LOGGED_OUT, TIMED_OUT, IS_SSO, _FLAGGED,
|
|
13
|
-
IS_SLO
|
|
13
|
+
IS_SLO, IS_SESSION_IDLE
|
|
14
14
|
} from '@shell/config/query-params';
|
|
15
15
|
import { Checkbox } from '@components/Form/Checkbox';
|
|
16
16
|
import Password from '@shell/components/form/Password';
|
|
@@ -47,6 +47,7 @@ export default {
|
|
|
47
47
|
|
|
48
48
|
timedOut: this.$route.query[TIMED_OUT] === _FLAGGED,
|
|
49
49
|
loggedOut: this.$route.query[LOGGED_OUT] === _FLAGGED,
|
|
50
|
+
isSessionIdle: this.$route.query[IS_SESSION_IDLE] === _FLAGGED,
|
|
50
51
|
isSsoLogout: this.$route.query[IS_SSO] === _FLAGGED,
|
|
51
52
|
isSlo: this.$route.query[IS_SLO] === _FLAGGED,
|
|
52
53
|
err: this.$route.query.err,
|
|
@@ -67,7 +68,9 @@ export default {
|
|
|
67
68
|
...mapGetters({ t: 'i18n/t', hasMultipleLocales: 'i18n/hasMultipleLocales' }),
|
|
68
69
|
|
|
69
70
|
loggedOutSuccessMsg() {
|
|
70
|
-
if (this.
|
|
71
|
+
if (this.isSessionIdle) {
|
|
72
|
+
return this.t('login.loggedOutSessionIdle');
|
|
73
|
+
} else if (this.isSlo) {
|
|
71
74
|
return this.t('login.loggedOutFromSlo');
|
|
72
75
|
} else if (this.isSsoLogout) {
|
|
73
76
|
return this.t('login.loggedOutFromSso');
|
package/pages/auth/verify.vue
CHANGED
|
@@ -10,7 +10,7 @@ import { AUTH_BROADCAST_CHANNEL_NAME } from '@shell/utils/auth';
|
|
|
10
10
|
|
|
11
11
|
const samlProviders = ['ping', 'adfs', 'keycloak', 'okta', 'shibboleth'];
|
|
12
12
|
|
|
13
|
-
const oauthProviders = ['github', 'googleoauth', 'azuread'];
|
|
13
|
+
const oauthProviders = ['github', 'githubapp', 'googleoauth', 'azuread'];
|
|
14
14
|
|
|
15
15
|
function reply(err, code) {
|
|
16
16
|
try {
|
|
@@ -19,7 +19,7 @@ defineProps<{
|
|
|
19
19
|
v-for="(subHeaderItem, i) in items"
|
|
20
20
|
:key="i"
|
|
21
21
|
class="app-chart-card-sub-header-item"
|
|
22
|
-
data-testid="app-chart-card-
|
|
22
|
+
data-testid="app-chart-card-sub-header-item"
|
|
23
23
|
>
|
|
24
24
|
<i
|
|
25
25
|
v-clean-tooltip="t(subHeaderItem.iconTooltip.key)"
|
|
@@ -35,7 +35,8 @@ defineProps<{
|
|
|
35
35
|
<style scoped lang="scss">
|
|
36
36
|
.app-chart-card-sub-header {
|
|
37
37
|
display: flex;
|
|
38
|
-
|
|
38
|
+
flex-wrap: wrap;
|
|
39
|
+
gap: var(--gap) var(--gap-md);
|
|
39
40
|
color: var(--link-text-secondary);
|
|
40
41
|
margin-bottom: 8px;
|
|
41
42
|
|
|
@@ -259,11 +259,11 @@ export default {
|
|
|
259
259
|
class="status"
|
|
260
260
|
>
|
|
261
261
|
<i
|
|
262
|
-
v-clean-tooltip="t(status.tooltip.key)"
|
|
262
|
+
v-clean-tooltip="status.tooltip.key ? t(status.tooltip.key) : status.tooltip.text"
|
|
263
263
|
:class="['icon', status.icon, status.color]"
|
|
264
264
|
:style="{color: status.customColor}"
|
|
265
265
|
role="img"
|
|
266
|
-
:aria-label="t(status.tooltip.key)"
|
|
266
|
+
:aria-label="status.tooltip.key ? t(status.tooltip.key) : status.tooltip.text"
|
|
267
267
|
/>
|
|
268
268
|
</div>
|
|
269
269
|
</div>
|
|
@@ -6,6 +6,8 @@ import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
|
|
|
6
6
|
import { STEVE_EVENT_FIRST_SEEN, STEVE_EVENT_LAST_SEEN, STEVE_EVENT_OBJECT, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
|
|
7
7
|
import { headerFromSchemaColString } from '@shell/store/type-map.utils';
|
|
8
8
|
import { NAME as EXPLORER } from '@shell/config/product/explorer';
|
|
9
|
+
import { ROWS_PER_PAGE } from '@shell/store/prefs';
|
|
10
|
+
import { RcDropdown, RcDropdownTrigger, RcDropdownItem } from '@components/RcDropdown';
|
|
9
11
|
|
|
10
12
|
const reason = {
|
|
11
13
|
...REASON,
|
|
@@ -29,15 +31,42 @@ const eventHeaders = [
|
|
|
29
31
|
},
|
|
30
32
|
];
|
|
31
33
|
|
|
34
|
+
// Local storage key for the events table row count preference
|
|
35
|
+
const ROWS_COUNT_PREF = 'events-row-count-pref';
|
|
36
|
+
// Value to use when we want to use the user's preference from the table
|
|
37
|
+
const ROWS_PREF_USE_TABLE = -1;
|
|
38
|
+
// Default number of rows to show in the events table when not set in the preference
|
|
39
|
+
const ROWS_COUNT_DEFAULT = 10;
|
|
40
|
+
|
|
32
41
|
export default {
|
|
33
|
-
components: {
|
|
42
|
+
components: {
|
|
43
|
+
PaginatedResourceTable,
|
|
44
|
+
RcDropdown,
|
|
45
|
+
RcDropdownItem,
|
|
46
|
+
RcDropdownTrigger
|
|
47
|
+
},
|
|
34
48
|
|
|
35
49
|
data() {
|
|
50
|
+
const tableRowOptions = this.$store.getters['prefs/options'](ROWS_PER_PAGE);
|
|
51
|
+
|
|
52
|
+
let rowsPerPage = ROWS_COUNT_DEFAULT;
|
|
53
|
+
|
|
54
|
+
// Read the current value from localStorage if it exists
|
|
55
|
+
if (window.localStorage.getItem(ROWS_COUNT_PREF)) {
|
|
56
|
+
try {
|
|
57
|
+
rowsPerPage = parseInt(window.localStorage.getItem(ROWS_COUNT_PREF));
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error('Error parsing rows count from localStorage:', e); // eslint-disable-line no-console
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
36
63
|
return {
|
|
64
|
+
rowsPerPage,
|
|
37
65
|
schema: null,
|
|
38
66
|
events: [],
|
|
39
67
|
eventHeaders,
|
|
40
68
|
paginationHeaders: null,
|
|
69
|
+
options: tableRowOptions || [],
|
|
41
70
|
allEventsLink: {
|
|
42
71
|
name: 'c-cluster-product-resource',
|
|
43
72
|
params: {
|
|
@@ -72,7 +101,34 @@ export default {
|
|
|
72
101
|
this.dismissRouteHandler = this.$router.beforeEach(this.onRouteChange);
|
|
73
102
|
},
|
|
74
103
|
|
|
104
|
+
computed: {
|
|
105
|
+
userPrefRowsPerPage() {
|
|
106
|
+
return parseInt(this.$store.getters['prefs/get'](ROWS_PER_PAGE), 10) || undefined;
|
|
107
|
+
},
|
|
108
|
+
rowOptions() {
|
|
109
|
+
const rowOptions = [];
|
|
110
|
+
|
|
111
|
+
this.options.forEach((item) => rowOptions.push({
|
|
112
|
+
label: this.t('glance.showXEvents', { count: item }),
|
|
113
|
+
value: item
|
|
114
|
+
}));
|
|
115
|
+
|
|
116
|
+
if (this.userPrefRowsPerPage) {
|
|
117
|
+
rowOptions.push({
|
|
118
|
+
label: this.t('glance.useUserPreference', { count: this.userPrefRowsPerPage }),
|
|
119
|
+
value: ROWS_PREF_USE_TABLE,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return rowOptions;
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
|
|
75
127
|
methods: {
|
|
128
|
+
updateRowsCount(val) {
|
|
129
|
+
this.rowsPerPage = val;
|
|
130
|
+
window.localStorage.setItem(ROWS_COUNT_PREF, val);
|
|
131
|
+
},
|
|
76
132
|
async onRouteChange(to, from, next) {
|
|
77
133
|
if (this.$route.name !== to.name) {
|
|
78
134
|
await this.$store.dispatch('cluster/forgetType', EVENT);
|
|
@@ -100,7 +156,7 @@ export default {
|
|
|
100
156
|
:table-actions="false"
|
|
101
157
|
:row-actions="false"
|
|
102
158
|
:groupable="false"
|
|
103
|
-
:rows-per-page="
|
|
159
|
+
:rows-per-page="rowsPerPage"
|
|
104
160
|
>
|
|
105
161
|
<template v-slot:header-right>
|
|
106
162
|
<router-link
|
|
@@ -110,14 +166,44 @@ export default {
|
|
|
110
166
|
>
|
|
111
167
|
<span>{{ t('glance.eventsTable') }}</span>
|
|
112
168
|
</router-link>
|
|
169
|
+
<rc-dropdown>
|
|
170
|
+
<rc-dropdown-trigger
|
|
171
|
+
data-testid="events-list-row-count-menu-toggle"
|
|
172
|
+
:aria-label="t('glance.changeEventsListRowCount')"
|
|
173
|
+
ghost
|
|
174
|
+
small
|
|
175
|
+
>
|
|
176
|
+
<i class="icon icon-gear" />
|
|
177
|
+
</rc-dropdown-trigger>
|
|
178
|
+
<template #dropdownCollection>
|
|
179
|
+
<rc-dropdown-item
|
|
180
|
+
v-for="(item, i) in rowOptions"
|
|
181
|
+
:key="i"
|
|
182
|
+
:value="item.value"
|
|
183
|
+
@click.stop="updateRowsCount(item.value)"
|
|
184
|
+
>
|
|
185
|
+
<span :class="{ 'selected-pagesize-option': rowsPerPage === item.value }">
|
|
186
|
+
{{ item.label }}
|
|
187
|
+
</span>
|
|
188
|
+
</rc-dropdown-item>
|
|
189
|
+
</template>
|
|
190
|
+
</rc-dropdown>
|
|
113
191
|
</template>
|
|
114
192
|
</PaginatedResourceTable>
|
|
115
193
|
</template>
|
|
116
194
|
|
|
117
195
|
<style lang="scss" scoped>
|
|
196
|
+
.icon.icon-gear {
|
|
197
|
+
color: var(--primary);
|
|
198
|
+
padding: 0 8px;
|
|
199
|
+
}
|
|
118
200
|
.events-link {
|
|
119
201
|
align-self: center;
|
|
120
|
-
|
|
202
|
+
margin-right: 10px;
|
|
121
203
|
white-space: nowrap;
|
|
122
204
|
}
|
|
205
|
+
|
|
206
|
+
.selected-pagesize-option {
|
|
207
|
+
font-weight: bold;
|
|
208
|
+
}
|
|
123
209
|
</style>
|
|
@@ -96,7 +96,7 @@ export default {
|
|
|
96
96
|
title: { text: chart.chartNameDisplay },
|
|
97
97
|
statuses: chart.cardContent.statuses
|
|
98
98
|
},
|
|
99
|
-
subHeaderItems: chart.cardContent.subHeaderItems
|
|
99
|
+
subHeaderItems: chart.cardContent.subHeaderItems,
|
|
100
100
|
footerItems: chart.deploysOnWindows ? [{
|
|
101
101
|
icon: 'icon-tag-alt',
|
|
102
102
|
iconTooltip: { key: 'generic.tags' },
|
|
@@ -151,7 +151,7 @@ export default {
|
|
|
151
151
|
action: 'edit',
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
const currentVersion = installedApp.spec
|
|
154
|
+
const currentVersion = installedApp.spec?.chart?.metadata?.version;
|
|
155
155
|
const versions = rawChart.versions;
|
|
156
156
|
const currentIndex = versions.findIndex((v) => v.version === currentVersion);
|
|
157
157
|
|
|
@@ -190,7 +190,7 @@ export default {
|
|
|
190
190
|
},
|
|
191
191
|
|
|
192
192
|
downgrade(app, chart) {
|
|
193
|
-
const currentVersion = app.spec
|
|
193
|
+
const currentVersion = app.spec?.chart?.metadata?.version;
|
|
194
194
|
const versions = chart.versions;
|
|
195
195
|
const currentIndex = versions.findIndex((v) => v.version === currentVersion);
|
|
196
196
|
|