@rancher/shell 0.1.2 → 0.1.4

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 (347) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/rancher-logo.svg +1 -130
  3. package/assets/images/featured/img1.jpg +0 -0
  4. package/assets/images/featured.jpg +0 -0
  5. package/assets/images/generic-plugin.svg +7 -0
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/translations/en-us.yaml +209 -813
  10. package/assets/translations/zh-hans.yaml +28 -792
  11. package/components/ActionMenu.vue +3 -3
  12. package/components/AsyncButton.vue +17 -2
  13. package/components/ButtonDropdown.vue +4 -0
  14. package/components/Carousel.vue +291 -0
  15. package/components/CodeMirror.vue +6 -8
  16. package/components/CommunityLinks.vue +70 -19
  17. package/components/ContainerResourceLimit.vue +14 -0
  18. package/components/CruResource.vue +11 -3
  19. package/components/Dialog.vue +102 -0
  20. package/components/ExplorerMembers.vue +121 -0
  21. package/components/ExplorerProjectsNamespaces.vue +404 -0
  22. package/components/GrafanaDashboard.vue +17 -2
  23. package/components/IconMessage.vue +9 -1
  24. package/components/LocaleSelector.vue +114 -0
  25. package/components/PromptModal.vue +2 -3
  26. package/components/ResourceList/index.vue +1 -1
  27. package/components/ResourceTable.vue +9 -7
  28. package/components/SimpleBox.vue +6 -4
  29. package/components/SingleClusterInfo.vue +1 -1
  30. package/components/SortableTable/index.vue +18 -25
  31. package/components/SortableTable/selection.js +1 -0
  32. package/components/Tabbed/Tab.vue +5 -0
  33. package/components/Tabbed/index.vue +29 -2
  34. package/components/auth/AzureWarning.vue +5 -1
  35. package/components/auth/Principal.vue +2 -1
  36. package/components/auth/RoleDetailEdit.vue +18 -11
  37. package/components/fleet/FleetBundles.vue +8 -3
  38. package/components/fleet/FleetRepos.vue +0 -2
  39. package/components/fleet/FleetSummary.vue +6 -0
  40. package/components/form/KeyValue.vue +80 -58
  41. package/components/form/NameNsDescription.vue +12 -8
  42. package/components/form/NodeScheduling.vue +1 -1
  43. package/components/form/ResourceTabs/index.vue +5 -1
  44. package/components/form/WorkloadPorts.vue +1 -1
  45. package/components/formatter/ClusterLink.vue +3 -7
  46. package/components/formatter/WorkloadHealthScale.vue +1 -1
  47. package/components/nav/Header.vue +9 -9
  48. package/components/nav/NamespaceFilter.vue +10 -7
  49. package/components/nav/TopLevelMenu.vue +10 -65
  50. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  51. package/config/footer.js +13 -14
  52. package/config/labels-annotations.js +2 -1
  53. package/config/product/explorer.js +5 -4
  54. package/config/product/harvester-manager.js +64 -2
  55. package/config/product/legacy.js +0 -47
  56. package/config/product/manager.js +9 -0
  57. package/config/product/multi-cluster-apps.js +0 -12
  58. package/config/product/settings.js +12 -1
  59. package/config/product/uiplugins.js +17 -0
  60. package/config/settings.js +37 -72
  61. package/config/table-headers.js +0 -1
  62. package/config/types.js +9 -25
  63. package/config/uiplugins.js +60 -0
  64. package/content/docs/en-us/getting-started.md +1 -26
  65. package/core/plugin-routes.ts +34 -22
  66. package/core/plugin.ts +15 -3
  67. package/core/plugins-loader.js +2 -0
  68. package/core/plugins.js +91 -36
  69. package/core/types.ts +7 -1
  70. package/detail/provisioning.cattle.io.cluster.vue +15 -2
  71. package/detail/workload/index.vue +11 -5
  72. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  73. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  74. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  75. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  76. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  77. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  78. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  79. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  80. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  81. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +9 -3
  82. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  83. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  84. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  85. package/edit/auth/azuread.vue +44 -6
  86. package/edit/management.cattle.io.project.vue +2 -2
  87. package/edit/namespace.vue +17 -10
  88. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  89. package/edit/persistentvolume/index.vue +3 -0
  90. package/edit/persistentvolumeclaim.vue +1 -0
  91. package/edit/pod.vue +27 -0
  92. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  93. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +33 -5
  94. package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
  95. package/edit/service.vue +8 -6
  96. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  97. package/edit/workload/index.vue +375 -15
  98. package/edit/workload/mixins/workload.js +62 -7
  99. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  100. package/edit/workload/storage/Mount.vue +1 -0
  101. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  102. package/edit/workload/storage/azureDisk.vue +22 -2
  103. package/edit/workload/storage/azureFile.vue +20 -2
  104. package/edit/workload/storage/csi/index.vue +23 -1
  105. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  106. package/edit/workload/storage/index.vue +23 -49
  107. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  108. package/edit/workload/storage/vsphereVolume.vue +11 -1
  109. package/layouts/default.vue +63 -32
  110. package/layouts/error.vue +5 -1
  111. package/layouts/home.vue +14 -5
  112. package/layouts/plain.vue +10 -5
  113. package/list/harvesterhci.io.management.cluster.vue +74 -33
  114. package/list/management.cattle.io.setting.vue +3 -3
  115. package/list/namespace.vue +3 -5
  116. package/list/provisioning.cattle.io.cluster.vue +1 -1
  117. package/machine-config/amazonec2.vue +2 -0
  118. package/machine-config/harvester.vue +100 -51
  119. package/middleware/authenticated.js +56 -52
  120. package/mixins/form-validation.js +1 -1
  121. package/mixins/resource-fetch.js +3 -1
  122. package/models/catalog.cattle.io.uiplugin.js +34 -0
  123. package/models/cluster/node.js +25 -2
  124. package/models/fleet.cattle.io.bundle.js +27 -20
  125. package/models/harvesterhci.io.management.cluster.js +200 -5
  126. package/models/management.cattle.io.cluster.js +1 -1
  127. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  128. package/models/management.cattle.io.project.js +23 -2
  129. package/models/namespace.js +19 -3
  130. package/models/pod.js +19 -2
  131. package/models/provisioning.cattle.io.cluster.js +16 -6
  132. package/models/workload.js +9 -246
  133. package/models/workload.service.js +314 -0
  134. package/nuxt.config.js +80 -34
  135. package/package.json +107 -108
  136. package/pages/auth/login.vue +11 -2
  137. package/pages/auth/setup.vue +1 -1
  138. package/pages/c/_cluster/_product/members/index.vue +3 -93
  139. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  140. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  141. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  142. package/pages/c/_cluster/explorer/index.vue +72 -9
  143. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  144. package/pages/c/_cluster/mcapps/index.vue +1 -1
  145. package/pages/c/_cluster/settings/brand.vue +0 -40
  146. package/pages/c/_cluster/settings/links.vue +200 -0
  147. package/pages/c/_cluster/settings/performance.vue +19 -16
  148. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  149. package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
  150. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
  151. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
  152. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
  153. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
  154. package/pages/c/_cluster/uiplugins/index.vue +694 -0
  155. package/pages/diagnostic.vue +185 -101
  156. package/pages/docs/_doc.vue +3 -1
  157. package/pages/fail-whale.vue +1 -10
  158. package/pages/home.vue +21 -56
  159. package/pages/index.vue +18 -4
  160. package/pages/prefs.vue +108 -86
  161. package/pages/safeMode.vue +17 -0
  162. package/pages/support/index.vue +23 -15
  163. package/pkg/auto-import.js +44 -7
  164. package/pkg/dynamic-importer.lib.js +4 -0
  165. package/pkg/dynamic-plugin-loader.js +28 -0
  166. package/pkg/import.js +2 -2
  167. package/pkg/model-loader-require.lib.js +3 -0
  168. package/pkg/vue.config.js +9 -6
  169. package/plugins/dashboard-store/model-loader-require.js +12 -0
  170. package/plugins/dashboard-store/model-loader.js +4 -1
  171. package/plugins/dashboard-store/resource-class.js +12 -5
  172. package/plugins/formatters.js +15 -0
  173. package/plugins/plugin.js +56 -4
  174. package/plugins/steve/actions.js +1 -1
  175. package/plugins/steve/index.js +6 -4
  176. package/plugins/steve/mutations.js +1 -1
  177. package/plugins/steve/subscribe.js +89 -56
  178. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  179. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  180. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  181. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  182. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  183. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  184. package/scripts/build-pkg.sh +48 -2
  185. package/scripts/drone-build-pkg.sh +31 -0
  186. package/scripts/publish-shell.sh +11 -12
  187. package/scripts/serve-pkgs +17 -10
  188. package/scripts/sync-shell-deps +37 -0
  189. package/store/catalog.js +12 -9
  190. package/store/i18n.js +26 -12
  191. package/store/index.js +4 -181
  192. package/store/prefs.js +46 -2
  193. package/store/type-map.js +47 -33
  194. package/store/uiplugins.ts +15 -61
  195. package/utils/__tests__/object.test.ts +0 -24
  196. package/utils/__tests__/selector.test.ts +1 -1
  197. package/utils/cluster.js +1 -1
  198. package/utils/custom-validators.js +1 -12
  199. package/utils/dynamic-importer.js +5 -1
  200. package/utils/grafana.js +2 -6
  201. package/utils/socket.js +41 -20
  202. package/utils/string.js +1 -7
  203. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  204. package/utils/validators/formRules/index.ts +9 -1
  205. package/utils/validators/setting.js +0 -35
  206. package/yarn-error.log +195 -0
  207. package/components/FilterLabel.vue +0 -254
  208. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  209. package/components/VMConsoleBar.vue +0 -87
  210. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  211. package/components/dialog/harvester/BackupModal.vue +0 -117
  212. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  213. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  214. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  215. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  216. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  217. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  218. package/components/dialog/harvester/SupportBundle.vue +0 -217
  219. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  220. package/components/form/SerialConsole/index.vue +0 -267
  221. package/components/formatter/AttachVMWithName.vue +0 -46
  222. package/components/formatter/CloudInitType.vue +0 -27
  223. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  224. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  225. package/components/formatter/HarvesterDiskState.vue +0 -66
  226. package/components/formatter/HarvesterHostName.vue +0 -66
  227. package/components/formatter/HarvesterIpAddress.vue +0 -90
  228. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  229. package/components/formatter/HarvesterMigrationState.vue +0 -85
  230. package/components/formatter/HarvesterNodeName.vue +0 -49
  231. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  232. package/components/formatter/HarvesterVmState.vue +0 -123
  233. package/components/nav/HarvesterUpgrade.vue +0 -232
  234. package/components/novnc/NovncConsole.vue +0 -93
  235. package/components/novnc/NovncConsoleItem.vue +0 -89
  236. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  237. package/config/harvester-map.js +0 -44
  238. package/config/harvester-table-headers.js +0 -27
  239. package/config/product/harvester.js +0 -305
  240. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  241. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  242. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  243. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  244. package/detail/harvesterhci.io.host/index.vue +0 -243
  245. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  246. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  247. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  248. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  249. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  250. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  251. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  252. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  253. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  254. package/edit/harvesterhci.io.host/index.vue +0 -533
  255. package/edit/harvesterhci.io.keypair.vue +0 -112
  256. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  257. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  258. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  259. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  260. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  261. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  262. package/edit/harvesterhci.io.setting/index.vue +0 -201
  263. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  264. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  265. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  266. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  267. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  268. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  269. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  270. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  271. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  272. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  273. package/edit/harvesterhci.io.volume.vue +0 -195
  274. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  275. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  276. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  277. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  278. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  279. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  280. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  281. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  282. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  283. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  284. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  285. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  286. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  287. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  288. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  289. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  290. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  291. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  292. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  293. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  294. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  295. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  296. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  297. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  298. package/edit/workload/types/Deployment.vue +0 -377
  299. package/edit/workload/types/Generic.vue +0 -295
  300. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  301. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  302. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  303. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  304. package/list/harvesterhci.io.host/index.vue +0 -186
  305. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  306. package/list/harvesterhci.io.setting.vue +0 -241
  307. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  308. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  309. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  310. package/list/harvesterhci.io.volume.vue +0 -122
  311. package/list/kubevirt.io.virtualmachine.vue +0 -193
  312. package/mixins/harvester-vm/impl.js +0 -267
  313. package/mixins/harvester-vm/index.js +0 -1357
  314. package/models/harvester/configmap.js +0 -32
  315. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  316. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  317. package/models/harvester/harvesterhci.io.setting.js +0 -127
  318. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  319. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  320. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  321. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  322. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  323. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  324. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  325. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  326. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  327. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  328. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  329. package/models/harvester/management.cattle.io.setting.js +0 -40
  330. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  331. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  332. package/models/harvester/node.js +0 -255
  333. package/models/harvester/persistentvolumeclaim.js +0 -166
  334. package/models/harvester/pod.js +0 -185
  335. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  336. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  337. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  338. package/pages/c/_cluster/harvester/index.vue +0 -24
  339. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  340. package/pages/plugins.vue +0 -387
  341. package/pkg/model-loader.lib.js +0 -3
  342. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  343. package/server/verdaccio-middleware.js +0 -56
  344. package/store/harvester-common.js +0 -126
  345. package/utils/validators/vm-datavolumes.js +0 -38
  346. package/utils/validators/vm-image.js +0 -32
  347. package/utils/validators/vm.js +0 -221
