@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
@@ -125,6 +125,13 @@ export default {
125
125
  ROLES,
126
126
  ];
127
127
 
128
+ const clusterServiceIcons = {
129
+ [STATES_ENUM.IN_PROGRESS]: 'icon-spinner icon-spin',
130
+ [STATES_ENUM.HEALTHY]: 'icon-checkmark',
131
+ [STATES_ENUM.WARNING]: 'icon-warning',
132
+ [STATES_ENUM.UNHEALTHY]: 'icon-warning',
133
+ };
134
+
128
135
  return {
129
136
  nodeHeaders,
130
137
  constraints: [],
@@ -148,6 +155,7 @@ export default {
148
155
  clusterCounts,
149
156
  selectedTab: 'cluster-events',
150
157
  extensionCards: getApplicableExtensionEnhancements(this, ExtensionPoint.CARD, CardLocation.CLUSTER_DASHBOARD_CARD, this.$route),
158
+ clusterServiceIcons,
151
159
  };
152
160
  },
153
161
 
@@ -283,52 +291,51 @@ export default {
283
291
  clusterServices() {
284
292
  const services = [];
285
293
 
286
- CLUSTER_COMPONENTS.forEach((cs) => {
294
+ CLUSTER_COMPONENTS.forEach((name) => {
295
+ const component = this.getComponentStatus(name);
296
+
287
297
  services.push({
288
- name: cs,
289
- status: this.getComponentStatus(cs),
290
- labelKey: `clusterIndexPage.sections.componentStatus.${ cs }`,
298
+ name,
299
+ status: component.state,
300
+ labelKey: `clusterIndexPage.sections.componentStatus.component.${ name }.label`,
301
+ icon: this.clusterServiceIcons[component.state],
302
+ tooltip: component.tooltip,
303
+ goTo: () => null,
291
304
  });
292
305
  });
293
306
 
294
307
  if (this.cattleAgentNamespace) {
295
308
  services.push({
296
309
  name: 'cattle',
297
- status: this.cattleStatus,
298
- labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
310
+ status: this.cattleAgent.state,
311
+ labelKey: 'clusterIndexPage.sections.componentStatus.component.cattle.label',
312
+ icon: this.clusterServiceIcons[this.cattleAgent.state],
313
+ tooltip: this.cattleAgent.tooltip,
314
+ goTo: () => this.goToClusterService(this.cattleAgent),
299
315
  });
300
316
  }
301
317
 
302
318
  if (this.fleetAgentNamespace) {
303
319
  services.push({
304
320
  name: 'fleet',
305
- status: this.fleetStatus,
306
- labelKey: 'clusterIndexPage.sections.componentStatus.fleet',
321
+ status: this.fleetAgent.state,
322
+ labelKey: 'clusterIndexPage.sections.componentStatus.component.fleet.label',
323
+ icon: this.clusterServiceIcons[this.fleetAgent.state],
324
+ tooltip: this.fleetAgent.tooltip,
325
+ goTo: () => this.goToClusterService(this.fleetAgent),
307
326
  });
308
327
  }
309
328
 
310
329
  return services;
311
330
  },
312
331
 
313
- cattleStatus() {
314
- const resource = this.cattleDeployment;
315
-
316
- if (resource === 'loading') {
317
- return STATES_ENUM.IN_PROGRESS;
318
- }
319
-
320
- if (!resource || this.disconnected || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
321
- return STATES_ENUM.UNHEALTHY;
322
- }
323
-
324
- if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
325
- return STATES_ENUM.WARNING;
326
- }
332
+ cattleAgent() {
333
+ const resources = [this.cattleDeployment];
327
334
 
328
- return STATES_ENUM.HEALTHY;
335
+ return this.getAgentStatus(resources, { checkDisconnected: true });
329
336
  },
330
337
 
331
- fleetStatus() {
338
+ fleetAgent() {
332
339
  const resources = this.currentCluster.isLocal ? [
333
340
  /**
334
341
  * 'fleetStatefulSet' could take a while to be created by rancher.
@@ -339,23 +346,7 @@ export default {
339
346
  this.fleetStatefulSet
340
347
  ];
341
348
 
342
- if (resources.find((r) => r === 'loading')) {
343
- return STATES_ENUM.IN_PROGRESS;
344
- }
345
-
346
- for (const resource of resources) {
347
- if (!resource || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
348
- return STATES_ENUM.UNHEALTHY;
349
- }
350
- }
351
-
352
- for (const resource of resources) {
353
- if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
354
- return STATES_ENUM.WARNING;
355
- }
356
- }
357
-
358
- return STATES_ENUM.HEALTHY;
349
+ return this.getAgentStatus(resources);
359
350
  },
360
351
 
361
352
  totalCountGaugeInput() {
@@ -532,25 +523,61 @@ export default {
532
523
  }
533
524
  },
534
525
 
526
+ getAgentStatus(resources, opt = { checkDisconnected: false }) {
527
+ if (resources.find((resource) => resource === 'loading')) {
528
+ return { state: STATES_ENUM.IN_PROGRESS };
529
+ }
530
+
531
+ for (const resource of resources) {
532
+ if (
533
+ !resource ||
534
+ (opt.checkDisconnected && this.disconnected) || // cattle
535
+ resource.status.conditions?.find((c) => c.status !== 'True') ||
536
+ resource.metadata.state?.error
537
+ ) {
538
+ return {
539
+ resource,
540
+ tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.disconnected`),
541
+ state: STATES_ENUM.UNHEALTHY,
542
+ };
543
+ }
544
+ }
545
+
546
+ for (const resource of resources) {
547
+ if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
548
+ return {
549
+ resource,
550
+ tooltip: resource?.stateDescription || this.t(`clusterIndexPage.sections.componentStatus.tooltip.unavailableReplicas`),
551
+ state: STATES_ENUM.WARNING,
552
+ };
553
+ }
554
+ }
555
+
556
+ return { state: STATES_ENUM.HEALTHY };
557
+ },
558
+
535
559
  getComponentStatus(field) {
536
560
  const matching = (this.currentCluster?.status?.componentStatuses || []).filter((s) => s.name.startsWith(field));
537
561
 
538
562
  // If there's no matching component status, it's "healthy"
539
563
  if ( !matching.length ) {
540
- return STATES_ENUM.HEALTHY;
564
+ return { state: STATES_ENUM.HEALTHY };
541
565
  }
542
566
 
543
- const count = matching.reduce((acc, status) => {
544
- const conditions = status.conditions.find((c) => c.status !== 'True');
567
+ const errorConditions = matching.reduce((acc, status) => {
568
+ const condition = status.conditions.find((c) => c.status !== 'True');
545
569
 
546
- return !conditions ? acc : acc + 1;
547
- }, 0);
570
+ return !condition ? acc : [...acc, condition];
571
+ }, []);
548
572
 
549
- if (count > 0) {
550
- return STATES_ENUM.UNHEALTHY;
573
+ if (errorConditions.length > 0) {
574
+ return {
575
+ tooltip: errorConditions[0].message,
576
+ state: STATES_ENUM.UNHEALTHY
577
+ };
551
578
  }
552
579
 
553
- return STATES_ENUM.HEALTHY;
580
+ return { state: STATES_ENUM.HEALTHY };
554
581
  },
555
582
 
556
583
  showActions() {
@@ -578,6 +605,23 @@ export default {
578
605
  await provCluster.goToHarvesterCluster();
579
606
  } catch {
580
607
  }
608
+ },
609
+
610
+ goToClusterService(agent) {
611
+ if (!agent.resource || agent.state === STATES_ENUM.HEALTHY) {
612
+ return;
613
+ }
614
+
615
+ this.$router.push({
616
+ name: 'c-cluster-product-resource-namespace-id',
617
+ params: {
618
+ cluster: this.currentCluster.id,
619
+ product: 'explorer',
620
+ resource: agent.resource.type,
621
+ namespace: agent.resource.metadata.namespace,
622
+ id: agent.resource.metadata.name,
623
+ }
624
+ });
581
625
  }
582
626
  },
583
627
  };
@@ -722,21 +766,15 @@ export default {
722
766
  <div
723
767
  v-for="(service, i) in clusterServices"
724
768
  :key="i"
769
+ v-clean-tooltip="service.tooltip"
725
770
  class="k8s-service-status"
726
771
  :class="{[service.status]: true }"
727
772
  :data-testid="`k8s-service-${ service.name }`"
773
+ @click="service.goTo"
728
774
  >
729
775
  <i
730
- v-if="service.status === STATES_ENUM.IN_PROGRESS"
731
- class="icon icon-spinner icon-spin"
732
- />
733
- <i
734
- v-else-if="service.status === STATES_ENUM.HEALTHY"
735
- class="icon icon-checkmark"
736
- />
737
- <i
738
- v-else
739
- class="icon icon-warning"
776
+ class="icon"
777
+ :class="service.icon"
740
778
  />
741
779
  <div class="label">
742
780
  {{ t(service.labelKey) }}
@@ -948,6 +986,7 @@ export default {
948
986
 
949
987
  &.unhealthy {
950
988
  border-color: var(--error-border);
989
+ cursor: pointer;
951
990
 
952
991
  > I {
953
992
  color: var(--error)
@@ -955,6 +994,8 @@ export default {
955
994
  }
956
995
 
957
996
  &.warning {
997
+ cursor: pointer;
998
+
958
999
  > I {
959
1000
  color: var(--warning)
960
1001
  }