@rancher/shell 3.0.1-rc.3 → 3.0.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.
Files changed (94) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/styles/base/_basic.scss +5 -0
  3. package/assets/styles/base/_mixins.scss +8 -0
  4. package/assets/styles/global/_button.scss +5 -0
  5. package/assets/styles/themes/_dark.scss +2 -0
  6. package/assets/styles/themes/_light.scss +2 -0
  7. package/assets/translations/en-us.yaml +40 -22
  8. package/assets/translations/zh-hans.yaml +1 -7
  9. package/chart/monitoring/StorageClassSelector.vue +1 -1
  10. package/components/AssignTo.vue +1 -0
  11. package/components/AsyncButton.vue +1 -0
  12. package/components/BackLink.vue +8 -2
  13. package/components/PaginatedResourceTable.vue +135 -0
  14. package/components/ResourceDetail/Masthead.vue +1 -1
  15. package/components/ResourceDetail/index.vue +66 -11
  16. package/components/ResourceList/index.vue +0 -1
  17. package/components/ResourceTable.vue +6 -1
  18. package/components/ResourceYaml.vue +0 -53
  19. package/components/SortableTable/index.vue +8 -6
  20. package/components/Tabbed/index.vue +35 -2
  21. package/components/form/ResourceLabeledSelect.vue +2 -2
  22. package/components/form/ResourceTabs/index.vue +0 -23
  23. package/components/form/Taints.vue +1 -1
  24. package/components/form/UnitInput.vue +1 -1
  25. package/components/form/__tests__/UnitInput.test.ts +1 -1
  26. package/components/nav/TopLevelMenu.helper.ts +546 -0
  27. package/components/nav/TopLevelMenu.vue +125 -160
  28. package/components/nav/WindowManager/ContainerShell.vue +13 -4
  29. package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +20 -18
  30. package/components/nav/__tests__/TopLevelMenu.test.ts +338 -326
  31. package/composables/useLabeledFormElement.ts +6 -2
  32. package/config/pagination-table-headers.js +4 -4
  33. package/config/product/explorer.js +2 -0
  34. package/config/router/navigation-guards/index.js +1 -2
  35. package/config/router/routes.js +1 -1
  36. package/config/settings.ts +15 -8
  37. package/core/plugin.ts +8 -1
  38. package/core/types-provisioning.ts +5 -0
  39. package/core/types.ts +26 -1
  40. package/dialog/DrainNode.vue +6 -6
  41. package/edit/catalog.cattle.io.clusterrepo.vue +95 -52
  42. package/edit/provisioning.cattle.io.cluster/index.vue +8 -3
  43. package/edit/workload/index.vue +1 -1
  44. package/edit/workload/storage/csi/index.vue +29 -1
  45. package/edit/workload/storage/index.vue +1 -0
  46. package/initialize/App.vue +3 -10
  47. package/initialize/install-plugins.js +1 -2
  48. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +6 -2
  49. package/list/node.vue +8 -5
  50. package/mixins/resource-fetch-api-pagination.js +40 -5
  51. package/mixins/resource-fetch.js +48 -5
  52. package/models/management.cattle.io.nodepool.js +5 -4
  53. package/models/nodedriver.js +2 -2
  54. package/models/provisioning.cattle.io.cluster.js +3 -11
  55. package/package.json +7 -8
  56. package/pages/about.vue +22 -0
  57. package/pages/auth/setup.vue +7 -28
  58. package/pages/c/_cluster/explorer/__tests__/index.test.ts +36 -24
  59. package/pages/c/_cluster/explorer/index.vue +100 -59
  60. package/pages/home.vue +308 -123
  61. package/plugins/dashboard-store/__tests__/mutations.test.ts +2 -0
  62. package/plugins/dashboard-store/actions.js +29 -19
  63. package/plugins/dashboard-store/getters.js +5 -2
  64. package/plugins/dashboard-store/mutations.js +4 -2
  65. package/plugins/steve/__tests__/mutations.test.ts +2 -1
  66. package/plugins/steve/steve-pagination-utils.ts +25 -2
  67. package/plugins/steve/subscribe.js +22 -8
  68. package/rancher-components/Banner/Banner.vue +1 -0
  69. package/rancher-components/Form/Checkbox/Checkbox.vue +2 -0
  70. package/rancher-components/Form/LabeledInput/LabeledInput.vue +2 -0
  71. package/rancher-components/Form/Radio/RadioButton.vue +2 -0
  72. package/rancher-components/Form/Radio/RadioGroup.vue +2 -0
  73. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +2 -0
  74. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +3 -0
  75. package/rancher-components/StringList/StringList.test.ts +15 -15
  76. package/rancher-components/StringList/StringList.vue +3 -0
  77. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +0 -2
  78. package/scripts/extension/parse-tag-name +2 -0
  79. package/scripts/test-plugins-build.sh +4 -2
  80. package/store/index.js +31 -9
  81. package/tsconfig.json +7 -1
  82. package/types/resources/settings.d.ts +1 -1
  83. package/types/shell/index.d.ts +1107 -1276
  84. package/types/store/dashboard-store.types.ts +4 -0
  85. package/types/store/pagination.types.ts +13 -0
  86. package/types/store/vuex.d.ts +8 -0
  87. package/types/vue-shim.d.ts +6 -31
  88. package/utils/cluster.js +92 -1
  89. package/utils/pagination-utils.ts +17 -8
  90. package/utils/pagination-wrapper.ts +70 -0
  91. package/utils/uiplugins.ts +307 -0
  92. package/components/templates/error.vue +0 -131
  93. package/config/router/navigation-guards/history.js +0 -13
  94. package/plugins/back-button.js +0 -3
