@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.
Files changed (92) hide show
  1. package/assets/images/pl/dark/rancher-logo.svg +131 -44
  2. package/assets/images/pl/rancher-logo.svg +120 -44
  3. package/assets/styles/base/_basic.scss +2 -2
  4. package/assets/styles/base/_color-classic.scss +51 -0
  5. package/assets/styles/base/_color.scss +3 -3
  6. package/assets/styles/base/_mixins.scss +1 -1
  7. package/assets/styles/base/_variables-classic.scss +47 -0
  8. package/assets/styles/global/_button.scss +49 -17
  9. package/assets/styles/global/_form.scss +1 -1
  10. package/assets/styles/themes/_dark.scss +4 -0
  11. package/assets/styles/themes/_light.scss +3 -69
  12. package/assets/styles/themes/_modern.scss +194 -50
  13. package/assets/styles/vendor/vue-select.scss +1 -2
  14. package/assets/translations/en-us.yaml +33 -21
  15. package/components/ClusterIconMenu.vue +1 -1
  16. package/components/ClusterProviderIcon.vue +1 -1
  17. package/components/CodeMirror.vue +1 -1
  18. package/components/FilterPanel.vue +8 -1
  19. package/components/IconOrSvg.vue +40 -29
  20. package/components/PaginatedResourceTable.vue +7 -2
  21. package/components/PromptRemove.vue +5 -0
  22. package/components/ResourceDetail/index.vue +1 -0
  23. package/components/ResourceTable.vue +30 -20
  24. package/components/SortableTable/sorting.js +3 -1
  25. package/components/Tabbed/index.vue +5 -5
  26. package/components/form/ResourceTabs/index.vue +37 -18
  27. package/components/form/SecretSelector.vue +6 -2
  28. package/components/nav/Group.vue +29 -9
  29. package/components/nav/Header.vue +6 -8
  30. package/components/nav/NamespaceFilter.vue +1 -1
  31. package/components/nav/TopLevelMenu.helper.ts +47 -20
  32. package/components/nav/TopLevelMenu.vue +44 -14
  33. package/components/nav/Type.vue +0 -5
  34. package/components/nav/__tests__/TopLevelMenu.test.ts +2 -0
  35. package/config/pagination-table-headers.js +10 -2
  36. package/config/product/explorer.js +9 -8
  37. package/config/table-headers.js +9 -0
  38. package/config/uiplugins.js +1 -1
  39. package/core/plugin.ts +33 -9
  40. package/core/types.ts +37 -6
  41. package/detail/provisioning.cattle.io.cluster.vue +1 -0
  42. package/dialog/InstallExtensionDialog.vue +71 -45
  43. package/dialog/UninstallExtensionDialog.vue +2 -1
  44. package/dialog/__tests__/InstallExtensionDialog.test.ts +111 -0
  45. package/edit/auth/oidc.vue +86 -16
  46. package/list/catalog.cattle.io.clusterrepo.vue +2 -2
  47. package/mixins/__tests__/chart.test.ts +1 -1
  48. package/mixins/chart.js +1 -1
  49. package/models/event.js +7 -0
  50. package/models/provisioning.cattle.io.cluster.js +9 -0
  51. package/package.json +2 -2
  52. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +6 -0
  53. package/pages/c/_cluster/apps/charts/StatusLabel.vue +4 -3
  54. package/pages/c/_cluster/apps/charts/index.vue +12 -11
  55. package/pages/c/_cluster/explorer/EventsTable.vue +3 -6
  56. package/pages/c/_cluster/settings/performance.vue +1 -1
  57. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +159 -62
  58. package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +102 -0
  59. package/pages/c/_cluster/uiplugins/__tests__/{index.spec.ts → index.test.ts} +121 -55
  60. package/pages/c/_cluster/uiplugins/index.vue +110 -94
  61. package/plugins/__tests__/subscribe.events.test.ts +194 -0
  62. package/plugins/dashboard-store/actions.js +3 -0
  63. package/plugins/dashboard-store/getters.js +1 -1
  64. package/plugins/dashboard-store/resource-class.js +15 -4
  65. package/plugins/steve/__tests__/subscribe.spec.ts +27 -24
  66. package/plugins/steve/index.js +18 -10
  67. package/plugins/steve/mutations.js +2 -2
  68. package/plugins/steve/resourceWatcher.js +2 -2
  69. package/plugins/steve/steve-pagination-utils.ts +26 -31
  70. package/plugins/steve/subscribe.js +113 -85
  71. package/plugins/subscribe-events.ts +211 -0
  72. package/rancher-components/BadgeState/BadgeState.vue +8 -6
  73. package/rancher-components/Banner/Banner.vue +2 -1
  74. package/rancher-components/Form/Checkbox/Checkbox.vue +3 -3
  75. package/rancher-components/Form/Radio/RadioButton.vue +3 -3
  76. package/scripts/test-plugins-build.sh +4 -5
  77. package/scripts/typegen.sh +2 -0
  78. package/store/auth.js +2 -2
  79. package/store/index.js +12 -22
  80. package/types/extension-manager.ts +8 -1
  81. package/types/resources/settings.d.ts +24 -17
  82. package/types/shell/index.d.ts +534 -336
  83. package/types/store/subscribe-events.types.ts +70 -0
  84. package/types/store/subscribe.types.ts +6 -22
  85. package/types/store/vuex.d.ts +2 -1
  86. package/types/vue-shim.d.ts +2 -5
  87. package/utils/pagination-utils.ts +98 -30
  88. package/utils/pagination-wrapper.ts +6 -8
  89. package/utils/sort.js +5 -0
  90. package/utils/unit-tests/pagination-utils.spec.ts +283 -0
  91. package/utils/validators/formRules/__tests__/index.test.ts +7 -0
  92. package/utils/validators/formRules/index.ts +2 -2
@@ -723,6 +723,17 @@ authConfig:
723
723
  tokenEndpoint: Token Endpoint
724
724
  userInfoEndpoint: User Info Endpoint
725
725
  acrValue: Authorization Context Reference
726
+ customClaims:
727
+ label: Custom Claims
728
+ enable:
729
+ label: Add custom claims
730
+ tooltip: Manually map OIDC claims when your provider doesn’t use standard claim names in tokens.
731
+ nameClaim:
732
+ label: Custom Name Claim
733
+ groupsClaim:
734
+ label: Custom Groups Claim
735
+ emailClaim:
736
+ label: Custom Email Claim
726
737
  cognitoIssuer: Issuer URL
727
738
  cognitoHelp: "You will need to create an application client in Cognito of type <b>Traditional web application</b> with the Return URL set to the URL shown below."
728
739
  scope:
@@ -941,10 +952,6 @@ asyncButton:
941
952
  success: Updated
942
953
  waiting: Updating&hellip;
943
954
  upgrade:
944
- action: Upgrade
945
- success: Upgrading
946
- waiting: Starting&hellip;
947
- upgradeVersion:
948
955
  action: Upgrade
949
956
  success: Upgraded
950
957
  waiting: Upgrading&hellip;
@@ -1262,7 +1269,6 @@ catalog:
1262
1269
  upgrade { upgrade }
1263
1270
  downgrade { upgrade }
1264
1271
  editVersion { update }
