@rancher/shell 3.0.7 → 3.0.8-rc.2

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.
Files changed (123) hide show
  1. package/assets/images/vendor/githubapp.svg +13 -0
  2. package/assets/styles/base/_typography.scss +1 -1
  3. package/assets/styles/global/_layout.scss +21 -35
  4. package/assets/styles/themes/_modern.scss +5 -5
  5. package/assets/translations/en-us.yaml +102 -17
  6. package/assets/translations/zh-hans.yaml +0 -4
  7. package/components/EmberPage.vue +1 -1
  8. package/components/Inactivity.vue +222 -106
  9. package/components/InstallHelmCharts.vue +2 -2
  10. package/components/Resource/Detail/CopyToClipboard.vue +1 -1
  11. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
  12. package/components/Resource/Detail/TitleBar/index.vue +10 -6
  13. package/components/ResourceDetail/index.vue +4 -1
  14. package/components/SortableTable/index.vue +18 -2
  15. package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
  16. package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
  17. package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
  18. package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
  19. package/components/fleet/FleetConfigMapSelector.vue +117 -0
  20. package/components/fleet/FleetSecretSelector.vue +127 -0
  21. package/components/fleet/__tests__/FleetConfigMapSelector.test.ts +125 -0
  22. package/components/fleet/__tests__/FleetSecretSelector.test.ts +82 -0
  23. package/components/form/FileImageSelector.vue +13 -4
  24. package/components/form/FileSelector.vue +11 -2
  25. package/components/form/ResourceLabeledSelect.vue +1 -0
  26. package/components/form/__tests__/ResourceLabeledSelect.test.ts +90 -0
  27. package/components/nav/Header.vue +34 -13
  28. package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
  29. package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
  30. package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
  31. package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
  32. package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
  33. package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
  34. package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
  35. package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
  36. package/components/nav/WindowManager/constants.ts +23 -0
  37. package/components/nav/WindowManager/index.vue +61 -575
  38. package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
  39. package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
  40. package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
  41. package/components/templates/default.vue +4 -40
  42. package/components/templates/home.vue +31 -5
  43. package/config/product/auth.js +1 -0
  44. package/config/query-params.js +1 -0
  45. package/config/settings.ts +8 -1
  46. package/config/store.js +4 -2
  47. package/config/types.js +2 -0
  48. package/detail/pod.vue +1 -0
  49. package/dialog/AddonConfigConfirmationDialog.vue +45 -1
  50. package/directives/ui-context.ts +97 -0
  51. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +52 -11
  52. package/edit/auth/AuthProviderWarningBanners.vue +14 -1
  53. package/edit/auth/github-app-steps.vue +97 -0
  54. package/edit/auth/github-steps.vue +75 -0
  55. package/edit/auth/github.vue +94 -65
  56. package/edit/fleet.cattle.io.helmop.vue +51 -2
  57. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +15 -5
  58. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +11 -9
  59. package/edit/provisioning.cattle.io.cluster/rke2.vue +56 -9
  60. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +28 -2
  61. package/initialize/install-directives.js +2 -0
  62. package/list/projectsecret.vue +1 -1
  63. package/machine-config/azure.vue +1 -1
  64. package/mixins/chart.js +1 -1
  65. package/models/__tests__/chart.test.ts +17 -9
  66. package/models/__tests__/compliance.cattle.io.clusterscanprofile.spec.js +30 -0
  67. package/models/catalog.cattle.io.app.js +1 -1
  68. package/models/chart.js +3 -1
  69. package/models/compliance.cattle.io.clusterscanprofile.js +1 -1
  70. package/models/management.cattle.io.authconfig.js +1 -0
  71. package/package.json +2 -2
  72. package/pages/auth/login.vue +5 -2
  73. package/pages/auth/verify.vue +1 -1
  74. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +3 -2
  75. package/pages/c/_cluster/apps/charts/chart.vue +2 -2
  76. package/pages/c/_cluster/explorer/EventsTable.vue +89 -3
  77. package/pages/c/_cluster/explorer/tools/index.vue +3 -3
  78. package/pages/c/_cluster/settings/performance.vue +12 -25
  79. package/pages/home.vue +313 -12
  80. package/plugins/axios.js +2 -1
  81. package/plugins/dashboard-store/actions.js +1 -1
  82. package/plugins/dashboard-store/resource-class.js +17 -2
  83. package/plugins/steve/steve-pagination-utils.ts +2 -2
  84. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
  85. package/scripts/extension/publish +1 -1
  86. package/store/auth.js +8 -3
  87. package/store/aws.js +8 -6
  88. package/store/features.js +1 -0
  89. package/store/index.js +9 -3
  90. package/store/prefs.js +6 -0
  91. package/store/ui-context.ts +86 -0
  92. package/store/wm.ts +244 -0
  93. package/types/kube/kube-api.ts +2 -1
  94. package/types/rancher/index.d.ts +1 -0
  95. package/types/resources/settings.d.ts +29 -7
  96. package/types/shell/index.d.ts +59 -0
  97. package/types/window-manager.ts +22 -0
  98. package/utils/__tests__/cluster.test.ts +379 -1
  99. package/utils/cluster.js +157 -3
  100. package/utils/dynamic-content/__tests__/config.test.ts +187 -0
  101. package/utils/dynamic-content/__tests__/index.test.ts +390 -0
  102. package/utils/dynamic-content/__tests__/info.test.ts +263 -0
  103. package/utils/dynamic-content/__tests__/new-release.test.ts +216 -0
  104. package/utils/dynamic-content/__tests__/support-notice.test.ts +262 -0
  105. package/utils/dynamic-content/__tests__/util.test.ts +235 -0
  106. package/utils/dynamic-content/config.ts +55 -0
  107. package/utils/dynamic-content/index.ts +273 -0
  108. package/utils/dynamic-content/info.ts +219 -0
  109. package/utils/dynamic-content/new-release.ts +126 -0
  110. package/utils/dynamic-content/support-notice.ts +169 -0
  111. package/utils/dynamic-content/types.d.ts +101 -0
  112. package/utils/dynamic-content/util.ts +122 -0
  113. package/utils/dynamic-importer.js +2 -2
  114. package/utils/inactivity.ts +104 -0
  115. package/utils/pagination-utils.ts +19 -4
  116. package/utils/release-notes.ts +1 -1
  117. package/assets/images/icons/document.svg +0 -3
  118. package/store/wm.js +0 -95
  119. /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
  120. /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
  121. /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
  122. /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
  123. /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
