@rancher/shell 0.3.23 → 0.3.25

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 (149) hide show
  1. package/assets/styles/base/_variables.scss +1 -0
  2. package/assets/styles/themes/_dark.scss +1 -0
  3. package/assets/styles/themes/_light.scss +6 -5
  4. package/assets/translations/en-us.yaml +44 -17
  5. package/assets/translations/zh-hans.yaml +2 -2
  6. package/components/ClusterIconMenu.vue +143 -0
  7. package/components/CruResource.vue +7 -1
  8. package/components/ExplorerProjectsNamespaces.vue +11 -1
  9. package/components/FixedBanner.vue +17 -1
  10. package/components/Loading.vue +1 -1
  11. package/components/Markdown.vue +1 -1
  12. package/components/Questions/__tests__/Yaml.test.ts +3 -2
  13. package/components/SideNav.vue +1 -1
  14. package/components/SortableTable/index.vue +3 -2
  15. package/components/auth/RoleDetailEdit.vue +15 -2
  16. package/components/auth/login/saml.vue +12 -1
  17. package/components/form/LabeledSelect.vue +12 -5
  18. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  19. package/components/form/Members/MembershipEditor.vue +6 -1
  20. package/components/form/SelectOrCreateAuthSecret.vue +7 -0
  21. package/components/form/__tests__/KeyValue.test.ts +6 -3
  22. package/components/form/__tests__/LabeledSelect.test.ts +18 -0
  23. package/components/formatter/PodsUsage.vue +11 -36
  24. package/components/formatter/PrincipalGroupBindings.vue +8 -5
  25. package/components/formatter/__tests__/PodsUsage.test.ts +36 -19
  26. package/components/nav/Group.vue +62 -34
  27. package/components/nav/Header.vue +13 -6
  28. package/components/nav/Pinned.vue +47 -0
  29. package/components/nav/TopLevelMenu.vue +673 -325
  30. package/components/nav/Type.vue +88 -8
  31. package/config/home-links.js +1 -1
  32. package/config/product/istio.js +15 -5
  33. package/config/router.js +3 -9
  34. package/config/table-headers.js +5 -6
  35. package/config/uiplugins.js +1 -0
  36. package/core/plugin-helpers.js +3 -0
  37. package/core/types.ts +6 -1
  38. package/creators/app/files/.vscode/settings.json +0 -1
  39. package/creators/pkg/init +2 -2
  40. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +118 -0
  41. package/detail/autoscaling.horizontalpodautoscaler/index.vue +4 -4
  42. package/detail/provisioning.cattle.io.cluster.vue +7 -5
  43. package/edit/__tests__/management.cattle.io.clusterroletemplatebinding.test.ts +58 -0
  44. package/edit/__tests__/namespace.test.ts +5 -3
  45. package/edit/fleet.cattle.io.gitrepo.vue +43 -15
  46. package/edit/logging.banzaicloud.io.output/index.vue +7 -0
  47. package/edit/management.cattle.io.clusterroletemplatebinding.vue +3 -11
  48. package/edit/namespace.vue +8 -4
  49. package/edit/provisioning.cattle.io.cluster/Basics.vue +662 -0
  50. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +9 -8
  51. package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +13 -8
  52. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -2
  53. package/edit/provisioning.cattle.io.cluster/MemberRoles.vue +40 -0
  54. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  55. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +71 -23
  56. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +52 -0
  57. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -142
  58. package/edit/provisioning.cattle.io.cluster/rke2.vue +253 -582
  59. package/edit/workload/storage/ContainerMountPaths.vue +7 -5
  60. package/edit/workload/storage/__tests__/Storage.test.ts +2 -2
  61. package/edit/workload/storage/persistentVolumeClaim/__tests__/persistentvolumeclaim.test.ts +36 -0
  62. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +15 -7
  63. package/initialize/App.js +2 -0
  64. package/initialize/client.js +63 -51
  65. package/initialize/index.js +7 -5
  66. package/layouts/default.vue +10 -2
  67. package/layouts/home.vue +6 -2
  68. package/layouts/plain.vue +9 -2
  69. package/list/fleet.cattle.io.cluster.vue +2 -2
  70. package/list/management.cattle.io.feature.vue +1 -1
  71. package/machine-config/amazonec2.vue +1 -0
  72. package/machine-config/vmwarevsphere.vue +48 -7
  73. package/mixins/brand.js +0 -8
  74. package/mixins/child-hook.js +2 -2
  75. package/mixins/create-edit-view/impl.js +3 -3
  76. package/mixins/fetch.client.js +3 -3
  77. package/models/__tests__/management.cattle.io.node.ts +96 -0
  78. package/models/__tests__/node.ts +74 -0
  79. package/models/cluster/node.js +6 -5
  80. package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
  81. package/models/management.cattle.io.cluster.js +22 -1
  82. package/models/management.cattle.io.clusterroletemplatebinding.js +3 -3
  83. package/models/management.cattle.io.globalrole.js +17 -2
  84. package/models/management.cattle.io.node.js +6 -4
  85. package/models/management.cattle.io.projectroletemplatebinding.js +3 -3
  86. package/models/management.cattle.io.roletemplate.js +17 -2
  87. package/package.json +2 -6
  88. package/pages/__tests__/prefs.test.ts +1 -1
  89. package/pages/about.vue +2 -0
  90. package/pages/auth/setup.vue +5 -4
  91. package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -0
  92. package/pages/c/_cluster/monitoring/index.vue +8 -3
  93. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +9 -66
  94. package/pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue +182 -0
  95. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +15 -32
  96. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +8 -46
  97. package/pages/c/_cluster/uiplugins/index.vue +64 -64
  98. package/pages/diagnostic.vue +0 -39
  99. package/pages/home.vue +1 -1
  100. package/pages/prefs.vue +3 -13
  101. package/plugins/dashboard-store/normalize.js +4 -4
  102. package/plugins/dashboard-store/resource-class.js +1 -1
  103. package/plugins/int-number.js +5 -2
  104. package/plugins/positive-int-number.js +19 -0
  105. package/plugins/steve/__tests__/getters.spec.ts +15 -0
  106. package/plugins/steve/getters.js +22 -10
  107. package/public/index.html +4 -2
  108. package/rancher-components/BadgeState/BadgeState.vue +5 -1
  109. package/rancher-components/Banner/Banner.test.ts +51 -1
  110. package/rancher-components/Banner/Banner.vue +134 -53
  111. package/rancher-components/Card/Card.test.ts +37 -0
  112. package/rancher-components/Card/Card.vue +24 -7
  113. package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
  114. package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
  115. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
  116. package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
  117. package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
  118. package/rancher-components/Form/Radio/RadioButton.vue +30 -13
  119. package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
  120. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
  121. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
  122. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
  123. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
  124. package/rancher-components/StringList/StringList.test.ts +453 -49
  125. package/rancher-components/StringList/StringList.vue +92 -58
  126. package/scripts/extension/parse-tag-name +0 -0
  127. package/store/index.js +4 -0
  128. package/store/prefs.js +4 -4
  129. package/store/type-map.js +2 -16
  130. package/types/shell/index.d.ts +26 -14
  131. package/utils/__tests__/cluster.test.ts +55 -0
  132. package/utils/__tests__/object.test.ts +21 -2
  133. package/utils/__tests__/sort.test.ts +61 -0
  134. package/utils/cluster.js +47 -1
  135. package/utils/object.js +12 -5
  136. package/utils/string.js +12 -0
  137. package/utils/validators/formRules/__tests__/index.test.ts +13 -1
  138. package/utils/validators/formRules/index.ts +4 -0
  139. package/utils/validators/role-template.js +9 -1
  140. package/utils/version.js +1 -1
  141. package/vue.config.js +1 -4
  142. package/yarn-error.log +200 -0
  143. package/content/docs/en-us/getting-started.md +0 -224
  144. package/content/docs/en-us/whats-new.md +0 -29
  145. package/content/docs/zh-hans/getting-started.md +0 -224
  146. package/content/docs/zh-hans/whats-new.md +0 -28
  147. package/pages/docs/_doc.vue +0 -345
  148. package/pages/docs/toc.js +0 -27
  149. package/plugins/console.js +0 -34