@@ -445,9 +445,12 @@ export default {
445
445
  return undefined;
446
446
  },
447
447
 
448
- paginationEnabled: (state, getters, rootState, rootGetters) => (type = null) => {
448
+ paginationEnabled: (state, getters, rootState, rootGetters) => (args) => {
449
+ const id = typeof args === 'object' ? args.id : args;
450
+ const context = typeof args === 'object' ? args.context : undefined;
451
+
449
452
  const store = state.config.namespace;
450
- const resource = type ? { id: type } : null;
453
+ const resource = id || context ? { id, context } : null;
451
454
 
452
455
  return paginationUtils.isEnabled({ rootGetters }, { store, resource });
453
456
  }
@@ -1,4 +1,4 @@
1
- import { markRaw, reactive } from 'vue';
1
+ import { reactive } from 'vue';
2
2
  import { addObject, addObjects, clear, removeObject } from '@shell/utils/array';
3
3
  import { SCHEMA, COUNT } from '@shell/config/types';
4
4
  import { normalizeType, keyFieldFor } from '@shell/plugins/dashboard-store/normalize';
@@ -36,7 +36,7 @@ function registerType(state, type) {
36
36
  loadCounter: 0,
37
37
 
38
38
  // Not enumerable so they don't get sent back to the client for SSR
39
- map: markRaw(new Map()),
39
+ map: new Map(),
40
40
  };
41
41
 
42
42
  state.types[type] = cache;
@@ -164,6 +164,8 @@ export function load(state, {
164
164
  }
165
165
  }
166
166
 
167
+ cache.havePage = false;
168
+
167
169
  return entry;
168
170
  }
169
171
 
@@ -15,9 +15,10 @@ describe('steve-store: mutations', () => {
15
15
  list: [new Resource(pod)],
16
16
  map: new Map([
17
17
  [pod.id, new Resource(pod)]
18
- ])
18
+ ]),
19
19
  }
20
20
  };
21
+ res.expected.types[POD].havePage = false;
21
22
 
22
23
  return res;
23
24
  };