@@ -1,14 +1,17 @@
1
1
  <script>
2
2
  import { CAPI } from '@shell/config/types';
3
3
  import AsyncButton from '@shell/components/AsyncButton';
4
+ import PromptModal from '@shell/components/PromptModal';
4
5
  import { downloadFile } from '@shell/utils/download';
5
6
  import { filterOnlyKubernetesClusters, filterHiddenLocalCluster } from '@shell/utils/cluster';
6
7
  import { sortBy } from '@shell/utils/sort';
7
- import { Checkbox } from '@components/Form/Checkbox';
8
8
 
9
9
  export default {
10
- layout: 'plain',
11
- components: { AsyncButton, Checkbox },
10
+ name: 'Diagnostic',
11
+ layout: 'plain',
12
+
13
+ components: { AsyncButton, PromptModal },
14
+
12
15
  async fetch() {
13
16
  const provClusters = await this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
14
17
  const readyClusters = provClusters.filter(c => c.mgmt?.isReady);
@@ -20,9 +23,11 @@ export default {
20
23
  clusterForCounts.forEach((cluster, i) => {
21
24
  finalCounts.push({
22
25
  id: cluster.id,
26
+ name: cluster.metadata?.name,
27
+ namespace: cluster.metadata?.namespace,
23
28
  capiId: cluster.mgmt?.id,
24
29
  counts: null,
25
- isTableVisible: i === 0
30
+ isTableVisible: !!(i === 0 && clusterForCounts.length === 1)
26
31
  });
27
32
  promises.push(this.$store.dispatch('management/request', { url: `/k8s/clusters/${ cluster.mgmt?.id }/v1/counts` }));
28
33
  });
@@ -47,7 +52,7 @@ export default {
47
52
 
48
53
  topTenForResponseTime = topTenForResponseTime.concat(sortedCount);
49
54
  topTenForResponseTime = sortBy(topTenForResponseTime, 'count:desc');
50
- topTenForResponseTime = topTenForResponseTime.splice(0, 10);
55
+ topTenForResponseTime = topTenForResponseTime.splice(0, 15);
51
56
 
52
57
  topTenForResponseTime.forEach((item, i) => {
53
58
  topTenForResponseTime[i].id = finalCounts[index].id;
@@ -63,58 +68,50 @@ export default {
63
68
  },
64
69
 
65
70
  data() {
71
+ const {
72
+ userAgent,
73
+ userAgentData,
74
+ language,
75
+ cookieEnabled,
76
+ hardwareConcurrency,
77
+ deviceMemory
78
+ } = window?.navigator;
79
+
66
80
  const systemInformation = {
67
- browserUserAgent: {
68
- label: this.t('about.diagnostic.systemInformation.browserUserAgent'),
69
- value: window?.navigator?.userAgent
81
+ browser: {
82
+ label: this.t('about.diagnostic.systemInformation.browser'),
83
+ value: this.t('about.diagnostic.systemInformation.browserInfo', {
84
+ userAgent, language, cookieEnabled
85
+ })
70
86
  },
71
- browserLanguage: {
72
- label: this.t('about.diagnostic.systemInformation.browserLanguage'),
73
- value: window?.navigator?.language
74
- },
75
- cookieEnabled: {
76
- label: this.t('about.diagnostic.systemInformation.cookieEnabled'),
77
- value: window?.navigator?.cookieEnabled
78
- },
79
- hardwareConcurrency: {
80
- label: this.t('about.diagnostic.systemInformation.hardwareConcurrency'),
81
- value: window?.navigator?.hardwareConcurrency
87
+ system: {
88
+ label: this.t('about.diagnostic.systemInformation.system'),
89
+ value: this.t('about.diagnostic.systemInformation.hardwareConcurrency', { hardwareConcurrency })
82
90
  },
91
+ jsMemory: {
92
+ label: this.t('about.diagnostic.systemInformation.jsMemory'),
93
+ value: ''
94
+ }
83
95
  };
84
96
 
85
- if (window?.navigator?.userAgentData?.platform) {
86
- systemInformation.os = {
87
- label: this.t('about.diagnostic.systemInformation.os'),
88
- value: window?.navigator?.userAgentData?.platform
89
- };
97
+ if ( userAgentData?.platform ) {
98
+ systemInformation.system.value = systemInformation.system.value.concat(', ', this.t('about.diagnostic.systemInformation.os', { platform: userAgentData.platform }));
90
99
  }
91
100
 
92
- if (window?.navigator?.deviceMemory) {
93
- systemInformation.deviceMemory = {
94
- label: this.t('about.diagnostic.systemInformation.deviceMemory'),
95
- value: window?.navigator?.deviceMemory
96
- };
101
+ if ( deviceMemory ) {
102
+ systemInformation.system.value = systemInformation.system.value.concat(', ', this.t('about.diagnostic.systemInformation.deviceMemory', { deviceMemory }));
97
103
  }
98
104
 
99
- if (window?.performance?.memory?.jsHeapSizeLimit) {
100
- systemInformation.memJsHeapLimit = {
101
- label: this.t('about.diagnostic.systemInformation.memJsHeapLimit'),
102
- value: window?.performance?.memory?.jsHeapSizeLimit
103
- };
105
+ if ( window?.performance?.memory?.jsHeapSizeLimit ) {
106
+ systemInformation.jsMemory.value += this.t('about.diagnostic.systemInformation.memJsHeapLimit', { jsHeapSizeLimit: window?.performance?.memory?.jsHeapSizeLimit });
104
107
  }
105
108
 
106
- if (window?.performance?.memory?.totalJSHeapSize) {
107
- systemInformation.memTotalJsHeapSize = {
108
- label: this.t('about.diagnostic.systemInformation.memTotalJsHeapSize'),
109
- value: window?.performance?.memory?.totalJSHeapSize
110
- };
109
+ if ( window?.performance?.memory?.totalJSHeapSize ) {
110
+ systemInformation.jsMemory.value += `, ${ this.t('about.diagnostic.systemInformation.memTotalJsHeapSize', { totalJSHeapSize: window?.performance?.memory?.totalJSHeapSize }) }`;
111
111
  }
112
112
 
113
- if (window?.performance?.memory?.usedJSHeapSize) {
114
- systemInformation.memUsedJsHeapSize = {
115
- label: this.t('about.diagnostic.systemInformation.memUsedJsHeapSize'),
116
- value: window?.performance?.memory?.usedJSHeapSize
117
- };
113
+ if ( window?.performance?.memory?.usedJSHeapSize ) {
114
+ systemInformation.jsMemory.value += `, ${ this.t('about.diagnostic.systemInformation.memUsedJsHeapSize', { usedJSHeapSize: window?.performance?.memory?.usedJSHeapSize }) }`;
118
115
  }
119
116
 
120
117
  // scroll logs container to the bottom
@@ -123,22 +120,26 @@ export default {
123
120
  return {
124
121
  systemInformation,
125
122
  topTenForResponseTime: null,
123
+ responseTimes: null,
126
124
  finalCounts: null,
127
125
  includeResponseTimes: true,
128
126
  storeMapping: this.$store?._modules?.root?.state,
129
127
  latestLogs: console.logs // eslint-disable-line no-console
130
128
  };
131
129
  },
130
+
132
131
  watch: {
133
132
  latestLogs() {
134
133
  this.scrollLogsToBottom();
135
134
  }
136
135
  },
136
+
137
137
  computed: {
138
- name() {
139
- return this.data;
138
+ clusterCount() {
139
+ return this.finalCounts?.length;
140
140
  }
141
141
  },
142
+
142
143
  methods: {
143
144
  scrollLogsToBottom() {
144
145
  this.$nextTick(() => {
@@ -147,12 +148,14 @@ export default {
147
148
  logsContainer.scrollTop = logsContainer.scrollHeight;
148
149
  });
149
150
  },
151
+
150
152
  generateKey(data) {
151
153
  const randomize = Math.random() * 10000;
152
154
 
153
155
  return `key_${ randomize }_${ data }`;
154
156
  },
155
- async downloadData(btnCb) {
157
+
158
+ downloadData(btnCb) {
156
159
  const date = new Date().toLocaleDateString();
157
160
  const time = new Date().toLocaleTimeString();
158
161
  const fileName = `rancher-diagnostic-data-${ date }-${ time.replaceAll(':', '_') }.json`;
@@ -160,25 +163,45 @@ export default {
160
163
  systemInformation: this.systemInformation,
161
164
  logs: this.latestLogs,
162
165
  storeMapping: this.parseStoreData(this.storeMapping),
163
- resourceCounts: this.finalCounts
166
+ resourceCounts: this.finalCounts,
167
+ responseTimes: this.responseTimes
164
168
  };
165
169
 
166
- if (this.includeResponseTimes) {
167
- const responseTimes = await this.gatherResponseTimes();
168
-
169
- data.responseTimes = responseTimes;
170
- }
171
-
172
170
  downloadFile(fileName, JSON.stringify(data), 'application/json')
173
171
  .then(() => btnCb(true))
174
172
  .catch(() => btnCb(false));
175
173
  },
174
+
175
+ setResourceResponseTiming(responseTimes) {
176
+ responseTimes?.forEach((res) => {
177
+ if ( res.outcome === 'success' ) {
178
+ const cluster = this.finalCounts.find(c => c.capiId === res.item.capiId);
179
+ const countIndex = cluster?.counts?.findIndex(c => c.resource === res.item.resource);
180
+
181
+ if ( (countIndex && countIndex !== -1) || countIndex === 0 ) {
182
+ this.$set(cluster?.counts[countIndex], 'durationMs', res.durationMs);
183
+ }
184
+ }
185
+ });
186
+ },
187
+
188
+ sumResourceCount(counts) {
189
+ return counts.reduce((a, b) => (a + b.count), 0);
190
+ },
191
+
192
+ nodeCount(counts) {
193
+ const resource = counts.findIndex(c => c.resource === 'node');
194
+
195
+ return counts[resource]?.count;
196
+ },
197
+
176
198
  toggleTable(area) {
177
199
  const itemIndex = this.finalCounts.findIndex(item => item.id === area);
178
200
 
179
201
  this.finalCounts[itemIndex].isTableVisible = !this.finalCounts[itemIndex].isTableVisible;
180
202
  },
181
- async gatherResponseTimes() {
203
+
204
+ async gatherResponseTimes(btnCb) {
182
205
  return await Promise.all(this.topTenForResponseTime.map((item) => {
183
206
  const t = Date.now();
184
207
 
@@ -190,11 +213,14 @@ export default {
190
213
  outcome: 'error', item, durationMs: Date.now() - t
191
214
  }));
192
215
  })).then((responseTimes) => {
193
- return responseTimes;
194
- });
216
+ this.responseTimes = responseTimes;
217
+ this.setResourceResponseTiming(responseTimes);
218
+ btnCb(true);
219
+ }).catch(() => btnCb(false));
195
220
  },
221
+
196
222
  parseStoreData(rootStore) {
197
- // clear potencial sensitive data
223
+ // clear potential sensitive data
198
224
  const disallowedDataKeys = [
199
225
  'aws',
200
226
  'digitalocean',
@@ -252,6 +278,21 @@ export default {
252
278
  });
253
279
 
254
280
  return cleanRootStore;
281
+ },
282
+
283
+ promptDownload(btnCb) {
284
+ const resources = [{ downloadData: this.downloadData, gatherResponseTimes: this.gatherResponseTimes }];
285
+
286
+ if ( !this.responseTimes ) {
287
+ this.$store.dispatch('management/promptModal', {
288
+ component: 'DiagnosticTimingsDialog',
289
+ resources
290
+ })
291
+ .then(() => btnCb(true))
292
+ .catch(() => btnCb(false));
293
+ } else {
294
+ this.downloadData(btnCb);
295
+ }
255
296
  }
256
297
  },
257
298
  };
@@ -260,27 +301,25 @@ export default {
260
301
  <template>
261
302
  <div>
262
303
  <div class="title-block mt-20 mb-40">
263
- <h1
264
- v-t="'about.diagnostic.title'"
265
- class="mt-20 mb-40"
266
- />
267
304
  <div>
268
- <Checkbox
269
- v-model="includeResponseTimes"
270
- v-tooltip.left="t('about.diagnostic.checkboxTooltip')"
271
- :label="t('about.diagnostic.checkboxLabel')"
305
+ <AsyncButton
306
+ mode="timing"
307
+ class="mr-20"
308
+ @click="gatherResponseTimes"
272
309
  />
273
310
  <AsyncButton
274
311
  mode="diagnostic"
275
- @click="downloadData"
312
+ @click="promptDownload"
276
313
  />
277
314
  </div>
278
315
  </div>
316
+
317
+ <!-- System info -->
279
318
  <div class="mb-40">
280
319
  <h2 class="mb-20">
281
320
  {{ t('about.diagnostic.systemInformation.subtitle') }}
282
321
  </h2>
283
- <table>
322
+ <table class="full-width">
284
323
  <thead>
285
324
  <tr>
286
325
  <th>Type</th>
@@ -289,33 +328,19 @@ export default {
289
328
  </thead>
290
329
  <tbody>
291
330
  <tr v-for="(item, objKey) in systemInformation" :key="objKey">
292
- <td>{{ item.label }}</td>
293
- <td>{{ item.value }}</td>
331
+ <template v-if="item.value.length">
332
+ <td>{{ item.label }}</td>
333
+ <td>{{ item.value }}</td>
334
+ </template>
294
335
  </tr>
295
336
  </tbody>
296
337
  </table>
297
338
  </div>
339
+
340
+ <!-- Resources -->
298
341
  <div class="mb-40">
299
342
  <h2 class="mb-20">
300
- {{ t('about.diagnostic.logs.subtitle') }}
301
- </h2>
302
- <ul class="logs-container">
303
- <li
304
- v-for="logEntry in latestLogs"
305
- :key="generateKey(logEntry.timestamp)"
306
- :class="logEntry.type"
307
- >
308
- <span class="log-entry-type">{{ logEntry.type }} :: </span>
309
- <span
310
- v-for="(arg, i) in logEntry.data"
311
- :key="i"
312
- >{{ arg }}</span>
313
- </li>
314
- </ul>
315
- </div>
316
- <div class="mb-40">
317
- <h2 class="mb-20">
318
- {{ t('about.diagnostic.resourceCounts.subtitle') }}
343
+ {{ t('about.diagnostic.resourceCounts', { count: clusterCount }) }}
319
344
  </h2>
320
345
  <div class="resources-count-container">
321
346
  <table
@@ -324,9 +349,12 @@ export default {
324
349
  class="full-width"
325
350
  >
326
351
  <thead @click="toggleTable(cluster.id)">
327
- <th colspan="2">
328
- <div>
329
- <span>{{ cluster.id }}</span>
352
+ <th colspan="4">
353
+ <div class="cluster-row">
354
+ <span>Cluster: <b>{{ cluster.name }}</b></span>
355
+ <span>Namespace: <b>{{ cluster.namespace }}</b></span>
356
+ <span>Total Resources: <b>{{ sumResourceCount(cluster.counts) }}</b></span>
357
+ <span>Nodes: <b>{{ nodeCount(cluster.counts) }}</b></span>
330
358
  <i
331
359
  class="icon"
332
360
  :class="{
@@ -338,21 +366,60 @@ export default {
338
366
  </th>
339
367
  </thead>
340
368
  <tbody v-show="cluster.isTableVisible">
369
+ <tr>
370
+ <th>
371
+ Resource
372
+ </th>
373
+ <th>
374
+ Count
375
+ </th>
376
+ <th>
377
+ Resource Timing (ms)
378
+ </th>
379
+ </tr>
380
+
341
381
  <tr v-for="item in cluster.counts" :key="item.resource">
342
- <td>{{ item.resource }}</td>
343
- <td>{{ item.count }}</td>
382
+ <template v-if="item.count > 0">
383
+ <td scope="row">
384
+ {{ item.resource }}
385
+ </td>
386
+ <td>{{ item.count }}</td>
387
+ <td>{{ item.durationMs || '-' }}</td>
388
+ </template>
344
389
  </tr>
345
390
  </tbody>
346
391
  </table>
347
392
  </div>
348
393
  </div>
394
+
395
+ <!-- Logs -->
396
+ <div class="mb-40">
397
+ <h2 class="mb-20">
398
+ {{ t('about.diagnostic.logs.subtitle') }}
399
+ </h2>
400
+ <ul class="logs-container">
401
+ <li
402
+ v-for="logEntry in latestLogs"
403
+ :key="generateKey(logEntry.timestamp)"
404
+ :class="logEntry.type"
405
+ >
406
+ <span class="log-entry-type">{{ logEntry.type }} :: </span>
407
+ <span
408
+ v-for="(arg, i) in logEntry.data"
409
+ :key="i"
410
+ >{{ arg }}</span>
411
+ </li>
412
+ </ul>
413
+ </div>
414
+
415
+ <PromptModal />
349
416
  </div>
350
417
  </template>
351
418
 
352
419
  <style lang="scss" scoped>
353
420
  .title-block {
354
421
  display: flex;
355
- justify-content: space-between;
422
+ justify-content: right;
356
423
  align-items: center;
357
424
 
358
425
  h1 {
@@ -383,6 +450,10 @@ table {
383
450
  justify-content: space-between;
384
451
  }
385
452
  }
453
+
454
+ tbody {
455
+ border-bottom: 1px solid var(--sortable-table-top-divider);
456
+ }
386
457
  }
387
458
 
388
459
  tr > td:first-of-type {
@@ -398,7 +469,7 @@ table {
398
469
 
399
470
  th {
400
471
  background-color: var(--sortable-table-top-divider);
401
- border-bottom: 1px solid var(--sortable-table-top-divider);
472
+ border-bottom: 1px solid var(--sortable-table-header-bg);
402
473
  }
403
474
 
404
475
  a {
@@ -458,11 +529,24 @@ table {
458
529
  }
459
530
 
460
531
  .resources-count-container {
461
- table:nth-child(even) {
462
- th {
463
- background-color: rgb(239, 239, 239);
464
- color: #000;
465
- }
532
+ .cluster-row {
533
+ display: grid;
534
+ grid-template-columns: repeat(4, 1fr) 20px;
535
+ grid-template-rows: 1fr;
536
+ align-content: center;
537
+ font-weight: normal;
538
+ }
539
+
540
+ tbody tr, tbody tr th {
541
+ background-color: var(--sortable-table-header-bg);
542
+ }
543
+
544
+ tbody tr th {
545
+ border-bottom: 1px solid var(--sortable-table-top-divider);
546
+ }
547
+
548
+ tbody tr:hover {
549
+ background-color: var(--sortable-table-top-divider);
466
550
  }
467
551
  }
468
552
  </style>
@@ -301,10 +301,12 @@ export default {
301
301
 
302
302
  thead > tr > th {
303
303
  background-color: var(--sortable-table-header-bg);
304
+ line-height: 1.75em;
304
305
  }
305
306
 
306
307
  tbody > tr.table-group > td {
307
- background-color: var(--sortable-table-selected-bg);
308
+ background-color: var(--sortable-table-header-bg);
309
+ font-weight: bold;
308
310
  }
309
311
 
310
312
  thead, tbody {
@@ -2,8 +2,6 @@
2
2
  import BrandImage from '@shell/components/BrandImage';
3
3
  import { mapGetters, mapState } from 'vuex';
4
4
  import { stringify } from '@shell/utils/error';
5
- import { getVendor } from '@shell/config/private-label';
6
- import { NAME as HARVESTER } from '@shell/config/product/harvester';
7
5
 
8
6
  export default {
9
7
  layout: 'home',
@@ -13,7 +11,7 @@ export default {
13
11
  data() {
14
12
  const store = this.$store;
15
13
 
16
- if ( process.client && !store.state.error && !store.state.cameFromError) {
14
+ if (!store.state.error && !store.state.cameFromError) {
17
15
  store.commit('cameFromError');
18
16
  this.$router.replace('/');
19
17
  }
@@ -29,13 +27,6 @@ export default {
29
27
  ...mapGetters(['isSingleProduct']),
30
28
 
31
29
  home() {
32
- const isOnlyHarvester = getVendor() === HARVESTER;
33
-
34
- if (isOnlyHarvester) {
35
- // This looks like it's covered by `isSingleProduct?.afterLoginRoute` too
36
- return 'c/local/harvester/harvesterhci.io.dashboard';
37
- }
38
-
39
30
  if (this.isSingleProduct?.afterLoginRoute) {
40
31
  return this.$router.resolve(this.isSingleProduct.afterLoginRoute).href;
41
32
  }
package/pages/home.vue CHANGED
@@ -6,7 +6,6 @@ import IndentedPanel from '@shell/components/IndentedPanel';
6
6
  import SortableTable from '@shell/components/SortableTable';
7
7
  import { BadgeState } from '@components/BadgeState';
8
8
  import CommunityLinks from '@shell/components/CommunityLinks';
9
- import SimpleBox from '@shell/components/SimpleBox';
10
9
  import SingleClusterInfo from '@shell/components/SingleClusterInfo';
11
10
  import { mapGetters, mapState } from 'vuex';
12
11
  import { MANAGEMENT, CAPI } from '@shell/config/types';
@@ -18,7 +17,6 @@ import { getVersionInfo, readReleaseNotes, markReadReleaseNotes, markSeenRelease
18
17
  import PageHeaderActions from '@shell/mixins/page-actions';
19
18
  import { getVendor } from '@shell/config/private-label';
20
19
  import { mapFeature, MULTI_CLUSTER } from '@shell/store/features';
21
- import { SETTING } from '@shell/config/settings';
22
20
  import { BLANK_CLUSTER } from '@shell/store';
23
21
  import { filterOnlyKubernetesClusters, filterHiddenLocalCluster } from '@shell/utils/cluster';
24
22
 
@@ -34,7 +32,6 @@ export default {
34
32
  SortableTable,
35
33
  BadgeState,
36
34
  CommunityLinks,
37
- SimpleBox,
38
35
  SingleClusterInfo,
39
36
  },
40
37
 
@@ -114,10 +111,6 @@ export default {
114
111
  return this.homePageCards?.setLoginPage;
115
112
  },
116
113
 
117
- showSidePanel() {
118
- return this.showCommercialSupport || this.showCommunityLinks;
119
- },
120
-
121
114
  clusterHeaders() {
122
115
  return [
123
116
  STATE,
@@ -170,24 +163,6 @@ export default {
170
163
  ];
171
164
  },
172
165
 
173
- showCommercialSupport() {
174
- const canEditSettings = (this.$store.getters['management/schemaFor'](MANAGEMENT.SETTING)?.resourceMethods || []).includes('PUT');
175
-
176
- const hasSupport = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SUPPORTED) || {};
177
-
178
- return !this.homePageCards.commercialSupportTip && hasSupport.value !== 'true' && canEditSettings;
179
- },
180
-
181
- showCommunityLinks() {
182
- const uiIssuesSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.UI_ISSUES) || {};
183
- const communityLinksSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.COMMUNITY_LINKS) || {};
184
-
185
- const hasSomethingToShow = communityLinksSetting?.value !== 'false' || !!( uiIssuesSetting.value && uiIssuesSetting.value !== '');
186
- const hiddenByPreference = this.homePageCards.communitySupportTip === true;
187
-
188
- return hasSomethingToShow && !hiddenByPreference;
189
- },
190
-
191
166
  ...mapGetters(['currentCluster', 'defaultClusterId']),
192
167
 
193
168
  kubeClusters() {
@@ -289,26 +264,9 @@ export default {
289
264
  </div>
290
265
  </div>
291
266
 
292
- <div class="row">
293
- <div :class="{'span-9': showSidePanel, 'span-12': !showSidePanel }" class="col">
294
- <SimpleBox
295
- id="migration"
296
- class="panel"
297
- :title="t('landing.gettingStarted.title')"
298
- :pref="HIDE_HOME_PAGE_CARDS"
299
- pref-key="migrationTip"
300
- >
301
- <div class="getting-started">
302
- <span>
303
- {{ t('landing.gettingStarted.body') }}
304
- </span>
305
- <nuxt-link :to="{name: 'docs-doc', params: {doc: 'getting-started'}}" class="getting-started-btn">
306
- {{ t('landing.learnMore') }}
307
- </nuxt-link>
308
- </div>
309
- </SimpleBox>
310
-
311
- <div v-if="!showSetLoginBanner" class="mt-5 mb-10 row">
267
+ <div class="row home-panels">
268
+ <div class="col main-panel">
269
+ <div v-if="!showSetLoginBanner" class="mb-10 row">
312
270
  <div class="col span-12">
313
271
  <Banner color="set-login-page" :closable="true" @close="closeSetLoginBanner()">
314
272
  <div>{{ t('landing.landingPrefs.title') }}</div>
@@ -316,7 +274,6 @@ export default {
316
274
  </Banner>
317
275
  </div>
318
276
  </div>
319
-
320
277
  <div class="row panel">
321
278
  <div v-if="mcm" class="col span-12">
322
279
  <SortableTable
@@ -354,7 +311,7 @@ export default {
354
311
  <template #col:name="{row}">
355
312
  <td>
356
313
  <span v-if="row.mgmt">
357
- <n-link v-if="row.mgmt.isReady" :to="{ name: 'c-cluster-explorer', params: { cluster: row.mgmt.id }}">
314
+ <n-link v-if="row.mgmt.isReady && !row.hasError" :to="{ name: 'c-cluster-explorer', params: { cluster: row.mgmt.id }}">
358
315
  {{ row.nameDisplay }}
359
316
  </n-link>
360
317
  <span v-else>{{ row.nameDisplay }}</span>
@@ -392,22 +349,30 @@ export default {
392
349
  </div>
393
350
  </div>
394
351
  </div>
395
- <div v-if="showSidePanel" class="col span-3">
396
- <CommunityLinks v-if="showCommunityLinks" :pref="HIDE_HOME_PAGE_CARDS" pref-key="communitySupportTip" class="mb-20" />
397
- <SimpleBox v-if="showCommercialSupport" :pref="HIDE_HOME_PAGE_CARDS" pref-key="commercialSupportTip" :title="t('landing.commercial.title')">
398
- <nuxt-link :to="{ path: 'support'}">
399
- {{ t('landing.commercial.body') }}
400
- </nuxt-link>
401
- </SimpleBox>
402
- </div>
352
+ <CommunityLinks class="col span-3 side-panel" />
403
353
  </div>
404
354
  </IndentedPanel>
405
355
  </div>
406
356
  </template>
407
357
  <style lang='scss' scoped>
358
+ .home-panels {
359
+ display: flex;
360
+ align-items: stretch;
361
+ .col {
362
+ margin: 0
363
+ }
364
+ .main-panel {
365
+ flex: auto;
366
+ }
367
+
368
+ .side-panel {
369
+ margin-left: 1.75%;
370
+ }
371
+ }
372
+
408
373
  .banner.info.whats-new, .banner.set-login-page {
409
374
  border: 0;
410
- margin-top: 10px;
375
+ margin-top: 0;
411
376
  display: flex;
412
377
  align-items: center;
413
378
  flex-direction: row;