@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,25 +1,50 @@
1
1
  <script setup lang="ts">
2
+ import { computed } from 'vue';
2
3
  import { RouterLink, RouteLocationRaw } from 'vue-router';
3
4
 
4
5
  export interface Props {
5
- to: RouteLocationRaw;
6
+ to?: RouteLocationRaw;
7
+ href?: string;
8
+ target?: string;
9
+ openInNewTabLabel?: string;
6
10
  }
7
11
 
8
- const { to } = defineProps<Props>();
12
+ const props = defineProps<Props>();
13
+
14
+ const isExternal = computed(() => !!props.href);
9
15
  </script>
10
16
 
11
17
  <template>
12
- <RouterLink
18
+ <component
19
+ :is="isExternal ? 'a' : RouterLink"
13
20
  class="subtle-link"
14
- :to="to"
21
+ v-bind="isExternal
22
+ ? { href, target, rel: target === '_blank' ? 'noopener noreferrer nofollow' : undefined }
23
+ : { to }"
15
24
  >
16
- <slot name="default" />
17
- </RouterLink>
25
+ <span
26
+ v-if="openInNewTabLabel"
27
+ class="sr-only"
28
+ >{{ openInNewTabLabel }}</span>
29
+ <slot name="default" /><span v-if="openInNewTabLabel">&nbsp;</span><i
30
+ v-if="openInNewTabLabel"
31
+ class="link-icon icon icon-external-link"
32
+ />
33
+ </component>
18
34
  </template>
19
35
 
20
36
  <style lang="scss" scoped>
21
37
  .subtle-link {
22
38
  text-decoration: underline;
23
39
  color: var(--body-text);
40
+
41
+ &:hover,
42
+ &:active {
43
+ text-decoration: none;
44
+ }
45
+ }
46
+
47
+ .link-icon {
48
+ display: inline;
24
49
  }
25
50
  </style>
@@ -1,8 +1,14 @@
1
1
  <script>
2
2
  import { useTabCountWatcher } from '@shell/components/form/ResourceTabs/composable';
3
+ import { useInSummary } from '@shell/components/TableOfContents/composables';
4
+ import { computed, inject, useTemplateRef } from 'vue';
5
+ import { useStore } from 'vuex';
6
+ import { useI18n } from '@shell/composables/useI18n';
3
7
 
