@rancher/shell 3.0.5 → 3.0.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.
@@ -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
@@ -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>
@@ -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
 
@@ -294,7 +294,7 @@ export function init(store) {
294
294
  STEVE_NAMESPACE_COL,
295
295
  {
296
296
  ...INGRESS_TARGET,
297
- sort: 'spec.rules[0].host', // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
297
+ sort: 'spec.rules[0].host',
298
298
  search: false, // This is broken in normal world, so disable here
299
299
  },
300
300
  {
@@ -359,10 +359,10 @@ export function init(store) {
359
359
  STEVE_STATE_COL,
360
360
  STEVE_NAME_COL,
361
361
  STEVE_NAMESPACE_COL,
362
- HPA_REFERENCE, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
363
- MIN_REPLICA, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
364
- MAX_REPLICA, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
365
- CURRENT_REPLICA, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
362
+ HPA_REFERENCE,
363
+ MIN_REPLICA,
364
+ MAX_REPLICA,
365
+ CURRENT_REPLICA,
366
366
  STEVE_AGE_COL
367
367
  ]
368
368
  );
@@ -107,7 +107,7 @@ export function uiPluginAnnotation(chart, name) {
107
107
  /**
108
108
  * Parse the Rancher version string
109
109
  */
110
- function parseRancherVersion(v) {
110
+ export function parseRancherVersion(v) {
111
111
  let parsedVersion = semver.coerce(v)?.version;
112
112
  const splitArr = parsedVersion?.split('.');
113
113
 
package/core/plugin.ts CHANGED
@@ -16,6 +16,7 @@ import {
16
16
  ModelExtensionConstructor,
17
17
  PluginRouteRecordRaw, RegisterStore, UnregisterStore, CoreStoreSpecifics, CoreStoreConfig,
18
18
  NavHooks, OnNavToPackage, OnNavAwayFromPackage, OnLogIn, OnLogOut,
19
+ PaginationTableColumn,
19
20
  ExtensionEnvironment
20
21
  } from './types';
21
22
  import coreStore, { coreStoreModule, coreStoreState } from '@shell/plugins/dashboard-store';
@@ -247,10 +248,21 @@ export class Plugin implements IPlugin {
247
248
  }
248
249
 
249
250
  /**
250
- * Adds a new column to a table on the UI
251
+ * Adds a new column to a ResourceTable
252
+ *
253
+ * @param where
254
+ * @param when
255
+ * @param action
256
+ * @param column
257
+ * The information required to show a header and values for a column in a table
258
+ * @param paginationColumn
259
+ * As per `column`, but is used where server-side pagination is enabled
251
260
  */
252
- addTableColumn(where: string, when: LocationConfig | string, column: TableColumn): void {
253
- this._addUIConfig(ExtensionPoint.TABLE_COL, where, when, column);
261
+ addTableColumn(where: string, when: LocationConfig | string, column: TableColumn, paginationColumn?: PaginationTableColumn): void {
262
+ this._addUIConfig(ExtensionPoint.TABLE_COL, where, when, {
263
+ column,
264
+ paginationColumn
265
+ });
254
266
  }
255
267
 
256
268
  setHomePage(component: any) {
package/core/types.ts CHANGED
@@ -130,9 +130,6 @@ export type Card = {
130
130
  component: Function;
131
131
  };
132
132
 
133
- // Duplication of HeaderOptions?
134
- export type TableColumn = any;
135
-
136
133
  /** Definition of a tab (options that can be passed when defining an extension tab enhancement) */
137
134
  export type Tab = {
138
135
  name: string;
@@ -281,6 +278,9 @@ export interface ProductOptions {
281
278
  // typeStoreMap: string;
282
279
  }
283
280
 
281
+ /**
282
+ * Configuration required to show a header in a ResourceTable
283
+ */
284
284
  export interface HeaderOptions {
285
285
  /**
286
286
  * Name of the header. This should be unique.
@@ -305,7 +305,7 @@ export interface HeaderOptions {
305
305
  /**
306
306
  * A string which represents the path to access the value from the row object which we'll use to sort i.e. `row.meta.value`
307
307
  */
308
- sort?: string | string[];
308
+ sort?: string | string[] | boolean;
309
309
 
310
310
  /**
311
311
  * A string which represents the path to access the value from the row object which we'll use to search i.e. `row.meta.value`.
@@ -336,6 +336,21 @@ export interface HeaderOptions {
336
336
  getValue?: (row: any) => string | number | null | undefined;
337
337
  }
338
338
 
339
+ /**
340
+ * Configuration required to show a header in a ResourceTable when server-side pagination is enable
341
+ */
342
+ export type PaginationHeaderOptions = Omit<HeaderOptions, 'getValue'>
343
+
344
+ /**
345
+ * External extension configuration for @HeaderOptions
346
+ */
347
+ export type TableColumn = HeaderOptions;
348
+
349
+ /**
350
+ * External extension configuration for @PaginationHeaderOptions
351
+ */
352
+ export type PaginationTableColumn = PaginationHeaderOptions;
353
+
339
354
  export interface ConfigureTypeOptions {
340
355
  /**
341
356
  * Override for the create button string on a list view
@@ -621,9 +636,17 @@ export interface IPlugin {
621
636
  addCard(where: CardLocation | string, when: LocationConfig | string, action: Card): void;
622
637
 
623
638
  /**
624
- * Adds a new column to the SortableTable component
625
- */
626
- addTableColumn(where: TableColumnLocation | string, when: LocationConfig | string, action: TableColumn): void;
639
+ * Adds a new column to a ResourceTable
640
+ *
641
+ * @param where
642
+ * @param when
643
+ * @param action
644
+ * @param column
645
+ * The information required to show a header and values for a column in a table
646
+ * @param paginationColumn
647
+ * As per `column`, but is used where server-side pagination is enabled
648
+ */
649
+ addTableColumn(where: TableColumnLocation | string, when: LocationConfig | string, column: TableColumn, paginationColumn?: TableColumn): void;
627
650
 
628
651
  /**
629
652
  * Set the component to use for the landing home page
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import PaginatedResourceTable from '@shell/components/PaginatedResourceTable.vue';
3
3
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
4
- import ClusterRepo from '@shell/models/catalog.cattle.io.clusterrepo';
4
+ import { RancherKubeMetadata } from '@shell/types/kube/kube-api';
5
5
  import { PaginationArgs, PaginationParamFilter } from '@shell/types/store/pagination.types';
6
6
  import { defineComponent } from 'vue';
7
7
 
@@ -25,7 +25,7 @@ export default defineComponent({
25
25
  /**
26
26
  * Filter out hidden repos from list of all repos
27
27
  */
28
- filterRowsLocal(rows: ClusterRepo[]) {
28
+ filterRowsLocal(rows: { metadata: RancherKubeMetadata}[]) {
29
29
  return rows.filter((repo) => !(repo?.metadata?.annotations?.[CATALOG_ANNOTATIONS.HIDDEN_REPO] === 'true'));
30
30
  },
31
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.5",
3
+ "version": "3.0.6",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -93,7 +93,7 @@
93
93
  "express": "4.17.1",
94
94
  "file-saver": "2.0.2",
95
95
  "floating-vue": "5.2.2",
96
- "focus-trap": "7.6.2",
96
+ "focus-trap": "7.6.5",
97
97
  "frontmatter-markdown-loader": "3.7.0",
98
98
  "identicon.js": "2.3.3",
99
99
  "intl-messageformat": "7.8.4",
@@ -80,6 +80,12 @@ function onClickItem(type: string, label: string) {
80
80
  &-text {
81
81
  text-transform: capitalize;
82
82
  margin-right: 8px;
83
+ display: -webkit-box;
84
+ -webkit-line-clamp: 1;
85
+ -webkit-box-orient: vertical;
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ word-break: break-all;
83
89
  }
84
90
 
85
91
  &-icon {
@@ -2,9 +2,9 @@
2
2
 
3
3
  defineProps<{
4
4
  label: string;
5
- icon: string;
5
+ icon?: string;
6
6
  iconColor?: string;
7
- tooltip?: string;
7
+ iconTooltip?: string;
8
8
  }>();
9
9
 
10
10
  </script>
@@ -13,7 +13,8 @@ defineProps<{
13
13
  <div class="status-label">
14
14
  {{ label }}
15
15
  <i
16
- v-clean-tooltip.right="tooltip"
16
+ v-if="!!icon"
17
+ v-clean-tooltip.right="iconTooltip"
17
18
  :class="['icon', icon, iconColor]"
18
19
  />
19
20
  </div>
@@ -82,10 +82,10 @@ export default {
82
82
  label: {
83
83
  component: markRaw(StatusLabel),
84
84
  componentProps: {
85
- label: this.t('generic.installed'),
86
- icon: 'icon-warning',
87
- iconColor: 'warning',
88
- tooltip: this.t('catalog.charts.statusFilterCautions.installation')
85
+ label: this.t('generic.installed'),
86
+ icon: 'icon-warning',
87
+ iconColor: 'warning',
88
+ iconTooltip: this.t('catalog.charts.statusFilterCautions.installation')
89
89
  }
90
90
  }
91
91
  },
@@ -98,10 +98,10 @@ export default {
98
98
  label: {
99
99
  component: markRaw(StatusLabel),
100
100
  componentProps: {
101
- label: this.t('generic.upgradeable'),
102
- icon: 'icon-warning',
103
- iconColor: 'warning',
104
- tooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
101
+ label: this.t('generic.upgradeable'),
102
+ icon: 'icon-warning',
103
+ iconColor: 'warning',
104
+ iconTooltip: this.t('catalog.charts.statusFilterCautions.upgradeable')
105
105
  }
106
106
  }
107
107
  }
@@ -125,9 +125,10 @@ export default {
125
125
  repoOptions() {
126
126
  let out = this.$store.getters['catalog/repos'].map((r) => {
127
127
  return {
128
- value: r._key,
129
- label: r.nameDisplay,
130
- weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
128
+ value: r._key,
129
+ label: r.nameDisplay,
130
+ labelTooltip: r.nameDisplay,
131
+ weight: ( r.isRancher ? 1 : ( r.isPartner ? 2 : 3 ) ),
131
132
  };
132
133
  });
133
134
 
@@ -1,4 +1,7 @@
1
1
  import { NORMAN_NAME } from '@shell/config/labels-annotations';
2
+ import { getVersionData } from '@shell/config/version';
3
+ import { parseRancherVersion } from '@shell/config/uiplugins';
4
+ import semver from 'semver';
2
5
  import {
3
6
  _CLONE,
4
7
  _CONFIG,
@@ -929,12 +932,20 @@ export default class Resource {
929
932
  const currentRoute = this.currentRouter().currentRoute.value;
930
933
  const extensionMenuActions = getApplicableExtensionEnhancements(this.$rootState, ExtensionPoint.ACTION, ActionLocation.TABLE, currentRoute, this);
931
934
 
935
+ const currRancherVersionData = getVersionData();
936
+ const parsedRancherVersion = parseRancherVersion(currRancherVersionData.Version);
937
+
938
+ // "showConfiguration" table action is only compatible with Rancher 2.13 and onwards
939
+ // defence against extension issue https://github.com/rancher/dashboard/issues/15564
940
+ // where mostly likely extension CRD model is extending from resource-class
941
+ const isResourceDetailDrawerCompatibleWithRancherSystem = semver.satisfies(parsedRancherVersion, '>= 2.13.0');
942
+
932
943
  const all = [
933
944
  {
934
945
  action: 'showConfiguration',
935
946
  label: this.t('action.showConfiguration'),
936
947
  icon: 'icon icon-document',
937
- enabled: this.disableResourceDetailDrawer !== true && (this.canCustomEdit || this.canYaml), // If the resource can't show an edit or a yaml we don't want to show the configuration drawer
948
+ enabled: isResourceDetailDrawerCompatibleWithRancherSystem && this.disableResourceDetailDrawer !== true && (this.canCustomEdit || this.canYaml), // If the resource can't show an edit or a yaml we don't want to show the configuration drawer
938
949
  },
939
950
  { divider: true },
940
951
  {
@@ -15,9 +15,7 @@ import {
15
15
  HPA,
16
16
  SECRET
17
17
  } from '@shell/config/types';
18
- import {
19
- CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY
20
- } from '@shell/config/labels-annotations';
18
+ import { CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
21
19
  import { Schema } from '@shell/plugins/steve/schema';
22
20
  import { PaginationSettingsStore } from '@shell/types/resources/settings';
23
21
  import paginationUtils from '@shell/utils/pagination-utils';
@@ -158,6 +156,7 @@ class StevePaginationUtils extends NamespaceProjectFilters {
158
156
  { field: 'id' },
159
157
  { field: 'metadata.state.name' },
160
158
  { field: 'metadata.creationTimestamp' },
159
+ { field: 'metadata.labels', startsWith: true },
161
160
  ],
162
161
  [NODE]: [
163
162
  { field: 'status.nodeInfo.kubeletVersion' },
@@ -180,18 +179,12 @@ class StevePaginationUtils extends NamespaceProjectFilters {
180
179
  { field: 'spec.internal' },
181
180
  { field: 'spec.displayName' },
182
181
  { field: `status.provider` },
183
- { field: `metadata.labels["${ CAPI_LAB_AND_ANO.PROVIDER }]` },
184
182
  { field: `status.connected` },
185
183
  ],
186
- [CONFIG_MAP]: [
187
- { field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
188
- ],
189
184
  [SECRET]: [
190
- { field: `metadata.labels[${ UI_PROJECT_SECRET }]` },
191
185
  { field: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]` },
192
186
  ],
193
187
  [NAMESPACE]: [
194
- { field: 'metadata.labels[field.cattle.io/projectId]' }
195
188
  ],
196
189
  [CAPI.MACHINE]: [
197
190
  { field: 'spec.clusterName' }
@@ -214,7 +207,6 @@ class StevePaginationUtils extends NamespaceProjectFilters {
214
207
  { field: 'status.releaseName' },
215
208
  ],
216
209
  [CAPI.RANCHER_CLUSTER]: [
217
- { field: `metadata.labels[${ CAPI_LAB_AND_ANO.PROVIDER }]` },
218
210
  { field: `status.provider` },
219
211
  { field: 'status.clusterName' },
220
212
  { field: `metadata.annotations[${ CAPI_LAB_AND_ANO.HUMAN_NAME }]` }
@@ -224,14 +216,14 @@ class StevePaginationUtils extends NamespaceProjectFilters {
224
216
  { field: 'spec.clusterIP' },
225
217
  ],
226
218
  [INGRESS]: [
227
- { field: 'spec.rules.host' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
219
+ { field: 'spec.rules.host' },
228
220
  { field: 'spec.ingressClassName' },
229
221
  ],
230
222
  [HPA]: [
231
- { field: 'spec.scaleTargetRef.name' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
232
- { field: 'spec.minReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
233
- { field: 'spec.maxReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
234
- { field: 'spec.currentReplicas' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50527
223
+ { field: 'spec.scaleTargetRef.name' },
224
+ { field: 'spec.minReplicas' },
225
+ { field: 'spec.maxReplicas' },
226
+ { field: 'spec.currentReplicas' },
235
227
  ],
236
228
  [PVC]: [
237
229
  { field: 'spec.volumeName' },
@@ -249,29 +241,29 @@ class StevePaginationUtils extends NamespaceProjectFilters {
249
241
  ],
250
242
  [WORKLOAD_TYPES.CRON_JOB]: [
251
243
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
252
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
244
+ { field: 'spec.template.spec.containers.image' },
253
245
  ],
254
246
  [WORKLOAD_TYPES.DAEMON_SET]: [
255
247
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
256
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
248
+ { field: 'spec.template.spec.containers.image' },
257
249
  ],
258
250
  [WORKLOAD_TYPES.DEPLOYMENT]: [
259
251
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
260
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
252
+ { field: 'spec.template.spec.containers.image' },
261
253
  ],
262
254
  [WORKLOAD_TYPES.JOB]: [
263
255
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
264
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
256
+ { field: 'spec.template.spec.containers.image' },
265
257
  ],
266
258
  [WORKLOAD_TYPES.STATEFUL_SET]: [
267
259
  { field: `metadata.annotations[${ CATTLE_PUBLIC_ENDPOINTS }]` },
268
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
260
+ { field: 'spec.template.spec.containers.image' },
269
261
  ],
270
262
  [WORKLOAD_TYPES.REPLICA_SET]: [
271
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
263
+ { field: 'spec.template.spec.containers.image' },
272
264
  ],
273
265
  [WORKLOAD_TYPES.REPLICATION_CONTROLLER]: [
274
- { field: 'spec.template.spec.containers.image' }, // Pending API Support - BUG - https://github.com/rancher/rancher/issues/50526
266
+ { field: 'spec.template.spec.containers.image' },
275
267
  ],
276
268
  }
277
269
 
@@ -98,12 +98,11 @@ createTestComponent() {
98
98
  # Add test list component to the test package
99
99
  # Validates rancher-components imports
100
100
 
101
- # NOTE - This fails if importing some components with TS imports...
102
- # cp ${SHELL_DIR}/list/catalog.cattle.io.clusterrepo.vue pkg/test-pkg/list
103
- # See https://github.com/rancher/dashboard/issues/12918
104
-
105
- # Use a basic list instead
101
+ # Basic list instead
106
102
  cp ${SHELL_DIR}/list/namespace.vue pkg/test-pkg/list
103
+
104
+ # More complex list
105
+ cp ${SHELL_DIR}/list/catalog.cattle.io.clusterrepo.vue pkg/test-pkg/list
107
106
  }
108
107
 
109
108
  # Publish shell pkg (tag is needed as publish-shell is optimized to work with release-shell-pkg workflow)
@@ -39,6 +39,8 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/steve/hybrid-class.js --d
39
39
  # # mixins
40
40
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/create-edit-view/index.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins/create-edit-view > /dev/null
41
41
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
42
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch-namespaced.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
43
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/mixins/resource-fetch-api-pagination.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/mixins > /dev/null
42
44
 
43
45
  # # models
44
46
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/models/namespace.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/models/ > /dev/null
package/store/auth.js CHANGED
@@ -207,7 +207,7 @@ export const actions = {
207
207
 
208
208
  commit('cookies/set', {
209
209
  key: KEY, value: strung, options
210
- });
210
+ }, { root: true });
211
211
 
212
212
  return strung;
213
213
  },
@@ -371,7 +371,7 @@ export const actions = {
371
371
  loggedInAs({ commit }, principalId) {
372
372
  commit('loggedInAs', principalId);
373
373
 
374
- commit('cookies/remove', { key: KEY });
374
+ commit('cookies/remove', { key: KEY }, { root: true });
375
375
  },
376
376
 
377
377
  uiLogout({ commit, dispatch }) {
@@ -2323,6 +2323,18 @@ export function setKubeVersionData(v: any): void;
2323
2323
  export const CURRENT_RANCHER_VERSION: "2.12";
2324
2324
  }
2325
2325
 
2326
+ // @shell/mixins/components/ResourceList/resource-list.config
2327
+
2328
+ declare module '@shell/mixins/components/ResourceList/resource-list.config' {
2329
+ /**
2330
+ * Component name of the `ResourceList`
2331
+ *
2332
+ * This needs to be a in separate file to avoid circular dependency of
2333
+ * index.vue --> resource-fetch mixin --> resource-fetch-namespaced mixin --> index.vue
2334
+ */
2335
+ export const ResourceListComponentName: "ResourceList";
2336
+ }
2337
+
2326
2338
  // @shell/mixins/create-edit-view/impl
2327
2339
 
2328
2340
  declare module '@shell/mixins/create-edit-view/impl' {
@@ -2468,6 +2480,175 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
2468
2480
  export default _default;
2469
2481
  }
2470
2482
 
2483
+ // @shell/mixins/mixins/resource-fetch-api-pagination
2484
+
2485
+ declare module '@shell/mixins/mixins/resource-fetch-api-pagination' {
2486
+ declare namespace _default {
2487
+ namespace props {
2488
+ namespace namespaced {
2489
+ export let type: BooleanConstructor;
2490
+ let _default: any;
2491
+ export { _default as default };
2492
+ }
2493
+ namespace context {
2494
+ let type_1: StringConstructor;
2495
+ export { type_1 as type };
2496
+ let _default_1: any;
2497
+ export { _default_1 as default };
2498
+ }
2499
+ }
2500
+ function data(): {
2501
+ forceUpdateLiveAndDelayed: number;
2502
+ /**
2503
+ * This of type `OptPagination`
2504
+ */
2505
+ pPagination: any;
2506
+ debouncedSetPagination: any;
2507
+ /**
2508
+ * Apply these additional filters given the ns / project header selection
2509
+ */
2510
+ requestFilters: {
2511
+ filters: any[];
2512
+ projectsOrNamespaces: any[];
2513
+ };
2514
+ paginationFromList: any;
2515
+ isPaginationManualRefreshEnabled: any;
2516
+ };
2517
+ namespace methods {
2518
+ /**
2519
+ * @param {PaginationArgs} pagination
2520
+ */
2521
+ function setPagination(pagination: PaginationArgs): void;
2522
+ /**
2523
+ * Primary point that handles changes from either a table or the namespace filter
2524
+ */
2525
+ function paginationChanged(event: any): void;
2526
+ /**
2527
+ * @param {PaginationArgs} neu
2528
+ * @param {PaginationArgs} old
2529
+ */
2530
+ function paginationEqual(neu: PaginationArgs, old: PaginationArgs): boolean;
2531
+ function calcCanPaginate(): any;
2532
+ }
2533
+ namespace computed {
2534
+ /**
2535
+ * Why is this a specific getter and not not in mapGetters?
2536
+ *
2537
+ * Adding it to mapGetters means the kubewarden unit tests fail as they don't mock it....
2538
+ */
2539
+ function namespaceFilters(): any;
2540
+ /**
2541
+ * Does the user need to update the filter to supply valid options?
2542
+ */
2543
+ function paginationNsFilterRequired(): boolean;
2544
+ /**
2545
+ * Check if the Project/Namespace filter from the header contains a valid ns / project filter
2546
+ */
2547
+ function __validPaginationNsFilter(): any;
2548
+ /**
2549
+ * ResourceList imports resource-fetch --> this mixin
2550
+ * When there is no custom list this is fine (ResourceList with mixins --> ResourceTable)
2551
+ * When there is a custom list there are two instances of this mixin (ResourceList with mixins --> CustomList with mixins --> ResourceTable)
2552
+ * - In this scenario, reduce churn by exiting earlier if mixin is from parent ResourceList and leave work for CustomList mixins
2553
+ */
2554
+ function isResourceList(): any;
2555
+ /**
2556
+ * Is Pagination supported and has the table supplied pagination settings from the table?
2557
+ */
2558
+ function pagination(): any;
2559
+ /**
2560
+ * Should this list be paginated via API?
2561
+ */
2562
+ function canPaginate(): any;
2563
+ function paginationResult(): any;
2564
+ function havePaginated(): any;
2565
+ /**
2566
+ * Links to ns.isSystem and covers things like ns with system annotation, hardcoded list, etc
2567
+ */
2568
+ function productHidesSystemNamespaces(): any;
2569
+ /**
2570
+ * Links to ns.isObscure and covers things like `c-`, `user-`, etc (see OBSCURE_NAMESPACE_PREFIX)
2571
+ */
2572
+ function showDynamicRancherNamespaces(): any;
2573
+ function isNamespaced(): any;
2574
+ let currentProduct: import("vuex").Computed;
2575
+ let isAllNamespaces: import("vuex").Computed;
2576
+ }
2577
+ let watch: {
2578
+ /**
2579
+ * Monitor the rows to ensure deleting the last entry in a server-side paginated page doesn't
2580
+ * result in an empty page
2581
+ */
2582
+ rows(neu: any): void;
2583
+ namespaceFilters: {
2584
+ immediate: boolean;
2585
+ handler(neu: any, old: any): Promise<void>;
2586
+ };
2587
+ 'requestFilters.filters'(): void;
2588
+ 'requestFilters.projectsOrNamespaces'(): void;
2589
+ /**
2590
+ * When a pagination is required and the user changes page / sort / filter, kick off a new set of API requests
2591
+ *
2592
+ * @param {StorePaginationResult} neu
2593
+ * @param {StorePaginationResult} old
2594
+ */
2595
+ pagination(neu: StorePaginationResult, old: StorePaginationResult): Promise<void>;
2596
+ /**
2597
+ * If the pagination result has changed fetch secondary resources
2598
+ *
2599
+ * Lists should implement fetchPageSecondaryResources to fetch them
2600
+ *
2601
+ * @param {StorePaginationResult} neu
2602
+ * @param {StorePaginationResult} old
2603
+ */
2604
+ paginationResult(neu: StorePaginationResult, old: StorePaginationResult): Promise<void>;
2605
+ };
2606
+ function beforeUnmount(): Promise<void>;
2607
+ }
2608
+ export default _default;
2609
+ }
2610
+
2611
+ // @shell/mixins/mixins/resource-fetch-namespaced
2612
+
2613
+ declare module '@shell/mixins/mixins/resource-fetch-namespaced' {
2614
+ declare namespace _default {
2615
+ function data(): {
2616
+ forceUpdateLiveAndDelayed: number;
2617
+ };
2618
+ namespace computed {
2619
+ /**
2620
+ * Does the user need to update the filter to supply a single namespace?
2621
+ */
2622
+ function namespaceFilterRequired(): boolean;
2623
+ /**
2624
+ * Returns the namespace that requests should be filtered by
2625
+ */
2626
+ function namespaceFilter(): "" | (() => import("vuex").Computed);
2627
+ /**
2628
+ * If the Project/Namespace filter from the header contains a valid ns / project filter ... return it
2629
+ */
2630
+ function __validFilter(): import("vuex").Computed;
2631
+ /**
2632
+ * Do we need to filter the list by a namespace? This will control whether the user is shown an error
2633
+ *
2634
+ * We shouldn't show an error on pages with resources that aren't namespaced
2635
+ */
2636
+ function __namespaceRequired(): false | (() => any);
2637
+ /**
2638
+ * Are all core list resources namespaced?
2639
+ */
2640
+ function __areResourcesNamespaced(): any;
2641
+ let currentProduct: import("vuex").Computed;
2642
+ let currentCluster: import("vuex").Computed;
2643
+ let namespaceFilters: import("vuex").Computed;
2644
+ }
2645
+ namespace watch {
2646
+ function namespaceFilter(neu: any): Promise<void>;
2647
+ }
2648
+ }
2649
+ export default _default;
2650
+ }
2651
+
2471
2652
  // @shell/mixins/resource-fetch
2472
2653
 
2473
2654
  declare module '@shell/mixins/resource-fetch' {
@@ -10,7 +10,8 @@ export interface VuexStoreGetters {
10
10
 
11
11
  export interface VuexStore {
12
12
  getters: VuexStoreGetters,
13
- dispatch: any,
13
+ dispatch: <T = any>(action: string, payload?: any) => Promise<T>,
14
+ commit: (mutation: string, payload?: any) => void,
14
15
 
15
16
  // When we have exact properties above we can remove below
16
17
  [name:string]: any
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable */
2
2
  import type ShellApi from '@shell/plugins/internal-api/shell/shell.api';
3
+ import { VuexStore } from '@shell/types/store/vuex';
3
4
 
4
5
  export {};
5
6
 
@@ -13,11 +14,7 @@ declare module 'vue' {
13
14
  (key: string, args?: Record<string, any>, raw?: boolean): string;
14
15
  (options: { k: string; raw?: boolean; tag?: string | Record<string, any>; escapehtml?: boolean }): string;
15
16
  },
16
- $store: {
17
- getters: Record<string, any>,
18
- dispatch: (action: string, payload?: any) => Promise<any>,
19
- commit: (mutation: string, payload?: any) => void,
20
- },
17
+ $store: VuexStore,
21
18
  $shell: ShellApi,
22
19
  }
23
20
  }
@@ -16,6 +16,7 @@ import { STEVE_CACHE } from '@shell/store/features';
16
16
  import { getPerformanceSetting } from '@shell/utils/settings';
17
17
  import { PAGINATION_SETTINGS_STORE_DEFAULTS } from '@shell/plugins/steve/steve-pagination-utils';
18
18
  import { MANAGEMENT } from '@shell/config/types';
19
+ import { DEFAULT_PERF_SETTING } from '@shell/config/settings';
19
20
 
20
21
  /**
21
22
  * Helper functions for server side pagination
@@ -43,7 +44,15 @@ class PaginationUtils {
43
44
  public getStoreSettings(arg: any | PaginationSettings): PaginationSettingsStore {
44
45
  const serverPagination: PaginationSettings = arg?.rootGetters !== undefined ? this.getSettings(arg) : arg;
45
46
 
46
- return serverPagination?.useDefaultStores ? this.getStoreDefault() : serverPagination?.stores || this.getStoreDefault();
47
+ // Ensure we use the current default store settings if
48
+ // 1. from 2.11.0 user saved `ui-performance` setting and it's applied the default pagination settings containing useDefaultStores
49
+ // 2. before 2.11.0 user has saved `ui-performance` setting and it's applied an obsolete pagination settings that lack useDefaultStore
50
+ // 3. user has manually set the `ui-performance` pagination setting useDefaultStores value
51
+ if (serverPagination?.useDefaultStores || serverPagination?.useDefaultStores === undefined) {
52
+ return this.getStoreDefault();
53
+ }
54
+
55
+ return serverPagination?.stores || this.getStoreDefault();
47
56
  }
48
57
 
49
58
  public getStoreDefault(): PaginationSettingsStore {
@@ -168,7 +177,7 @@ class PaginationUtils {
168
177
  resourceChangesDebounceMs({ rootGetters }: any): number | undefined {
169
178
  const settings = this.getSettings({ rootGetters });
170
179
 
171
- return settings.resourceChangesDebounceMs;
180
+ return settings.resourceChangesDebounceMs || DEFAULT_PERF_SETTING.serverPagination.resourceChangesDebounceMs;
172
181
  }
173
182
 
174
183
  validateNsProjectFilters(nsProjectFilters: string[]) {