@@ -4,8 +4,10 @@ import { NAMESPACE_FILTER_ALL_SYSTEM, NAMESPACE_FILTER_ALL_USER, NAMESPACE_FILTE
4
4
  import Namespace from '@shell/models/namespace';
5
5
  import { uniq } from '@shell/utils/array';
6
6
  import {
7
+ CAPI,
7
8
  CONFIG_MAP, MANAGEMENT, NAMESPACE, NODE, POD
8
9
  } from '@shell/config/types';
10
+ import { CAPI as CAPI_LABELS } from '@shell/config/labels-annotations';
9
11
  import { Schema } from '@shell/plugins/steve/schema';
10
12
 
11
13
  class NamespaceProjectFilters {
@@ -107,8 +109,8 @@ class StevePaginationUtils extends NamespaceProjectFilters {
107
109
  '': [// all types
108
110
  { field: 'metadata.name' },
109
111
  { field: 'metadata.namespace' },
110
- // { field: 'id' }, // Pending API support
111
- // { field: 'metadata.state.name' }, // Pending API support
112
+ { field: 'id' },
113
+ { field: 'metadata.state.name' },
112
114
  { field: 'metadata.creationTimestamp' },
113
115
  ],
114
116
  [NODE]: [
@@ -122,11 +124,32 @@ class StevePaginationUtils extends NamespaceProjectFilters {
122
124
  [MANAGEMENT.NODE]: [
123
125
  { field: 'status.nodeName' },
124
126
  ],
127
+ [MANAGEMENT.NODE_POOL]: [
128
+ { field: 'spec.clusterName' },
129
+ ],
130
+ [MANAGEMENT.NODE_TEMPLATE]: [
131
+ { field: 'spec.clusterName' },
132
+ ],
133
+ [MANAGEMENT.CLUSTER]: [
134
+ { field: 'spec.internal' },
135
+ { field: 'spec.displayName' },
136
+ // { field: `status.provider` }, // Pending API Support - https://github.com/rancher/rancher/issues/48256
137
+ // { field: `metadata.labels."${ CAPI_LABELS.PROVIDER }"` }, // Pending API Support - https://github.com/rancher/rancher/issues/48256
138
+
139
+ ],
125
140
  [CONFIG_MAP]: [
126
141
  { field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
127
142
  ],
128
143
  [NAMESPACE]: [
129
144
  { field: 'metadata.labels[field.cattle.io/projectId]' }
145
+ ],
146
+ [CAPI.MACHINE]: [
147
+ { field: 'spec.clusterName' }
148
+ ],
149
+ [CAPI.RANCHER_CLUSTER]: [
150
+ { field: `metadata.labels."${ CAPI_LABELS.PROVIDER }"` },
151
+ { field: `status.provider` },
152
+ { field: 'status.clusterName' },
130
153
  ]
131
154
  }
132
155
 
@@ -452,7 +452,7 @@ const sharedActions = {
452
452
  },
453
453
 
454
454
  unwatch(ctx, {
455
- type, id, namespace, selector
455
+ type, id, namespace, selector, all
456
456
  }) {
457
457
  const { commit, getters, dispatch } = ctx;
458
458
 
@@ -467,16 +467,26 @@ const sharedActions = {
467
467
  stop: true, // Stops the watch on a type
468
468
  };
469
469
 
470
+ const unwatch = (obj) => {
471
+ if (getters['watchStarted'](obj)) {
472
+ // Set that we don't want to watch this type
473
+ // Otherwise, the dispatch to unwatch below will just cause a re-watch when we
474
+ // detect the stop message from the backend over the web socket
475
+ commit('setWatchStopped', obj);
476
+ dispatch('watch', obj); // Ask the backend to stop watching the type
477
+ // Make sure anything in the pending queue for the type is removed, since we've now removed the type
478
+ commit('clearFromQueue', type);
479
+ }
480
+ };
481
+
470
482
  if (isAdvancedWorker(ctx)) {
471
483
  dispatch('watch', obj); // Ask the backend to stop watching the type
484
+ } else if (all) {
485
+ getters['watchesOfType'](type).forEach((obj) => {
486
+ unwatch(obj);
487
+ });
472
488
  } else if (getters['watchStarted'](obj)) {
473
- // Set that we don't want to watch this type
474
- // Otherwise, the dispatch to unwatch below will just cause a re-watch when we
475
- // detect the stop message from the backend over the web socket
476
- commit('setWatchStopped', obj);
477
- dispatch('watch', obj); // Ask the backend to stop watching the type
478
- // Make sure anything in the pending queue for the type is removed, since we've now removed the type
479
- commit('clearFromQueue', type);
489
+ unwatch(obj);
480
490
  }
481
491
  }
482
492
  },
@@ -1025,6 +1035,10 @@ const defaultGetters = {
1025
1035
  return state.inError[keyForSubscribe(obj)];
1026
1036
  },
1027
1037
 
1038
+ watchesOfType: (state) => (type) => {
1039
+ return state.started.filter((entry) => type === (entry.resourceType || entry.type));
1040
+ },
1041
+
1028
1042
  watchStarted: (state) => (obj) => {
1029
1043
  return !!state.started.find((entry) => equivalentWatch(obj, entry));
1030
1044
  },
@@ -49,6 +49,7 @@ export default defineComponent({
49
49
  default: false
50
50
  }
51
51
  },
52
+ emits: ['close'],
52
53
  computed: {
53
54
  /**
54
55
  * Return message text as label.
@@ -116,6 +116,8 @@ export default defineComponent({
116
116
  },
117
117
  },
118
118
 
119
+ emits: ['update:value'],
120
+
119
121
  computed: {
120
122
  /**
121
123
  * Determines if the checkbox is disabled.
@@ -108,6 +108,8 @@ export default defineComponent({
108
108
  }
109
109
  },
110
110
 
111
+ emits: ['change', 'update:value', 'blur', 'update:validation'],
112
+
111
113
  setup(props, { emit }) {
112
114
  const {
113
115
  focused,
@@ -71,6 +71,8 @@ export default defineComponent({
71
71
  }
72
72
  },
73
73
 
74
+ emits: ['update:value'],
75
+
74
76
  data() {
75
77
  return {
76
78
  isChecked: this.value === this.val,
@@ -103,6 +103,8 @@ export default defineComponent({
103
103
  }
104
104
  },
105
105
 
106
+ emits: ['update:value'],
107
+
106
108
  computed: {
107
109
  /**
108
110
  * Creates a collection of Options from the provided props.
@@ -80,6 +80,8 @@ export default defineComponent({
80
80
  }
81
81
  },
82
82
 
83
+ emits: ['update:value', 'paste', 'focus', 'blur'],
84
+
83
85
  setup() {
84
86
  const queueResize = inject('queueResize', provideProps.queueResize);
85
87
 
@@ -30,6 +30,9 @@ export default defineComponent({
30
30
  default: '',
31
31
  },
32
32
  },
33
+
34
+ emits: ['update:value'],
35
+
33
36
  data() {
34
37
  return { state: false as StateType };
35
38
  },
@@ -297,7 +297,7 @@ describe('stringList.vue', () => {
297
297
  await inputField.trigger('keydown.enter');
298
298
  await wrapper.vm.$nextTick();
299
299
 
300
- const emitted = (wrapper.emitted('change') || [])[1][0][0];
300
+ const emitted = (wrapper.emitted('change') || [])[0][0][0];
301
301
 
302
302
  expect(emitted).toBe(validItem.trim());
303
303
  });
@@ -318,7 +318,7 @@ describe('stringList.vue', () => {
318
318
  await inputField.trigger('keydown.enter');
319
319
  await wrapper.vm.$nextTick();
320
320
 
321
- const emitted = (wrapper.emitted('change') || [])[1][0][0];
321
+ const emitted = (wrapper.emitted('change') || [])[0][0][0];
322
322
 
323
323
  expect(emitted).toBe(validItem.trim());
324
324
  });
@@ -336,7 +336,7 @@ describe('stringList.vue', () => {
336
336
  await inputField.trigger('keydown.enter');
337
337
  await wrapper.vm.$nextTick();
338
338
 
339
- expect(wrapper.emitted('change')[1]).toBeFalsy();
339
+ expect(wrapper.emitted('change')).toBeFalsy();
340
340
  });
341
341
 
342
342
  it('reject a new item in create mode when item name is duplicate', async() => {
@@ -356,7 +356,7 @@ describe('stringList.vue', () => {
356
356
  await inputField.trigger('keydown.enter');
357
357
  await wrapper.vm.$nextTick();
358
358
 
359
- expect(wrapper.emitted('change')[1]).toBeFalsy();
359
+ expect(wrapper.emitted('change')).toBeFalsy();
360
360
  });
361
361
 
362
362
  it('reject an item in edit mode when item name is empty', async() => {
@@ -375,7 +375,7 @@ describe('stringList.vue', () => {
375
375
  await inputField.trigger('keydown.enter');
376
376
  await wrapper.vm.$nextTick();
377
377
 
378
- expect(wrapper.emitted('change')[1]).toBeFalsy();
378
+ expect(wrapper.emitted('change')).toBeFalsy();
379
379
  });
380
380
 
381
381
  it('reject an item in edit mode when item name is duplicate', async() => {
@@ -394,7 +394,7 @@ describe('stringList.vue', () => {
394
394
  await inputField.trigger('keydown.enter');
395
395
  await wrapper.vm.$nextTick();
396
396
 
397
- expect(wrapper.emitted('change')[1]).toBeFalsy();
397
+ expect(wrapper.emitted('change')).toBeFalsy();
398
398
  });
399
399
  });
400
400
 
@@ -428,7 +428,7 @@ describe('stringList.vue', () => {
428
428
  await inputField.trigger('keydown.enter');
429
429
  await wrapper.vm.$nextTick();
430
430
 
431
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
431
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
432
432
 
433
433
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
434
434
  });
@@ -485,7 +485,7 @@ describe('stringList.vue', () => {
485
485
  await inputField.trigger('keydown.enter');
486
486
  await wrapper.vm.$nextTick();
487
487
 
488
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
488
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
489
489
 
490
490
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
491
491
  });
@@ -504,7 +504,7 @@ describe('stringList.vue', () => {
504
504
  await inputField.trigger('keydown.enter');
505
505
  await wrapper.vm.$nextTick();
506
506
 
507
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
507
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
508
508
 
509
509
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
510
510
  });
@@ -523,7 +523,7 @@ describe('stringList.vue', () => {
523
523
  await inputField.trigger('keydown.enter');
524
524
  await wrapper.vm.$nextTick();
525
525
 
526
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
526
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
527
527
 
528
528
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
529
529
  });
@@ -555,7 +555,7 @@ describe('stringList.vue', () => {
555
555
  await inputField.trigger('keydown.enter');
556
556
  await wrapper.vm.$nextTick();
557
557
 
558
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
558
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
559
559
 
560
560
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
561
561
  });
@@ -607,7 +607,7 @@ describe('stringList.vue', () => {
607
607
  await inputField.trigger('keydown.enter');
608
608
  await wrapper.vm.$nextTick();
609
609
 
610
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
610
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
611
611
 
612
612
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
613
613
  });
@@ -625,7 +625,7 @@ describe('stringList.vue', () => {
625
625
  await inputField.trigger('keydown.enter');
626
626
  await wrapper.vm.$nextTick();
627
627
 
628
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
628
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
629
629
 
630
630
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
631
631
  });
@@ -643,7 +643,7 @@ describe('stringList.vue', () => {
643
643
  await inputField.trigger('keydown.enter');
644
644
  await wrapper.vm.$nextTick();
645
645
 
646
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
646
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
647
647
 
648
648
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
649
649
  });
@@ -661,7 +661,7 @@ describe('stringList.vue', () => {
661
661
  await inputField.trigger('keydown.enter');
662
662
  await wrapper.vm.$nextTick();
663
663
 
664
- const itemsResult = (wrapper.emitted('change') || [])[1][0];
664
+ const itemsResult = (wrapper.emitted('change') || [])[0][0];
665
665
 
666
666
  expect(JSON.stringify(itemsResult)).toBe(JSON.stringify(result));
667
667
  });
@@ -83,6 +83,9 @@ export default defineComponent({
83
83
  default: null,
84
84
  }
85
85
  },
86
+
87
+ emits: ['type:item', 'errors', 'change', 'update:value', 'blur', 'update:validation'],
88
+
86
89
  data() {
87
90
  return {
88
91
  value: undefined as string | undefined,
@@ -1,10 +1,8 @@
1
1
  annotations:
2
2
  catalog.cattle.io/certified: rancher # Any application we are adding as a helm chart
3
- catalog.cattle.io/kube-version: '>= 1.16.0-0'
4
3
  catalog.cattle.io/namespace: cattle-ui-plugin-system # Must prefix with cattle- and suffix with -system=
5
4
  catalog.cattle.io/os: linux
6
5
  catalog.cattle.io/permits-os: linux, windows
7
- catalog.cattle.io/rancher-version: '>= 2.7.0-0 < 2.9.0-0'
8
6
  catalog.cattle.io/scope: management
9
7
  catalog.cattle.io/ui-component: plugins
10
8
  apiVersion: v2
@@ -14,6 +14,7 @@ if [[ "${GITHUB_WORKFLOW_TYPE}" == "catalog" ]]; then
14
14
  if [[ "${GITHUB_RELEASE_TAG}" != "${BASE_EXT}-${EXT_VERSION}" ]]; then
15
15
  echo -e "release tag doesn't match catalog tag: release tag -> ${GITHUB_RELEASE_TAG} ::: curr catalog tag -> ${BASE_EXT}-${EXT_VERSION}"
16
16
  gh run cancel ${GITHUB_RUN_ID}
17
+ exit 1
17
18
  fi
18
19
  # Ensure "chart" workflow release tag name matches some pkg/<pkg-name>
19
20
  else
@@ -33,5 +34,6 @@ else
33
34
  if [[ "${NO_MATCHES}" == "true" ]]; then
34
35
  echo -e "release tag doesn't match any chart tag: ${GITHUB_RELEASE_TAG}. Check your pkg/<!-YOUR-EXT-> folders and corresponding versions to complete the match"
35
36
  gh run cancel ${GITHUB_RUN_ID}
37
+ exit 1
36
38
  fi
37
39
  fi
@@ -200,7 +200,7 @@ function clone_repo_test_extension_build() {
200
200
  echo -e "\nInstalling newly built shell version\n"
201
201
 
202
202
  # installing new version of shell
203
- yarn add @rancher/shell@${SHELL_VERSION}
203
+ yarn add @rancher/shell@${SHELL_VERSION} -W
204
204
 
205
205
  # test build-pkg
206
206
  FORCE_COLOR=true yarn build-pkg $PKG_NAME | cat
@@ -224,6 +224,8 @@ function clone_repo_test_extension_build() {
224
224
  clone_repo_test_extension_build "rancher" "kubewarden-ui" "kubewarden"
225
225
  clone_repo_test_extension_build "rancher" "elemental-ui" "elemental"
226
226
  clone_repo_test_extension_build "neuvector" "manager-ext" "neuvector-ui-ext"
227
- # clone_repo_test_extension_build "rancher" "capi-ui-extension" "capi"
227
+ clone_repo_test_extension_build "rancher" "capi-ui-extension" "capi"
228
+ clone_repo_test_extension_build "StackVista" "rancher-extension-stackstate" "observability"
229
+ clone_repo_test_extension_build "harvester" "harvester-ui-extension" "harvester"
228
230
 
229
231
  echo "All done"
package/store/index.js CHANGED
@@ -38,6 +38,7 @@ import semver from 'semver';
38
38
  import { STORE, BLANK_CLUSTER } from '@shell/store/store-types';
39
39
  import { isDevBuild } from '@shell/utils/version';
40
40
  import { markRaw } from 'vue';
41
+ import paginationUtils from '@shell/utils/pagination-utils';
41
42
 
42
43
  // Disables strict mode for all store instances to prevent warning about changing state outside of mutations
43
44
  // because it's more efficient to do that sometimes.
@@ -225,6 +226,13 @@ const updateActiveNamespaceCache = (state, activeNamespaceCache) => {
225
226
  }
226
227
  };
227
228
 
229
+ /**
230
+ * Are we in the vai enabled world where mgmt clusters are paginated?
231
+ */
232
+ const paginateClusters = (rootGetters) => {
233
+ return paginationUtils.isEnabled({ rootGetters }, { store: 'management', resource: { id: MANAGEMENT.CLUSTER, context: 'side-bar' } });
234
+ };
235
+
228
236
  export const state = () => {
229
237
  return {
230
238
  managementReady: false,
@@ -780,15 +788,11 @@ export const actions = {
780
788
  // The alternative is simpler (fetch features up front) but would add another blocking request in
781
789
 
782
790
  const promises = {
783
- // Clusters guaranteed always available or your money back
784
- clusters: dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } }),
785
-
786
791
  // Features checks on its own if they are available
787
792
  features: dispatch('features/loadServer'),
788
793
  };
789
794
 
790
795
  const toWatch = [
791
- MANAGEMENT.CLUSTER,
792
796
  MANAGEMENT.FEATURE,
793
797
  ];
794
798
 
@@ -823,6 +827,13 @@ export const actions = {
823
827
 
824
828
  res = await allHash(promises);
825
829
 
830
+ if (!res.settings || !paginateClusters(rootGetters)) {
831
+ // This introduces a synchronous request, however we need settings to determine if SSP is enabled
832
+ // Eventually it will be removed when SSP is always on
833
+ res.clusters = await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER, opt: { watch: false } });
834
+ toWatch.push(MANAGEMENT.CLUSTER);
835
+ }
836
+
826
837
  // See comment above. Now that we have feature flags we can watch resources
827
838
  toWatch.forEach((type) => {
828
839
  dispatch('management/watch', { type });
@@ -879,7 +890,7 @@ export const actions = {
879
890
  // - state.clusterId is the old cluster id (or undefined)
880
891
  // - id is the new cluster id (or undefined)
881
892
  async loadCluster({
882
- state, commit, dispatch, getters
893
+ state, commit, dispatch, getters, rootGetters
883
894
  }, {
884
895
  id, product, oldProduct, oldPkg, newPkg, targetRoute
885
896
  }) {
@@ -983,9 +994,10 @@ export const actions = {
983
994
  // Try and wait until the schema exists before proceeding
984
995
  await dispatch('management/waitForSchema', { type: MANAGEMENT.CLUSTER });
985
996
 
986
- // Similar to above, we're still waiting on loadManagement to fetch required resources
987
- // If we don't have all mgmt clusters yet a request to fetch this cluster and then all clusters (in cleanNamespaces) is kicked off
988
- await dispatch('management/waitForHaveAll', { type: MANAGEMENT.CLUSTER });
997
+ // If SSP is on we won't have requested all clusters
998
+ if (!paginateClusters(rootGetters)) {
999
+ await dispatch('management/waitForHaveAll', { type: MANAGEMENT.CLUSTER });
1000
+ }
989
1001
 
990
1002
  // See if it really exists
991
1003
  try {
@@ -1082,7 +1094,17 @@ export const actions = {
1082
1094
  commit('updateNamespaces', { filters: ids, getters });
1083
1095
  },
1084
1096
 
1085
- async cleanNamespaces({ getters, dispatch }) {
1097
+ async cleanNamespaces({ getters, dispatch, rootGetters }) {
1098
+ if (paginateClusters(rootGetters)) {
1099
+ // See https://github.com/rancher/dashboard/issues/12864
1100
+ // old world...
1101
+ // - loadManagement makes a request to fetch all mgmt clusters
1102
+ // - we would block on that that request above before getting here (otherwise x2 requests for all clusters were made)
1103
+ // new world...
1104
+ // - we won't have all mgmt clusters, so this whole function needs updating (see issue)
1105
+ return;
1106
+ }
1107
+
1086
1108
  // Initialise / Remove any filters that the user no-longer has access to
1087
1109
  await dispatch('management/findAll', { type: MANAGEMENT.CLUSTER }); // So they can be got byId below
1088
1110
 
package/tsconfig.json CHANGED
@@ -25,6 +25,12 @@
25
25
  "../node_modules/@types"
26
26
  ],
27
27
  },
28
+ "include": [
29
+ "./**/*.ts",
30
+ "./**/*.d.ts",
31
+ "./**/*.tsx",
32
+ "./**/*.vue"
33
+ ],
28
34
  "exclude": [
29
35
  "node_modules",
30
36
  "dist",
@@ -38,4 +44,4 @@
38
44
  "../docusaurus",
39
45
  "../**/*.spec.ts"
40
46
  ]
41
- }
47
+ }
@@ -20,7 +20,7 @@ export interface PaginationSettings {
20
20
  /**
21
21
  * Specific resource type to enable
22
22
  */
23
- enabled: string[],
23
+ enabled: (string | { resource: string, context: string[]})[],
24
24
  /**
25
25
  * There's no hardcoded headers or custom list for the resource type, headers will be generated from schema attributes.columns
26
26
  */