@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
@@ -1,8 +1,9 @@
1
1
  import { IExtension } from '@shell/core/types';
2
2
  import {
3
3
  ProductChild, ProductMetadata,
4
- ConfigureTypeConfiguration, VirtualTypeConfiguration,
5
- ProductChildCustomPage, VueRouteComponent, OverviewPageRoutingMetadata
4
+ ResourcePageConfiguration, CustomPageConfiguration,
5
+ ProductChildCustomPage, VueRouteComponent,
6
+ OverviewPageRoutingMetadata
6
7
  } from '@shell/core/plugin-types';
7
8
  import EmptyProductPage from '@shell/components/EmptyProductPage.vue';
8
9
  import pluginProductsHelpers from '@shell/core/plugin-products-helpers';
@@ -11,7 +12,7 @@ import {
11
12
  isProductChildWithComponent,
12
13
  isProductChildWithType,
13
14
  hasNameProperty,
14
- hasTypeProperty
15
+ hasTypeProperty,
15
16
  } from '@shell/core/plugin-products-type-guards';
16
17
 
17
18
  /**
@@ -27,6 +28,16 @@ export abstract class BasePluginProduct {
27
28
 
28
29
  protected registeredPageNames: Set<string> = new Set();
29
30
 
31
+ // Maps user-friendly group name → internal resolved name (e.g. 'monitoring' → 'myapp-monitoring')
32
+ // Populated during processGroupRecursively, consumed by moveToGroup resolution in processProductLevelDSLOptions
33
+ protected groupNameMap: Map<string, string> = new Map();
34
+
35
+ // Maps user-facing page identifier → internal basicType key
36
+ // Resource pages: type → type (identity, e.g. 'pod' → 'pod')
37
+ // Custom pages: name → prefixed name (e.g. 'myPage' → 'product1-myPage')
38
+ // Populated during configurePageItem, consumed by moveToGroup resolution in processProductLevelDSLOptions
39
+ protected pageIdMap: Map<string, string> = new Map();
40
+
30
41
  protected DSLMethods: any;
31
42
 
32
43
  protected config: ProductChild[];
@@ -40,11 +51,16 @@ export abstract class BasePluginProduct {
40
51
  */
41
52
  abstract get isNewProduct(): boolean;
42
53
 
54
+ get productName(): string {
55
+ return this.name;
56
+ }
57
+
43
58
  /**
44
59
  * Helper to throw errors during product registration
45
60
  */
46
- protected surfaceError(message: string): void {
47
- throw new Error(`Extensions - product "${ this.name }" registration error ::: ${ message }`);
61
+ protected surfaceError(message: string, e?: any): never {
62
+ console.error(`Extensions - product "${ this.name }" registration error ::: ${ message }`); // eslint-disable-line no-console
63
+ throw new Error(`Extensions - product "${ this.name }" registration error ::: ${ message }`, { cause: e });
48
64
  }
49
65
 
50
66
  /**
@@ -106,6 +122,12 @@ export abstract class BasePluginProduct {
106
122
  this.processGroupRecursively(item, this.name);
107
123
  }
108
124
  });
125
+
126
+ // Process product-level DSL options after all groups are registered
127
+ // so that the groupNameMap is fully populated for moveToGroup resolution
128
+ if (this.product) {
129
+ this.processProductLevelDSLOptions();
130
+ }
109
131
  }
110
132
 
111
133
  /**
@@ -124,6 +146,10 @@ export abstract class BasePluginProduct {
124
146
  const itemGroup = item;
125
147
  const groupName = parentGroupName ? `${ productName }-${ parentGroupName }-${ itemGroup.name }` : `${ productName }-${ itemGroup.name }`;
126
148
 
149
+ // Map the user's friendly group name to the resolved internal name
150
+ // so that moveToGroup can translate friendly names automatically
151
+ this.groupNameMap.set(itemGroup.name, groupName);
152
+
127
153
  if (!Array.isArray(itemGroup.children)) {
128
154
  this.surfaceError('Children defined for group are not in an array format');
129
155
 
@@ -181,7 +207,7 @@ export abstract class BasePluginProduct {
181
207
  }
182
208
 
183
209
  /**
184
- * Handles product registration via DSL
210
+ * Handles product registration via DSL (we also define entry route for the product here based on the config of the product - ordering)
185
211
  */
186
212
  protected handleProductRegistration(): void {
187
213
  const { basicType, product } = this.DSLMethods;
@@ -196,7 +222,7 @@ export abstract class BasePluginProduct {
196
222
 
197
223
  if (isProductChildGroup(firstConfig)) {
198
224
  // First config item is a group
199
- if (firstConfig.children.length) {
225
+ if (firstConfig.children.length > 0) {
200
226
  const entryChild = firstConfig.children[0];
201
227
 
202
228
  if (!firstConfig.component) {
@@ -241,11 +267,67 @@ export abstract class BasePluginProduct {
241
267
  });
242
268
  }
243
269
 
270
+ /**
271
+ * Process product-level DSL options: renameGroups, ignoreGroups, moveToGroup.
272
+ * Called after all config items and groups are registered so that the groupNameMap is fully populated.
273
+ */
274
+ protected processProductLevelDSLOptions(): void {
275
+ const {
276
+ mapGroup, ignoreGroup, moveType, basicType
277
+ } = this.DSLMethods;
278
+
279
+ if (this.product?.renameGroups?.length) {
280
+ this.product.renameGroups.forEach((mapping) => {
281
+ mapGroup(mapping.groupSelector, mapping.newName);
282
+ });
283
+ }
284
+
285
+ if (this.product?.ignoreGroups?.length) {
286
+ this.product.ignoreGroups.forEach((ignore) => {
287
+ if (ignore.condition) {
288
+ ignoreGroup(ignore.groupSelector, ignore.condition);
289
+ } else {
290
+ ignoreGroup(ignore.groupSelector);
291
+ }
292
+ });
293
+ }
294
+
295
+ if (this.product?.moveToGroup?.length) {
296
+ this.product.moveToGroup.forEach((move) => {
297
+ const resolvedGroup = this.groupNameMap.get(move.groupName);
298
+
299
+ if (!resolvedGroup) {
300
+ this.surfaceError(`moveToGroup target group "${ move.groupName }" not found. Available groups: ${ Array.from(this.groupNameMap.keys()).join(', ') }`);
301
+ }
302
+
303
+ const resolvedPageId = this.pageIdMap.get(move.entryId);
304
+
305
+ if (!resolvedPageId) {
306
+ this.surfaceError(`moveToGroup entryId "${ move.entryId }" not found. Available pages: ${ Array.from(this.pageIdMap.keys()).join(', ') }`);
307
+ }
308
+
309
+ // Re-register via basicType to move the page in the nav tree (basic view mode)
310
+ basicType([resolvedPageId], resolvedGroup);
311
+
312
+ // Also register via moveType for non-basic view modes (e.g. "in use" mode).
313
+ // moveType uses regex matching against schema IDs, so it only works for resource types.
314
+ const isResourceType = resolvedPageId === move.entryId;
315
+
316
+ if (isResourceType) {
317
+ moveType(move.entryId, resolvedGroup, move.weight);
318
+ }
319
+ });
320
+ }
321
+ }
322
+
244
323
  /**
245
324
  * Configure virtualType (custom page) or configureType (resource page) for a page item
246
325
  */
247
326
  protected configurePageItem(parentName: string, item: ProductChild, groupNaming?: string): void {
248
- const { configureType, virtualType, weightType } = this.DSLMethods;
327
+ const {
328
+ configureType, virtualType, weightType,
329
+ mapType, ignoreType, hideBulkActions, headers
330
+ } = this.DSLMethods;
249
331
 
250
332
  // Page with a "component" specified maps to a virtualType
251
333
  if (isProductChildWithComponent(item) || (isProductChildGroup(item) && item.component)) {
@@ -259,8 +341,9 @@ export abstract class BasePluginProduct {
259
341
  }
260
342
 
261
343
  this.registeredPageNames.add(finalName);
344
+ this.pageIdMap.set(item.name, finalName);
262
345
 
263
- const virtualTypeConfig: VirtualTypeConfiguration = {
346
+ const virtualTypeConfig: CustomPageConfiguration = {
264
347
  label: item.label,
265
348
  labelKey: item.labelKey,
266
349
  namespaced: false,
@@ -290,10 +373,11 @@ export abstract class BasePluginProduct {
290
373
  }
291
374
 
292
375
  this.registeredPageNames.add(typeValue);
376
+ this.pageIdMap.set(typeValue, typeValue);
293
377
 
294
378
  const route = pluginProductsHelpers.generateConfigureTypeRoute(parentName, item, { extendProduct: !this.isNewProduct });
295
379
 
296
- const configureTypeConfig: ConfigureTypeConfiguration = {
380
+ const configureTypeConfig: ResourcePageConfiguration = {
297
381
  isCreatable: true,
298
382
  isEditable: true,
299
383
  isRemovable: true,
@@ -301,6 +385,22 @@ export abstract class BasePluginProduct {
301
385
  customRoute: route
302
386
  };
303
387
 
388
+ if (item.headers || item.sspHeaders) {
389
+ headers(item.type, item.headers, item.sspHeaders);
390
+ }
391
+
392
+ if (item.overrideListResourceName) {
393
+ mapType(item.type, item.overrideListResourceName);
394
+ }
395
+
396
+ if (item.hideFromNav) {
397
+ ignoreType(item.type);
398
+ }
399
+
400
+ if (item.hideBulkActions) {
401
+ hideBulkActions(item.type, true);
402
+ }
403
+
304
404
  configureType(typeValue, { ...configureTypeConfig, ...(item.config || {}) });
305
405
 
306
406
  if (item.weight) {
@@ -47,4 +47,8 @@ export class PluginProduct {
47
47
  get newProduct(): boolean {
48
48
  return this.instance.isNewProduct;
49
49
  }
50
+
51
+ get productName(): string {
52
+ return this.instance.productName;
53
+ }
50
54
  }
@@ -4,7 +4,7 @@ import { NAME as EXPLORER_PROD_NAME } from '@shell/config/product/explorer.js';
4
4
  import { NAME as CLUSTER_MAN_PROD_NAME } from '@shell/config/product/manager.js';
5
5
  import { NAME as SETTINGS_PROD_NAME } from '@shell/config/product/settings.js';
6
6
  import { NAME as AUTH_PROD_NAME } from '@shell/config/product/auth.js';
7
- import { ProductOptions } from '@shell/core/types';
7
+ import { ProductOptions, HeaderOptions, PaginationHeaderOptions } from '@shell/core/types';
8
8
 
9
9
  type Async<T> = () => Promise<T>;
10
10
 
@@ -35,6 +35,12 @@ export type ProductRegistrationRouteGenerationOptions = {
35
35
  * Generated route should omit the path property
36
36
  */
37
37
  omitPath?: boolean;
38
+ /**
39
+ * @internal
40
+ * Whether the route should start with the product name or not (e.g. "my-product/c/:cluster/:resource" vs "c/:cluster/my-product/:resource")
41
+ * only to be used in very special usecases (internal use only - check FLEET product config for an example)
42
+ * */
43
+ startRouteWithProduct?: boolean;
38
44
  }
39
45
 
40
46
  /**
@@ -72,7 +78,7 @@ export type ProductChildMetadata = {
72
78
  /**
73
79
  * Represents the allowed configuration for a custom page (virtualType)
74
80
  */
75
- export type VirtualTypeConfiguration = {
81
+ export type CustomPageConfiguration = {
76
82
  /** Display only if condition is met (relates to IF_HAVE in shell/store/type-map) */
77
83
  ifHave?: boolean;
78
84
  /** Display only if feature is present (relates to shell/store/features) */
@@ -81,23 +87,44 @@ export type VirtualTypeConfiguration = {
81
87
  ifHaveType?: string;
82
88
  /** Used in conjunction with "ifHaveType", display only if resource type allows this verb (GET, POST, PUT, DELETE) */
83
89
  ifHaveVerb?: string;
84
- /** Display label for the custom page */
90
+ /**
91
+ * @internal
92
+ * Display label for the custom page
93
+ */
85
94
  label?: string;
86
- /** Translation key for the label */
95
+ /**
96
+ * @internal
97
+ * Translation key for the label
98
+ * */
87
99
  labelKey?: string;
88
- /** Name of the page (unique identifier) */
100
+ /**
101
+ * @internal
102
+ * Name of the page (unique identifier)
103
+ */
89
104
  name?: string;
90
- /** Entry route definition for this custom page */
105
+ /**
106
+ * @internal
107
+ * Entry route definition for this custom page
108
+ */
91
109
  route?: RouteRecordRawWithParams | PluginRouteRecordRaw | Object;
92
- /** Icon for the custom page (relates to icons in https://github.com/rancher/icons) */
110
+ /**
111
+ * @internal
112
+ * Icon for the custom page (relates to icons in https://github.com/rancher/icons)
113
+ */
93
114
  icon?: 'compass';
94
115
  /** Whether this custom page is namespaced or not */
95
116
  namespaced?: boolean;
96
- /** Ordering weight for the custom page */
117
+ /**
118
+ * @internal
119
+ * Ordering weight for the custom page
120
+ */
97
121
  weight?: number;
98
122
  /** Whether this custom page is exact match */
99
123
  exact?: boolean;
100
- /** Whether this custom page will act as an overview page */
124
+ /**
125
+ * @internal
126
+ * Whether this custom page will act as an overview page
127
+ * */
101
128
  overview?: boolean;
102
129
  /** Whether this custom page has an exact path match */
103
130
  'exact-path'?: boolean;
@@ -106,7 +133,11 @@ export type VirtualTypeConfiguration = {
106
133
  /**
107
134
  * Represents the allowed configuration for a resource page (configureType)
108
135
  */
109
- export type ConfigureTypeConfiguration = {
136
+ export type ResourcePageConfiguration = {
137
+ /**
138
+ * @internal
139
+ * Entry route definition for this custom page
140
+ */
110
141
  /** Override for the name displayed */
111
142
  displayName?: string;
112
143
  /** Override for the create button string on a list view */
@@ -129,25 +160,47 @@ export type ConfigureTypeConfiguration = {
129
160
  canYaml?: boolean;
130
161
  /** Show the Masthead in the edit resource component */
131
162
  resourceEditMasthead?: boolean;
132
- /** Entry route definition for this resource page */
163
+ /**
164
+ * @internal
165
+ * Entry route definition for this resource page
166
+ */
133
167
  customRoute?: RouteRecordRawWithParams;
134
168
  /** Hide this type from the nav/search bar on downstream clusters (will only show in "local" cluster) */
135
169
  localOnly?: boolean;
170
+ /** Whether this custom page is namespaced or not */
171
+ namespaced?: boolean;
172
+ /**
173
+ * @internal
174
+ * Whether this custom page has list groups (definition for grouping items in the list view)
175
+ */
176
+ listGroups?: {
177
+ /** Icon for the group (relates to icons in rancher-icons */
178
+ icon?: string;
179
+ /** Value for the group (used for grouping items in the list view) */
180
+ value?: string;
181
+ /** Field for the group (used for grouping items in the list view) */
182
+ field?: string;
183
+ /** Column to hide when this group is active */
184
+ hideColumn?: string;
185
+ /** Tooltip key for the group */
186
+ tooltipKey?: string;
187
+ }[];
188
+ /**
189
+ * @internal
190
+ * Whether the provided list groups will override the default grouping options (e.g. group by namespace, group by cluster, etc.) or be added to them
191
+ */
192
+ listGroupsWillOverride?: boolean;
193
+ /**
194
+ * @internal
195
+ * Use this to configure subtypes that should be shown in the list view for this type (e.g. show "pods" and "deployments" in the list view for "workloads")
196
+ */
197
+ subTypes?: string[];
136
198
  // resource: undefined; // Use this resource in ResourceDetails instead
137
199
  // resourceDetail: undefined; // Use this resource specifically for ResourceDetail's detail component
138
200
  // resourceEdit: undefined; // Use this resource specifically for ResourceDetail's edit component
139
201
  // depaginate: undefined; // Use this to depaginate requests for this type
140
202
  // notFilterNamespace: undefined; // Define namespaces that do not need to be filtered
141
203
  // used in configureType options, to be typed later if needed
142
- // listGroups: [
143
- // {
144
- // icon: 'icon-role-binding',
145
- // value: 'node',
146
- // field: 'roleDisplay',
147
- // hideColumn: ROLE.name,
148
- // tooltipKey: 'resourceTable.groupBy.role'
149
- // }
150
- // ]
151
204
  }
152
205
 
153
206
  /**
@@ -165,16 +218,6 @@ export type OverviewPageRoutingMetadata = {
165
218
  component: VueRouteComponent;
166
219
  }
167
220
 
168
- /**
169
- * Represents a custom page with a component
170
- */
171
- export type ProductChildCustomPage = ProductChildMetadata & {
172
- /** Component to render for this custom page */
173
- component: VueRouteComponent;
174
- /** Optional configuration for the page */
175
- config?: VirtualTypeConfiguration;
176
- };
177
-
178
221
  /**
179
222
  * Represents a resource page with a type (K8s resource)
180
223
  */
@@ -182,9 +225,29 @@ export type ProductChildResourcePage = {
182
225
  /** K8s resource type name for a resource page */
183
226
  type: string;
184
227
  /** Optional configuration for the resource page */
185
- config?: ConfigureTypeConfiguration;
228
+ config?: ResourcePageConfiguration;
186
229
  /** Ordering weight for this page among its siblings */
187
230
  weight?: number;
231
+ /** Use this to override the resource name used in the list view for this type */
232
+ overrideListResourceName?: string;
233
+ /** Whether to hide this resource from the side-menu entirely */
234
+ hideFromNav?: boolean;
235
+ /** Whether to hide bulk actions for this resource */
236
+ hideBulkActions?: boolean;
237
+ /** Table headers for this resource type (client-side pagination) */
238
+ headers?: HeaderOptions[];
239
+ /** Table headers for this resource type (server-side pagination) */
240
+ sspHeaders?: PaginationHeaderOptions[];
241
+ };
242
+
243
+ /**
244
+ * Represents a custom page with a component
245
+ */
246
+ export type ProductChildCustomPage = ProductChildMetadata & {
247
+ /** Component to render for this custom page */
248
+ component: VueRouteComponent;
249
+ /** Optional configuration for the page */
250
+ config?: CustomPageConfiguration;
188
251
  };
189
252
 
190
253
  /**
@@ -218,6 +281,106 @@ export type ProductMetadata = Omit<ProductOptions, 'name' | 'label' | 'labelKey'
218
281
  * Product name (unique identifier)
219
282
  */
220
283
  name: string;
284
+ /**
285
+ * @internal
286
+ * Use `renameGroups` on the product metadata to remap group display names in the side-menu. Each entry matches a group's internal ID (via string or regex) and replaces its display label with a new name. This only changes how the group is labelled in the UI — it does not move resources between groups.
287
+ *
288
+ * The `groupSelector` is evaluated against group internal IDs. It can be an exact string or a `RegExp` pattern. The `newName` value is the new display name.
289
+ *
290
+ * const product: ProductMetadata = {
291
+ * name: 'my-app',
292
+ * label: 'My App',
293
+ * renameGroups: [
294
+ * // Rename a group with an ugly internal ID to a friendlier display name
295
+ * { groupSelector: 'cert-manager.io', newName: 'Certificates' },
296
+ * // Use a regex to rename all groups matching a pattern
297
+ * { groupSelector: /^networking\./, newName: 'Networking' },
298
+ * ],
299
+ * };
300
+ */
301
+ renameGroups?: {
302
+ /** String or regex to match against group internal IDs */
303
+ groupSelector: RegExp | string;
304
+ /** Display name to use for matching groups */
305
+ newName: string;
306
+ }[];
307
+ /**
308
+ * @internal
309
+ *
310
+ * Use `moveToGroup` on the product metadata to move pages (resource types or custom pages) into specific side-menu groups. This is useful when a page should appear inside a group but isn't defined as a child of that group in the config.
311
+ * Each entry identifies a page by its `entryId` — the resource `type` string or the custom page `name` — and moves it into the specified group. Use the group's `name` as you defined it in your config.
312
+ *
313
+ * const monitoringGroup: ProductChildGroup = {
314
+ * name: 'monitoring',
315
+ * label: 'Monitoring',
316
+ * children: [
317
+ * { name: 'alerts', label: 'Alerts', component: () => import('./pages/Alerts.vue') },
318
+ * ],
319
+ * };
320
+
321
+ * const dashboardPage: ProductChildCustomPage = {
322
+ * name: 'dashboard', label: 'Dashboard', component: () => import('./pages/Dashboard.vue'),
323
+ * };
324
+
325
+ * const product: ProductMetadata = {
326
+ * name: 'my-app',
327
+ * label: 'My App',
328
+ * moveToGroup: [
329
+ * // Move the 'pod' resource type into the 'monitoring' group
330
+ * { entryId: 'pod', groupName: 'monitoring' },
331
+ * // Move a custom page into the 'monitoring' group
332
+ * { entryId: 'dashboard', groupName: 'monitoring' },
333
+ * ],
334
+ * };
335
+ *
336
+ * extension.addProduct(product, [monitoringGroup, { type: 'pod' }, dashboardPage]);
337
+ *
338
+ * Note: The `entryId` must match a page declared in the same product config — either a resource page's `type` or a custom page's `name`. The target `groupName` must be a `ProductChildGroup` defined in the same config. If either is not found, an error is thrown at registration time listing the available options. Only exact string identifiers are supported (no regex).
339
+ *
340
+ * The optional `weight` parameter controls precedence when multiple `moveToGroup` rules target the same page (default: `5`). Higher weight takes precedence.
341
+ */
342
+ moveToGroup?: {
343
+ /** Page identifier — the resource `type` string or the custom page `name` */
344
+ entryId: string;
345
+ /** Target group name as defined in your group config (`name` property) */
346
+ groupName: string;
347
+ /** Ordering weight for the mapping (default: 5). Higher weight takes precedence when multiple rules match */
348
+ weight?: number;
349
+ }[];
350
+ /**
351
+ * @internal
352
+ *
353
+ * maps to DSL ignoreGroup
354
+ *
355
+ * Use `ignoreGroups` on the product metadata to hide specific side-menu groups. Each entry specifies a `groupSelector` to match group names — either an exact string or a regex pattern.
356
+ *
357
+ * The `condition` callback is optional. When provided, it receives the store getters and returns `true` to hide the group (conditional hide). When omitted, the group is always hidden (unconditional hide).
358
+ *
359
+ * Example usage:
360
+ * const product: ProductMetadata = {
361
+ * name: 'my-app',
362
+ * label: 'My App',
363
+ * ignoreGroups: [
364
+ * // Always hide the "internal" group (unconditional — no condition)
365
+ * { groupSelector: 'internal' },
366
+ * // Hide all groups matching a regex pattern (unconditional)
367
+ * { groupSelector: /^deprecated/ },
368
+ * // Conditionally hide based on a feature flag
369
+ * {
370
+ * groupSelector: 'experimental',
371
+ * condition: (getters) => !getters['features/isEnabled']('experimental-feature'),
372
+ * },
373
+ * ],
374
+ * };
375
+ *
376
+ *
377
+ * In this example, the "internal" group is always hidden, any group with a name starting with "deprecated-" is hidden, and the "experimental" group is hidden unless the "experimental-feature" flag is enabled in the store.
378
+ */
379
+ ignoreGroups?: {
380
+ /** String or regex to match against group names */
381
+ groupSelector: string | RegExp;
382
+ /** Optional conditional function that accepts the root Dashboard Vuex store getters and returns true if the group should be ignored */
383
+ condition?: (getters: any) => boolean }[];
221
384
  } & (
222
385
  /** Human-readable label for the product
223
386
  * Either label or labelKey are required */
package/core/plugin.ts CHANGED
@@ -124,6 +124,9 @@ export class Plugin implements IPlugin {
124
124
  this.topLevelProduct = true;
125
125
  }
126
126
 
127
+ _setStartRouteWithProduct(_value: boolean): void {
128
+ }
129
+
127
130
  // Track which products the plugin creates
128
131
  // Legacy DSL method
129
132
  DSL(store: any, productName: string) {
@@ -135,21 +138,29 @@ export class Plugin implements IPlugin {
135
138
  }
136
139
 
137
140
  addProduct(product: ProductFunction | ProductMetadata | ProductSinglePage | string, config?: ProductChild[]): void {
141
+ let pluginProduct: PluginProduct;
142
+
138
143
  if (typeof product === 'string') {
139
- this.productConfigs.push(PluginProduct.fromName(this, product));
144
+ pluginProduct = PluginProduct.fromName(this, product);
140
145
  } else if (product?.name) {
141
146
  if (!config) {
142
- const p = product as ProductSinglePage;
143
-
144
- this.productConfigs.push(new PluginProduct(this, p, []));
147
+ pluginProduct = new PluginProduct(this, product as ProductSinglePage, []);
145
148
  } else {
146
- const p = product as ProductMetadata;
147
-
148
- this.productConfigs.push(new PluginProduct(this, p, config));
149
+ pluginProduct = new PluginProduct(this, product as ProductMetadata, config);
149
150
  }
150
151
  } else {
151
152
  this.products.push(product as ProductFunction);
153
+
154
+ return;
152
155
  }
156
+
157
+ const existingProduct = this.productConfigs.find((p) => p.newProduct && p.productName === pluginProduct.productName);
158
+
159
+ if (existingProduct) {
160
+ throw new Error(`Extensions - product "${ pluginProduct.productName }" registration error ::: addProduct can only be called once per product. Use extendProduct to add pages to an existing product.`);
161
+ }
162
+
163
+ this.productConfigs.push(pluginProduct);
153
164
  }
154
165
 
155
166
  extendProduct(product: StandardProductName | string, config: ProductChild[] | ProductChild): void {
@@ -21,8 +21,13 @@ export function DSLRegistrationsPerProduct(store, prodName) {
21
21
  }
22
22
 
23
23
  // prod configureType
24
- if (dataType === 'typeOptions' && typeMapData[dataType].filter((item) => item.customRoute && item.customRoute.name.includes(prodName))) {
25
- parsedData['configureType'] = typeMapData[dataType].filter((item) => item.customRoute && item.customRoute.name.includes(prodName));
24
+ if (dataType === 'typeOptions') {
25
+ const allTypeOptions = Object.values(typeMapData[dataType]).flat();
26
+ const filtered = allTypeOptions.filter((item) => item.customRoute && item.customRoute.name.includes(prodName));
27
+
28
+ if (filtered.length > 0) {
29
+ parsedData['configureType'] = filtered;
30
+ }
26
31
  }
27
32
 
28
33
  // other types which map with prodName
@@ -36,7 +41,7 @@ export function DSLRegistrationsPerProduct(store, prodName) {
36
41
  }
37
42
  });
38
43
 
39
- console.error('*** PRODUCT DATA DEBUGGER **** DSLRegistrationsPerProduct', parsedData); // eslint-disable-line no-console
44
+ console.error(`*** PRODUCT DATA DEBUGGER ${ prodName } **** DSLRegistrationsPerProduct`, parsedData); // eslint-disable-line no-console
40
45
  }
41
46
 
42
47
  export function registeredRoutes(store, prodName) {
@@ -44,5 +49,5 @@ export function registeredRoutes(store, prodName) {
44
49
 
45
50
  const parsedData = routes.filter((route) => route.path.includes(prodName));
46
51
 
47
- console.error('*** PRODUCT DATA DEBUGGER **** registeredRoutes', parsedData); // eslint-disable-line no-console
52
+ console.error(`*** PRODUCT DATA DEBUGGER ${ prodName } **** registeredRoutes`, parsedData); // eslint-disable-line no-console
48
53
  }