@rancher/shell 3.0.12-rc.2 → 3.0.12-rc.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 (473) hide show
  1. package/apis/impl/apis.ts +6 -0
  2. package/apis/index.ts +26 -0
  3. package/apis/intf/resources-api/cluster-api.ts +18 -0
  4. package/apis/intf/resources-api/mgmt-api.ts +15 -0
  5. package/apis/intf/resources-api/resource-base.ts +107 -0
  6. package/apis/intf/resources-api/resource-constants.ts +147 -0
  7. package/apis/intf/resources-api/resources-api.ts +143 -0
  8. package/apis/intf/resources.ts +49 -0
  9. package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
  10. package/apis/intf/shell-api/proxy.ts +216 -0
  11. package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
  12. package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
  13. package/apis/intf/shell.ts +12 -6
  14. package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
  15. package/apis/resources/index.ts +22 -0
  16. package/apis/resources/resources-api-class.ts +187 -0
  17. package/apis/shell/__tests__/proxy.test.ts +369 -0
  18. package/apis/shell/index.ts +8 -1
  19. package/apis/shell/modal.ts +4 -1
  20. package/apis/shell/notifications.ts +9 -6
  21. package/apis/shell/proxy.ts +256 -0
  22. package/apis/shell/slide-in.ts +4 -1
  23. package/apis/vue-shim.d.ts +2 -1
  24. package/assets/data/aws-regions.json +4 -0
  25. package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
  26. package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
  27. package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
  28. package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
  29. package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
  30. package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
  31. package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
  32. package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
  33. package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
  34. package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
  35. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
  36. package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
  37. package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
  38. package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
  39. package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
  40. package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
  41. package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
  42. package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
  43. package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
  44. package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
  45. package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
  46. package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
  47. package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
  48. package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
  49. package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
  50. package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
  51. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
  52. package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
  53. package/assets/styles/base/_variables.scss +2 -0
  54. package/assets/styles/fonts/_fontstack.scss +132 -8
  55. package/assets/styles/global/_layout.scss +4 -0
  56. package/assets/translations/en-us.yaml +165 -45
  57. package/assets/translations/zh-hans.yaml +1 -7
  58. package/chart/monitoring/ClusterSelector.vue +0 -21
  59. package/chart/monitoring/index.vue +10 -1
  60. package/chart/monitoring/prometheus/index.vue +6 -3
  61. package/components/ActionDropdownShell.vue +2 -1
  62. package/components/CruResource.vue +161 -14
  63. package/components/CruResourceFooter.vue +9 -5
  64. package/components/ExplorerMembers.vue +8 -4
  65. package/components/ExplorerProjectsNamespaces.vue +11 -7
  66. package/components/GrowlManager.vue +4 -0
  67. package/components/InstallHelmCharts.vue +2 -2
  68. package/components/LandingPagePreference.vue +14 -5
  69. package/components/MgmtNodeList.vue +184 -0
  70. package/components/Resource/Detail/Card/StateCard/__tests__/composables.test.ts +90 -1
  71. package/components/Resource/Detail/Card/StateCard/composables.ts +57 -87
  72. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +61 -0
  73. package/components/Resource/Detail/Card/StatusCard/index.vue +61 -15
  74. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +17 -1
  75. package/components/Resource/Detail/Metadata/KeyValue.vue +5 -2
  76. package/components/Resource/Detail/Metadata/KeyValueRow.vue +2 -6
  77. package/components/Resource/Detail/Metadata/index.vue +6 -0
  78. package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
  79. package/components/Resource/Detail/SpacedRow.vue +3 -1
  80. package/components/Resource/Detail/TitleBar/index.vue +10 -11
  81. package/components/ResourceDetail/index.vue +1 -1
  82. package/components/ResourceList/Masthead.vue +19 -9
  83. package/components/ResourceList/index.vue +82 -1
  84. package/components/RichTranslation.vue +5 -2
  85. package/components/SelectIconGrid.vue +0 -10
  86. package/components/Setting.vue +1 -0
  87. package/components/SingleClusterInfo.vue +1 -0
  88. package/components/SortableTable/__tests__/sorting.test.ts +126 -0
  89. package/components/SortableTable/index.vue +6 -9
  90. package/components/SortableTable/selection.js +23 -5
  91. package/components/SortableTable/sorting.js +6 -3
  92. package/components/SubtleLink.vue +31 -6
  93. package/components/Tabbed/Tab.vue +29 -3
  94. package/components/Tabbed/index.vue +25 -3
  95. package/components/TableOfContents/TableOfContents.vue +109 -0
  96. package/components/TableOfContents/composables.ts +258 -0
  97. package/components/Window/ContainerShell.vue +21 -11
  98. package/components/Window/__tests__/ContainerShell.test.ts +107 -37
  99. package/components/Wizard.vue +23 -17
  100. package/components/fleet/AppCoChartGrid.vue +401 -0
  101. package/components/fleet/AppCoEmptyState.vue +127 -0
  102. package/components/fleet/AppCoPageHeader.vue +119 -0
  103. package/components/fleet/AppCoVersionSelect.vue +70 -0
  104. package/components/fleet/FleetBundles.vue +100 -12
  105. package/components/fleet/FleetClusterTargets/ClusterSelectionFields.vue +217 -0
  106. package/components/fleet/FleetClusterTargets/TargetsList.vue +123 -35
  107. package/components/fleet/FleetClusterTargets/index.vue +226 -161
  108. package/components/fleet/FleetIntro.vue +7 -3
  109. package/components/fleet/FleetNoWorkspaces.vue +7 -3
  110. package/components/fleet/FleetSecretSelector.vue +5 -3
  111. package/components/fleet/FleetValuesFrom.vue +8 -2
  112. package/components/fleet/GitRepoTargetTab.vue +0 -2
  113. package/components/fleet/HelmOpAdvancedTab.vue +19 -53
  114. package/components/fleet/HelmOpAppCoConfigTab.vue +593 -0
  115. package/components/fleet/HelmOpAppCoResourcesSection.vue +162 -0
  116. package/components/fleet/HelmOpResourcesSection.vue +82 -0
  117. package/components/fleet/HelmOpTargetOptionsSection.vue +89 -0
  118. package/components/fleet/HelmOpTargetTab.vue +64 -60
  119. package/components/fleet/HelmOpValuesTab.vue +129 -105
  120. package/components/fleet/__tests__/AppCoEmptyState.test.ts +71 -0
  121. package/components/fleet/__tests__/AppCoVersionSelect.test.ts +36 -0
  122. package/components/fleet/__tests__/ClusterSelectionFields.test.ts +62 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +402 -115
  124. package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
  125. package/components/fleet/__tests__/FleetSecretSelector.test.ts +16 -0
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +44 -0
  127. package/components/fleet/__tests__/HelmOpAppCoConfigTab.test.ts +59 -0
  128. package/components/fleet/__tests__/HelmOpAppCoResourcesSection.test.ts +62 -0
  129. package/components/fleet/__tests__/HelmOpResourcesSection.test.ts +43 -0
  130. package/components/fleet/__tests__/HelmOpTargetOptionsSection.test.ts +34 -0
  131. package/components/fleet/__tests__/HelmOpValuesTab.test.ts +39 -0
  132. package/components/fleet/__tests__/__snapshots__/AppCoEmptyState.test.ts.snap +97 -0
  133. package/components/fleet/__tests__/__snapshots__/AppCoVersionSelect.test.ts.snap +30 -0
  134. package/components/fleet/__tests__/__snapshots__/ClusterSelectionFields.test.ts.snap +209 -0
  135. package/components/fleet/__tests__/__snapshots__/HelmOpTargetOptionsSection.test.ts.snap +140 -0
  136. package/components/fleet/dashboard/Empty.vue +8 -4
  137. package/components/fleet/dashboard/ResourceCard.vue +28 -0
  138. package/components/fleet/dashboard/ResourceDetails.vue +28 -0
  139. package/components/fleet/dashboard/__tests__/ResourceCard.test.ts +87 -0
  140. package/components/form/ArrayList.vue +61 -4
  141. package/components/form/KeyValue.vue +23 -2
  142. package/components/form/LabeledSelect.vue +59 -4
  143. package/components/form/Labels.vue +22 -3
  144. package/components/form/NameNsDescription.vue +24 -5
  145. package/components/form/ResourceTabs/index.vue +1 -0
  146. package/components/form/Security.vue +6 -2
  147. package/components/form/WorkloadPorts.vue +2 -7
  148. package/components/form/__tests__/NameNsDescription.test.ts +75 -0
  149. package/components/form/__tests__/Security.test.ts +76 -0
  150. package/components/formatter/Autoscaler.vue +4 -4
  151. package/components/formatter/ClusterKubeVersion.vue +27 -0
  152. package/components/formatter/ClusterLink.vue +1 -7
  153. package/components/formatter/ClusterProvider.vue +6 -10
  154. package/components/formatter/FleetSummaryGraph.vue +0 -3
  155. package/components/formatter/InternalExternalIP.vue +10 -4
  156. package/components/formatter/MachineSummaryGraph.vue +1 -1
  157. package/components/formatter/PodsUsage.vue +2 -2
  158. package/components/formatter/ServiceTargets.vue +26 -7
  159. package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
  160. package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
  161. package/components/formatter/__tests__/InternalExternalIP.test.ts +132 -0
  162. package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
  163. package/components/formatter/__tests__/ServiceTargets.test.ts +412 -0
  164. package/components/nav/Header.vue +4 -0
  165. package/components/nav/NamespaceFilter.vue +2 -2
  166. package/components/nav/TopLevelMenu.helper.ts +15 -3
  167. package/components/nav/TopLevelMenu.vue +22 -6
  168. package/components/nav/__tests__/Header.test.ts +15 -0
  169. package/components/nav/__tests__/TopLevelMenu.test.ts +263 -21
  170. package/components/templates/default.vue +9 -4
  171. package/components/templates/home.vue +23 -0
  172. package/components/templates/plain.vue +23 -0
  173. package/components/templates/standalone.vue +17 -0
  174. package/composables/useFormValidation.ts +93 -0
  175. package/composables/useHelmOpResources.test.ts +56 -0
  176. package/composables/useHelmOpResources.ts +32 -0
  177. package/composables/useStateColor.test.ts +325 -0
  178. package/composables/useStateColor.ts +128 -0
  179. package/composables/useVeeValidateField.test.ts +159 -0
  180. package/composables/useVeeValidateField.ts +67 -0
  181. package/config/home-links.js +1 -1
  182. package/config/labels-annotations.js +1 -0
  183. package/config/pagination-table-headers.js +18 -1
  184. package/config/product/explorer.js +17 -4
  185. package/config/product/manager.js +84 -21
  186. package/config/router/index.js +16 -0
  187. package/config/router/navigation-guards/__tests__/authentication.test.ts +130 -0
  188. package/config/router/navigation-guards/authentication.js +10 -4
  189. package/config/router/routes.js +26 -6
  190. package/config/settings.ts +0 -2
  191. package/config/table-headers.js +23 -5
  192. package/config/types.js +11 -1
  193. package/core/__tests__/plugin-products.test.ts +904 -20
  194. package/core/plugin-products-base.ts +110 -10
  195. package/core/plugin-products.ts +4 -0
  196. package/core/plugin-types.ts +194 -31
  197. package/core/plugin.ts +18 -7
  198. package/core/productDebugger.js +9 -4
  199. package/core/types-provisioning.ts +77 -31
  200. package/core/types.ts +72 -22
  201. package/detail/__tests__/pod.test.ts +41 -0
  202. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +114 -0
  203. package/detail/__tests__/workload.test.ts +3 -152
  204. package/detail/catalog.cattle.io.clusterrepo.vue +1 -1
  205. package/detail/harvesterhci.io.management.cluster.vue +6 -2
  206. package/detail/pod.vue +1 -1
  207. package/detail/provisioning.cattle.io.cluster.vue +34 -14
  208. package/detail/workload/index.vue +12 -55
  209. package/edit/__tests__/catalog.cattle.io.clusterrepo.test.ts +248 -0
  210. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +105 -0
  211. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
  212. package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/index.test.ts.snap +1 -0
  213. package/edit/auth/__tests__/azuread.test.ts +247 -39
  214. package/edit/auth/__tests__/github.test.ts +234 -0
  215. package/edit/auth/__tests__/oidc.test.ts +26 -6
  216. package/edit/auth/__tests__/saml.test.ts +196 -0
  217. package/edit/auth/azuread.vue +197 -56
  218. package/edit/auth/github.vue +72 -13
  219. package/edit/auth/ldap/__tests__/index.test.ts +206 -0
  220. package/edit/auth/ldap/config.vue +8 -0
  221. package/edit/auth/ldap/index.vue +75 -1
  222. package/edit/auth/oidc.vue +119 -73
  223. package/edit/auth/saml.vue +76 -12
  224. package/edit/catalog.cattle.io.clusterrepo.vue +140 -32
  225. package/edit/fleet.cattle.io.helmop.vue +491 -136
  226. package/edit/management.cattle.io.user.vue +5 -2
  227. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
  228. package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
  229. package/edit/networking.k8s.io.ingress/index.vue +75 -20
  230. package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
  231. package/edit/provisioning.cattle.io.cluster/index.vue +11 -7
  232. package/edit/provisioning.cattle.io.cluster/rke2.vue +92 -14
  233. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +22 -0
  234. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
  235. package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
  236. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
  237. package/edit/secret/__tests__/ssh.test.ts +5 -6
  238. package/edit/secret/basic.vue +31 -0
  239. package/edit/secret/index.vue +68 -17
  240. package/edit/secret/registry.vue +38 -0
  241. package/edit/secret/ssh.vue +29 -0
  242. package/edit/secret/tls.vue +30 -0
  243. package/edit/service.vue +4 -4
  244. package/edit/workload/Upgrading.vue +3 -3
  245. package/edit/workload/__tests__/Upgrading.test.ts +6 -9
  246. package/edit/workload/mixins/workload.js +2 -1
  247. package/list/fleet.cattle.io.bundle.vue +7 -104
  248. package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
  249. package/list/group.principal.vue +5 -4
  250. package/list/harvesterhci.io.management.cluster.vue +8 -9
  251. package/list/management.cattle.io.user.vue +12 -9
  252. package/list/provisioning.cattle.io.cluster.vue +268 -180
  253. package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
  254. package/mixins/__tests__/auth-config.test.ts +90 -0
  255. package/mixins/__tests__/chart.test.ts +206 -0
  256. package/mixins/__tests__/resource-fetch-api-pagination.test.ts +48 -0
  257. package/mixins/auth-config.js +7 -0
  258. package/mixins/brand.js +2 -1
  259. package/mixins/chart.js +22 -9
  260. package/mixins/child-hook.js +12 -6
  261. package/mixins/create-edit-view/impl.js +5 -3
  262. package/mixins/resource-fetch-api-pagination.js +62 -6
  263. package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +57 -0
  264. package/models/__tests__/compliance.cattle.io.clusterscan.test.ts +144 -0
  265. package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
  266. package/models/__tests__/fleet-application.test.ts +175 -0
  267. package/models/__tests__/fleet.cattle.io.bundle.test.ts +169 -0
  268. package/models/__tests__/fleet.cattle.io.helmop.test.ts +84 -0
  269. package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
  270. package/models/__tests__/management.cattle.io.node.ts +28 -5
  271. package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
  272. package/models/__tests__/namespace.test.ts +36 -0
  273. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +81 -11
  274. package/models/__tests__/workload.test.ts +401 -26
  275. package/models/base-cluster.x-k8s.io.js +26 -0
  276. package/models/catalog.cattle.io.clusterrepo.js +28 -4
  277. package/models/cluster.js +1 -1
  278. package/models/cluster.x-k8s.io.machine.js +4 -22
  279. package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
  280. package/models/cluster.x-k8s.io.machineset.js +2 -20
  281. package/models/compliance.cattle.io.clusterscan.js +165 -2
  282. package/models/ext.cattle.io.kubeconfig.ts +4 -7
  283. package/models/fleet-application.js +7 -1
  284. package/models/fleet.cattle.io.helmop.js +20 -1
  285. package/models/management.cattle.io.cluster.js +434 -41
  286. package/models/management.cattle.io.node.js +50 -7
  287. package/models/management.cattle.io.nodepool.js +1 -1
  288. package/models/namespace.js +1 -1
  289. package/models/networking.k8s.io.ingress.js +12 -4
  290. package/models/pod.js +33 -1
  291. package/models/provisioning.cattle.io.cluster.js +51 -334
  292. package/models/rke.cattle.io.etcdsnapshot.js +1 -2
  293. package/models/workload.js +108 -13
  294. package/models/workload.service.js +5 -0
  295. package/package.json +22 -39
  296. package/pages/__tests__/readme.test.ts +49 -0
  297. package/pages/about.vue +5 -6
  298. package/pages/auth/login.vue +0 -35
  299. package/pages/auth/setup.vue +13 -3
  300. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +2 -2
  301. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +10 -1
  302. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +76 -0
  303. package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +93 -0
  304. package/pages/c/_cluster/apps/charts/chart.vue +62 -9
  305. package/pages/c/_cluster/apps/charts/index.vue +48 -10
  306. package/pages/c/_cluster/apps/charts/install.vue +122 -113
  307. package/pages/c/_cluster/auth/roles/index.vue +5 -4
  308. package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
  309. package/pages/c/_cluster/explorer/index.vue +5 -49
  310. package/pages/c/_cluster/explorer/workload-dashboard/ByNamespaceSection.vue +31 -0
  311. package/pages/c/_cluster/explorer/workload-dashboard/ByStateSection.vue +138 -0
  312. package/pages/c/_cluster/explorer/workload-dashboard/ByTypeSection.vue +30 -0
  313. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadCard.vue +155 -0
  314. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadNamespaceCard.vue +142 -0
  315. package/pages/c/_cluster/explorer/workload-dashboard/WorkloadTypeCard.vue +159 -0
  316. package/pages/c/_cluster/explorer/workload-dashboard/__tests__/composable.test.ts +561 -0
  317. package/pages/c/_cluster/explorer/workload-dashboard/composable.ts +440 -0
  318. package/pages/c/_cluster/explorer/workload-dashboard/index.vue +187 -0
  319. package/pages/c/_cluster/explorer/workload-dashboard/types.ts +80 -0
  320. package/pages/c/_cluster/fleet/application/create.vue +187 -136
  321. package/pages/c/_cluster/fleet/application/index.vue +5 -3
  322. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailBody.vue +338 -0
  323. package/pages/c/_cluster/fleet/application/suse-app-collection/ChartDetailHeader.vue +121 -0
  324. package/pages/c/_cluster/fleet/application/suse-app-collection/chart.vue +369 -0
  325. package/pages/c/_cluster/fleet/application/suse-app-collection/charts.vue +248 -0
  326. package/pages/c/_cluster/fleet/application/suse-app-collection/credentials.vue +310 -0
  327. package/pages/c/_cluster/fleet/index.vue +2 -2
  328. package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
  329. package/pages/c/_cluster/istio/index.vue +21 -6
  330. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -0
  331. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +815 -2
  332. package/pages/c/_cluster/uiplugins/index.vue +218 -197
  333. package/pages/diagnostic.vue +13 -17
  334. package/pages/fail-whale.vue +30 -7
  335. package/pages/home.vue +93 -306
  336. package/pages/readme.vue +88 -0
  337. package/plugins/clean-html.d.ts +9 -0
  338. package/plugins/dashboard-store/__tests__/resource-class.test.ts +181 -0
  339. package/plugins/dashboard-store/actions.js +40 -18
  340. package/plugins/dashboard-store/resource-class.js +67 -9
  341. package/plugins/steve/__tests__/actions.test.ts +212 -0
  342. package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
  343. package/plugins/steve/actions.js +96 -0
  344. package/plugins/steve/steve-pagination-utils.ts +12 -4
  345. package/plugins/steve/subscribe.js +35 -5
  346. package/rancher-components/Accordion/Accordion.vue +53 -9
  347. package/rancher-components/Form/Checkbox/Checkbox.vue +14 -0
  348. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +10 -4
  349. package/rancher-components/Form/LabeledInput/LabeledInput.vue +7 -52
  350. package/rancher-components/Form/Radio/RadioButton.vue +17 -1
  351. package/rancher-components/Form/Radio/RadioGroup.vue +10 -0
  352. package/rancher-components/Pill/RcTag/RcTag.vue +3 -2
  353. package/rancher-components/RcButton/RcButton.test.ts +140 -1
  354. package/rancher-components/RcButton/RcButton.vue +126 -17
  355. package/rancher-components/RcButton/types.ts +3 -0
  356. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
  357. package/rancher-components/RcItemCard/RcItemCard.test.ts +18 -0
  358. package/rancher-components/RcItemCard/RcItemCard.vue +2 -2
  359. package/rancher-components/RcSection/RcSection.vue +28 -3
  360. package/scripts/extension/helm/package/Dockerfile +1 -1
  361. package/scripts/test-plugins-build.sh +2 -1
  362. package/store/__tests__/catalog.test.ts +115 -1
  363. package/store/__tests__/notifications.test.ts +434 -0
  364. package/store/__tests__/type-map.test.ts +556 -1
  365. package/store/action-menu.js +8 -3
  366. package/store/auth.js +1 -1
  367. package/store/aws.js +27 -16
  368. package/store/catalog.js +84 -3
  369. package/store/digitalocean.js +20 -38
  370. package/store/index.js +2 -0
  371. package/store/linode.js +25 -40
  372. package/store/plugins.js +7 -4
  373. package/store/pnap.js +1 -0
  374. package/store/type-map.js +111 -29
  375. package/tsconfig.paths.json +8 -8
  376. package/types/components/buttonGroup.ts +5 -0
  377. package/types/kube/kube-api.ts +14 -1
  378. package/types/rancher/steve.api.ts +12 -12
  379. package/types/resources/settings.d.ts +2 -1
  380. package/types/shell/index.d.ts +206 -72
  381. package/types/store/dashboard-store.types.ts +108 -11
  382. package/types/store/pagination.types.ts +6 -3
  383. package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
  384. package/utils/__tests__/async.test.ts +87 -0
  385. package/utils/__tests__/auth.test.ts +273 -0
  386. package/utils/__tests__/aws.test.ts +140 -0
  387. package/utils/__tests__/banners.test.ts +176 -0
  388. package/utils/__tests__/chart.test.ts +64 -1
  389. package/utils/__tests__/color.test.ts +226 -0
  390. package/utils/__tests__/computed.test.ts +193 -0
  391. package/utils/__tests__/cspAdaptor.test.ts +163 -0
  392. package/utils/__tests__/dom.test.ts +81 -0
  393. package/utils/__tests__/duration.test.ts +176 -0
  394. package/utils/__tests__/dynamic-importer.test.ts +102 -0
  395. package/utils/__tests__/fleet-appco.test.ts +312 -0
  396. package/utils/__tests__/fleet.test.ts +340 -0
  397. package/utils/__tests__/ingress.test.ts +553 -0
  398. package/utils/__tests__/kube.test.ts +68 -0
  399. package/utils/__tests__/monitoring.test.ts +130 -0
  400. package/utils/__tests__/namespace-filter.test.ts +109 -0
  401. package/utils/__tests__/object.test.ts +22 -0
  402. package/utils/__tests__/pagination-utils.test.ts +361 -0
  403. package/utils/__tests__/parse-externalid.test.ts +137 -0
  404. package/utils/__tests__/perf-setting.utils.test.ts +98 -0
  405. package/utils/__tests__/platform.test.ts +91 -0
  406. package/utils/__tests__/poller-sequential.test.ts +177 -0
  407. package/utils/__tests__/poller.test.ts +170 -0
  408. package/utils/__tests__/position.test.ts +237 -0
  409. package/utils/__tests__/promise.test.ts +346 -0
  410. package/utils/__tests__/provider.test.ts +51 -1
  411. package/utils/__tests__/queue.test.ts +232 -0
  412. package/utils/__tests__/release-notes.test.ts +221 -0
  413. package/utils/__tests__/router.test.js +254 -1
  414. package/utils/__tests__/select.test.ts +208 -0
  415. package/utils/__tests__/settings.test.ts +140 -0
  416. package/utils/__tests__/sort-utils.test.ts +301 -0
  417. package/utils/__tests__/string-utils.test.ts +798 -0
  418. package/utils/__tests__/string.test.ts +23 -1
  419. package/utils/__tests__/style.test.ts +154 -0
  420. package/utils/__tests__/svg-filter.test.ts +184 -0
  421. package/utils/__tests__/time.test.ts +265 -1
  422. package/utils/__tests__/title.test.ts +47 -0
  423. package/utils/__tests__/units.test.ts +417 -0
  424. package/utils/__tests__/versions.test.ts +128 -0
  425. package/utils/__tests__/width.test.ts +53 -0
  426. package/utils/__tests__/window.test.ts +158 -0
  427. package/utils/__tests__/xccdf.test.ts +511 -0
  428. package/utils/chart.js +36 -0
  429. package/utils/crypto/__tests__/browserHashUtils.test.ts +98 -0
  430. package/utils/crypto/__tests__/index.test.ts +144 -0
  431. package/utils/duration.ts +104 -0
  432. package/utils/dynamic-content/__tests__/notification-handler.test.ts +196 -0
  433. package/utils/dynamic-content/info.ts +2 -1
  434. package/utils/error.js +13 -0
  435. package/utils/fleet-appco.ts +323 -0
  436. package/utils/fleet.ts +13 -3
  437. package/utils/gatekeeper/__tests__/util.test.ts +174 -0
  438. package/utils/gc/__tests__/gc-interval.test.ts +119 -0
  439. package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
  440. package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
  441. package/utils/gc/__tests__/gc.test.ts +487 -0
  442. package/utils/ingress.ts +9 -1
  443. package/utils/object.js +22 -2
  444. package/utils/pagination-utils.ts +2 -1
  445. package/utils/provider.ts +12 -0
  446. package/utils/string.js +25 -2
  447. package/utils/uiplugins.ts +5 -5
  448. package/utils/validators/__tests__/cluster-name.test.ts +110 -0
  449. package/utils/validators/__tests__/container-images.test.ts +104 -0
  450. package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
  451. package/utils/validators/__tests__/flow-output.test.ts +91 -0
  452. package/utils/validators/__tests__/index.test.ts +481 -0
  453. package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
  454. package/utils/validators/__tests__/logging-outputs.test.ts +58 -0
  455. package/utils/validators/__tests__/misc-validators.test.ts +246 -0
  456. package/utils/validators/__tests__/monitoring-route.test.ts +119 -0
  457. package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
  458. package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
  459. package/utils/validators/__tests__/role-template.test.ts +149 -0
  460. package/utils/validators/__tests__/service.test.ts +283 -0
  461. package/utils/validators/__tests__/setting.test.js +32 -0
  462. package/utils/validators/formRules/__tests__/index.test.ts +50 -0
  463. package/utils/validators/formRules/index.ts +5 -5
  464. package/utils/validators/machine-pool.ts +1 -1
  465. package/utils/validators/setting.js +18 -3
  466. package/utils/xccdf.ts +415 -0
  467. package/vue.config.js +1 -1
  468. package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
  469. package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
  470. package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
  471. package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
  472. package/pages/support/index.vue +0 -264
  473. package/utils/duration.js +0 -43