@@ -30,9 +30,9 @@ const CLASS = {
30
30
  * Manage a list of strings
31
31
  */
32
32
  export default Vue.extend({
33
- components: { LabeledInput },
34
33
 
35
- name: 'StringList',
34
+ name: 'StringList',
35
+ components: { LabeledInput },
36
36
 
37
37
  props: {
38
38
  /**
@@ -85,11 +85,11 @@ export default Vue.extend({
85
85
  },
86
86
  data() {
87
87
  return {
88
- value: null as string | null,
89
- selected: null as string | null,
90
- isEditItem: null as string | null,
91
- isCreateItem: false,
92
- errors: { duplicate: false } as Record<Error, boolean>
88
+ value: null as string | null,
89
+ selected: null as string | null,
90
+ editedItem: null as string | null,
91
+ isCreateItem: false,
92
+ errors: { duplicate: false } as Record<Error, boolean>
93
93
  };
94
94
  },
95
95
 
@@ -100,8 +100,8 @@ export default Vue.extend({
100
100
  */
101
101
  errorMessagesArray(): string[] {
102
102
  return (Object.keys(this.errors) as Error[])
103
- .filter(f => !!(this.errors)[f])
104
- .map(k => this.errorMessages[k]);
103
+ .filter((f) => this.errors[f] && this.errorMessages[f])
104
+ .map((k) => this.errorMessages[k]);
105
105
  },
106
106
  },
107
107
 
@@ -113,23 +113,35 @@ export default Vue.extend({
113
113
  this.toggleEditMode(false);
114
114
  this.toggleCreateMode(false);
115
115
  },
116
+ value(val) {
117
+ this.$emit('type:item', val);
118
+ },
119
+ errors: {
120
+ handler(val) {
121
+ this.$emit('errors', val);
122
+ },
123
+ deep: true
124
+ }
116
125
  },
117
126
 
118
127
  methods: {
119
128
  onChange(value: string) {
120
129
  this.value = value;
121
- /**
122
- * Remove duplicate error when a new value is typed
123
- */
130
+
131
+ const items = [
132
+ ...this.items,
133
+ this.value
134
+ ];
135
+
124
136
  this.toggleError(
125
137
  'duplicate',
126
- false,
127
- this.isCreateItem ? INPUT.create : INPUT.edit,
138
+ hasDuplicatedStrings(items, this.caseSensitive),
139
+ this.isCreateItem ? INPUT.create : INPUT.edit
128
140
  );
129
141
  },
130
142
 
131
143
  onSelect(item: string) {
132
- if (this.isCreateItem || this.isEditItem === item) {
144
+ if (this.readonly || this.isCreateItem || this.editedItem === item) {
133
145
  return;
134
146
  }
135
147
  this.selected = item;
@@ -160,7 +172,7 @@ export default Vue.extend({
160
172
  },
161
173
 
162
174
  onClickEmptyBody() {
163
- if (!this.isCreateItem && !this.isEditItem) {
175
+ if (!this.isCreateItem && !this.editedItem) {
164
176
  this.toggleCreateMode(true);
165
177
  }
166
178
  },
@@ -176,38 +188,43 @@ export default Vue.extend({
176
188
 
177
189
  return;
178
190
  }
179
- if (this.isEditItem) {
191
+ if (this.editedItem) {
192
+ this.deleteAndSelectNext(this.editedItem);
180
193
  this.toggleEditMode(false);
181
194
 
182
195
  return;
183
196
  }
184
197
  if (this.selected) {
185
- const index = findStringIndex(this.items, this.selected, false);
198
+ this.deleteAndSelectNext(this.selected);
199
+ }
200
+ },
186
201
 
187
- if (index !== -1) {
188
- /**
189
- * Select the next item in the list when an item is to be deleted.
190
- */
191
- const item = (this.items[index + 1] || this.items[index - 1]);
202
+ deleteAndSelectNext(currItem: string) {
203
+ const index = findStringIndex(this.items, currItem, false);
204
+
205
+ if (index !== -1) {
206
+ /**
207
+ * Select the next item in the list.
208
+ */
209
+ const item = (this.items[index + 1] || this.items[index - 1]);
192
210
 
193
- this.onSelect(item);
194
- this.setFocus(item);
211
+ this.onSelect(item);
212
+ this.setFocus(item);
195
213
 
196
- this.deleteItem(this.items[index]);
197
- }
214
+ this.deleteItem(this.items[index]);
198
215
  }
199
216
  },
200
217
 
201
218
  setFocus(refId: string) {
202
- this.$nextTick(() => this.getElemByRef(refId)?.focus());
219
+ this.$nextTick(() => (this.getElemByRef(refId) as Vue & HTMLElement)?.focus());
203
220
  },
204
221
 
205
222
  /**
206
223
  * Move scrollbar when the selected item is over the top or bottom side of the box
207
224
  */
208
225
  moveScrollbar(arrow: Arrow, value?: number) {
209
- const box = this.getElemByRef(BOX);
210
- const item = this.getElemByRef(this.selected || '');
226
+ const box = this.getElemByRef(BOX) as HTMLElement;
227
+ const item = this.getElemByRef(this.selected || '') as HTMLElement;
211
228
 
212
229
  if (box && item && item.className.includes(CLASS.item)) {
213
230
  const boxRect = box.getClientRects()[0];
@@ -229,13 +246,14 @@ export default Vue.extend({
229
246
  */
230
247
  toggleError(type: Error, val: boolean, refId?: string) {
231
248
  this.errors[type] = val;
249
+
232
250
  if (refId) {
233
251
  this.toggleErrorClass(refId, val);
234
252
  }
235
253
  },
236
254
 
237
255
  toggleErrorClass(refId: string, val: boolean) {
238
- const input = this.getElemByRef(refId)?.$el;
256
+ const input = (this.getElemByRef(refId) as Vue)?.$el;
239
257
 
240
258
  if (input) {
241
259
  if (val) {
@@ -250,7 +268,11 @@ export default Vue.extend({
250
268
  * Show/Hide the input line to create new item
251
269
  */
252
270
  toggleCreateMode(show: boolean) {
271
+ if (this.readonly) {
272
+ return;
273
+ }
253
274
  if (show) {
275
+ this.toggleEditMode(false);
254
276
  this.value = '';
255
277
 
256
278
  this.isCreateItem = true;
@@ -268,31 +290,34 @@ export default Vue.extend({
268
290
  * Show/Hide the in-line editing to edit an existing item
269
291
  */
270
292
  toggleEditMode(show: boolean, item?: string) {
293
+ if (this.readonly) {
294
+ return;
295
+ }
271
296
  if (show) {
272
297
  this.toggleCreateMode(false);
273
- this.value = this.isEditItem;
298
+ this.value = this.editedItem;
274
299
 
275
- this.isEditItem = item || '';
300
+ this.editedItem = item || '';
276
301
  this.setFocus(INPUT.edit);
277
302
  } else {
278
303
  this.value = null;
279
304
  this.toggleError('duplicate', false);
280
305
  this.onSelectLeave();
281
306
 
282
- this.isEditItem = null;
307
+ this.editedItem = null;
283
308
  }
284
309
  },
285
310
 
286
311
  getElemByRef(id: string) {
287
312
  const ref = this.$refs[id];
288
313
 
289
- return (Array.isArray(ref) ? ref[0] : ref) as any;
314
+ return Array.isArray(ref) ? ref[0] : ref;
290
315
  },
291
316
 
292
317
  /**
293
318
  * Create a new item and insert in the items list
294
319
  */
295
- saveItem() {
320
+ saveItem(closeInput = true) {
296
321
  const value = this.value?.trim();
297
322
 
298
323
  if (value) {
@@ -301,21 +326,20 @@ export default Vue.extend({
301
326
  value,
302
327
  ];
303
328
 
304
- if (hasDuplicatedStrings(items, this.caseSensitive)) {
305
- this.toggleError('duplicate', true, INPUT.create);
306
-
307
- return;
329
+ if (!hasDuplicatedStrings(items, this.caseSensitive)) {
330
+ this.updateItems(items);
308
331
  }
332
+ }
309
333
 
310
- this.updateItems(items);
334
+ if (closeInput) {
335
+ this.toggleCreateMode(false);
311
336
  }
312
- this.toggleCreateMode(false);
313
337
  },
314
338
 
315
339
  /**
316
340
  * Update an existing item in the items list
317
341
  */
318
- updateItem(item: string) {
342
+ updateItem(item: string, closeInput = true) {
319
343
  const value = this.value?.trim();
320
344
 
321
345
  if (value) {
@@ -326,22 +350,21 @@ export default Vue.extend({
326
350
  items[index] = value;
327
351
  }
328
352
 
329
- if (hasDuplicatedStrings(items, this.caseSensitive)) {
330
- this.toggleError('duplicate', true, INPUT.edit);
331
-
332
- return;
353
+ if (!hasDuplicatedStrings(items, this.caseSensitive)) {
354
+ this.updateItems(items);
333
355
  }
356
+ }
334
357
 
335
- this.updateItems(items);
358
+ if (closeInput) {
359
+ this.toggleEditMode(false);
336
360
  }
337
- this.toggleEditMode(false);
338
361
  },
339
362
 
340
363
  /**
341
364
  * Remove an item from items list
342
365
  */
343
366
  deleteItem(item?: string) {
344
- const items = this.items.filter(f => f !== item);
367
+ const items = this.items.filter((f) => f !== item);
345
368
 
346
369
  this.updateItems(items);
347
370
  },
@@ -387,19 +410,20 @@ export default Vue.extend({
387
410
  @blur="onSelectLeave(item)"
388
411
  >
389
412
  <span
390
- v-if="!isEditItem || isEditItem !== item"
413
+ v-if="!editedItem || editedItem !== item"
391
414
  class="label static"
392
415
  >
393
416
  {{ item }}
394
417
  </span>
395
418
  <LabeledInput
396
- v-if="isEditItem && isEditItem === item"
419
+ v-if="editedItem && editedItem === item"
397
420
  ref="item-edit"
421
+ :data-testid="`item-edit-${item}`"
398
422
  class="edit-input static"
399
423
  :value="value != null ? value : item"
400
424
  @input="onChange($event)"
401
- @blur.prevent="toggleEditMode(false)"
402
- @keydown.native.enter="updateItem(item)"
425
+ @blur.prevent="updateItem(item)"
426
+ @keydown.native.enter="updateItem(item, !errors.duplicate)"
403
427
  />
404
428
  </div>
405
429
  <div
@@ -408,12 +432,14 @@ export default Vue.extend({
408
432
  >
409
433
  <LabeledInput
410
434
  ref="item-create"
435
+ data-testid="item-create"
411
436
  class="create-input static"
412
437
  type="text"
413
438
  :value="value"
414
439
  :placeholder="placeholder"
415
440
  @input="onChange($event)"
416
- @keydown.native.enter="saveItem"
441
+ @blur.prevent="saveItem"
442
+ @keydown.native.enter="saveItem(!errors.duplicate)"
417
443
  />
418
444
  </div>
419
445
  </div>
@@ -427,25 +453,32 @@ export default Vue.extend({
427
453
  class="action-buttons"
428
454
  >
429
455
  <button
456
+ data-testid="button-remove"
430
457
  class="btn btn-sm role-tertiary remove-button"
431
- :disabled="!selected && !isCreateItem && !isEditItem"
458
+ :disabled="!selected && !isCreateItem && !editedItem"
432
459
  @mousedown.prevent="onClickMinusButton"
433
460
  >
434
461
  <span class="icon icon-minus icon-sm" />
435
462
  </button>
436
463
  <button
464
+ data-testid="button-add"
437
465
  class="btn btn-sm role-tertiary add-button"
438
- :disabled="isCreateItem"
466
+ :disabled="isCreateItem || editedItem"
439
467
  @click.prevent="onClickPlusButton"
440
468
  >
441
469
  <span class="icon icon-plus icon-sm" />
442
470
  </button>
443
471
  </div>
444
472
  <div class="messages">
445
- <i v-if="errorMessagesArray.length > 0" class="icon icon-warning icon-lg" />
473
+ <i
474
+ v-if="errorMessagesArray.length > 0"
475
+ data-testid="i-warning-icon"
476
+ class="icon icon-warning icon-lg"
477
+ />
446
478
  <span
447
479
  v-for="(msg, idx) in errorMessagesArray"
448
480
  :key="idx"
481
+ :data-testid="`span-error-message-${msg}`"
449
482
  class="error"
450
483
  >
451
484
  {{ idx > 0 ? '; ' : '' }}
@@ -499,6 +532,7 @@ export default Vue.extend({
499
532
  width: auto;
500
533
  user-select: none;
501
534
  overflow: hidden;
535
+ white-space: no-wrap;
502
536
  text-overflow: ellipsis;
503
537
  padding-top: 1px;
504
538
  }
File without changes
package/store/index.js CHANGED
@@ -568,6 +568,10 @@ export const getters = {
568
568
  return getters['isSingleProduct'] && cluster.isHarvester && !getters['isRancherInHarvester'];
569
569
  },
570
570
 
571
+ showTopLevelMenu(getters) {
572
+ return getters['isRancherInHarvester'] || getters['isMultiCluster'] || !getters['isSingleProduct'];
573
+ },
574
+
571
575
  targetRoute(state) {
572
576
  return state.targetRoute;
573
577
  },
package/store/prefs.js CHANGED
@@ -1,7 +1,7 @@
1
- import Vue from 'vue';
1
+ import { SETTING } from '@shell/config/settings';
2
2
  import { MANAGEMENT, STEVE } from '@shell/config/types';
3
3
  import { clone } from '@shell/utils/object';
4
- import { SETTING } from '@shell/config/settings';
4
+ import Vue from 'vue';
5
5
 
6
6
  const definitions = {};
7
7
  /**
@@ -54,6 +54,7 @@ export const NAMESPACE_FILTERS = create('ns-by-cluster', {}, { parseJSON });
54
54
  export const WORKSPACE = create('workspace', '');
55
55
  export const EXPANDED_GROUPS = create('open-groups', ['cluster', 'policy', 'rbac', 'serviceDiscovery', 'storage', 'workload'], { parseJSON });
56
56
  export const FAVORITE_TYPES = create('fav-type', [], { parseJSON });
57
+ export const PINNED_CLUSTERS = create('pinned-clusters', [], { parseJSON });
57
58
  export const GROUP_RESOURCES = create('group-by', 'namespace');
58
59
  export const DIFF = create('diff', 'unified', { options: ['unified', 'split'] });
59
60
  export const THEME = create('theme', 'auto', {
@@ -115,8 +116,7 @@ export const PROVISIONER = create('provisioner', _RKE2, { options: [_RKE1, _RKE2
115
116
  export const PSP_DEPRECATION_BANNER = create('hide-psp-deprecation-banner', false, { parseJSON });
116
117
 
117
118
  // Maximum number of clusters to show in the slide-in menu
118
- export const MENU_MAX_CLUSTERS = create('menu-max-clusters', 4, { options: [2, 3, 4, 5, 6, 7, 8, 9, 10], parseJSON });
119
-
119
+ export const MENU_MAX_CLUSTERS = 10;
120
120
  // Prompt for confirm when scaling down node pool in GUI and save the pref
121
121
  export const SCALE_POOL_PROMPT = create('scale-pool-prompt', null, { parseJSON });
122
122
  // --------------------
package/store/type-map.js CHANGED
@@ -593,18 +593,8 @@ export const getters = {
593
593
  }
594
594
 
595
595
  const label = typeObj.labelKey ? rootGetters['i18n/t'](typeObj.labelKey) || typeObj.label : typeObj.label;
596
- const virtual = !!typeObj.virtual;
597
- let icon = typeObj.icon;
598
596
 
599
- if ( (!virtual || typeObj.isSpoofed ) && !icon ) {
600
- if ( namespaced ) {
601
- icon = 'folder';
602
- } else {
603
- icon = 'globe';
604
- }
605
- }
606
-
607
- const labelDisplay = highlightLabel(label, icon, typeObj.count, typeObj.schema);
597
+ const labelDisplay = highlightLabel(label, typeObj.count, typeObj.schema);
608
598
 
609
599
  if ( !labelDisplay ) {
610
600
  // Search happens in highlight and returns null if not found
@@ -711,7 +701,7 @@ export const getters = {
711
701
  return group;
712
702
  }
713
703
 
714
- function highlightLabel(original, icon, count, schema) {
704
+ function highlightLabel(original, count, schema) {
715
705
  let label = escapeHtml(original);
716
706
 
717
707
  if ( searchRegex ) {
@@ -735,10 +725,6 @@ export const getters = {
735
725
  }
736
726
  }
737
727
 
738
- if ( icon ) {
739
- label = `<i class="icon icon-fw icon-${ icon }"></i>${ label }`;
740
- }
741
-
742
728
  return label;
743
729
  }
744
730
  };
@@ -2049,8 +2049,8 @@ declare namespace _default {
2049
2049
  namespace methods {
2050
2050
  function done(): any;
2051
2051
  function done(): any;
2052
- function conflict(): any;
2053
- function conflict(): any;
2052
+ function conflict(): Promise<any>;
2053
+ function conflict(): Promise<any>;
2054
2054
  function save(buttonDone: any, url: any, depth?: number): any;
2055
2055
  function save(buttonDone: any, url: any, depth?: number): any;
2056
2056
  function actuallySave(url: any): Promise<void>;
@@ -2069,7 +2069,7 @@ declare var _default: import("vue/types/vue").ExtendedVue<Vue<Record<string, any
2069
2069
  errors: any[];
2070
2070
  }, {
2071
2071
  done(): any;
2072
- conflict(): any;
2072
+ conflict(): Promise<any>;
2073
2073
  save(buttonDone: any, url: any, depth?: number): any;
2074
2074
  actuallySave(url: any): Promise<void>;
2075
2075
  setErrors(errors: any): void;
@@ -2407,7 +2407,7 @@ export const SELF: "__[[SELF]]__";
2407
2407
  declare module '@shell/plugins/dashboard-store/normalize' {
2408
2408
  export function keyFieldFor(type: any): string;
2409
2409
  export function normalizeType(type: any): any;
2410
- export function handleConflict(initialValueJSON: any, value: any, liveValue: any, rootGetters: any, store: any): false | any[];
2410
+ export function handleConflict(initialValueJSON: any, value: any, liveValue: any, rootGetters: any, store: any, storeNamespace: any): Promise<false | any[]>;
2411
2411
  export const KEY_FIELD_FOR: {
2412
2412
  [x: number]: string;
2413
2413
  default: string;
@@ -2836,6 +2836,7 @@ export const NAMESPACE_FILTERS: any;
2836
2836
  export const WORKSPACE: any;
2837
2837
  export const EXPANDED_GROUPS: any;
2838
2838
  export const FAVORITE_TYPES: any;
2839
+ export const PINNED_CLUSTERS: any;
2839
2840
  export const GROUP_RESOURCES: any;
2840
2841
  export const DIFF: any;
2841
2842
  export const THEME: any;
@@ -2868,7 +2869,7 @@ export const _RKE1: "rke1";
2868
2869
  export const _RKE2: "rke2";
2869
2870
  export const PROVISIONER: any;
2870
2871
  export const PSP_DEPRECATION_BANNER: any;
2871
- export const MENU_MAX_CLUSTERS: any;
2872
+ export const MENU_MAX_CLUSTERS: 10;
2872
2873
  export const SCALE_POOL_PROMPT: any;
2873
2874
  export function state(): {
2874
2875
  cookiesLoaded: boolean;
@@ -3052,6 +3053,14 @@ export function filterOnlyKubernetesClusters(mgmtClusters: any, store: any): any
3052
3053
  export function isHarvesterCluster(mgmtCluster: any): boolean;
3053
3054
  export function isHarvesterSatisfiesVersion(version?: string): any;
3054
3055
  export function filterHiddenLocalCluster(mgmtClusters: any, store: any): any;
3056
+ /**
3057
+ * Shortens an input string based on the number of segments it contains.
3058
+ * @param {string} input - The input string to be shortened.
3059
+ * @returns {string} - The shortened string.
3060
+ * @example smallIdentifier('local') => 'lcl'
3061
+ * @example smallIdentifier('word-wide-web') => 'www'
3062
+ */
3063
+ export function abbreviateClusterName(input: string): string;
3055
3064
  }
3056
3065
 
3057
3066
  // @shell/utils/color
@@ -3605,35 +3614,35 @@ export namespace KEY {
3605
3614
  }
3606
3615
  }
3607
3616
 
3608
- // @shell/utils/poller
3617
+ // @shell/utils/poller-sequential
3609
3618
 
3610
- declare module '@shell/utils/poller' {
3611
- export default class Poller {
3619
+ declare module '@shell/utils/poller-sequential' {
3620
+ export default class PollerSequential {
3612
3621
  constructor(fn: any, pollRateMs: any, maxRetries?: number);
3613
3622
  fn: any;
3614
3623
  pollRateMs: any;
3615
3624
  maxRetries: number;
3616
- intervalId: any;
3625
+ timeoutId: any;
3617
3626
  tryCount: number;
3618
3627
  start(): void;
3619
3628
  stop(): void;
3629
+ _poll(): void;
3620
3630
  _intervalMethod(): Promise<void>;
3621
3631
  }
3622
3632
  }
3623
3633
 
3624
- // @shell/utils/poller-sequential
3634
+ // @shell/utils/poller
3625
3635
 
3626
- declare module '@shell/utils/poller-sequential' {
3627
- export default class PollerSequential {
3636
+ declare module '@shell/utils/poller' {
3637
+ export default class Poller {
3628
3638
  constructor(fn: any, pollRateMs: any, maxRetries?: number);
3629
3639
  fn: any;
3630
3640
  pollRateMs: any;
3631
3641
  maxRetries: number;
3632
- timeoutId: any;
3642
+ intervalId: any;
3633
3643
  tryCount: number;
3634
3644
  start(): void;
3635
3645
  stop(): void;
3636
- _poll(): void;
3637
3646
  _intervalMethod(): Promise<void>;
3638
3647
  }
3639
3648
  }
@@ -3908,6 +3917,9 @@ export function splitObjectPath(path: any): any;
3908
3917
  export function joinObjectPath(ary: any): string;
3909
3918
  export function shortenedImage(image: any): any;
3910
3919
  export function isIpv4(ip: any): boolean;
3920
+ export function sanitizeKey(k: any): any;
3921
+ export function sanitizeValue(v: any): any;
3922
+ export function sanitizeIP(v: any): any;
3911
3923
  export namespace CHARSET {
3912
3924
  export { num as NUMERIC };
3913
3925
  export const NO_VOWELS: string;
@@ -0,0 +1,55 @@
1
+ import { abbreviateClusterName } from '@shell/utils/cluster';
2
+
3
+ describe('fx: abbreviateClusterName', () => {
4
+ it.each([
5
+ ['local', 'lcl'],
6
+ ['world-wide-web', 'www'],
7
+ ['a', 'a'],
8
+ ['ab', 'ab'],
9
+ ['abc', 'abc'],
10
+ ['', ''],
11
+ ['1', '1'],
12
+ ['12', '12'],
13
+ ['123', '123'],
14
+ ['a1', 'a1'],
15
+ ['aa1', 'aa1'],
16
+ ['aaa1', 'aa1'],
17
+ ['a-b', 'a-b'],
18
+ ['1-2', '1-2'],
19
+ ['a-b-c', 'abc'],
20
+ ['abc-def-ghi', 'adg'],
21
+ ['abcd-efgh', 'adh'],
22
+ ['a-bc', 'abc'],
23
+ ['ab-c', 'abc'],
24
+ ['ab-cd', 'abd'],
25
+ ['a-bcd', 'abd'],
26
+ ['abc-d', 'acd'],
27
+ ['0123-4567-89ab-cdef', '048'],
28
+ ['0123-4567-89ab-cdef-ghij', '048'],
29
+ ['0123-4567-8901-2345', '048'],
30
+ ['0123-4567-8901-2345-6789', '048'],
31
+ ['a1b', 'a1b'],
32
+ ['a1b2', 'a1b'],
33
+ ['ab12cd34', 'a1c'],
34
+ ['test-cluster-one', 'tco'],
35
+ ['test-cluster-1', 'tc1'],
36
+ ['customer-support-team-1', 'cst'],
37
+ ['customer-support-team-one', 'cst'],
38
+ ['customer-support-team-prod', 'cst'],
39
+ ['customer-support-team-dev', 'cst'],
40
+ ['customer-support-team-prod-1', 'cst'],
41
+ ['customer-support-team-dev-1', 'cst'],
42
+ ['customer-support-team-prod-2', 'cst'],
43
+ ['customer-support-team-dev-2', 'cst'],
44
+
45
+ ['s322', 's32'],
46
+ ['sowmya2', 'sa2'],
47
+ ['sowmya4', 'sa4'],
48
+ ['sowmya', 'sma'],
49
+ ['sowmyatest4', 'st4'],
50
+ ])('should evaluate %p as %p', (value, expected) => {
51
+ const result = abbreviateClusterName(value);
52
+
53
+ expect(result).toStrictEqual(expected);
54
+ });
55
+ });
@@ -1,5 +1,5 @@
1
1
  import {
2
- clone, get, getter, isEmpty, toDictionary
2
+ clone, get, getter, isEmpty, toDictionary, remove
3
3
  } from '@shell/utils/object';
4
4
 
5
5
  describe('fx: get', () => {
@@ -129,7 +129,7 @@ describe('fx: isEmpty', () => {
129
129
  });
130
130
  });
131
131
 
132
- describe('fX: toDictionary', () => {
132
+ describe('fx: toDictionary', () => {
133
133
  it('should return a dictionary from an array', () => {
134
134
  const array = ['a', 'b', 'c'];
135
135
  const asd = (value: string) => value.toUpperCase();
@@ -142,3 +142,22 @@ describe('fX: toDictionary', () => {
142
142
  expect(result).toStrictEqual(expectation);
143
143
  });
144
144
  });
145
+
146
+ describe('fx: remove', () => {
147
+ it.each([
148
+ [{}, '', {}],
149
+ [{}, 'not_there', {}],
150
+ [{}, 'not.there.again', {}],
151
+ [{ level1: true }, 'level1', {}],
152
+ [{ level1: true }, 'not_there', { level1: true }],
153
+ [{ level1: { level2: true } }, 'level1.level2', { level1: { } }],
154
+ [{ level1: { level2: true, other: true } }, 'level1.level2', { level1: { other: true } }],
155
+ [{ level1: { level2: true }, other: true }, 'level1.level2', { level1: { }, other: true }],
156
+ [{ level1: { level2: true }, other: true }, 'not_there.level1.level2', { level1: { level2: true }, other: true }],
157
+ [{ level1: { level2: true }, other: true }, 'level1', { other: true }],
158
+ ])('should evaluate %p as %p', (obj, path, expected) => {
159
+ const result = remove(obj, path);
160
+
161
+ expect(result).toStrictEqual(expected);
162
+ });
163
+ });