@@ -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: string }; color: string }[];
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.key === 'generic.deprecated');
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.key === 'generic.installed');
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.key === 'generic.upgradeable');
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 keys = result.statuses.map((s) => s.tooltip.key);
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(keys).toStrictEqual(expect.arrayContaining([
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.chart.metadata.annotations[CATALOG_ANNOTATIONS.AUTO_INSTALL].replace('=match', '');
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: { key: 'generic.installed' }
201
+ icon: 'icon-confirmation-alt', color: 'success', tooltip: { text: `${ this.t('generic.installed') } (${ installedVersion })` }
200
202
  });
201
203
  }
202
204
 
@@ -11,7 +11,7 @@ export default class ComplianceProfile extends SteveModel {
11
11
  get numberTestsSkipped() {
12
12
  const { skipTests = [] } = this.spec;
13
13
 
14
- return skipTests.length;
14
+ return skipTests?.length || 0;
15
15
  }
16
16
 
17
17
  get benchmarkVersionLink() {
@@ -14,6 +14,7 @@ export const configType = {
14
14
  googleoauth: 'oauth',
15
15
  local: '',
16
16
  github: 'oauth',
17
+ githubapp: 'oauth',
17
18
  keycloakoidc: 'oidc',
18
19
  genericoidc: 'oidc',
19
20
  cognito: 'oidc',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.7",
3
+ "version": "3.0.8-rc.2",
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.38",
41
+ "@rancher/icons": "2.0.51",
42
42
  "@types/is-url": "1.2.30",
43
43
  "@types/node": "20.10.8",
44
44
  "@types/semver": "^7.5.8",
@@ -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.isSlo) {
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');
@@ -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-version"
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
- gap: var(--gap-md);
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: { PaginatedResourceTable },
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="10"
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
- padding-right: 20px;
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.slice(0, 1),
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.chart.metadata.version;
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.chart.metadata.version;
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
 
@@ -76,6 +76,13 @@ export default {
76
76
  resource: MANAGEMENT.FEATURE
77
77
  }
78
78
  }).href,
79
+ settingsPageUrl: this.$router.resolve({
80
+ name: 'c-cluster-product-resource',
81
+ params: {
82
+ product: SETTING_PRODUCT,
83
+ resource: MANAGEMENT.SETTING
84
+ }
85
+ }).href,
79
86
  ssPApplicableTypesOpen: false,
80
87
  };
81
88
  },
@@ -206,31 +213,11 @@ export default {
206
213
  <!-- Inactivity -->
207
214
  <div class="mt-20">
208
215
  <h2>{{ t('performance.inactivity.title') }}</h2>
209
- <p>{{ t('performance.inactivity.description') }}</p>
210
- <Checkbox
211
- v-model:value="value.inactivity.enabled"
212
- :mode="mode"
213
- :label="t('performance.inactivity.checkboxLabel')"
214
- class="mt-10 mb-20"
215
- :primary="true"
216
- />
217
- <div class="ml-20">
218
- <LabeledInput
219
- v-model:value="value.inactivity.threshold"
220
- data-testid="inactivity-threshold"
221
- :mode="mode"
222
- :label="t('performance.inactivity.inputLabel')"
223
- :disabled="!value.inactivity.enabled"
224
- class="input mb-10"
225
- type="number"
226
- min="0"
227
- :rules="[validateInactivityThreshold]"
228
- />
229
- <span
230
- v-clean-html="t('performance.inactivity.information', {}, true)"
231
- :class="{ 'text-muted': !value.incrementalLoading.enabled }"
232
- />
233
- </div>
216
+ <Banner
217
+ color="warning"
218
+ >
219
+ <span v-clean-html="t(`performance.deprecatedInactivitySetting`, { settingsPageUrl }, true)" />
220
+ </Banner>
234
221
  </div>
235
222
  <!-- Websocket Notifications -->
236
223
  <div class="mt-40">