4
8
  export default {
5
- inject: ['addTab', 'removeTab', 'sideTabs'],
9
+ name: 'Tab',
10
+
11
+ inject: ['addTab', 'removeTab', 'sideTabs', 'select'],
6
12
 
7
13
  emits: ['active'],
8
14
 
@@ -64,9 +70,28 @@ export default {
64
70
  },
65
71
 
66
72
  setup(props) {
67
- const { count, isCountVisible } = useTabCountWatcher();
73
+ const select = inject('select');
74
+ const store = useStore();
75
+ const { t } = useI18n(store);
76
+ const label = computed(() => {
77
+ if (props.labelKey && typeof t === 'function') {
78
+ return t(props.labelKey);
79
+ }
68
80
 
69
- return { inferredCount: count, isInferredCountVisible: isCountVisible };
81
+ return props.label ?? props.name;
82
+ });
83
+ const { count, isCountVisible } = useTabCountWatcher();
84
+ const summarizedContainerRef = useTemplateRef('tab-summarized-container');
85
+ // when a Tab is scrolled to, call its Tabbed's 'select' method to ensure the Tab is active
86
+ const { summary } = useInSummary({
87
+ scrollTo: () => select(props.name),
88
+ label,
89
+ elementRef: summarizedContainerRef,
90
+ });
91
+
92
+ return {
93
+ inferredCount: count, isInferredCountVisible: isCountVisible, summary
94
+ };
70
95
  },
71
96
 
72
97
  data() {
@@ -143,6 +168,7 @@ export default {
143
168
  <section
144
169
  v-show="active"
145
170
  :id="name"
171
+ ref="tab-summarized-container"
146
172
  :aria-hidden="!active"
147
173
  role="tabpanel"
148
174
  :aria-labelledby="`tab-${name}`"
@@ -7,10 +7,11 @@ import findIndex from 'lodash/findIndex';
7
7
  import { ExtensionPoint, TabLocation } from '@shell/core/types';
8
8
  import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
9
9
  import Tab from '@shell/components/Tabbed/Tab';
10
- import { ref } from 'vue';
10
+ import { computed, ref, useTemplateRef } from 'vue';
11
11
  import { useIsInResourceDetailDrawer } from '@shell/components/Drawer/ResourceDetailDrawer/composables';
12
12
  import { useIsInResourceDetailPage } from '@shell/composables/resourceDetail';
13
13
  import { useIsInResourceCreatePage, useIsInResourceEditPage } from '@shell/composables/cruResource';
14
+ import { useInSummary } from '@shell/components/TableOfContents/composables';
14
15
 
15
16
  export default {
16
17
  name: 'Tabbed',
@@ -94,6 +95,17 @@ export default {
94
95
  removeBorders: {
95
96
  type: Boolean,
96
97
  default: false,
98
+ },
99
+
100
+ /**
101
+ * title is NOT displayed within the Tabbed component itself
102
+ * this prop is used to determine a label to use for the set of tabs in the table of contents component
103
+ * if a title is not provided a random string will be used
104
+ * components using the table of contents may exclude tabbed and only show tab components, too
105
+ */
106
+ title: {
107
+ type: String,
108
+ default: null,
97
109
  }
98
110
  },
99
111
 
@@ -101,6 +113,8 @@ export default {
101
113
  const tabs = this.tabs;
102
114
 
103
115
  return {
116
+ select: this.select,
117
+
104
118
  sideTabs: this.sideTabs,
105
119
 
106
120
  addTab(tab) {
@@ -156,14 +170,20 @@ export default {
156
170
  },
157
171
  },
158
172
 
159
- setup() {
173
+ setup(props) {
160
174
  const isInResourceDetailDrawer = ref(useIsInResourceDetailDrawer());
161
175
  const isInResourceDetailPage = ref(useIsInResourceDetailPage());
162
176
  const isInResourceEditPage = ref(useIsInResourceEditPage());
163
177
  const isInResourceCreatePage = ref(useIsInResourceCreatePage());
178
+ const tabbedSummarizedContainer = useTemplateRef('tabbed-summarized-container');
179
+ const { summary } = useInSummary({
180
+ label: computed(() => props.title ?? ''),
181
+ scrollTo: () => tabbedSummarizedContainer.value?.scrollIntoView(true),
182
+ elementRef: tabbedSummarizedContainer,
183
+ });
164
184
 
165
185
  return {
166
- isInResourceDetailDrawer, isInResourceDetailPage, isInResourceEditPage, isInResourceCreatePage
186
+ isInResourceDetailDrawer, isInResourceDetailPage, isInResourceEditPage, isInResourceCreatePage, summary
167
187
  };
168
188
  },
169
189
 
@@ -311,6 +331,7 @@ export default {
311
331
 
312
332
  <template>
313
333
  <div
334
+ ref="tabbed-summarized-container"
314
335
  class="tabbed-container"
315
336
  :class="{
316
337
  'side-tabs': !!sideTabs,
@@ -435,6 +456,7 @@ export default {
435
456
  <component
436
457
  :is="tab.component"
437
458
  :resource="resource"
459
+ @select="select(tab.name)"
438
460
  />
439
461
  </Tab>
440
462
  </div>
@@ -0,0 +1,109 @@
1
+ <script setup>
2
+ const props = defineProps({
3
+ accordions: {
4
+ type: Array,
5
+ required: true,
6
+ }
7
+ });
8
+
9
+ const handleScrollTo = (entry, event) => {
10
+ entry?.scrollTo?.();
11
+ event?.currentTarget?.blur?.();
12
+ };
13
+ </script>
14
+
15
+ <template>
16
+ <div class="toc-root">
17
+ <div class="toc-container">
18
+ <h4>
19
+ {{ t('cruResource.tableOfContents.jumpTo') }}
20
+ </h4>
21
+ <ul>
22
+ <li
23
+ v-for="(acc, i) in props.accordions"
24
+ :key="i"
25
+ :data-testid="`toc-list-item-${i}`"
26
+ >
27
+ <button
28
+ v-if="acc.scrollTo"
29
+ type="button"
30
+ class="btn role-link accordion-link"
31
+ @click="handleScrollTo(acc, $event)"
32
+ >
33
+ {{ acc.label }}
34
+ </button>
35
+ <span v-else>{{ acc.label }}</span>
36
+ <template v-if="acc?.children?.length">
37
+ <ul data-testid="toc-list">
38
+ <li
39
+ v-for="(childAcc, j) in acc.children"
40
+ :key="j"
41
+ :data-testid="`toc-list-item-${i}-${j}`"
42
+ >
43
+ <button
44
+ v-if="childAcc.scrollTo"
45
+ type="button"
46
+ class="btn role-link accordion-link"
47
+ @click="handleScrollTo(childAcc, $event)"
48
+ >
49
+ {{ childAcc.label }}
50
+ </button>
51
+ <span v-else>{{ childAcc.label }}</span>
52
+ </li>
53
+ </ul>
54
+ </template>
55
+ </li>
56
+ </ul>
57
+ </div>
58
+ </div>
59
+ </template>
60
+
61
+ <style lang="scss" scoped>
62
+ ul {
63
+ list-style-type: none;
64
+ margin: 0;
65
+ padding: 0;
66
+ }
67
+
68
+ li:not(:last-child) {
69
+ margin-bottom: var(--gap);
70
+ }
71
+
72
+ h4 {
73
+ margin-bottom: 12px;
74
+ margin-top: 0px
75
+ }
76
+
77
+ li ul {
78
+ padding-left: var(--gap-md);
79
+ & li {
80
+ margin-top: var(--gap);
81
+ margin-bottom: 0px;
82
+ }
83
+ }
84
+
85
+ .toc-container {
86
+ padding: var(--gap-md);
87
+ border-radius: var(--border-radius);
88
+ background-color: var(--subtle-overlay-bg);
89
+ }
90
+
91
+ .accordion-link {
92
+ padding: 0px;
93
+ min-height: 0px;
94
+ line-height: 1.3em;
95
+ white-space: normal;
96
+ overflow-wrap: anywhere;
97
+ word-break: break-word;
98
+ text-align: left;
99
+ display: block;
100
+ width: 100%;
101
+ }
102
+
103
+ li > span {
104
+ white-space: normal;
105
+ overflow-wrap: anywhere;
106
+ word-break: break-word;
107
+ display: block;
108
+ }
109
+ </style>
@@ -0,0 +1,258 @@
1
+ import debounce from 'lodash/debounce';
2
+ import { randomStr } from '@shell/utils/string';
3
+ import {
4
+ computed, inject, onMounted, onUnmounted, provide, ref, watch
5
+ } from 'vue';
6
+ import type {
7
+ ComputedRef,
8
+ Ref,
9
+ VNode
10
+ } from 'vue';
11
+
12
+ type SummaryInfo = {
13
+ id: string;
14
+ label?: ComputedRef<string> | string;
15
+ scrollTo?: () => void;
16
+ };
17
+
18
+ type SummaryComponent = {
19
+ summary: SummaryInfo;
20
+ summaryID: string;
21
+ $options?: { name?: string };
22
+ $?: { type?: { name?: string } };
23
+ };
24
+
25
+ type SummaryEntry = {
26
+ node: VNode;
27
+ children: SummaryEntry[];
28
+ label?: string | ComputedRef<string>;
29
+ scrollTo?: () => void;
30
+ component?: SummaryComponent;
31
+ };
32
+
33
+ type RegisterComponent = (component?: SummaryComponent | null) => void;
34
+
35
+ type FormSummaryContext = {
36
+ registerComponent: RegisterComponent;
37
+ unRegisterComponent: RegisterComponent;
38
+ refreshComponents: () => void;
39
+ updateComponentLabel: (summaryID: string, label: string) => boolean;
40
+ };
41
+
42
+ type ElementWithVNodeChildren = {
43
+ children?: ArrayLike<Element>;
44
+ };
45
+
46
+ type ElementWithSummaryID = HTMLElement & {
47
+ summaryID?: string;
48
+ };
49
+
50
+ // Unique key used by provide/inject so each form subtree gets its own
51
+ // summary registration context
52
+ const FORM_SUMMARY_KEY = Symbol('formSummary');
53
+
54
+ /**
55
+ * useFormSummary will determine the relative position of all descendant components
56
+ * that are using the useInSummary composable. It is used to build summaries of elaborate form components
57
+ * that may have interactable elements deeply nested in child components. The list of located components
58
+ * returned by locateComponentsByNamePattern includes access to the component instance and a scrollTo method.
59
+ */
60
+ export function useFormSummary(rootComponentRef: Readonly<Ref<HTMLElement | null>>) {
61
+ const registeredComponents = ref<Record<string, SummaryComponent>>({});
62
+ const locatedComponents = ref<SummaryEntry[]>([]);
63
+ const buildTree = (
64
+ components: SummaryEntry[] = [],
65
+ node?: any,
66
+ found = new Set<string>()
67
+ ) => {
68
+ let nextInput = components;
69
+
70
+ const summaryID = node?.el ? (node?.el as ElementWithSummaryID | null | undefined)?.summaryID || '' : node?.summaryID || '';
71
+ const component = registeredComponents.value[summaryID];
72
+ const summary = component?.summary;
73
+
74
+ if (component && summary && registeredComponents.value[summary.id] && !found.has(summary.id)) {
75
+ found.add(summary.id);
76
+
77
+ const out: SummaryEntry = {
78
+ node: node as VNode,
79
+ children: [],
80
+ ...summary,
81
+ scrollTo: component ? () => scrollToComponent(component) : undefined
82
+ };
83
+
84
+ out.component = component;
85
+
86
+ components.push(out);
87
+ nextInput = out.children;
88
+ }
89
+
90
+ if (!node) {
91
+ return;
92
+ }
93
+
94
+ const children = node.el ? Array.from((node.el as ElementWithVNodeChildren | null | undefined)?.children ?? []) : Array.from(node.children ?? []);
95
+
96
+ children.forEach((child: any) => {
97
+ buildTree(nextInput, child, found);
98
+ });
99
+
100
+ return components;
101
+ };
102
+
103
+ const locateRegisteredComponents = () => {
104
+ if (rootComponentRef?.value) {
105
+ locatedComponents.value = buildTree([], rootComponentRef.value) || [];
106
+ } else {
107
+ locatedComponents.value = [];
108
+ }
109
+ };
110
+
111
+ // when forms initially this is called synchonously by every component using the summary composable
112
+ // debounce without a delay reduces that to one call on initial page load
113
+ const debouncedLocateRegisteredComponents = debounce(locateRegisteredComponents);
114
+
115
+ // onMounted fires on the calling component (CruResource) after its template refs are
116
+ // populated and after all children have run their own onMounted hooks. This guarantees
117
+ // rootComponentRef is available and all child registrations have arrived.
118
+ onMounted(() => {
119
+ debouncedLocateRegisteredComponents();
120
+ });
121
+
122
+ const findParent = (component: SummaryComponent) => {
123
+ const walk = (entries: SummaryEntry[] = [], parent: SummaryEntry | null = null): SummaryEntry | null => {
124
+ for (const entry of entries) {
125
+ if (entry?.component?.summary?.id === component?.summary?.id) {
126
+ return parent;
127
+ }
128
+
129
+ if (entry?.children?.length) {
130
+ const found = walk(entry.children, entry);
131
+
132
+ if (found) {
133
+ return found;
134
+ }
135
+ }
136
+ }
137
+
138
+ return null;
139
+ };
140
+
141
+ return walk(locatedComponents.value);
142
+ };
143
+
144
+ const updateComponentLabel = (summaryID: string, label: string) => {
145
+ const walk = (entries: SummaryEntry[] = []): boolean => {
146
+ for (const entry of entries) {
147
+ if (entry?.component?.summary?.id === summaryID) {
148
+ entry.label = label;
149
+
150
+ return true;
151
+ }
152
+
153
+ if (entry?.children?.length && walk(entry.children)) {
154
+ return true;
155
+ }
156
+ }
157
+
158
+ return false;
159
+ };
160
+
161
+ return walk(locatedComponents.value);
162
+ };
163
+
164
+ const scrollToComponent = (component: SummaryComponent) => {
165
+ const parent = findParent(component);
166
+
167
+ if (parent?.component) {
168
+ scrollToComponent(parent.component);
169
+ }
170
+ if (component?.summary?.scrollTo) {
171
+ component.summary.scrollTo();
172
+ }
173
+ };
174
+
175
+ const registerComponent: RegisterComponent = (component) => {
176
+ if (!component || !component.summary?.id) {
177
+ return;
178
+ }
179
+ registeredComponents.value[component.summary?.id] = component;
180
+ debouncedLocateRegisteredComponents();
181
+ };
182
+
183
+ const unRegisterComponent: RegisterComponent = (component) => {
184
+ if (!component || !component.summary?.id) {
185
+ return;
186
+ }
187
+
188
+ delete registeredComponents.value[component.summary?.id];
189
+ debouncedLocateRegisteredComponents();
190
+ };
191
+
192
+ // Provide the register/unregister functions to all descendants
193
+ provide<FormSummaryContext>(FORM_SUMMARY_KEY, {
194
+ registerComponent,
195
+ unRegisterComponent,
196
+ refreshComponents: debouncedLocateRegisteredComponents,
197
+ updateComponentLabel,
198
+ });
199
+
200
+ return { locatedComponents };
201
+ }
202
+
203
+ /**
204
+ * Hook to register a component in the summary system.
205
+ * Injects register/unregister from the nearest ancestor that called useFormSummary().
206
+ * When the component is mounted (including after v-if re-reveals it), it re-registers
207
+ * into the correct scoped context. Components using inFormSummary will register themselves
208
+ * with the nearest ancestor containing useFormSummary
209
+ *
210
+ * @param options.scrollTo - Scroll handler. The ToC system calls this function when the
211
+ * user navigates to this component via the Table of Contents. Use this to perform any
212
+ * additional work before scrolling (e.g. expanding an accordion, revealing a tab).
213
+ * @param options.label - Label for this component's ToC entry. Accepts a plain string or
214
+ * a `ComputedRef<string>`.
215
+ * @param options.elementRef - A template ref pointing to the component's root element.
216
+ * Used by the ToC system to locate this component during DOM tree traversal.
217
+ */
218
+ export function useInSummary(options: { scrollTo: () => void; label: ComputedRef<string> | string; elementRef: Readonly<Ref<HTMLElement | null>> }) {
219
+ const {
220
+ registerComponent = () => {},
221
+ unRegisterComponent = () => {},
222
+ refreshComponents = () => {},
223
+ updateComponentLabel = () => false
224
+ } = inject<FormSummaryContext>(FORM_SUMMARY_KEY) || {};
225
+
226
+ const { scrollTo, label, elementRef } = options;
227
+
228
+ const summaryID = randomStr();
229
+ const summary: SummaryInfo = { id: summaryID, scrollTo };
230
+
231
+ // Wrap a plain string in a computed so the type is always ComputedRef<string>.
232
+ summary.label = typeof label === 'string' ? computed(() => label) : label;
233
+
234
+ watch(summary.label, (label) => {
235
+ const updated = updateComponentLabel(summaryID, label);
236
+
237
+ if (!updated) {
238
+ refreshComponents();
239
+ }
240
+ });
241
+
242
+ onMounted(() => {
243
+ if (elementRef.value) {
244
+ (elementRef.value as ElementWithSummaryID).summaryID = summaryID;
245
+ }
246
+
247
+ registerComponent({ summary, summaryID } as SummaryComponent);
248
+ });
249
+
250
+ onUnmounted(() => {
251
+ // Unregister by summary ID — only the ID is needed for deletion
252
+ const stub = { summary } as SummaryComponent;
253
+
254
+ unRegisterComponent(stub);
255
+ });
256
+
257
+ return { summary };
258
+ }
@@ -80,7 +80,6 @@ export default {
80
80
  fitAddon: null,
81
81
  searchAddon: null,
82
82
  webglAddon: null,
83
- canvasAddon: null,
84
83
  isOpen: false,
85
84
  isOpening: false,
86
85
  backlog: [],
@@ -168,7 +167,7 @@ export default {
168
167
  try {
169
168
  const schema = this.$store.getters[`cluster/schemaFor`](NODE);
170
169
 
171
- if (schema) {
170
+ if (schema && nodeId) {
172
171
  await this.$store.dispatch('cluster/find', { type: NODE, id: nodeId });
173
172
  }
174
173
  } catch {}
@@ -215,14 +214,13 @@ export default {
215
214
 
216
215
  async setupTerminal() {
217
216
  const docStyle = getComputedStyle(document.querySelector('body'));
218
- const xterm = await import(/* webpackChunkName: "xterm" */ 'xterm');
217
+ const xterm = await import(/* webpackChunkName: "xterm" */ '@xterm/xterm');
219
218
 
220
219
  const addons = await allHash({
221
- fit: import(/* webpackChunkName: "xterm" */ 'xterm-addon-fit'),
222
- webgl: import(/* webpackChunkName: "xterm" */ 'xterm-addon-webgl'),
223
- weblinks: import(/* webpackChunkName: "xterm" */ 'xterm-addon-web-links'),
224
- search: import(/* webpackChunkName: "xterm" */ 'xterm-addon-search'),
225
- canvas: import(/* webpackChunkName: "xterm" */ 'xterm-addon-canvas')
220
+ fit: import(/* webpackChunkName: "xterm" */ '@xterm/addon-fit'),
221
+ webgl: import(/* webpackChunkName: "xterm" */ '@xterm/addon-webgl'),
222
+ weblinks: import(/* webpackChunkName: "xterm" */ '@xterm/addon-web-links'),
223
+ search: import(/* webpackChunkName: "xterm" */ '@xterm/addon-search'),
226
224
  });
227
225
 
228
226
  const terminal = new xterm.Terminal({
@@ -242,9 +240,21 @@ export default {
242
240
  terminal.loadAddon(new addons.weblinks.WebLinksAddon());
243
241
  terminal.open(this.$refs.xterm);
244
242
 
243
+ // if user is using Safari with webGPU disabled, webglAddon will silently fail
244
+ // and we do not have a way to detect that.
245
+ // To avoid it, default to DOM rendering for Safari browsers
245
246
  try {
246
- this.webglAddon = new addons.webgl.WebglAddon();
247
- terminal.loadAddon(this.webglAddon);
247
+ const ua = window.navigator.userAgent.toLowerCase();
248
+ const isSafari = ua.includes('safari') &&
249
+ !ua.includes('crios') && // Chrome iOS
250
+ !ua.includes('fxios') && // Firefox iOS
251
+ !ua.includes('edgios') && // Edge iOS
252
+ !ua.includes('opr'); // Opera
253
+
254
+ if (!isSafari) {
255
+ this.webglAddon = new addons.webgl.WebglAddon();
256
+ terminal.loadAddon(this.webglAddon);
257
+ }
248
258
  } catch (e) {
249
259
  // Some browsers (Safari) don't support the webgl renderer, so don't use it.
250
260
  this.webglAddon = null;
@@ -288,7 +298,7 @@ export default {
288
298
  }
289
299
 
290
300
  const url = addParams(
291
- `${ this.pod.links.view.replace(/^http/, 'ws') }/exec`,
301
+ `${ this.pod.links?.view.replace(/^http/, 'ws') }/exec`,
292
302
  {
293
303
  container: this.container,
294
304
  stdout: 1,