1265
- upgradeVersion { upgrade }
1266
1272
  } the {existing, select,
1267
1273
  true { app}
1268
1274
  false { chart}
@@ -5128,16 +5134,17 @@ plugins:
5128
5134
  closePluginPanel: Close plugin description panel
5129
5135
  viewVersionDetails: View extension {name} version {version} details/Readme
5130
5136
  labels:
5131
- builtin: Built-in
5137
+ builtin: Built-In
5132
5138
  experimental: Experimental
5133
5139
  third-party: Third-Party
5134
5140
  image: Image
5135
5141
  installing: Installing ...
5136
5142
  uninstalling: Uninstalling ...
5137
- updating: Updating ...
5138
- rollingBack: Rolling back ...
5143
+ upgrading: Upgrading ...
5144
+ downgrading: Downgrading ...
5139
5145
  menu: Extensions menu
5140
5146
  reloadRancher: Reload Rancher
5147
+ current: current
5141
5148
  descriptions:
5142
5149
  experimental: This Extension is marked as experimental
5143
5150
  third-party: This Extension is provided by a Third-Party
@@ -5166,6 +5173,8 @@ plugins:
5166
5173
  name: Extension module name
5167
5174
  persist: Persist extension by creating custom resource
5168
5175
  info:
5176
+ actions: Actions
5177
+ noActions: No actions available
5169
5178
  detail: Detail
5170
5179
  versions: Versions
5171
5180
  versionError: Could not load version information
@@ -5229,7 +5238,7 @@ plugins:
5229
5238
  tabs:
5230
5239
  all: All
5231
5240
  available: Available
5232
- builtin: Built-in
5241
+ builtin: Built-In
5233
5242
  images: Images
5234
5243
  installed: Installed
5235
5244
  updates: Updates
@@ -5237,22 +5246,22 @@ plugins:
5237
5246
  version: "Version: {version}"
5238
5247
  install:
5239
5248
  label: Install
5240
- title: Install Extension {name}
5241
- prompt: "Are you sure that you want to install this Extension?"
5249
+ title: Install extension {name}
5250
+ prompt: "Are you sure that you want to install this extension?"
5242
5251
  version: Version
5243
5252
  warnNotCertified: Please ensure that you are aware of the risks of installing Extensions from untrusted authors
5244
- update:
5245
- label: Update
5246
- title: Update Extension {name}
5247
- prompt: "Are you sure that you want to update this Extension?"
5248
- rollback:
5249
- label: Rollback
5250
- title: Rollback Extension {name}
5251
- prompt: "Are you sure that you want to rollback this Extension?"
5253
+ upgrade:
5254
+ label: Upgrade
5255
+ title: Upgrade extension {name}
5256
+ prompt: "Are you sure that you want to upgrade this extension?"
5257
+ downgrade:
5258
+ label: Downgrade
5259
+ title: Downgrade extension {name}
5260
+ prompt: "Are you sure that you want to downgrade this extension?"
5252
5261
  uninstall:
5253
5262
  label: Uninstall
5254
- title: "Uninstall Extension: {name}"
5255
- prompt: "Are you sure that you want to uninstall this Extension?"
5263
+ title: Uninstall extension {name}
5264
+ prompt: "Are you sure that you want to uninstall this extension?"
5256
5265
  catalog: "Are you sure that you want to uninstall this Extension Catalog Image? This will also remove any Extensions provided by this image."
5257
5266
  upgradeAvailable: A newer version of this Extension is available
5258
5267
  reload: Extensions changed - reload required
@@ -5852,6 +5861,8 @@ resourceTabs:
5852
5861
  tab: Conditions
5853
5862
  events:
5854
5863
  tab: Recent Events
5864
+ namespaceTab: "Events in Namespace"
5865
+ namespaceCaption: "Shows all events from resources in <span class='namespace-name'><b>{namespace}</b></span> namespace"
5855
5866
  related:
5856
5867
  tab: Related Resources
5857
5868
  from: Referred To By
@@ -6558,6 +6569,7 @@ tableHeaders:
6558
6569
  endpoints: Endpoints
6559
6570
  expires: Expires
6560
6571
  firstSeen: First Seen
6572
+ firstSeenTooltip: The time at which the event was first recorded
6561
6573
  flow: Flow
6562
6574
  fingerprint: Fingerprint
6563
6575
  gitRepos: Git Repos
@@ -119,7 +119,7 @@ export default {
119
119
 
120
120
  <style lang="scss" scoped>
121
121
  .rancher-icon-fill {
122
- fill: var(--primary);
122
+ fill: var(--link, var(--primary));
123
123
  }
124
124
 
125
125
  .cluster-icon-menu {
@@ -79,7 +79,7 @@ export default {
79
79
 
80
80
  <style lang="scss" scoped>
81
81
  .rancher-icon-fill {
82
- fill: var(--primary);
82
+ fill: var(--link, var(--primary));
83
83
  }
84
84
  .cluster-icon {
85
85
  align-items: center;
@@ -327,7 +327,7 @@ export default {
327
327
 
328
328
  &:focus, &.focus {
329
329
  outline: none;
330
- border-color: var(--outline);
330
+ border-color: var(--primary-border);
331
331
  }
332
332
 
333
333
  .CodeMirror-wrap pre {
@@ -20,6 +20,8 @@ type FilterOption = {
20
20
  componentProps?: Record<string, unknown>;
21
21
  /** Label to show next to the checkbox, or a custom component next to the checkbox */
22
22
  label?: string | { component: ComponentType; componentProps: Record<string, unknown>; };
23
+ /** Tooltip to be displayed above the checkbox on hover */
24
+ labelTooltip?: string;
23
25
  };
24
26
 
25
27
  /**
@@ -97,7 +99,12 @@ const updateFilter = (key: string, value: string[]) => {
97
99
  @update:value="updateFilter(filter.key, $event)"
98
100
  >
99
101
  <template #label>
100
- <span v-if="typeof option.label === 'string'">{{ option.label }}</span>
102
+ <span
103
+ v-if="typeof option.label === 'string'"
104
+ v-clean-tooltip="{content: option.labelTooltip, delay: { show: 1000 }}"
105
+ >
106
+ {{ option.label }}
107
+ </span>
101
108
  <component
102
109
  :is="option.label.component"
103
110
  v-else
@@ -24,12 +24,20 @@ const cssCache = {};
24
24
 
25
25
  const colors = {
26
26
  header: {
27
- color: '--header-btn-text',
28
- hover: '--header-btn-text-hover'
27
+ color: '--on-tertiary-header',
28
+ hover: '--on-tertiary-header-hover',
29
+ colorFallback: '--header-btn-text',
30
+ hoverFallback: '--header-btn-text-hover',
31
+ active: '--on-tertiary-header-hover',
32
+ activeFallback: '--header-btn-text-hover',
29
33
  },
30
34
  primary: {
31
- color: '--link',
32
- hover: '--primary-hover-text'
35
+ color: '--link',
36
+ hover: '--link',
37
+ colorFallback: '--link',
38
+ hoverFallback: '--primary-hover-text',
39
+ active: '--on-active',
40
+ activeFallback: '--primary-hover-text',
33
41
  }
34
42
  };
35
43
 
@@ -65,45 +73,48 @@ export default {
65
73
  },
66
74
 
67
75
  methods: {
68
- getComputedStyleFor(cssVar) {
69
- return normalizeHex(mapStandardColors((window.getComputedStyle(document.body).getPropertyValue(cssVar)).trim()));
76
+ getComputedStyleFor(cssVar, fallback) {
77
+ const value = window.getComputedStyle(document.body).getPropertyValue(cssVar).trim();
78
+
79
+ return normalizeHex(mapStandardColors(value ?? fallback));
80
+ },
81
+
82
+ resolveColorFilter(cacheKey, rgb) {
83
+ if (filterCache[cacheKey]) {
84
+ return filterCache[cacheKey];
85
+ }
86
+
87
+ const solver = new Solver(rgb);
88
+ const res = solver.solve();
89
+ const filter = res?.filter;
90
+
91
+ filterCache[cacheKey] = filter;
92
+
93
+ return filter;
70
94
  },
71
95
 
72
96
  setColor() {
73
- const uiColor = this.getComputedStyleFor(colors[this.color].color);
74
- const hoverColor = this.getComputedStyleFor(colors[this.color].hover);
97
+ const colorConfig = colors[this.color];
98
+ const uiColor = this.getComputedStyleFor(colorConfig.color, colorConfig.colorFallback);
99
+ const hoverColor = this.getComputedStyleFor(colorConfig.hover, colorConfig.hoverFallback);
100
+ const activeColor = this.getComputedStyleFor(colorConfig.active, colorConfig.activeFallback);
75
101
 
76
- if (!uiColor || !hoverColor) {
102
+ if (!uiColor || !hoverColor || !activeColor) {
77
103
  return;
78
104
  }
79
105
 
80
106
  const uiColorRGB = colorToRgb(uiColor);
81
107
  const hoverColorRGB = colorToRgb(hoverColor);
108
+ const activeColorRGB = colorToRgb(activeColor);
82
109
  const uiColorStr = `${ uiColorRGB.r }-${ uiColorRGB.g }-${ uiColorRGB.b }`;
83
110
  const hoverColorStr = `${ hoverColorRGB.r }-${ hoverColorRGB.g }-${ hoverColorRGB.b }`;
84
111
 
85
112
  const className = `svg-icon-${ uiColorStr }-${ hoverColorStr }`;
86
113
 
87
114
  if (!cssCache[className]) {
88
- let hoverFilter = filterCache[hoverColor];
89
-
90
- if (!hoverFilter) {
91
- const solver = new Solver(hoverColorRGB);
92
- const res = solver.solve();
93
-
94
- hoverFilter = res?.filter;
95
- filterCache[hoverColor] = hoverFilter;
96
- }
97
-
98
- let mainFilter = filterCache[uiColor];
99
-
100
- if (!mainFilter) {
101
- const solver = new Solver(uiColorRGB);
102
- const res = solver.solve();
103
-
104
- mainFilter = res?.filter;
105
- filterCache[uiColor] = mainFilter;
106
- }
115
+ const hoverFilter = this.resolveColorFilter(hoverColor, hoverColorRGB);
116
+ const mainFilter = this.resolveColorFilter(uiColor, uiColorRGB);
117
+ const activeFilter = this.resolveColorFilter(activeColor, activeColorRGB);
107
118
 
108
119
  // Add stylesheet (added as global styles)
109
120
  const styles = `
@@ -123,7 +134,7 @@ export default {
123
134
  ${ hoverFilter };
124
135
  }
125
136
  a.option.active-menu-link > img.${ className } {
126
- ${ hoverFilter };
137
+ ${ activeFilter };
127
138
  }
128
139
  `;
129
140
 
@@ -2,6 +2,7 @@
2
2
  import { defineComponent } from 'vue';
3
3
  import ResourceFetch from '@shell/mixins/resource-fetch';
4
4
  import ResourceTable from '@shell/components/ResourceTable.vue';
5
+ import { VuexStore } from '@shell/types/store/vuex';
5
6
 
6
7
  /**
7
8
  * This is meant to enable ResourceList like capabilities outside of List pages / components
@@ -130,13 +131,17 @@ export default defineComponent({
130
131
  safeHeaders(): any[] {
131
132
  const customHeaders: any[] = this.canPaginate ? this.paginationHeaders : this.headers;
132
133
 
133
- return customHeaders || this.$store.getters['type-map/headersFor'](this.schema, this.canPaginate);
134
+ const $store = this.$store as VuexStore;
135
+
136
+ return customHeaders || $store.getters['type-map/headersFor'](this.schema, this.canPaginate);
134
137
  }
135
138
  },
136
139
 
137
140
  methods: {
138
141
  clearSelection() {
139
- this.$refs.table.clearSelection();
142
+ const table = this.$refs.table as { clearSelection: () => void };
143
+
144
+ table.clearSelection();
140
145
  },
141
146
  }
142
147
  });
@@ -384,6 +384,7 @@ export default {
384
384
  >
385
385
  <span
386
386
  v-clean-html="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) }, true)"
387
+ class="confirm-text"
387
388
  />
388
389
  </div>
389
390
  </div>
@@ -472,5 +473,9 @@ export default {
472
473
  flex: 1;
473
474
  }
474
475
  }
476
+
477
+ .confirm-text b {
478
+ user-select: all;
479
+ }
475
480
  }
476
481
  </style>
@@ -181,6 +181,7 @@ export default {
181
181
  if (e.status === 404 || e.status === 403) {
182
182
  store.dispatch('loadingError', new Error(this.t('nav.failWhale.resourceIdNotFound', { resource: resourceType, fqid }, true)));
183
183
  }
184
+ console.debug(`Could not find '${ resourceType }' with id '${ id }''`, e); // eslint-disable-line no-console
184
185
  liveModel = {};
185
186
  notFound = fqid;
186
187
  }
@@ -317,6 +317,7 @@ export default {
317
317
  // add custom table columns provided by the extensions ExtensionPoint.TABLE_COL hook
318
318
  // gate it so that we prevent errors on older versions of dashboard
319
319
  if (this.$store.$plugin?.getUIConfig) {
320
+ // { column: TableColumn, paginationColumn: PaginationTableColumn }[]
320
321
  const extensionCols = getApplicableExtensionEnhancements(this, ExtensionPoint.TABLE_COL, TableColumnLocation.RESOURCE, this.$route);
321
322
 
322
323
  // Try and insert the columns before the Age column
@@ -339,27 +340,36 @@ export default {
339
340
  }
340
341
 
341
342
  // adding extension defined cols to the correct header config
342
- extensionCols.forEach((col) => {
343
- if (this.externalPaginationEnabled) {
344
- // validate that the required settings are supplied to enable search and sort server-side
345
- // these do not check other invalid scenarios like a path is a string but to a model property, or that the field supports sort/search via api (some basic non-breaking checks are done further on)
346
- if (
347
- col.search !== false && // search is explicitly disabled
348
- (typeof col.search !== 'string' && !Array.isArray(col.search)) && // primary property path to search on
349
- typeof col.value !== 'string' // secondary property path to search on
350
- ) {
351
- console.warn(`Unable to support server-side search for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`search\` or \`value\` property containing a path to a property in the resource. search can be an array).`); // eslint-disable-line no-console
352
-
353
- col.search = false;
354
- }
343
+ extensionCols.forEach((config) => {
344
+ let { column: col, paginationColumn } = config;
355
345
 
356
- if (
357
- col.sort !== false && // sort is explicitly disabled
358
- (typeof col.sort !== 'string' && !Array.isArray(col.sort)) // primary property path to sort on
359
- ) {
360
- console.warn(`Unable to support server-side sort for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`sort\` property containing a path to a property, or array of paths, in the resource)`); // eslint-disable-line no-console
361
-
362
- col.sort = false;
346
+ if (this.externalPaginationEnabled) {
347
+ if (paginationColumn) {
348
+ // Use the pagination column, no need to
349
+ col = paginationColumn;
350
+ } else {
351
+ // Attempt to fall back on the single column
352
+
353
+ // validate that the required settings are supplied to enable search and sort server-side
354
+ // these do not check other invalid scenarios like a path is a string but to a model property, or that the field supports sort/search via api (some basic non-breaking checks are done further on)
355
+ if (
356
+ col.search !== false && // search is explicitly disabled
357
+ (typeof col.search !== 'string' && !Array.isArray(col.search)) && // primary property path to search on
358
+ typeof col.value !== 'string' // secondary property path to search on
359
+ ) {
360
+ console.warn(`Unable to support server-side search for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`search\` or \`value\` property containing a path to a property in the resource. search can be an array).`); // eslint-disable-line no-console
361
+
362
+ col.search = false;
363
+ }
364
+
365
+ if (
366
+ col.sort !== false && // sort is explicitly disabled
367
+ (typeof col.sort !== 'string' && !Array.isArray(col.sort)) // primary property path to sort on
368
+ ) {
369
+ console.warn(`Unable to support server-side sort for extension provided column "${ col.name || col.label || col.labelKey }" (column must provide \`sort\` property containing a path to a property, or array of paths, in the resource)`); // eslint-disable-line no-console
370
+
371
+ col.sort = false;
372
+ }
363
373
  }
364
374
  }
365
375
 
@@ -68,6 +68,7 @@ export default {
68
68
 
69
69
  data() {
70
70
  let sortBy = null;
71
+ let descending = false;
71
72
 
72
73
  this._defaultSortBy = this.defaultSortBy;
73
74
 
@@ -78,6 +79,7 @@ export default {
78
79
 
79
80
  if ( markedColumn ) {
80
81
  this._defaultSortBy = markedColumn.name;
82
+ descending = markedColumn.defaultSortDescending;
81
83
  } else if ( nameColumn ) {
82
84
  // Use the name column if there is one
83
85
  this._defaultSortBy = nameColumn.name;
@@ -101,7 +103,7 @@ export default {
101
103
 
102
104
  return {
103
105
  sortBy,
104
- descending: false,
106
+ descending,
105
107
  cachedRows: null,
106
108
  cacheKey: null,
107
109
  };
@@ -412,7 +412,7 @@ export default {
412
412
  }
413
413
 
414
414
  .tab.active {
415
- border-bottom: solid 2px var(--primary);
415
+ border-bottom: solid 2px var(--active, var(--primary));
416
416
  }
417
417
  }
418
418
 
@@ -450,7 +450,7 @@ export default {
450
450
 
451
451
  &.active {
452
452
  > A {
453
- color: var(--primary);
453
+ color: var(--active, var(--primary));
454
454
  text-decoration: none;
455
455
  }
456
456
  }
@@ -530,16 +530,16 @@ export default {
530
530
  border-left: solid 5px transparent;
531
531
 
532
532
  &.toggle A {
533
- color: var(--primary);
533
+ color: var(--active, var(--primary));
534
534
  }
535
535
 
536
536
  A {
537
- color: var(--primary);
537
+ color: var(--link, var(--primary));
538
538
  }
539
539
 
540
540
  &.active {
541
541
  background-color: var(--body-bg);
542
- border-left: solid 5px var(--primary);
542
+ border-left: solid 5px var(--active, var(--primary));
543
543
 
544
544
  & A {
545
545
  color: var(--input-label);
@@ -7,14 +7,14 @@ import Tabbed from '@shell/components/Tabbed';
7
7
  import Tab from '@shell/components/Tabbed/Tab';
8
8
  import CreateEditView from '@shell/mixins/create-edit-view';
9
9
  import Conditions from '@shell/components/form/Conditions';
10
- import { EVENT } from '@shell/config/types';
10
+ import { EVENT, NAMESPACE } from '@shell/config/types';
11
11
  import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
12
12
  import { _VIEW } from '@shell/config/query-params';
13
13
  import RelatedResources from '@shell/components/RelatedResources';
14
14
  import { isConditionReadyAndWaiting } from '@shell/plugins/dashboard-store/resource-class';
15
15
  import { PaginationParamFilter } from '@shell/types/store/pagination.types';
16
16
  import { MESSAGE, REASON } from '@shell/config/table-headers';
17
- import { STEVE_EVENT_LAST_SEEN, STEVE_EVENT_TYPE, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
17
+ import { STEVE_EVENT_FIRST_SEEN, STEVE_EVENT_LAST_SEEN, STEVE_EVENT_TYPE, STEVE_NAME_COL } from '@shell/config/pagination-table-headers';
18
18
  import { headerFromSchemaColString } from '@shell/store/type-map.utils';
19
19
  import { useIndicateUseCounts } from '@shell/components/form/ResourceTabs/composable';
20
20
 
@@ -93,7 +93,7 @@ export default {
93
93
  headerFromSchemaColString('Subobject', eventSchema, this.$store.getters, true),
94
94
  headerFromSchemaColString('Source', eventSchema, this.$store.getters, true),
95
95
  MESSAGE,
96
- headerFromSchemaColString('First Seen', eventSchema, this.$store.getters, true),
96
+ STEVE_EVENT_FIRST_SEEN,
97
97
  headerFromSchemaColString('Count', eventSchema, this.$store.getters, true),
98
98
  STEVE_NAME_COL,
99
99
  ] : [];
@@ -119,6 +119,9 @@ export default {
119
119
  },
120
120
 
121
121
  computed: {
122
+ isNamespace() {
123
+ return this.value?.type === NAMESPACE;
124
+ },
122
125
  showEvents() {
123
126
  return this.isView && this.needEvents && this.eventSchema;
124
127
  },
@@ -190,7 +193,9 @@ export default {
190
193
  * Filter out hidden repos from list of all repos
191
194
  */
192
195
  filterEventsLocal(rows) {
193
- return rows.filter((event) => event.involvedObject?.uid === this.value?.metadata?.uid);
196
+ return rows.filter((event) => {
197
+ return this.isNamespace ? event.metadata?.namespace === this.value?.metadata?.name : event.involvedObject?.uid === this.value?.metadata?.uid;
198
+ });
194
199
  },
195
200
 
196
201
  /**
@@ -204,27 +209,22 @@ export default {
204
209
  pagination.filters = [];
205
210
  }
206
211
 
207
- const field = `involvedObject.uid`;
208
-
209
- // of type PaginationParamFilter
210
- let existing = null;
211
-
212
- for (let i = 0; i < pagination.filters.length; i++) {
213
- const filter = pagination.filters[i];
212
+ // Determine the field and value based on type
213
+ const field = this.isNamespace ? 'metadata.namespace' : 'involvedObject.uid';
214
+ const value = this.isNamespace ? this.value.metadata.name : this.value.metadata.uid;
214
215
 
215
- if (!!filter.fields.find((f) => f.field === field)) {
216
- existing = filter;
217
- break;
218
- }
219
- }
216
+ // Check if a filter for this field already exists
217
+ const existing = pagination.filters.find((f) => f.fields.some((ff) => ff.field === field));
220
218
 
219
+ // Create the required filter
221
220
  const required = PaginationParamFilter.createSingleField({
222
221
  field,
223
222
  exact: true,
224
- value: this.value.metadata.uid,
223
+ value,
225
224
  equals: true
226
225
  });
227
226
 
227
+ // Merge or add the filter
228
228
  if (!!existing) {
229
229
  Object.assign(existing, required);
230
230
  } else {
@@ -260,10 +260,16 @@ export default {
260
260
 
261
261
  <Tab
262
262
  v-if="showEvents"
263
- label-key="resourceTabs.events.tab"
263
+ :label="isNamespace ? t('resourceTabs.events.namespaceTab') : t('resourceTabs.events.tab')"
264
264
  name="events"
265
265
  :weight="-2"
266
266
  >
267
+ <!-- Caption for namespace pages -->
268
+ <div
269
+ v-if="isNamespace"
270
+ v-clean-html="t('resourceTabs.events.namespaceCaption', { namespace: value.metadata.name }, true)"
271
+ class="tab-caption"
272
+ />
267
273
  <!-- namespaced: false given we don't want the default handling of namespaced resource (apply header filter) -->
268
274
  <PaginatedResourceTable
269
275
  :schema="eventSchema"
@@ -318,4 +324,17 @@ export default {
318
324
  }
319
325
  }
320
326
  }
327
+ /* Caption for namespace events tab */
328
+ .tab-caption {
329
+ align-items: center;
330
+ font-size: 16px;
331
+ margin-bottom: 24px;
332
+
333
+ .namespace-name {
334
+ display: inline;
335
+ font-weight: bold;
336
+ margin-right: 0 4px;
337
+ white-space: nowrap;
338
+ }
339
+ }
321
340
  </style>
@@ -61,7 +61,7 @@ export default {
61
61
  },
62
62
  inStore: {
63
63
  type: String,
64
- default: 'cluster',
64
+ default: undefined,
65
65
  }
66
66
  },
67
67
 
@@ -129,6 +129,10 @@ export default {
129
129
  }));
130
130
  },
131
131
 
132
+ validInStore() {
133
+ return this.inStore || this.$store.getters['currentStore']() || 'cluster';
134
+ },
135
+
132
136
  isView() {
133
137
  return this.mode === _VIEW;
134
138
  },
@@ -221,7 +225,7 @@ export default {
221
225
  :label="secretNameLabel"
222
226
  :mode="mode"
223
227
  :resource-type="SECRET"
224
- :in-store="inStore"
228
+ :in-store="validInStore"
225
229
  :paginated-resource-settings="paginateSecretsSetting"
226
230
  :all-resources-settings="allSecretsSettings"
227
231
  />