@@ -12,6 +12,7 @@ import { KEY } from '@shell/utils/platform';
12
12
  import { getVersionInfo } from '@shell/utils/version';
13
13
  import { SETTING } from '@shell/config/settings';
14
14
  import { getProductFromRoute } from '@shell/utils/router';
15
+ import { NAME as EXPLORER } from '@shell/config/product/explorer';
15
16
  import { isRancherPrime } from '@shell/config/version';
16
17
  import Pinned from '@shell/components/nav/Pinned';
17
18
  import sideNavService from '@shell/components/nav/TopLevelMenu.helper';
@@ -98,6 +99,17 @@ export default {
98
99
  return count?.summary.count;
99
100
  },
100
101
 
102
+ routeComboActive() {
103
+ if (!this.routeCombo || !this.isCurrRouteClusterExplorer) {
104
+ return false;
105
+ }
106
+
107
+ const ready = [...this.appBar.pinFiltered, ...this.appBar.clustersFiltered].filter((c) => c.ready);
108
+ const readyCount = ready.length;
109
+
110
+ return readyCount > 1 || (readyCount === 1 && this.clusterId !== ready[0].id);
111
+ },
112
+
101
113
  // New
102
114
  search() {
103
115
  return (this.clusterFilter || '').toLowerCase();
@@ -226,7 +238,7 @@ export default {
226
238
  },
227
239
 
228
240
  isCurrRouteClusterExplorer() {
229
- return this.$route?.name?.startsWith('c-cluster');
241
+ return this.$route?.name?.startsWith('c-cluster') && this.productFromRoute === EXPLORER;
230
242
  },
231
243
 
232
244
  productFromRoute() {
@@ -382,11 +394,15 @@ export default {
382
394
  },
383
395
 
384
396
  handleKeyComboClick() {
397
+ if (!this.isCurrRouteClusterExplorer) {
398
+ return;
399
+ }
400
+
385
401
  this.routeCombo = !this.routeCombo;
386
402
  },
387
403
 
388
404
  clusterMenuClick(ev, cluster) {
389
- if (this.routeCombo) {
405
+ if (this.routeComboActive) {
390
406
  ev.preventDefault();
391
407
 
392
408
  if (this.isCurrRouteClusterExplorer && this.productFromRoute === this.currentProduct?.name) {
@@ -423,7 +439,7 @@ export default {
423
439
  },
424
440
 
425
441
  async goToHarvesterCluster() {
426
- const localCluster = this.$store.getters['management/all'](CAPI.RANCHER_CLUSTER).find((C) => C.id === 'fleet-local/local');
442
+ const localCluster = this.$store.getters['management/byId'](CAPI.RANCHER_CLUSTER, 'fleet-local/local');
427
443
 
428
444
  try {
429
445
  await localCluster.goToHarvesterCluster();
@@ -446,7 +462,7 @@ export default {
446
462
  content = this.shown ? null : contentText;
447
463
 
448
464
  // if key combo is pressed, then we update the tooltip as well
449
- } else if (this.routeCombo &&
465
+ } else if (this.routeComboActive &&
450
466
  typeof item === 'object' &&
451
467
  !Array.isArray(item) &&
452
468
  item !== null &&
@@ -706,7 +722,7 @@ export default {
706
722
  <ClusterIconMenu
707
723
  v-clean-tooltip="getTooltipConfig(c, true)"
708
724
  :cluster="c"
709
- :route-combo="routeCombo"
725
+ :route-combo="routeComboActive"
710
726
  class="rancher-provider-icon"
711
727
  />
712
728
  <div
@@ -785,7 +801,7 @@ export default {
785
801
  <ClusterIconMenu
786
802
  v-clean-tooltip="getTooltipConfig(c, true)"
787
803
  :cluster="c"
788
- :route-combo="routeCombo"
804
+ :route-combo="routeComboActive"
789
805
  class="rancher-provider-icon"
790
806
  />
791
807
  <div
@@ -157,6 +157,21 @@ describe('component: Header', () => {
157
157
 
158
158
  expect((wrapper.vm as any).disableWorkspaceSwitcher).toBe(true);
159
159
  });
160
+
161
+ it.each([
162
+ ['c-cluster-fleet-application-appco-credentials', '/c/local/fleet/application/suse-app-collection/credentials'],
163
+ ['c-cluster-fleet-application-appco-charts', '/c/local/fleet/application/suse-app-collection/charts'],
164
+ ['c-cluster-fleet-application-appco-chart', '/c/local/fleet/application/suse-app-collection/chart'],
165
+ ])('should disable Workspace Switcher on AppCo page %s (via route meta)', (name, path) => {
166
+ const wrapper = createWrapper({
167
+ name,
168
+ path,
169
+ params: {},
170
+ meta: { disableWorkspaceSwitcher: true },
171
+ });
172
+
173
+ expect((wrapper.vm as any).disableWorkspaceSwitcher).toBe(true);
174
+ });
160
175
  });
161
176
 
162
177
  describe('showFilter', () => {
@@ -110,28 +110,28 @@ describe('topLevelMenu', () => {
110
110
  id: 'an-id1',
111
111
  mgmt: { id: 'an-id1' },
112
112
  nameDisplay: 'c-cluster',
113
- isReady: true
113
+ canExplore: true
114
114
  },
115
115
  {
116
116
  name: 'x33-cwf5-name',
117
117
  id: 'an-id2',
118
118
  mgmt: { id: 'an-id2' },
119
119
  nameDisplay: 'a-cluster',
120
- isReady: true
120
+ canExplore: true
121
121
  },
122
122
  {
123
123
  name: 'x34-cwf5-name',
124
124
  id: 'an-id3',
125
125
  mgmt: { id: 'an-id3' },
126
126
  nameDisplay: 'b-cluster',
127
- isReady: true
127
+ canExplore: true
128
128
  },
129
129
  {
130
130
  name: 'local-name',
131
131
  id: 'local',
132
132
  mgmt: { id: 'local' },
133
133
  nameDisplay: 'local',
134
- isReady: true
134
+ canExplore: true
135
135
  },
136
136
  ])
137
137
  }
@@ -156,28 +156,28 @@ describe('topLevelMenu', () => {
156
156
  id: 'an-id1',
157
157
  mgmt: { id: 'an-id1' },
158
158
  nameDisplay: 'c-cluster',
159
- isReady: true
159
+ canExplore: true
160
160
  },
161
161
  {
162
162
  name: 'x33-cwf5-name',
163
163
  id: 'an-id2',
164
164
  mgmt: { id: 'an-id2' },
165
165
  nameDisplay: 'a-cluster',
166
- isReady: false
166
+ canExplore: false
167
167
  },
168
168
  {
169
169
  name: 'x34-cwf5-name',
170
170
  id: 'an-id3',
171
171
  mgmt: { id: 'an-id3' },
172
172
  nameDisplay: 'b-cluster',
173
- isReady: true
173
+ canExplore: true
174
174
  },
175
175
  {
176
176
  name: 'local-name',
177
177
  id: 'local',
178
178
  mgmt: { id: 'local' },
179
179
  nameDisplay: 'local',
180
- isReady: true,
180
+ canExplore: true,
181
181
  isLocal: true,
182
182
  },
183
183
  ];
@@ -195,9 +195,9 @@ describe('topLevelMenu', () => {
195
195
  await waitForIt();
196
196
 
197
197
  expect(wrapper.find('[data-testid="top-level-menu-cluster-0"] .cluster-name p').text()).toStrictEqual('local');
198
+ expect(wrapper.find('[data-testid="top-level-menu-cluster-3"] .cluster-name p').text()).toStrictEqual('a-cluster');
198
199
  expect(wrapper.find('[data-testid="top-level-menu-cluster-1"] .cluster-name p').text()).toStrictEqual('b-cluster');
199
200
  expect(wrapper.find('[data-testid="top-level-menu-cluster-2"] .cluster-name p').text()).toStrictEqual('c-cluster');
200
- expect(wrapper.find('[data-testid="top-level-menu-cluster-3"] .cluster-name p').text()).toStrictEqual('a-cluster');
201
201
  });
202
202
 
203
203
  it('should show local cluster always on top of the list of clusters (pinned and ready clusters)', async() => {
@@ -212,7 +212,7 @@ describe('topLevelMenu', () => {
212
212
  id: 'an-id1',
213
213
  mgmt: { id: 'an-id1' },
214
214
  nameDisplay: 'c-cluster',
215
- isReady: true,
215
+ canExplore: true,
216
216
  pinned: true
217
217
  },
218
218
  {
@@ -220,7 +220,7 @@ describe('topLevelMenu', () => {
220
220
  id: 'an-id2',
221
221
  mgmt: { id: 'an-id2' },
222
222
  nameDisplay: 'a-cluster',
223
- isReady: true,
223
+ canExplore: true,
224
224
  pinned: true
225
225
  },
226
226
  {
@@ -228,7 +228,7 @@ describe('topLevelMenu', () => {
228
228
  id: 'an-id3',
229
229
  mgmt: { id: 'an-id3' },
230
230
  nameDisplay: 'b-cluster',
231
- isReady: true,
231
+ canExplore: true,
232
232
  pinned: true
233
233
  },
234
234
  {
@@ -236,7 +236,7 @@ describe('topLevelMenu', () => {
236
236
  id: 'local',
237
237
  mgmt: { id: 'local' },
238
238
  nameDisplay: 'local',
239
- isReady: true,
239
+ canExplore: true,
240
240
  pinned: true
241
241
  },
242
242
  ])
@@ -271,7 +271,7 @@ describe('topLevelMenu', () => {
271
271
  id: 'an-id1',
272
272
  mgmt: { id: 'an-id1' },
273
273
  nameDisplay: 'c-cluster',
274
- isReady: true,
274
+ canExplore: true,
275
275
  pinned: true
276
276
  },
277
277
  {
@@ -279,7 +279,7 @@ describe('topLevelMenu', () => {
279
279
  id: 'an-id2',
280
280
  mgmt: { id: 'an-id2' },
281
281
  nameDisplay: 'a-cluster',
282
- isReady: true,
282
+ canExplore: true,
283
283
  pinned: true
284
284
  },
285
285
  {
@@ -287,7 +287,7 @@ describe('topLevelMenu', () => {
287
287
  id: 'an-id3',
288
288
  mgmt: { id: 'an-id3' },
289
289
  nameDisplay: 'b-cluster',
290
- isReady: false,
290
+ canExplore: false,
291
291
  pinned: true
292
292
  },
293
293
  {
@@ -295,7 +295,7 @@ describe('topLevelMenu', () => {
295
295
  id: 'local',
296
296
  mgmt: { id: 'local' },
297
297
  nameDisplay: 'local',
298
- isReady: true,
298
+ canExplore: true,
299
299
  pinned: true
300
300
  },
301
301
  ])
@@ -328,7 +328,7 @@ describe('topLevelMenu', () => {
328
328
  mgmt: { id: 'an-id1' },
329
329
  description: 'some-description1',
330
330
  nameDisplay: 'some-label',
331
- isReady: true,
331
+ canExplore: true,
332
332
  pinned: true
333
333
  },
334
334
  // pinned NOT ready cluster
@@ -347,7 +347,7 @@ describe('topLevelMenu', () => {
347
347
  mgmt: { id: 'an-id3' },
348
348
  description: 'some-description3',
349
349
  nameDisplay: 'some-label',
350
- isReady: true
350
+ canExplore: true
351
351
  },
352
352
  // unpinned NOT ready cluster
353
353
  {
@@ -392,7 +392,7 @@ describe('topLevelMenu', () => {
392
392
  mgmt: { id: 'an-id1' },
393
393
  description: 'some-description1',
394
394
  nameDisplay: 'some-label',
395
- isReady: true,
395
+ canExplore: true,
396
396
  pinned: true
397
397
  },
398
398
  // pinned NOT ready cluster
@@ -411,7 +411,7 @@ describe('topLevelMenu', () => {
411
411
  mgmt: { id: 'an-id3' },
412
412
  description: 'some-description3',
413
413
  nameDisplay: 'some-label',
414
- isReady: true
414
+ canExplore: true
415
415
  },
416
416
  // unpinned NOT ready cluster
417
417
  {
@@ -713,4 +713,246 @@ describe('topLevelMenu', () => {
713
713
  expect(wrapper.vm.mgmtClusters).toStrictEqual([]);
714
714
  });
715
715
  });
716
+
717
+ describe('computed properties', () => {
718
+ describe('routeComboActive', () => {
719
+ it('should be true when routeCombo is true and there are multiple ready clusters', async() => {
720
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
721
+ global: {
722
+ mocks: {
723
+ $route: { name: 'c-cluster-explorer', params: { cluster: 'local', product: 'explorer' } },
724
+ $store: {
725
+ ...generateStore([
726
+ {
727
+ nameDisplay: 'cluster1',
728
+ id: 'an-id1',
729
+ mgmt: { id: 'an-id1' },
730
+ canExplore: true
731
+ },
732
+ {
733
+ nameDisplay: 'cluster2',
734
+ id: 'an-id2',
735
+ mgmt: { id: 'an-id2' },
736
+ canExplore: true
737
+ }
738
+ ])
739
+ }
740
+ },
741
+ stubs: ['BrandImage', 'router-link'],
742
+ }
743
+ });
744
+
745
+ await waitForIt();
746
+ await wrapper.setData({ routeCombo: true });
747
+
748
+ expect(wrapper.vm.routeComboActive).toBe(true);
749
+ });
750
+
751
+ it('should be false when routeCombo is false', async() => {
752
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
753
+ global: {
754
+ mocks: {
755
+ $route: {},
756
+ $store: {
757
+ ...generateStore([
758
+ {
759
+ nameDisplay: 'cluster1',
760
+ id: 'an-id1',
761
+ mgmt: { id: 'an-id1' },
762
+ canExplore: true
763
+ },
764
+ {
765
+ nameDisplay: 'cluster2',
766
+ id: 'an-id2',
767
+ mgmt: { id: 'an-id2' },
768
+ canExplore: true
769
+ }
770
+ ])
771
+ }
772
+ },
773
+ stubs: ['BrandImage', 'router-link'],
774
+ }
775
+ });
776
+
777
+ await waitForIt();
778
+ await wrapper.setData({ routeCombo: false });
779
+
780
+ expect(wrapper.vm.routeComboActive).toBe(false);
781
+ });
782
+
783
+ it('should be false when there is only one ready cluster and it is the current cluster', async() => {
784
+ const store = generateStore([
785
+ {
786
+ nameDisplay: 'cluster1',
787
+ id: 'an-id1',
788
+ mgmt: { id: 'an-id1' },
789
+ canExplore: true
790
+ }
791
+ ]);
792
+
793
+ store.getters.clusterId = 'an-id1' as any;
794
+
795
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
796
+ global: {
797
+ mocks: {
798
+ $route: {},
799
+ $store: store
800
+ },
801
+ stubs: ['BrandImage', 'router-link'],
802
+ }
803
+ });
804
+
805
+ await waitForIt();
806
+ await wrapper.setData({ routeCombo: true });
807
+
808
+ expect(wrapper.vm.routeComboActive).toBe(false);
809
+ });
810
+
811
+ it('should be true when there is only one ready cluster but it is not the current cluster', async() => {
812
+ const store = generateStore([
813
+ {
814
+ nameDisplay: 'cluster1',
815
+ id: 'an-id1',
816
+ mgmt: { id: 'an-id1' },
817
+ canExplore: true
818
+ }
819
+ ]);
820
+
821
+ store.getters.clusterId = 'some-other-cluster-id' as any;
822
+
823
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
824
+ global: {
825
+ mocks: {
826
+ $route: { name: 'c-cluster-explorer', params: { cluster: 'local', product: 'explorer' } },
827
+ $store: store
828
+ },
829
+ stubs: ['BrandImage', 'router-link'],
830
+ }
831
+ });
832
+
833
+ await waitForIt();
834
+ await wrapper.setData({ routeCombo: true });
835
+
836
+ expect(wrapper.vm.routeComboActive).toBe(true);
837
+ });
838
+ });
839
+
840
+ describe('handleKeyComboClick', () => {
841
+ it('should not toggle routeCombo when route is a non-explorer c-cluster route', async() => {
842
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
843
+ global: {
844
+ mocks: {
845
+ $route: { name: 'c-cluster-fleet', params: { cluster: 'local', product: 'fleet' } },
846
+ $router: { push: jest.fn() },
847
+ $store: { ...generateStore([]) }
848
+ },
849
+ stubs: ['BrandImage', 'router-link'],
850
+ }
851
+ });
852
+
853
+ await waitForIt();
854
+
855
+ expect(wrapper.vm.routeCombo).toBe(false);
856
+ wrapper.vm.handleKeyComboClick();
857
+ expect(wrapper.vm.routeCombo).toBe(false);
858
+ });
859
+
860
+ it('should toggle routeCombo when route is cluster explorer', async() => {
861
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
862
+ global: {
863
+ mocks: {
864
+ $route: { name: 'c-cluster-explorer', params: { cluster: 'local', product: 'explorer' } },
865
+ $router: { push: jest.fn() },
866
+ $store: { ...generateStore([]) }
867
+ },
868
+ stubs: ['BrandImage', 'router-link'],
869
+ }
870
+ });
871
+
872
+ await waitForIt();
873
+
874
+ expect(wrapper.vm.routeCombo).toBe(false);
875
+ wrapper.vm.handleKeyComboClick();
876
+ expect(wrapper.vm.routeCombo).toBe(true);
877
+ });
878
+ });
879
+
880
+ describe('clusterMenuClick', () => {
881
+ it('should navigate normally on non-explorer c-cluster route even with routeCombo set', async() => {
882
+ const mockPush = jest.fn();
883
+ const clusterRoute = { name: 'c-cluster-explorer' };
884
+ const clusters = [
885
+ {
886
+ nameDisplay: 'cluster1',
887
+ id: 'an-id1',
888
+ mgmt: { id: 'an-id1' },
889
+ canExplore: true,
890
+ clusterRoute
891
+ },
892
+ {
893
+ nameDisplay: 'cluster2',
894
+ id: 'an-id2',
895
+ mgmt: { id: 'an-id2' },
896
+ canExplore: true,
897
+ clusterRoute
898
+ }
899
+ ];
900
+
901
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
902
+ global: {
903
+ mocks: {
904
+ $route: { name: 'c-cluster-fleet', params: { cluster: 'local', product: 'fleet' } },
905
+ $router: { push: mockPush },
906
+ $store: { ...generateStore(clusters) }
907
+ },
908
+ stubs: ['BrandImage', 'router-link'],
909
+ }
910
+ });
911
+
912
+ await waitForIt();
913
+ await wrapper.setData({ routeCombo: true });
914
+
915
+ expect(wrapper.vm.routeComboActive).toBe(false);
916
+
917
+ const ev = { preventDefault: jest.fn() };
918
+
919
+ wrapper.vm.clusterMenuClick(ev, clusters[1]);
920
+
921
+ expect(mockPush).toHaveBeenCalledWith(clusterRoute);
922
+ });
923
+
924
+ it('should navigate to cluster route when routeComboActive is false', async() => {
925
+ const mockPush = jest.fn();
926
+ const clusterRoute = { name: 'c-cluster-explorer' };
927
+ const clusters = [
928
+ {
929
+ nameDisplay: 'cluster1',
930
+ id: 'an-id1',
931
+ mgmt: { id: 'an-id1' },
932
+ canExplore: true,
933
+ clusterRoute
934
+ }
935
+ ];
936
+
937
+ const wrapper: Wrapper<InstanceType<typeof TopLevelMenu>> = mount(TopLevelMenu, {
938
+ global: {
939
+ mocks: {
940
+ $route: { name: 'fleet-management', params: {} },
941
+ $router: { push: mockPush },
942
+ $store: { ...generateStore(clusters) }
943
+ },
944
+ stubs: ['BrandImage', 'router-link'],
945
+ }
946
+ });
947
+
948
+ await waitForIt();
949
+
950
+ const ev = { preventDefault: jest.fn() };
951
+
952
+ wrapper.vm.clusterMenuClick(ev, clusters[0]);
953
+
954
+ expect(mockPush).toHaveBeenCalledWith(clusterRoute);
955
+ });
956
+ });
957
+ });
716
958
  });
@@ -24,6 +24,7 @@ import BrowserTabVisibility from '@shell/mixins/browser-tab-visibility';
24
24
  import { getClusterFromRoute, getProductFromRoute } from '@shell/utils/router';
25
25
  import SideNav from '@shell/components/SideNav';
26
26
  import { Layout } from '@shell/types/window-manager';
27
+ import { RcButton } from '@components/RcButton';
27
28
 
28
29
  const SET_LOGIN_ACTION = 'set-as-login';
29
30
 
@@ -42,6 +43,7 @@ export default {
42
43
  AwsComplianceBanner,
43
44
  Inactivity,
44
45
  SideNav,
46
+ RcButton,
45
47
  },
46
48
 
47
49
  mixins: [PageHeaderActions, Brand, BrowserTabVisibility],
@@ -162,10 +164,13 @@ export default {
162
164
 
163
165
  <template>
164
166
  <div class="dashboard-root">
165
- <a
166
- href="#main-content"
167
- class="skip-to-content btn role-primary"
168
- >{{ t('nav.skipToContent') }}</a>
167
+ <rc-button
168
+ size="large"
169
+ class="skip-to-content"
170
+ :to="{ hash: '#main-content' }"
171
+ >
172
+ {{ t('nav.skipToContent') }}
173
+ </rc-button>
169
174
  <FixedBanner :header="true" />
170
175
  <AwsComplianceBanner v-if="managementReady" />
171
176
  <div
@@ -12,6 +12,7 @@ import Inactivity from '@shell/components/Inactivity';
12
12
  import { mapState, mapGetters } from 'vuex';
13
13
  import PromptModal from '@shell/components/PromptModal';
14
14
  import { Layout } from '@shell/types/window-manager';
15
+ import { RcButton } from '@components/RcButton';
15
16
 
16
17
  export default {
17
18
 
@@ -24,6 +25,7 @@ export default {
24
25
  AwsComplianceBanner,
25
26
  Inactivity,
26
27
  PromptModal,
28
+ RcButton
27
29
  },
28
30
 
29
31
  mixins: [Brand, BrowserTabVisibility],
@@ -62,6 +64,13 @@ export default {
62
64
 
63
65
  <template>
64
66
  <div class="dashboard-root">
67
+ <rc-button
68
+ size="large"
69
+ class="skip-to-content"
70
+ :to="{ hash: '#main-content' }"
71
+ >
72
+ {{ t('nav.skipToContent') }}
73
+ </rc-button>
65
74
  <FixedBanner :header="true" />
66
75
  <Inactivity />
67
76
  <AwsComplianceBanner />
@@ -77,8 +86,10 @@ export default {
77
86
  />
78
87
 
79
88
  <main
89
+ id="main-content"
80
90
  class="main-layout"
81
91
  :aria-label="t('layouts.home')"
92
+ tabindex="-1"
82
93
  >
83
94
  <router-view
84
95
  :key="$route.path"
@@ -142,4 +153,16 @@ export default {
142
153
  padding: 0;
143
154
  }
144
155
  }
156
+
157
+ .skip-to-content {
158
+ position: fixed;
159
+ top: 0;
160
+ left: 0;
161
+ z-index: 9999;
162
+ transform: translateY(-100%);
163
+
164
+ &:focus {
165
+ transform: translate(1rem, 1rem);
166
+ }
167
+ }
145
168
  </style>
@@ -15,6 +15,7 @@ import Inactivity from '@shell/components/Inactivity';
15
15
  import { mapGetters } from 'vuex';
16
16
  import PromptModal from '@shell/components/PromptModal';
17
17
  import { Layout } from '@shell/types/window-manager';
18
+ import { RcButton } from '@components/RcButton';
18
19
 
19
20
  export default {
20
21
 
@@ -30,6 +31,7 @@ export default {
30
31
  SlideInPanelManager,
31
32
  AwsComplianceBanner,
32
33
  Inactivity,
34
+ RcButton
33
35
  },
34
36
 
35
37
  mixins: [Brand, BrowserTabVisibility],
@@ -66,6 +68,13 @@ export default {
66
68
 
67
69
  <template>
68
70
  <div class="dashboard-root">
71
+ <rc-button
72
+ size="large"
73
+ class="skip-to-content"
74
+ :to="{ hash: '#main-content' }"
75
+ >
76
+ {{ t('nav.skipToContent') }}
77
+ </rc-button>
69
78
  <FixedBanner :header="true" />
70
79
  <AwsComplianceBanner />
71
80
 
@@ -75,8 +84,10 @@ export default {
75
84
  >
76
85
  <Header :simple="true" />
77
86
  <main
87
+ id="main-content"
78
88
  class="main-layout"
79
89
  :aria-label="t('layouts.plain')"
90
+ tabindex="-1"
80
91
  >
81
92
  <IndentedPanel class="pt-20">
82
93
  <router-view
@@ -147,4 +158,16 @@ export default {
147
158
  padding: 0;
148
159
  }
149
160
  }
161
+
162
+ .skip-to-content {
163
+ position: fixed;
164
+ top: 0;
165
+ left: 0;
166
+ z-index: 9999;
167
+ transform: translateY(-100%);
168
+
169
+ &:focus {
170
+ transform: translate(1rem, 1rem);
171
+ }
172
+ }
150
173
  </style>