@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
@@ -110,9 +110,12 @@ const showConfigurationMoreFocusSelector = computed(() => `[data-testid="${ show
110
110
  }
111
111
 
112
112
  .row {
113
- display: block;
114
- width: 100%;
115
113
  display: inline-block;
114
+ width: 100%;
115
+
116
+ &::before, &::after {
117
+ display: none;
118
+ }
116
119
 
117
120
  &:not(:nth-child(2)) {
118
121
  margin-top: 4px;
@@ -92,18 +92,14 @@ const previewId = randomStr();
92
92
  max-width: calc(100%);
93
93
  }
94
94
 
95
- .rc-tag {
96
- display: inline-block;
97
- line-height: normal;
98
- }
99
-
100
95
  .tag-data {
101
96
  display: inline-block;
102
97
  overflow: hidden;
103
98
  text-overflow: ellipsis;
104
99
  white-space: nowrap;
100
+ min-width: 0;
105
101
  max-width: calc(100%);
106
- line-height: normal;
102
+ line-height: 1;
107
103
  }
108
104
 
109
105
  & .btn.btn-medium.rc-button.variant-ghost {
@@ -82,6 +82,12 @@ const showBothEmpty = computed(() => labels.length === 0 && annotations.length =
82
82
 
83
83
  <style lang="scss" scoped>
84
84
  .metadata {
85
+ .identifying-info {
86
+ // Allow the grid cell to shrink below its content size without
87
+ // using overflow:hidden, which would clip the namespace popover
88
+ min-width: 0;
89
+ }
90
+
85
91
  .labels-and-annotations-empty {
86
92
  grid-column: span 2;
87
93
  }
@@ -115,11 +115,22 @@ const actionInvoked = () => {
115
115
 
116
116
  .display {
117
117
  display: inline-flex;
118
+ align-items: center;
119
+ max-width: 100%;
120
+
121
+ // Truncate the link text instead of wrapping to a second line
122
+ a {
123
+ overflow: hidden;
124
+ text-overflow: ellipsis;
125
+ white-space: nowrap;
126
+ min-width: 0;
127
+ }
118
128
  }
119
129
 
120
130
  .rc-status-indicator {
131
+ // Keep the status dot from collapsing when the link text is long
132
+ flex-shrink: 0;
121
133
  margin-right: 12px;
122
- margin-top: 4px;
123
134
  height: initial;
124
135
  line-height: initial;
125
136
  }
@@ -7,9 +7,11 @@
7
7
  <style lang="scss" scoped>
8
8
  .spaced-row {
9
9
  display: grid;
10
- grid-template-columns: repeat(3, minmax(0, 1fr));;
10
+ grid-template-columns: repeat(3, minmax(0, 1fr));
11
11
  grid-auto-flow: dense;
12
12
  grid-gap: 24px;
13
13
  justify-content: space-evenly;
14
+ // Match the title bar floor so sections scroll together
15
+ min-width: $resource-detail-min-width;
14
16
  }
15
17
  </style>
@@ -159,23 +159,20 @@ const showAdditionalActionButtons = computed(() => isArray(additionalActions));
159
159
 
160
160
  <style lang="scss" scoped>
161
161
  .title-bar {
162
- min-width: 740px;
162
+ min-width: $resource-detail-min-width;
163
163
 
164
164
  .badge-state {
165
165
  font-size: 16px;
166
166
  margin-left: 12px;
167
167
  position: relative;
168
- }
169
-
170
- .icon-document {
171
- width: 15px;
172
- font-size: 16px;
173
- margin-right: 10px;
168
+ flex: 0 0 auto;
174
169
  }
175
170
 
176
171
  .actions {
177
172
  display: flex;
178
173
  align-items: center;
174
+ flex: 0 0 auto;
175
+ margin-left: 16px;
179
176
  }
180
177
 
181
178
  .show-configuration, &:deep() .actions > button {
@@ -198,15 +195,17 @@ const showAdditionalActionButtons = computed(() => isArray(additionalActions));
198
195
  max-width: 60%;
199
196
  }
200
197
 
201
- // This prevents the title from overlapping with the actions
198
+ // Title takes the remaining row space; min-width: 0 lets its children
199
+ // (resource-name) shrink so the action buttons stay visible on narrow viewports.
202
200
  .title {
203
- max-width: calc(100% - 260px);
201
+ flex: 1 1 auto;
202
+ min-width: 0;
204
203
  }
205
204
 
206
- // We want the resource name to be what collaspes wh
207
205
  .resource-name {
208
206
  display: inline-block;
209
- flex: 1;
207
+ flex: 0 1 auto;
208
+ min-width: 0;
210
209
  white-space: nowrap;
211
210
  overflow-x: hidden;
212
211
  overflow-y: clip;
@@ -169,7 +169,7 @@ export default {
169
169
  } else {
170
170
  let fqid = id;
171
171
 
172
- if ( schema.attributes?.namespaced && namespace ) {
172
+ if ( schema?.attributes?.namespaced && namespace ) {
173
173
  fqid = `${ namespace }/${ fqid }`;
174
174
  }
175
175
 
@@ -2,6 +2,7 @@
2
2
  import { mapGetters } from 'vuex';
3
3
  import Favorite from '@shell/components/nav/Favorite';
4
4
  import TypeDescription from '@shell/components/TypeDescription';
5
+ import { RcButton } from '@components/RcButton';
5
6
  import { get } from '@shell/utils/object';
6
7
  import { AS, _YAML } from '@shell/config/query-params';
7
8
  import ResourceLoadingIndicator from './ResourceLoadingIndicator';
@@ -16,6 +17,7 @@ export default {
16
17
 
17
18
  components: {
18
19
  Favorite,
20
+ RcButton,
19
21
  TypeDescription,
20
22
  ResourceLoadingIndicator,
21
23
  TabTitle
@@ -72,6 +74,11 @@ export default {
72
74
  default: false
73
75
  },
74
76
 
77
+ showFavorite: {
78
+ type: Boolean,
79
+ default: true
80
+ },
81
+
75
82
  /**
76
83
  * Inherited global identifier prefix for tests
77
84
  * Define a term based on the parent component to avoid conflicts on multiple components
@@ -200,7 +207,7 @@ export default {
200
207
  <div class="title">
201
208
  <h1 class="m-0">
202
209
  <TabTitle>{{ _typeDisplay }}</TabTitle> <Favorite
203
- v-if="isExplorer"
210
+ v-if="isExplorer && showFavorite"
204
211
  :resource="favoriteResource || resource"
205
212
  />
206
213
  </h1>
@@ -221,22 +228,24 @@ export default {
221
228
  <slot name="extraActions" />
222
229
 
223
230
  <slot name="createButton">
224
- <router-link
231
+ <RcButton
225
232
  v-if="hasEditComponent && _isCreatable"
226
- :to="_createLocation"
227
- class="btn role-primary"
233
+ variant="primary"
234
+ size="large"
228
235
  :data-testid="componentTestid+'-create'"
236
+ :to="_createLocation"
229
237
  >
230
238
  {{ _createButtonlabel }}
231
- </router-link>
232
- <router-link
239
+ </RcButton>
240
+ <RcButton
233
241
  v-else-if="_isYamlCreatable"
234
- :to="_yamlCreateLocation"
235
- class="btn role-primary"
242
+ variant="primary"
243
+ size="large"
236
244
  :data-testid="componentTestid+'-create-yaml'"
245
+ :to="_yamlCreateLocation"
237
246
  >
238
247
  {{ t("resourceList.head.createFromYaml") }}
239
- </router-link>
248
+ </RcButton>
240
249
  </slot>
241
250
  </div>
242
251
  </slot>
@@ -263,6 +272,7 @@ export default {
263
272
  'title actions'
264
273
  'sub-header sub-header'
265
274
  'state-banner state-banner';
275
+ margin-bottom: 24px;
266
276
  }
267
277
 
268
278
  .sub-header {
@@ -10,6 +10,9 @@ import { PanelLocation, ExtensionPoint } from '@shell/core/types';
10
10
  import ExtensionPanel from '@shell/components/ExtensionPanel';
11
11
  import { sameContents } from '@shell/utils/array';
12
12
  import perfSettingsUtils from '@shell/utils/perf-setting.utils';
13
+ import { BadgeState } from '@components/BadgeState';
14
+ import { stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
15
+ import { useStateColor } from '@shell/composables/useStateColor';
13
16
 
14
17
  export default {
15
18
  name: ResourceListComponentName,
@@ -20,10 +23,17 @@ export default {
20
23
  Masthead,
21
24
  ResourceLoadingIndicator,
22
25
  IconMessage,
23
- ExtensionPanel
26
+ ExtensionPanel,
27
+ BadgeState,
24
28
  },
25
29
  mixins: [ResourceFetch],
26
30
 
31
+ setup() {
32
+ const { toStateColor } = useStateColor();
33
+
34
+ return { toStateColor };
35
+ },
36
+
27
37
  props: {
28
38
  hasAdvancedFiltering: {
29
39
  type: Boolean,
@@ -155,6 +165,41 @@ export default {
155
165
  return perfSettingsUtils.incrementalLoadingUtils.isEnabled(this.calcCanPaginate(), this.perfConfig);
156
166
  },
157
167
 
168
+ activeStateFilters() {
169
+ const raw = this.$route?.query?.stateFilter;
170
+
171
+ if (!raw) {
172
+ return [];
173
+ }
174
+
175
+ const states = raw.split(',').filter(Boolean);
176
+
177
+ return states.map((s) => {
178
+ const match = this.rows.find((row) => row.metadata?.state?.name === s);
179
+
180
+ if (match) {
181
+ return {
182
+ label: match.stateDisplay,
183
+ color: match.stateBackground,
184
+ };
185
+ }
186
+
187
+ return {
188
+ label: stateDisplay(s, true),
189
+ color: `bg-${ this.toStateColor(s, this.resource) }`,
190
+ };
191
+ });
192
+ },
193
+
194
+ },
195
+
196
+ methods: {
197
+ clearStateFilter() {
198
+ const query = { ...this.$route.query };
199
+
200
+ delete query.stateFilter;
201
+ this.$router.push({ ...this.$route, query });
202
+ },
158
203
  },
159
204
 
160
205
  watch: {
@@ -260,6 +305,28 @@ export default {
260
305
  :load-resources="loadResources"
261
306
  :load-indeterminate="loadIndeterminate"
262
307
  >
308
+ <template
309
+ v-if="activeStateFilters.length"
310
+ #subHeader
311
+ >
312
+ <div class="state-filter-bar text-muted">
313
+ {{ t('resourceList.stateFilterApplied') }}
314
+ <BadgeState
315
+ v-for="state in activeStateFilters"
316
+ :key="state.label"
317
+ :color="state.color"
318
+ :label="state.label"
319
+ class="badge-state-font-size"
320
+ />
321
+ <span>.</span>
322
+ <a
323
+ role="button"
324
+ @click="clearStateFilter"
325
+ >
326
+ {{ t('resourceList.clearStateFilter') }}
327
+ </a>
328
+ </div>
329
+ </template>
263
330
  <template #extraActions>
264
331
  <slot name="extraActions" />
265
332
  </template>
@@ -317,4 +384,18 @@ export default {
317
384
  top: 10px;
318
385
  right: 10px;
319
386
  }
387
+
388
+ .state-filter-bar {
389
+ display: flex;
390
+ align-items: center;
391
+ gap: 4px;
392
+
393
+ a {
394
+ cursor: pointer;
395
+ }
396
+ }
397
+
398
+ .badge-state-font-size {
399
+ font-size: .85em;
400
+ }
320
401
  </style>
@@ -74,8 +74,11 @@ export default defineComponent({
74
74
  const content = enclosingTagName ? match[2] : '';
75
75
 
76
76
  if (slots[tagName]) {
77
- // If a slot is provided for this tag, render the slot with the content.
78
- children.push(slots[tagName]({ content: purifyHTML(content) }));
77
+ const slotContent = slots[tagName]({ content: purifyHTML(content) });
78
+
79
+ if (slotContent) {
80
+ children.push(...slotContent);
81
+ }
79
82
  } else if (ALLOWED_TAGS.includes(tagName.toLowerCase())) {
80
83
  // If it's an allowed HTML tag, render it directly.
81
84
  if (content) {
@@ -131,16 +131,6 @@ export default {
131
131
  class="side-label"
132
132
  :class="{'indicator': true }"
133
133
  />
134
- <div v-if="r.deploysOnWindows">
135
- <label class="deploys-os-label">
136
- {{ t('catalog.charts.deploysOnWindows') }}
137
- </label>
138
- </div>
139
- <div v-if="r.windowsIncompatible">
140
- <label class="os-incompatible-label">
141
- {{ t('catalog.charts.windowsIncompatible') }}
142
- </label>
143
- </div>
144
134
  <div
145
135
  v-if="get(r, sideLabelField)"
146
136
  class="side-label"
@@ -29,6 +29,7 @@ export default {
29
29
  <span
30
30
  v-if="value.fromEnv"
31
31
  class="modified"
32
+ :data-testid="`advanced-setting-env-label-${value.id}`"
32
33
  >{{ t('advancedSettings.setEnv') }}</span>
33
34
  <span
34
35
  v-else-if="value.customized"
@@ -13,6 +13,7 @@ export default {
13
13
  },
14
14
 
15
15
  async fetch() {
16
+ // There's only one cluster, might as well fetch them all...
16
17
  this.clusters = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER });
17
18
  },
18
19
 
@@ -0,0 +1,126 @@
1
+ import sorting from '@shell/components/SortableTable/sorting';
2
+
3
+ const { arrangedRows } = sorting.computed;
4
+
5
+ describe('sorting mixin', () => {
6
+ describe('arrangedRows', () => {
7
+ function createContext({
8
+ rows = [] as any[],
9
+ sortFields = ['id'],
10
+ descending = false,
11
+ sortGeneration = undefined as string | undefined,
12
+ sortGenerationFn = (() => 'gen1') as (() => string) | undefined,
13
+ externalPaginationEnabled = false,
14
+ cacheKey = null as string | null,
15
+ cachedRows = null as any[] | null,
16
+ cachedRowsRef = null as any[] | null,
17
+ } = {}) {
18
+ return {
19
+ rows,
20
+ sortFields,
21
+ descending,
22
+ sortGeneration,
23
+ sortGenerationFn,
24
+ externalPaginationEnabled,
25
+ cacheKey,
26
+ cachedRows,
27
+ cachedRowsRef,
28
+ };
29
+ }
30
+
31
+ it('should return undefined when externalPaginationEnabled is true', () => {
32
+ const ctx = createContext({ externalPaginationEnabled: true });
33
+
34
+ expect(arrangedRows.call(ctx)).toBeUndefined();
35
+ });
36
+
37
+ it('should sort rows by the given sort fields', () => {
38
+ const rows = [{ id: 'b' }, { id: 'a' }, { id: 'c' }];
39
+ const ctx = createContext({ rows, sortGenerationFn: undefined });
40
+
41
+ const result = arrangedRows.call(ctx);
42
+
43
+ expect(result.map((r: any) => r.id)).toStrictEqual(['a', 'b', 'c']);
44
+ });
45
+
46
+ it('should cache results when sortGenerationFn is provided', () => {
47
+ const rows = [{ id: 'b' }, { id: 'a' }];
48
+ const ctx = createContext({ rows });
49
+
50
+ const result1 = arrangedRows.call(ctx);
51
+
52
+ expect(ctx.cacheKey).not.toBeNull();
53
+ expect(ctx.cachedRows).toStrictEqual(result1);
54
+
55
+ const result2 = arrangedRows.call(ctx);
56
+
57
+ expect(result2).toBe(ctx.cachedRows);
58
+ });
59
+
60
+ it('should invalidate cache when rows change to different items with the same count', () => {
61
+ const rowsA = [{ id: 'alpha' }];
62
+ const rowsB = [{ id: 'beta' }];
63
+ const ctx = createContext({ rows: rowsA });
64
+
65
+ const resultA = arrangedRows.call(ctx);
66
+
67
+ expect(resultA.map((r: any) => r.id)).toStrictEqual(['alpha']);
68
+
69
+ ctx.rows = rowsB;
70
+ const resultB = arrangedRows.call(ctx);
71
+
72
+ expect(resultB.map((r: any) => r.id)).toStrictEqual(['beta']);
73
+ });
74
+
75
+ it('should return cached rows when same rows are passed again', () => {
76
+ const rows = [{ id: 'x' }, { id: 'y' }];
77
+ const ctx = createContext({ rows });
78
+
79
+ arrangedRows.call(ctx);
80
+ const cached = ctx.cachedRows;
81
+
82
+ const result = arrangedRows.call(ctx);
83
+
84
+ expect(result).toBe(cached);
85
+ });
86
+
87
+ it('should invalidate cache when descending changes', () => {
88
+ const rows = [{ id: 'a' }, { id: 'b' }];
89
+ const ctx = createContext({ rows });
90
+
91
+ arrangedRows.call(ctx);
92
+
93
+ ctx.descending = true;
94
+ const result = arrangedRows.call(ctx);
95
+
96
+ expect(result.map((r: any) => r.id)).toStrictEqual(['b', 'a']);
97
+ });
98
+
99
+ it('should not cache when there is no sortGenerationFn or sortGeneration', () => {
100
+ const rows = [{ id: 'a' }];
101
+ const ctx = createContext({ rows });
102
+
103
+ ctx.sortGenerationFn = undefined;
104
+ ctx.sortGeneration = undefined;
105
+
106
+ arrangedRows.call(ctx);
107
+
108
+ expect(ctx.cacheKey).toBeNull();
109
+ expect(ctx.cachedRows).toBeNull();
110
+ });
111
+
112
+ it('should use sortGeneration over sortGenerationFn when provided', () => {
113
+ const rows = [{ id: 'a' }];
114
+ const ctx = createContext({
115
+ rows,
116
+ sortGeneration: 'custom-gen',
117
+ sortGenerationFn: () => 'fn-gen',
118
+ });
119
+
120
+ arrangedRows.call(ctx);
121
+
122
+ expect(ctx.cacheKey).toContain('custom-gen');
123
+ expect(ctx.cacheKey).not.toContain('fn-gen');
124
+ });
125
+ });
126
+ });
@@ -26,6 +26,7 @@ import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
26
26
  import ActionMenu from '@shell/components/ActionMenuShell.vue';
27
27
  import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
28
28
  import ActionDropdownShell from '@shell/components/ActionDropdownShell.vue';
29
+ import { RcButton } from '@components/RcButton';
29
30
  import { useTabCountUpdater } from '@shell/components/form/ResourceTabs/composable';
30
31
 
31
32
  // Uncomment for table performance debugging
@@ -65,6 +66,7 @@ export default {
65
66
  ButtonMultiAction,
66
67
  ActionMenu,
67
68
  ActionDropdownShell,
69
+ RcButton,
68
70
  },
69
71
 
70
72
  mixins: [
@@ -1116,17 +1118,17 @@ export default {
1116
1118
  >
1117
1119
  <slot name="header-left">
1118
1120
  <template v-if="tableActions">
1119
- <button
1121
+ <RcButton
1120
1122
  v-for="(act) in availableActions"
1121
1123
  :id="act.action"
1122
1124
  :key="act.action"
1123
1125
  v-clean-tooltip="actionTooltip"
1124
1126
  type="button"
1125
- class="btn role-primary"
1127
+ variant="primary"
1128
+ size="large"
1126
1129
  :class="{[bulkActionClass]:true}"
1127
1130
  :disabled="!act.enabled"
1128
1131
  :data-testid="componentTestid + '-' + act.action"
1129
- role="button"
1130
1132
  :aria-label="act.label"
1131
1133
  @click="applyTableAction(act, null, $event)"
1132
1134
  @keydown.enter.stop
@@ -1138,7 +1140,7 @@ export default {
1138
1140
  :class="act.icon"
1139
1141
  />
1140
1142
  <span v-clean-html="act.label" />
1141
- </button>
1143
+ </RcButton>
1142
1144
  <template v-if="featureDropdownMenu">
1143
1145
  <ActionDropdownShell
1144
1146
  :disabled="!selectedRows.length"
@@ -2154,11 +2156,6 @@ export default {
2154
2156
  }
2155
2157
  }
2156
2158
 
2157
- .bulk-action {
2158
- .icon {
2159
- vertical-align: -10%;
2160
- }
2161
- }
2162
2159
  }
2163
2160
 
2164
2161
  .middle {
@@ -626,27 +626,45 @@ function _execute(resources, action, args, opts = {}, ctx) {
626
626
  return action.invoke.apply(ctx, [actionOpts, resources || [], args]);
627
627
  }
628
628
 
629
+ /**
630
+ * for the given resource find it's action matching the target action. if that target action has an alt resource return it
631
+ */
632
+ const findResourceFromAction = (r) => {
633
+ const actualAction = r.availableActions.find((aa) => aa.action === action.action);
634
+
635
+ return actualAction?.altResource || r;
636
+ };
637
+
638
+ // if there there are multiple resources and a bulk action, use it and pass in the resources
639
+ // for example cluster management cluster list Download KubeConfig
629
640
  if ( resources.length > 1 && action.bulkAction && !opts.alt ) {
630
- const fn = resources[0][action.bulkAction];
641
+ const applyResource = findResourceFromAction(resources[0]);
642
+ const fn = applyResource[action.bulkAction];
631
643
 
632
644
  if ( fn ) {
633
- return fn.call(resources[0], resources, ...args);
645
+ const applyResources = resources.map(findResourceFromAction);
646
+
647
+ return fn.call(applyResource, applyResources, ...args);
634
648
  }
635
649
  }
636
650
 
637
651
  const promises = [];
638
652
 
653
+ // if there is a single resource or no bulk action, for each resource execute it's action
654
+ // for example delete when only one row is selected
639
655
  for ( const resource of resources ) {
640
656
  let fn;
641
657
 
658
+ const applyResource = findResourceFromAction(resource);
659
+
642
660
  if (opts.alt && action.altAction) {
643
- fn = resource[action.altAction];
661
+ fn = applyResource[action.altAction];
644
662
  } else {
645
- fn = resource[action.action];
663
+ fn = applyResource[action.action];
646
664
  }
647
665
 
648
666
  if ( fn ) {
649
- promises.push(fn.apply(resource, args));
667
+ promises.push(fn.apply(applyResource, args));
650
668
  }
651
669
  }
652
670
 
@@ -50,7 +50,8 @@ export default {
50
50
 
51
51
  if ( sortGenerationKey) {
52
52
  key = `${ sortGenerationKey }/${ this.rows.length }/${ this.descending }/${ this.sortFields.join(',') }`;
53
- if ( this.cacheKey === key ) {
53
+
54
+ if ( this.cacheKey === key && this.cachedRowsRef === this.rows ) {
54
55
  return this.cachedRows;
55
56
  }
56
57
  }
@@ -60,6 +61,7 @@ export default {
60
61
  if ( key ) {
61
62
  this.cacheKey = key;
62
63
  this.cachedRows = out;
64
+ this.cachedRowsRef = this.rows;
63
65
  }
64
66
 
65
67
  return out;
@@ -104,8 +106,9 @@ export default {
104
106
  return {
105
107
  sortBy,
106
108
  descending,
107
- cachedRows: null,
108
- cacheKey: null,
109
+ cachedRows: null,
110
+ cachedRowsRef: null,
111
+ cacheKey: null,
109
112
  };
110
113
  },
111
114