@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
@@ -0,0 +1,212 @@
1
+ import actions from '@shell/plugins/steve/actions';
2
+ import paginationUtils from '@shell/utils/pagination-utils';
3
+ import stevePaginationUtils from '@shell/plugins/steve/steve-pagination-utils';
4
+ import { PaginationParamFilter } from '@shell/types/store/pagination.types';
5
+
6
+ const { fetchResourceSummary } = actions;
7
+
8
+ describe('steve: actions:', () => {
9
+ describe('fetchResourceSummary', () => {
10
+ const schema = {
11
+ id: 'pod',
12
+ links: { collection: '/v1/pods' },
13
+ attributes: { namespaced: true },
14
+ };
15
+
16
+ const baseCtx = () => ({
17
+ getters: {
18
+ normalizeType: (type: string) => type,
19
+ schemaFor: (type: string) => (type === 'pod' ? schema : undefined),
20
+ },
21
+ dispatch: jest.fn(),
22
+ rootGetters: {},
23
+ });
24
+
25
+ let warnSpy: jest.SpyInstance;
26
+
27
+ beforeEach(() => {
28
+ warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
29
+ jest.spyOn(paginationUtils, 'isSteveCacheEnabled').mockReturnValue(true);
30
+ });
31
+
32
+ afterEach(() => {
33
+ jest.restoreAllMocks();
34
+ });
35
+
36
+ it('should return undefined and warn when schema is not found', async() => {
37
+ const ctx = baseCtx();
38
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'nonexistent', opt: { summaryField: 'metadata.state.name' } });
39
+
40
+ expect(result).toBeUndefined();
41
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('no schema found'));
42
+ });
43
+
44
+ it('should return undefined and warn when VAI is not enabled', async() => {
45
+ jest.spyOn(paginationUtils, 'isSteveCacheEnabled').mockReturnValue(false);
46
+ const ctx = baseCtx();
47
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
48
+
49
+ expect(result).toBeUndefined();
50
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('VAI is not enabled'));
51
+ });
52
+
53
+ it('should return undefined and warn when summaryField is missing', async() => {
54
+ const ctx = baseCtx();
55
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: {} });
56
+
57
+ expect(result).toBeUndefined();
58
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('summaryField is required'));
59
+ });
60
+
61
+ it('should construct the correct URL with summary and summaryonly params', async() => {
62
+ const ctx = baseCtx();
63
+
64
+ ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
65
+
66
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
67
+
68
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
69
+
70
+ expect(requestUrl).toContain('summary=metadata.state.name');
71
+ expect(requestUrl).toContain('summaryonly=');
72
+ expect(requestUrl).not.toContain('summarynamespaced');
73
+ });
74
+
75
+ it('should not include summaryonly when summaryOnly is false', async() => {
76
+ const ctx = baseCtx();
77
+
78
+ ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
79
+
80
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', summaryOnly: false } });
81
+
82
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
83
+
84
+ expect(requestUrl).not.toContain('summaryonly');
85
+ });
86
+
87
+ it('should include summarynamespaced param when namespaceCounts is true', async() => {
88
+ const ctx = baseCtx();
89
+
90
+ ctx.dispatch.mockResolvedValue({ count: 5, summary: [{ property: 'metadata.state.name', counts: { running: { total: 5 } } }] });
91
+
92
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespaceCounts: true } });
93
+
94
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
95
+
96
+ expect(requestUrl).toContain('summarynamespaced=');
97
+ });
98
+
99
+ it('should append namespace to path for namespaced resources', async() => {
100
+ const ctx = baseCtx();
101
+
102
+ ctx.dispatch.mockResolvedValue({ count: 2, summary: null });
103
+
104
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespace: 'cattle-system' } });
105
+
106
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
107
+
108
+ expect(requestUrl).toMatch(/\/v1\/pods\/cattle-system\?/);
109
+ });
110
+
111
+ it('should not append namespace when schema is not namespaced', async() => {
112
+ const nonNsSchema = { ...schema, attributes: { namespaced: false } };
113
+ const ctx = baseCtx();
114
+
115
+ ctx.getters.schemaFor = () => nonNsSchema;
116
+ ctx.dispatch.mockResolvedValue({ count: 1, summary: null });
117
+
118
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', namespace: 'default' } });
119
+
120
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
121
+
122
+ expect(requestUrl).not.toContain('/default');
123
+ });
124
+
125
+ it('should append filter params when filters are provided', async() => {
126
+ const ctx = baseCtx();
127
+ const filters = [PaginationParamFilter.createSingleField({ field: 'metadata.namespace', value: 'default' })];
128
+
129
+ jest.spyOn(stevePaginationUtils, 'convertPaginationParams').mockReturnValue('filter=metadata.namespace%3Ddefault');
130
+ ctx.dispatch.mockResolvedValue({ count: 3, summary: null });
131
+
132
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', filters } });
133
+
134
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
135
+
136
+ expect(requestUrl).toContain('filter=');
137
+ expect(stevePaginationUtils.convertPaginationParams).toHaveBeenCalledWith(expect.objectContaining({ filters }));
138
+ });
139
+
140
+ it('should return count and summary from the response', async() => {
141
+ const ctx = baseCtx();
142
+ const apiResponse = {
143
+ count: 10,
144
+ summary: [{ property: 'metadata.state.name', counts: { running: { total: 7 }, error: { total: 3 } } }]
145
+ };
146
+
147
+ ctx.dispatch.mockResolvedValue(apiResponse);
148
+
149
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
150
+
151
+ expect(result).toStrictEqual(apiResponse);
152
+ });
153
+
154
+ it('should pass through object-style counts as-is', async() => {
155
+ const ctx = baseCtx();
156
+ const counts = { running: { total: 7 }, error: { total: 3 } };
157
+ const apiResponse = {
158
+ count: 10,
159
+ summary: [{ property: 'metadata.state.name', counts }]
160
+ };
161
+
162
+ ctx.dispatch.mockResolvedValue(apiResponse);
163
+
164
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
165
+
166
+ expect(result).toStrictEqual({
167
+ count: 10,
168
+ summary: [{ property: 'metadata.state.name', counts }]
169
+ });
170
+ });
171
+
172
+ it('should default count to 0 and summary to null when response is empty', async() => {
173
+ const ctx = baseCtx();
174
+
175
+ ctx.dispatch.mockResolvedValue({});
176
+
177
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
178
+
179
+ expect(result).toStrictEqual({ count: 0, summary: null });
180
+ });
181
+
182
+ it('should append label selector params when labelSelector is provided', async() => {
183
+ const ctx = baseCtx();
184
+ const labelSelector = {
185
+ matchExpressions: [{
186
+ key: 'app', operator: 'In', values: ['nginx']
187
+ }]
188
+ };
189
+
190
+ jest.spyOn(stevePaginationUtils, 'convertLabelSelectorPaginationParams').mockReturnValue('filter=metadata.labels[app] IN (nginx)');
191
+ ctx.dispatch.mockResolvedValue({ count: 2, summary: null });
192
+
193
+ await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name', labelSelector } });
194
+
195
+ const requestUrl = ctx.dispatch.mock.calls[0][1].opt.url;
196
+
197
+ expect(requestUrl).toContain('filter=');
198
+ expect(stevePaginationUtils.convertLabelSelectorPaginationParams).toHaveBeenCalledWith({ labelSelector });
199
+ });
200
+
201
+ it('should return undefined and warn when the request fails', async() => {
202
+ const ctx = baseCtx();
203
+
204
+ ctx.dispatch.mockRejectedValue(new Error('network error'));
205
+
206
+ const result = await fetchResourceSummary.call({}, ctx, { type: 'pod', opt: { summaryField: 'metadata.state.name' } });
207
+
208
+ expect(result).toBeUndefined();
209
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('summary API request failed'), expect.any(Error));
210
+ });
211
+ });
212
+ });
@@ -14,7 +14,8 @@ describe('steve: subscribe', () => {
14
14
  schemaFor: () => null,
15
15
  inError: () => false,
16
16
  watchStarted: () => false,
17
- listenerManager: state.listenerManager
17
+ listenerManager: state.listenerManager,
18
+ typeRegistered: () => true,
18
19
  };
19
20
  const rootGetters = {
20
21
  'type-map/isSpoofed': () => false,
@@ -343,7 +344,7 @@ describe('steve: subscribe', () => {
343
344
 
344
345
  // call watch
345
346
  actions.watch({
346
- state, dispatch, getters, rootGetters
347
+ state, dispatch, getters, rootGetters, commit
347
348
  }, {
348
349
  ...obj,
349
350
  revision,
@@ -488,6 +489,7 @@ describe('steve: subscribe', () => {
488
489
  const state = {
489
490
  started: [],
490
491
  inError: {},
492
+ queue: [],
491
493
  listenerManager: new SteveWatchEventListenerManager()
492
494
  };
493
495
  const _getters = {
@@ -498,7 +500,8 @@ describe('steve: subscribe', () => {
498
500
  watchStarted: (...args) => getters.watchStarted(state)(...args),
499
501
  backOffId: (...args) => getters.backOffId()(...args),
500
502
  canBackoff: () => true,
501
- listenerManager: state.listenerManager
503
+ listenerManager: state.listenerManager,
504
+ typeRegistered: () => true,
502
505
  };
503
506
  const commit = (type, ...args) => mutations[type](state, ...args);
504
507
 
@@ -10,6 +10,7 @@ import { NAMESPACE } from '@shell/config/types';
10
10
  import { handleKubeApiHeaderWarnings } from '@shell/plugins/steve/header-warnings';
11
11
  import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
12
12
  import paginationUtils from '@shell/utils/pagination-utils';
13
+ import stevePaginationUtils from '@shell/plugins/steve/steve-pagination-utils';
13
14
 
14
15
  export default {
15
16
 
@@ -221,6 +222,101 @@ export default {
221
222
  }
222
223
  },
223
224
 
225
+ /**
226
+ * Fetch aggregated state counts for a resource type via the Steve summary API.
227
+ * Requires VAI (ui-sql-cache) to be enabled; returns undefined otherwise.
228
+ *
229
+ * Uses `summaryonly` by default so no resource data is returned.
230
+ *
231
+ * @param {string} type - Resource type (e.g. 'pod', 'service')
232
+ * @param {object} [opt] - Options object
233
+ * @param {string} opt.summaryField - Field to aggregate counts by.
234
+ * Must be a field indexed by the VAI cache (see StevePaginationUtils.VALID_FIELDS in steve-pagination-utils.ts)
235
+ * @param {string} [opt.namespace] - Namespace to scope the request to (only applies to namespaced resource types)
236
+ * @param {boolean} [opt.summaryOnly=true] - Omit resource data from the response (set to false to include data)
237
+ * @param {boolean} [opt.namespaceCounts] - Include per-namespace breakdowns in counts
238
+ * @param {PaginationParamFilter[]} [opt.filters] - Pre-built filters from PaginationParamFilter.createSingleField()
239
+ * @param {KubeLabelSelector} [opt.labelSelector] - Kube label selector to filter by (converted via convertLabelSelectorPaginationParams)
240
+ * @returns {Promise<{ count: number, summary: { property: string, counts: Record<string, { total: number, namespace?: Record<string, number> }> }[] | null } | undefined>}
241
+ *
242
+ * @example
243
+ * const result = await dispatch('fetchResourceSummary', {
244
+ * type: 'pod',
245
+ * opt: { summaryField: 'metadata.state.name', labelSelector: { matchExpressions: podMatchExpression } }
246
+ * });
247
+ * // result.summary[0].counts => { running: { total: 3 }, error: { total: 1 } }
248
+ *
249
+ * // With namespace breakdowns:
250
+ * const result = await dispatch('fetchResourceSummary', {
251
+ * type: 'pod',
252
+ * opt: { summaryField: 'metadata.state.name', namespaceCounts: true }
253
+ * });
254
+ * // result.summary[0].counts => { running: { total: 3, namespace: { default: 2, 'kube-system': 1 } } }
255
+ */
256
+ async fetchResourceSummary({ getters, dispatch, rootGetters }, { type, opt = {} }) {
257
+ type = getters.normalizeType(type);
258
+ const schema = getters.schemaFor(type);
259
+
260
+ if (!schema) {
261
+ console.warn(`fetchResourceSummary: no schema found for type "${ type }"`); // eslint-disable-line no-console
262
+
263
+ return undefined;
264
+ }
265
+
266
+ if (!paginationUtils.isSteveCacheEnabled({ rootGetters })) {
267
+ console.warn(`fetchResourceSummary: VAI is not enabled, summary API unavailable for type "${ type }"`); // eslint-disable-line no-console
268
+
269
+ return undefined;
270
+ }
271
+
272
+ if (!opt.summaryField) {
273
+ console.warn(`fetchResourceSummary: summaryField is required and must be a string for type "${ type }"`); // eslint-disable-line no-console
274
+
275
+ return undefined;
276
+ }
277
+
278
+ try {
279
+ const url = new URL(schema.links.collection, window.location.origin);
280
+
281
+ if (schema.attributes?.namespaced && opt.namespace) {
282
+ url.pathname += `/${ opt.namespace }`;
283
+ }
284
+
285
+ url.searchParams.set('summary', opt.summaryField);
286
+
287
+ if (opt.summaryOnly !== false) {
288
+ url.searchParams.set('summaryonly', '');
289
+ }
290
+
291
+ if (opt.namespaceCounts) {
292
+ url.searchParams.set('summarynamespaced', '');
293
+ }
294
+
295
+ if (opt.filters?.length) {
296
+ const filterParams = new URLSearchParams(stevePaginationUtils.convertPaginationParams({ schema, filters: opt.filters }));
297
+
298
+ filterParams.forEach((v, k) => url.searchParams.append(k, v));
299
+ }
300
+
301
+ if (opt.labelSelector) {
302
+ const labelParams = new URLSearchParams(stevePaginationUtils.convertLabelSelectorPaginationParams({ labelSelector: opt.labelSelector }));
303
+
304
+ labelParams.forEach((v, k) => url.searchParams.append(k, v));
305
+ }
306
+
307
+ const res = await dispatch('request', { opt: { url: url.pathname + url.search } });
308
+
309
+ return {
310
+ count: res.count ?? 0,
311
+ summary: res.summary || null
312
+ };
313
+ } catch (e) {
314
+ console.warn(`fetchResourceSummary: summary API request failed for type "${ type }"`, e); // eslint-disable-line no-console
315
+
316
+ return undefined;
317
+ }
318
+ },
319
+
224
320
  promptRestore({ commit, state }, resources ) {
225
321
  commit('action-menu/togglePromptRestore', resources, { root: true });
226
322
  },
@@ -258,6 +258,11 @@ class StevePaginationUtils extends NamespaceProjectFilters {
258
258
  { field: 'spec.displayName' },
259
259
  { field: `status.provider` },
260
260
  { field: `status.connected` },
261
+ { field: `status.info.machineProvider` },
262
+ { field: `status.driver` },
263
+ { field: `status.provider` },
264
+ { field: `status.info.kubernetesVersion` },
265
+ { field: `spec.fleetWorkspaceName` },
261
266
  ],
262
267
  [SECRET]: [
263
268
  { field: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]` },
@@ -265,7 +270,10 @@ class StevePaginationUtils extends NamespaceProjectFilters {
265
270
  [NAMESPACE]: [
266
271
  ],
267
272
  [CAPI.MACHINE]: [
268
- { field: 'spec.clusterName' }
273
+ { field: 'spec.clusterName' },
274
+ ],
275
+ [CAPI.MACHINE_DEPLOYMENT]: [
276
+ { field: 'spec.clusterName' },
269
277
  ],
270
278
  [EVENT]: [
271
279
  { field: '_type' },
@@ -648,7 +656,7 @@ class StevePaginationUtils extends NamespaceProjectFilters {
648
656
  * A lot of the requirements and details are taken directly from
649
657
  * https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
650
658
  */
651
- private convertLabelSelectorPaginationParams({ labelSelector }: { labelSelector: KubeLabelSelector}): string {
659
+ convertLabelSelectorPaginationParams({ labelSelector }: { labelSelector: KubeLabelSelector}): string {
652
660
  // Get a list of matchExpressions
653
661
  const expressions: KubeLabelSelectorExpression[] = labelSelector.matchExpressions ? [...labelSelector.matchExpressions] : [];
654
662
 
@@ -770,8 +778,8 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStores = {
770
778
  enableAll: false,
771
779
  enableSome: {
772
780
  enabled: [
773
- { resource: CAPI.RANCHER_CLUSTER, context: ['side-bar'] },
774
- { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
781
+ { resource: CAPI.RANCHER_CLUSTER, context: ['side-bar', 'home', 'cluster-management'] },
782
+ { resource: MANAGEMENT.CLUSTER, context: ['side-bar', 'home', 'cluster-management'] },
775
783
  { resource: CATALOG.APP, context: ['branding'] },
776
784
  SECRET
777
785
  ],
@@ -469,8 +469,10 @@ const sharedActions = {
469
469
  const worker = (this.$workers || {})[getters.storeName];
470
470
 
471
471
  if (worker) {
472
+ const storeName = getters.storeName;
473
+
472
474
  worker.postMessage({ destroyWorker: true }); // we're only passing the boolean here because the key needs to be something truthy to ensure it's passed on the object.
473
- cleanupTasks.push(waitFor(() => !this.$workers[getters.storeName], 'Worker is destroyed'));
475
+ cleanupTasks.push(waitFor(() => !this.$workers?.[storeName], 'Worker to be destroyed', 30000, 10, true));
474
476
  }
475
477
 
476
478
  if ( socket ) {
@@ -553,17 +555,32 @@ const sharedActions = {
553
555
  * @param {STEVE_WATCH_PARAMS} params
554
556
  */
555
557
  watch({
556
- state, dispatch, getters, rootGetters
558
+ state, dispatch, getters, rootGetters, commit
557
559
  }, params) {
558
560
  state.debugSocket && console.info(`Watch Request [${ getters.storeName }]`, JSON.stringify(params)); // eslint-disable-line no-console
559
561
  let {
560
562
  // eslint-disable-next-line prefer-const
561
- type, selector, id, revision, namespace, stop, force, mode, standardWatch = true
563
+ type, selector, id, revision, namespace, stop, force, mode, standardWatch = true, registerType = false
562
564
  } = params;
563
565
 
564
566
  namespace = acceptOrRejectSocketMessage.subscribeNamespace(namespace);
565
567
  type = getters.normalizeType(type);
566
568
 
569
+ if ( !getters.typeRegistered(type) ) {
570
+ if (registerType) {
571
+ commit('registerType', type);
572
+ } else if (mode !== STEVE_WATCH_MODE.RESOURCE_CHANGES) {
573
+ // - If we continue and open up a watch whenever we receive a `resource.` notification we go to queueChanges (bar resource.changes mode).
574
+ // - queueChanges ignores any change that's for a type that hasn't been registered
575
+ // - So here we're just exiting early, avoiding the watch --> queueChanges --> ignore loop
576
+ //
577
+ // Interestingly this is hit quite a few times (on cluster create screens there's token, cluster, project, projectRoleTemplateBinding, etc)
578
+ state.debugSocket && console.info('Will not Watch (type is not registered)', JSON.stringify(params)); // eslint-disable-line no-console
579
+
580
+ return;
581
+ }
582
+ }
583
+
567
584
  if (rootGetters['type-map/isSpoofed'](type)) {
568
585
  state.debugSocket && console.info('Will not Watch (type is spoofed)', JSON.stringify(params)); // eslint-disable-line no-console
569
586
 
@@ -620,6 +637,9 @@ const sharedActions = {
620
637
  if (debounceMs) {
621
638
  msg.debounceMs = debounceMs;
622
639
  }
640
+
641
+ // Anything in the queue will pollute the result set, so clear (and print to console so we know it's working)
642
+ commit('clearFromQueue', { type, log: true });
623
643
  }
624
644
  }
625
645
 
@@ -1556,10 +1576,20 @@ const defaultMutations = {
1556
1576
  state.socketListenerManager = new SteveWatchEventListenerManager(state.config.namespace);
1557
1577
  },
1558
1578
 
1559
- clearFromQueue(state, type) {
1579
+ clearFromQueue(state, args) {
1580
+ const safeArgs = typeof args === 'object' ? args : { type: args };
1581
+ const { type, log } = safeArgs;
1582
+
1560
1583
  // Remove anything in the queue that is a resource update for the given type
1561
1584
  state.queue = state.queue.filter((item) => {
1562
- return item.body?.type !== type;
1585
+ const keep = item.body?.type !== type;
1586
+
1587
+ if (!keep && log) {
1588
+ // eslint-disable-next-line no-console
1589
+ console.info(`Clearing queued item of type \`${ type }\` from queue`, item);
1590
+ }
1591
+
1592
+ return keep;
1563
1593
  });
1564
1594
  },
1565
1595
  };
@@ -1,8 +1,14 @@
1
1
  <script lang="ts">
2
- import { defineComponent } from 'vue';
3
- import { mapGetters } from 'vuex';
2
+ import {
3
+ computed, defineComponent, nextTick, ref, useTemplateRef
4
+ } from 'vue';
5
+ import { mapGetters, useStore } from 'vuex';
6
+ import { useInSummary } from '@shell/components/TableOfContents/composables';
7
+ import { useI18n } from '@shell/composables/useI18n';
4
8
 
5
9
  export default defineComponent({
10
+ name: 'Accordion',
11
+
6
12
  props: {
7
13
  title: {
8
14
  type: String,
@@ -20,22 +26,59 @@ export default defineComponent({
20
26
  }
21
27
  },
22
28
 
29
+ setup(props) {
30
+ const store = useStore();
31
+ const { t } = useI18n(store);
32
+ const label = computed(() => props.titleKey && typeof t === 'function' ? t(props.titleKey) : props.title);
33
+
34
+ const isOpen = ref(props.openInitially);
35
+ const accordionSummarizedContainer = useTemplateRef<HTMLElement>('accordion-summarized-container');
36
+
37
+ const scrollTo = () => {
38
+ isOpen.value = true;
39
+ nextTick(() => {
40
+ accordionSummarizedContainer.value?.scrollIntoView();
41
+ });
42
+ };
43
+
44
+ const { summary } = useInSummary({
45
+ scrollTo,
46
+ label,
47
+ elementRef: accordionSummarizedContainer,
48
+ });
49
+
50
+ return {
51
+ summary,
52
+ isOpen,
53
+ scrollTo,
54
+ };
55
+ },
56
+
23
57
  data() {
24
- return { isOpen: this.openInitially };
58
+ return {};
25
59
  },
26
60
 
27
- computed: { ...mapGetters({ t: 'i18n/t' }) },
61
+ computed: {
62
+ ...mapGetters({ t: 'i18n/t' }),
63
+
64
+ displayTitle() {
65
+ return this.titleKey ? this.t(this.titleKey) : this.title;
66
+ },
67
+ },
28
68
 
29
69
  methods: {
30
70
  toggle() {
31
71
  this.isOpen = !this.isOpen;
32
- }
33
- }
72
+ },
73
+ },
34
74
  });
35
75
  </script>
36
76
 
37
77
  <template>
38
- <div class="accordion-container">
78
+ <div
79
+ ref="accordion-summarized-container"
80
+ class="accordion-container"
81
+ >
39
82
  <div
40
83
  class="accordion-header"
41
84
  data-testid="accordion-header"
@@ -51,7 +94,7 @@ export default defineComponent({
51
94
  data-testid="accordion-title-slot-content"
52
95
  class="mb-0"
53
96
  >
54
- {{ titleKey ? t(titleKey) : title }}
97
+ {{ displayTitle }}
55
98
  </h2>
56
99
  </slot>
57
100
  </div>
@@ -67,7 +110,8 @@ export default defineComponent({
67
110
 
68
111
  <style lang="scss" scoped>
69
112
  .accordion-container {
70
- border: 1px solid var(--border)
113
+ border: 1px solid var(--border);
114
+ border-radius: var(--border-radius);
71
115
  }
72
116
  .accordion-header {
73
117
  padding: 16px 16px 16px 11px;
@@ -125,6 +125,14 @@ export default defineComponent({
125
125
  default: undefined
126
126
  },
127
127
 
128
+ /**
129
+ * Use body text color for the label instead of the default input-label color.
130
+ */
131
+ useBodyTextColor: {
132
+ type: Boolean,
133
+ default: false
134
+ },
135
+
128
136
  /**
129
137
  * Inherited global identifier prefix for tests
130
138
  * Define a term based on the parent component to avoid conflicts on multiple components
@@ -316,6 +324,7 @@ export default defineComponent({
316
324
  <span
317
325
  v-if="labelKey"
318
326
  :id="idForLabel"
327
+ :class="{ 'body-text-color': useBodyTextColor }"
319
328
  >
320
329
  <t
321
330
  :k="labelKey"
@@ -325,6 +334,7 @@ export default defineComponent({
325
334
  <span
326
335
  v-else-if="label"
327
336
  :id="idForLabel"
337
+ :class="{ 'body-text-color': useBodyTextColor }"
328
338
  >{{ label }}</span>
329
339
  <i
330
340
  v-if="tooltipKey"
@@ -403,6 +413,10 @@ $fontColor: var(--input-label);
403
413
  display: inline-flex;
404
414
  margin: 0px 10px 0px 5px;
405
415
 
416
+ .body-text-color {
417
+ color: var(--body-text);
418
+ }
419
+
406
420
  &.checkbox-primary {
407
421
  color: inherit;
408
422
  font-weight: 600;
@@ -1,4 +1,4 @@
1
- import { defineComponent, nextTick } from 'vue';
1
+ import { defineComponent, nextTick, provide, ref } from 'vue';
2
2
  import { mount, flushPromises } from '@vue/test-utils';
3
3
  import { useForm } from 'vee-validate';
4
4
  import { LabeledInput } from './index';
@@ -195,21 +195,27 @@ describe('component: LabeledInput', () => {
195
195
 
196
196
  it('with name prop: form-level validation schema error is shown when the form validates', async() => {
197
197
  const errorMessage = 'Username is required';
198
+ const showAllErrors = ref(false);
198
199
  let triggerFormValidation!: () => Promise<unknown>;
199
200
 
200
201
  const TestWrapper = defineComponent({
201
202
  components: { LabeledInput },
202
203
  setup() {
204
+ provide('vee-show-all-errors', showAllErrors);
205
+
203
206
  const { validate } = useForm({
204
207
  validationSchema: { username: (v: string) => (!v ? errorMessage : true) },
205
- initialValues: { username: '' }
208
+ initialValues: { username: '' },
206
209
  });
207
210
 
208
- triggerFormValidation = validate;
211
+ triggerFormValidation = async() => {
212
+ await validate();
213
+ showAllErrors.value = true;
214
+ };
209
215
 
210
216
  return {};
211
217
  },
212
- template: '<LabeledInput name="username" value="" />'
218
+ template: '<LabeledInput name="username" value="" />',
213
219
  });
214
220
 
215
221
  const wrapper = mount(TestWrapper, { global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } } });