@rancher/shell 3.0.5-rc.3 → 3.0.5-rc.6

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 (424) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/icons/document.svg +3 -0
  3. package/assets/images/key.svg +17 -0
  4. package/assets/images/vendor/cognito.svg +1 -0
  5. package/assets/styles/app.scss +1 -0
  6. package/assets/styles/base/_basic.scss +10 -0
  7. package/assets/styles/base/_spacing.scss +29 -0
  8. package/assets/styles/global/_form.scss +1 -1
  9. package/assets/styles/global/_labeled-input.scss +1 -1
  10. package/assets/styles/global/_layout.scss +1 -1
  11. package/assets/styles/themes/_dark.scss +28 -0
  12. package/assets/styles/themes/_light.scss +68 -0
  13. package/assets/styles/vendor/vue-select.scss +1 -1
  14. package/assets/translations/en-us.yaml +721 -83
  15. package/assets/translations/zh-hans.yaml +11 -9
  16. package/cloud-credential/gcp.vue +9 -1
  17. package/components/AppModal.vue +2 -0
  18. package/components/Certificates.vue +5 -0
  19. package/components/CodeMirror.vue +1 -1
  20. package/components/ConfigMapSettings/Settings.vue +377 -0
  21. package/components/ConfigMapSettings/index.vue +354 -0
  22. package/components/CruResource.vue +1 -2
  23. package/components/DetailText.vue +61 -11
  24. package/components/Drawer/Chrome.vue +116 -0
  25. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  26. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  27. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  28. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  29. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +82 -0
  30. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  31. package/components/Drawer/ResourceDetailDrawer/composables.ts +50 -0
  32. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  33. package/components/Drawer/ResourceDetailDrawer/index.vue +110 -0
  34. package/components/FilterPanel.vue +156 -0
  35. package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
  36. package/components/GrowlManager.vue +16 -15
  37. package/components/IconOrSvg.vue +19 -35
  38. package/components/KeyValueView.vue +1 -1
  39. package/components/LocaleSelector.vue +9 -1
  40. package/components/ProgressBarMulti.vue +1 -0
  41. package/components/PromptModal.vue +6 -1
  42. package/components/PromptRemove.vue +5 -1
  43. package/components/RelatedResources.vue +4 -12
  44. package/components/Resource/Detail/Additional.vue +46 -0
  45. package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
  46. package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
  47. package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
  48. package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
  49. package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
  50. package/components/Resource/Detail/Card/Scaler.vue +89 -0
  51. package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
  52. package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
  53. package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
  54. package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
  55. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
  56. package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
  57. package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
  58. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
  59. package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
  60. package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
  61. package/components/Resource/Detail/Card/index.vue +56 -0
  62. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
  63. package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
  64. package/components/Resource/Detail/Metadata/Annotations/index.vue +31 -0
  65. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  66. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
  67. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +64 -0
  68. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +298 -0
  69. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +133 -0
  70. package/components/Resource/Detail/Metadata/KeyValue.vue +138 -0
  71. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
  72. package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
  73. package/components/Resource/Detail/Metadata/Labels/index.vue +31 -0
  74. package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
  75. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
  76. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
  77. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  78. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
  79. package/components/Resource/Detail/Metadata/composables.ts +78 -0
  80. package/components/Resource/Detail/Metadata/index.vue +73 -0
  81. package/components/Resource/Detail/Page.vue +37 -0
  82. package/components/Resource/Detail/PercentageBar.vue +40 -0
  83. package/components/Resource/Detail/ResourceRow.vue +138 -0
  84. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  85. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  86. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  87. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  88. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  89. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  90. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  91. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  92. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  93. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  94. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  95. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  96. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  97. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  98. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  99. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  100. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  101. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  102. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  103. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  104. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  105. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  106. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  107. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  108. package/components/Resource/Detail/SpacedRow.vue +14 -0
  109. package/components/Resource/Detail/StatusBar.vue +59 -0
  110. package/components/Resource/Detail/StatusRow.vue +61 -0
  111. package/components/Resource/Detail/TitleBar/Title.vue +14 -0
  112. package/components/Resource/Detail/TitleBar/Top.vue +14 -0
  113. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
  114. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
  115. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  116. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
  117. package/components/Resource/Detail/TitleBar/composables.ts +44 -0
  118. package/components/Resource/Detail/TitleBar/index.vue +196 -0
  119. package/components/Resource/Detail/Top/index.vue +34 -0
  120. package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
  121. package/components/Resource/Detail/composables.ts +45 -0
  122. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  123. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  124. package/components/ResourceDetail/Masthead/index.vue +65 -0
  125. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  126. package/components/ResourceDetail/__tests__/index.test.ts +135 -0
  127. package/components/ResourceDetail/index.vue +73 -557
  128. package/components/ResourceDetail/legacy.vue +562 -0
  129. package/components/ResourceList/Masthead.vue +6 -0
  130. package/components/ResourceTable.vue +41 -7
  131. package/components/ResourceYaml.vue +14 -1
  132. package/components/SlideInPanelManager.vue +117 -10
  133. package/components/SortableTable/index.vue +13 -2
  134. package/components/SortableTable/selection.js +21 -8
  135. package/components/StateDot/index.vue +28 -0
  136. package/components/StatusBadge.vue +6 -4
  137. package/components/SubtleLink.vue +25 -0
  138. package/components/Tabbed/index.vue +11 -15
  139. package/components/Wizard.vue +16 -3
  140. package/components/YamlEditor.vue +1 -1
  141. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  142. package/components/__tests__/FilterPanel.test.ts +81 -0
  143. package/components/__tests__/GrowlManager.test.ts +0 -25
  144. package/components/auth/AuthBanner.vue +2 -3
  145. package/components/auth/RoleDetailEdit.vue +45 -3
  146. package/components/auth/login/ldap.vue +1 -1
  147. package/components/auth/login/oidc.vue +6 -1
  148. package/components/fleet/FleetApplications.vue +174 -0
  149. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  150. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  151. package/components/fleet/FleetClusters.vue +25 -6
  152. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  153. package/components/fleet/FleetHelmOps.vue +123 -0
  154. package/components/fleet/FleetIntro.vue +58 -28
  155. package/components/fleet/FleetNoWorkspaces.vue +5 -1
  156. package/components/fleet/FleetOCIStorageSecret.vue +171 -0
  157. package/components/fleet/FleetRepos.vue +37 -80
  158. package/components/fleet/FleetResources.vue +53 -26
  159. package/components/fleet/FleetSummary.vue +26 -51
  160. package/components/fleet/FleetValuesFrom.vue +295 -0
  161. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  162. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  163. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
  164. package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
  165. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  166. package/components/fleet/dashboard/Empty.vue +73 -0
  167. package/components/fleet/dashboard/ResourceCard.vue +184 -0
  168. package/components/fleet/dashboard/ResourceCardSummary.vue +195 -0
  169. package/components/fleet/dashboard/ResourceDetails.vue +194 -0
  170. package/components/fleet/dashboard/ResourcePanel.vue +383 -0
  171. package/components/form/ArrayList.vue +19 -2
  172. package/components/form/ChangePassword.vue +3 -1
  173. package/components/form/Footer.vue +10 -4
  174. package/components/form/KeyValue.vue +81 -43
  175. package/components/form/LabeledSelect.vue +56 -16
  176. package/components/form/Labels.vue +90 -17
  177. package/components/form/MatchExpressions.vue +46 -5
  178. package/components/form/NameNsDescription.vue +1 -1
  179. package/components/form/ResourceSelector.vue +1 -0
  180. package/components/form/ResourceTabs/index.vue +5 -0
  181. package/components/form/SecretSelector.vue +9 -2
  182. package/components/form/Select.vue +57 -19
  183. package/components/form/SimpleSecretSelector.vue +17 -4
  184. package/components/form/Taints.vue +21 -2
  185. package/components/form/UnitInput.vue +8 -0
  186. package/components/form/ValueFromResource.vue +31 -19
  187. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  188. package/components/form/__tests__/Labels.test.ts +360 -0
  189. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  190. package/components/form/__tests__/Select.test.ts +5 -2
  191. package/components/formatter/FleetApplicationClustersReady.vue +77 -0
  192. package/components/formatter/FleetApplicationSource.vue +71 -0
  193. package/components/formatter/FleetSummaryGraph.vue +7 -0
  194. package/components/formatter/WorkloadHealthScale.vue +1 -1
  195. package/components/google/AccountAccess.vue +211 -0
  196. package/components/google/types/gcp.d.ts +136 -0
  197. package/components/google/types/index.d.ts +101 -0
  198. package/components/google/util/__mocks__/gcp.ts +465 -0
  199. package/components/google/util/formatter.ts +82 -0
  200. package/components/google/util/gcp.ts +134 -0
  201. package/components/google/util/index.d.ts +11 -0
  202. package/components/nav/Favorite.vue +1 -1
  203. package/components/nav/Group.vue +70 -47
  204. package/components/nav/Header.vue +13 -8
  205. package/components/nav/NamespaceFilter.vue +13 -1
  206. package/components/nav/NotificationCenter/Notification.vue +510 -0
  207. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  208. package/components/nav/NotificationCenter/index.vue +148 -0
  209. package/components/nav/TopLevelMenu.helper.ts +55 -34
  210. package/components/nav/TopLevelMenu.vue +11 -0
  211. package/components/nav/Type.vue +4 -1
  212. package/composables/drawer.ts +26 -0
  213. package/composables/resources.test.ts +63 -0
  214. package/composables/resources.ts +38 -0
  215. package/composables/useI18n.ts +12 -11
  216. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  217. package/config/labels-annotations.js +20 -11
  218. package/config/product/auth.js +17 -1
  219. package/config/product/{cis.js → compliance.js} +23 -26
  220. package/config/product/explorer.js +5 -1
  221. package/config/product/fleet.js +77 -17
  222. package/config/product/settings.js +22 -11
  223. package/config/query-params.js +6 -1
  224. package/config/roles.ts +2 -1
  225. package/config/router/navigation-guards/authentication.js +51 -2
  226. package/config/router/routes.js +45 -31
  227. package/config/secret.ts +15 -0
  228. package/config/settings.ts +24 -5
  229. package/config/store.js +2 -0
  230. package/config/system-namespaces.js +1 -1
  231. package/config/table-headers.js +53 -23
  232. package/config/types.js +17 -6
  233. package/core/plugin-helpers.ts +3 -2
  234. package/core/plugin.ts +32 -7
  235. package/core/types.ts +18 -1
  236. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  237. package/detail/fleet.cattle.io.cluster.vue +28 -15
  238. package/detail/fleet.cattle.io.gitrepo.vue +10 -1
  239. package/detail/fleet.cattle.io.helmop.vue +157 -0
  240. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  241. package/detail/management.cattle.io.oidcclient.vue +369 -0
  242. package/detail/node.vue +2 -2
  243. package/detail/pod.vue +2 -2
  244. package/detail/service.vue +10 -1
  245. package/detail/workload/index.vue +8 -2
  246. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  247. package/dialog/GenericPrompt.vue +1 -1
  248. package/dialog/HelmOpForceUpdateDialog.vue +132 -0
  249. package/dialog/ImportDialog.vue +8 -8
  250. package/dialog/OidcClientSecretDialog.vue +117 -0
  251. package/dialog/RedeployWorkloadDialog.vue +164 -0
  252. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  253. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +60 -68
  254. package/edit/auth/oidc.vue +159 -93
  255. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  256. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  257. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  258. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  259. package/edit/configmap.vue +4 -1
  260. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  261. package/edit/fleet.cattle.io.gitrepo.vue +70 -255
  262. package/edit/fleet.cattle.io.helmop.vue +772 -0
  263. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  264. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  265. package/edit/logging-flow/index.vue +1 -0
  266. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  267. package/edit/management.cattle.io.fleetworkspace.vue +44 -10
  268. package/edit/management.cattle.io.oidcclient.vue +162 -0
  269. package/edit/management.cattle.io.project.vue +4 -1
  270. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  271. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  272. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  273. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  274. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  275. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  276. package/edit/monitoring.coreos.com.route.vue +1 -0
  277. package/edit/namespace.vue +1 -0
  278. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  279. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  280. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  281. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  282. package/edit/node.vue +1 -0
  283. package/edit/persistentvolume/index.vue +4 -1
  284. package/edit/provisioning.cattle.io.cluster/rke2.vue +418 -382
  285. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +27 -27
  286. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  287. package/edit/resources.cattle.io.restore.vue +1 -1
  288. package/edit/secret/index.vue +1 -0
  289. package/edit/service.vue +4 -1
  290. package/edit/serviceaccount.vue +4 -1
  291. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  292. package/edit/workload/index.vue +5 -0
  293. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  294. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  295. package/list/fleet.cattle.io.helmop.vue +108 -0
  296. package/list/management.cattle.io.oidcclient.vue +108 -0
  297. package/list/namespace.vue +5 -2
  298. package/list/node.vue +2 -0
  299. package/machine-config/amazonec2.vue +3 -24
  300. package/machine-config/components/GCEImage.vue +374 -0
  301. package/machine-config/google.vue +617 -0
  302. package/mixins/__tests__/brand.spec.ts +170 -0
  303. package/mixins/auth-config.js +8 -1
  304. package/mixins/brand.js +16 -17
  305. package/mixins/create-edit-view/index.js +5 -0
  306. package/mixins/preset.js +100 -0
  307. package/mixins/resource-fetch-api-pagination.js +18 -0
  308. package/mixins/resource-fetch.js +1 -1
  309. package/mixins/resource-table-watch.js +45 -0
  310. package/mixins/vue-select-overrides.js +1 -0
  311. package/models/__tests__/chart.test.ts +273 -0
  312. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  313. package/models/chart.js +144 -2
  314. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  315. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  316. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  317. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  318. package/models/fleet-application.js +314 -0
  319. package/models/fleet.cattle.io.bundle.js +9 -8
  320. package/models/fleet.cattle.io.cluster.js +11 -0
  321. package/models/fleet.cattle.io.gitrepo.js +41 -365
  322. package/models/fleet.cattle.io.helmop.js +198 -0
  323. package/models/management.cattle.io.authconfig.js +1 -0
  324. package/models/management.cattle.io.fleetworkspace.js +14 -1
  325. package/models/management.cattle.io.oidcclient.js +18 -0
  326. package/models/management.cattle.io.registration.js +3 -0
  327. package/models/provisioning.cattle.io.cluster.js +5 -5
  328. package/models/service.js +4 -0
  329. package/models/workload.js +19 -18
  330. package/package.json +2 -1
  331. package/pages/about.vue +4 -58
  332. package/pages/auth/login.vue +1 -1
  333. package/pages/auth/verify.vue +13 -1
  334. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +36 -0
  335. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
  336. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
  337. package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
  338. package/pages/c/_cluster/apps/charts/index.vue +487 -465
  339. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  340. package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
  341. package/pages/c/_cluster/explorer/index.vue +3 -3
  342. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  343. package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
  344. package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
  345. package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
  346. package/pages/c/_cluster/fleet/application/create.vue +341 -0
  347. package/pages/c/_cluster/fleet/application/index.vue +139 -0
  348. package/pages/c/_cluster/fleet/graph/config.js +277 -0
  349. package/pages/c/_cluster/fleet/index.vue +809 -329
  350. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  351. package/pages/c/_cluster/longhorn/index.vue +5 -2
  352. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  353. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  354. package/pages/explorer/resource/detail/configmap.vue +42 -0
  355. package/pages/explorer/resource/detail/secret.vue +50 -0
  356. package/pages/home.vue +9 -55
  357. package/pages/support/index.vue +4 -6
  358. package/plugins/dashboard-store/actions.js +50 -14
  359. package/plugins/dashboard-store/getters.js +38 -21
  360. package/plugins/dashboard-store/mutations.js +51 -7
  361. package/plugins/dashboard-store/resource-class.js +30 -4
  362. package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
  363. package/plugins/steve/actions.js +3 -0
  364. package/plugins/steve/steve-pagination-utils.ts +17 -8
  365. package/plugins/steve/subscribe.js +235 -43
  366. package/rancher-components/BadgeState/BadgeState.vue +3 -1
  367. package/rancher-components/Banner/Banner.vue +13 -0
  368. package/rancher-components/Form/Checkbox/Checkbox.vue +11 -6
  369. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  370. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  371. package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
  372. package/rancher-components/RcItemCard/RcItemCard.vue +430 -0
  373. package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
  374. package/rancher-components/RcItemCard/index.ts +2 -0
  375. package/store/auth.js +3 -0
  376. package/store/catalog.js +85 -25
  377. package/store/growl.js +97 -8
  378. package/store/index.js +39 -14
  379. package/store/notifications.ts +426 -0
  380. package/store/prefs.js +0 -1
  381. package/store/slideInPanel.ts +6 -0
  382. package/store/type-map.js +19 -15
  383. package/store/uiplugins.ts +15 -1
  384. package/types/fleet.d.ts +59 -0
  385. package/types/notifications/index.ts +74 -0
  386. package/types/resources/settings.d.ts +19 -1
  387. package/types/shell/index.d.ts +388 -307
  388. package/types/store/dashboard-store.types.ts +33 -3
  389. package/types/store/pagination.types.ts +6 -1
  390. package/types/store/subscribe.types.ts +50 -0
  391. package/utils/__tests__/fleet.test.ts +148 -0
  392. package/utils/__tests__/object.test.ts +54 -1
  393. package/utils/__tests__/string.test.ts +273 -1
  394. package/utils/__tests__/time.test.ts +31 -0
  395. package/utils/auth.js +41 -5
  396. package/utils/crypto/encryption.ts +103 -0
  397. package/utils/cspAdaptor.ts +51 -0
  398. package/utils/fleet-types.ts +0 -0
  399. package/utils/fleet.ts +190 -2
  400. package/utils/object.js +36 -0
  401. package/utils/pagination-utils.ts +27 -2
  402. package/utils/pagination-wrapper.ts +132 -50
  403. package/utils/release-notes.ts +48 -0
  404. package/utils/selector-typed.ts +7 -2
  405. package/utils/settings.ts +4 -1
  406. package/utils/string.js +24 -0
  407. package/utils/style.ts +39 -0
  408. package/utils/{time.js → time.ts} +25 -6
  409. package/utils/uiplugins.ts +22 -0
  410. package/utils/validators/formRules/__tests__/index.test.ts +36 -3
  411. package/utils/validators/formRules/index.ts +13 -3
  412. package/utils/window.js +11 -7
  413. package/components/__tests__/ApplicationCard.test.ts +0 -27
  414. package/components/cards/ApplicationCard.vue +0 -145
  415. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
  416. package/config/product/legacy.js +0 -62
  417. package/config/secret.js +0 -14
  418. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
  419. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  420. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  421. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  422. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
  423. /package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +0 -0
  424. /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
@@ -0,0 +1,148 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ computed,
4
+ ref,
5
+ } from 'vue';
6
+ import { useStore } from 'vuex';
7
+ import Notification from './Notification.vue';
8
+ import NotificationHeader from './NotificationHeader.vue';
9
+ import {
10
+ RcDropdown,
11
+ RcDropdownSeparator,
12
+ RcDropdownTrigger
13
+ } from '@components/RcDropdown';
14
+
15
+ const store = useStore();
16
+ const allNotifications = computed(() => store.getters['notifications/all']);
17
+ const unreadLevelClass = computed(() => {
18
+ return store.getters['notifications/unreadCount'] === 0 ? '' : 'unread';
19
+ });
20
+
21
+ // There may be more notifications than we can show on screen, so the popover needs to scroll
22
+ const scroller = ref<HTMLElement>();
23
+
24
+ // Close all of the open growls when the notification center is shown, so that they do not overlap
25
+ const open = (opened: boolean) => {
26
+ if (opened) {
27
+ store.dispatch('growl/clear');
28
+ }
29
+ };
30
+ </script>
31
+
32
+ <template>
33
+ <rc-dropdown
34
+ :aria-label="t('nav.notifications.label')"
35
+ @update:open="open"
36
+ >
37
+ <rc-dropdown-trigger
38
+ tertiary
39
+ data-testid="notifications-center"
40
+ :aria-label="t('nav.notifications.button.label')"
41
+ >
42
+ <div class="level-indicator">
43
+ <i class="icon icon-lg icon-notify-bell" />
44
+ <div
45
+ :data-testid="`notifications-center-status${ unreadLevelClass }`"
46
+ class="trigger-level"
47
+ :class="unreadLevelClass"
48
+ />
49
+ </div>
50
+ </rc-dropdown-trigger>
51
+ <template #dropdownCollection>
52
+ <div
53
+ data-testid="notifications-center-panel"
54
+ class="notification-dropdown"
55
+ >
56
+ <NotificationHeader class="header" />
57
+ <div
58
+ v-if="allNotifications.length === 0"
59
+ class="no-notifications"
60
+ >
61
+ <div class="hands">
62
+ &#x1F64C;
63
+ </div>
64
+ <div>
65
+ {{ t('notificationCenter.caughtUp', {}, true) }}
66
+ </div>
67
+ </div>
68
+ <div
69
+ ref="scroller"
70
+ class="scroll-container"
71
+ >
72
+ <template
73
+ v-for="(a, index) in allNotifications"
74
+ :key="a.id"
75
+ >
76
+ <rc-dropdown-separator
77
+ v-if="index > 0"
78
+ class="notification-separator"
79
+ />
80
+ <Notification :item="a" />
81
+ </template>
82
+ </div>
83
+ </div>
84
+ </template>
85
+ </rc-dropdown>
86
+ </template>
87
+
88
+ <style lang="scss" scoped>
89
+ .notification-dropdown {
90
+ display: flex;
91
+ overflow: hidden;
92
+ flex-direction: column;
93
+
94
+ .header {
95
+ flex: 0;
96
+ }
97
+
98
+ .scroll-container {
99
+ overflow: auto;
100
+ max-height: 80vh;
101
+ padding: 3px 0; // Need padding at top and bottom in order to show the focus border for the notification
102
+ }
103
+ }
104
+
105
+ .notification-separator {
106
+ margin: 0 3px;
107
+ width: auto;
108
+ }
109
+
110
+ .no-notifications {
111
+ text-align: center;
112
+ min-width: 340px;
113
+ margin: 40px 16px;
114
+
115
+ .hands {
116
+ font-size: 53px;
117
+ padding-top: 0;
118
+ }
119
+
120
+ > div {
121
+ padding-top: 16px;
122
+ }
123
+ }
124
+
125
+ .level-indicator {
126
+ display: flex;
127
+ position: relative;
128
+ height: 20px;
129
+ width: 18px;
130
+
131
+ .trigger-level {
132
+ position: absolute;
133
+ right: -6px;
134
+ top: -4px;
135
+ border-radius: 50%;
136
+ height: 8px;
137
+ width: 8px;
138
+ background-color: var(--primary);
139
+ transition: opacity 0.5s ease-in-out;
140
+ opacity: 0;
141
+
142
+ &.unread {
143
+ opacity: 1;
144
+ background-color: var(--error);
145
+ }
146
+ }
147
+ }
148
+ </style>
@@ -1,10 +1,12 @@
1
1
  import { CAPI, MANAGEMENT } from '@shell/config/types';
2
+ import { STORE } from '@shell/store/store-types';
2
3
  import { PaginationParam, PaginationParamFilter, PaginationSort } from '@shell/types/store/pagination.types';
3
4
  import { VuexStore } from '@shell/types/store/vuex';
4
5
  import { filterHiddenLocalCluster, filterOnlyKubernetesClusters, paginationFilterClusters } from '@shell/utils/cluster';
5
6
  import PaginationWrapper from '@shell/utils/pagination-wrapper';
6
7
  import { allHash } from '@shell/utils/promise';
7
8
  import { sortBy } from '@shell/utils/sort';
9
+ import { reactive } from 'vue';
8
10
  import { LocationAsRelativeRaw } from 'vue-router';
9
11
 
10
12
  interface TopLevelMenuCluster {
@@ -86,7 +88,15 @@ export interface TopLevelMenuHelper {
86
88
  */
87
89
  clustersOthers: Array<TopLevelMenuCluster>;
88
90
 
89
- update: (args: UpdateArgs) => Promise<void>
91
+ /**
92
+ * Fetch all cluster resources
93
+ */
94
+ update: (args: UpdateArgs) => Promise<void>;
95
+
96
+ /**
97
+ * Cleanup on destroy of TopLevelMenu
98
+ */
99
+ destroy: () => Promise<void>;
90
100
  }
91
101
 
92
102
  export abstract class BaseTopLevelMenuHelper {
@@ -106,7 +116,7 @@ export abstract class BaseTopLevelMenuHelper {
106
116
  * 2. ready
107
117
  * 3. name
108
118
  */
109
- public clustersPinned: Array<TopLevelMenuCluster> = [];
119
+ public clustersPinned: Array<TopLevelMenuCluster> = reactive([]);
110
120
 
111
121
  /**
112
122
  * Filter mgmt clusters by
@@ -121,7 +131,7 @@ export abstract class BaseTopLevelMenuHelper {
121
131
  * 2. ready
122
132
  * 3. name
123
133
  */
124
- public clustersOthers: Array<TopLevelMenuCluster> = [];
134
+ public clustersOthers: Array<TopLevelMenuCluster> = reactive([]);
125
135
 
126
136
  constructor({ $store }: {
127
137
  $store: VuexStore,
@@ -141,7 +151,7 @@ export abstract class BaseTopLevelMenuHelper {
141
151
  return {
142
152
  id: mgmtCluster.id,
143
153
  label: mgmtCluster.nameDisplay,
144
- ready: mgmtCluster.isReady, // && !provCluster?.hasError,
154
+ ready: mgmtCluster.isReady,
145
155
  providerNavLogo: mgmtCluster.providerMenuLogo,
146
156
  badge: mgmtCluster.badge,
147
157
  iconColor: mgmtCluster.iconColor,
@@ -165,69 +175,64 @@ export abstract class BaseTopLevelMenuHelper {
165
175
  export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper implements TopLevelMenuHelper {
166
176
  private args?: UpdateArgs;
167
177
 
168
- private clustersPinnedWrapper: PaginationWrapper;
169
- private clustersOthersWrapper: PaginationWrapper;
170
- private provClusterWrapper: PaginationWrapper;
171
-
172
- private commonClusterFilters: PaginationParam[];
178
+ private clustersPinnedWrapper: PaginationWrapper<any>;
179
+ private clustersOthersWrapper: PaginationWrapper<any>;
180
+ private provClusterWrapper: PaginationWrapper<any>;
173
181
 
174
182
  constructor({ $store }: {
175
183
  $store: VuexStore,
176
184
  }) {
177
185
  super({ $store });
178
186
 
179
- this.commonClusterFilters = paginationFilterClusters({ getters: this.$store.getters });
180
-
187
+ // Fetch all PINNED clusters (see `clustersPinned` description for details)
188
+ // No need to monitor for changes, the UNPINNED request will handle it
181
189
  this.clustersPinnedWrapper = new PaginationWrapper({
182
190
  $store,
183
- onUpdate: () => {
184
- // trigger on websocket update (only need 1 trigger for this cluster type)
185
- // https://github.com/rancher/rancher/issues/40773 / https://github.com/rancher/dashboard/issues/12734
186
- if (this.args) {
187
- this.update(this.args);
188
- }
189
- },
191
+ id: 'tlm-pinned-clusters',
190
192
  enabledFor: {
191
- store: 'management',
193
+ store: STORE.MANAGEMENT,
192
194
  resource: {
193
195
  id: MANAGEMENT.CLUSTER,
194
196
  context: 'side-bar',
195
197
  }
196
- }
198
+ },
199
+ formatResponse: { classify: true }
197
200
  });
201
+ // Fetch all UNPINNED clusters capped at 10 (see `clustersOthers` description for details)
198
202
  this.clustersOthersWrapper = new PaginationWrapper({
199
203
  $store,
200
- onUpdate: (res) => {
201
- // trigger on websocket update (only need 1 trigger for this cluster type)
202
- // https://github.com/rancher/rancher/issues/40773 / https://github.com/rancher/dashboard/issues/12734
204
+ id: 'tlm-unpinned-clusters',
205
+ onChange: () => {
203
206
  if (this.args) {
204
207
  this.update(this.args);
205
208
  }
206
209
  },
207
210
  enabledFor: {
208
- store: 'management',
211
+ store: STORE.MANAGEMENT,
209
212
  resource: {
210
213
  id: MANAGEMENT.CLUSTER,
211
214
  context: 'side-bar',
212
215
  }
213
- }
216
+ },
217
+ formatResponse: { classify: true }
214
218
  });
219
+ // Fetch all prov clusters for the mgmt clusters we have
215
220
  this.provClusterWrapper = new PaginationWrapper({
216
221
  $store,
217
- onUpdate: (res) => {
218
- // trigger on websocket update (only need 1 trigger for this cluster type)
219
- // https://github.com/rancher/rancher/issues/40773 / https://github.com/rancher/dashboard/issues/12734
222
+ id: 'tlm-prov-clusters',
223
+ onChange: () => {
220
224
  if (this.args) {
221
225
  this.update(this.args);
222
226
  }
223
227
  },
224
228
  enabledFor: {
225
- store: 'management',
229
+ store: STORE.MANAGEMENT,
226
230
  resource: {
227
231
  id: CAPI.RANCHER_CLUSTER,
228
232
  context: 'side-bar',
229
233
  }
230
- }
234
+ },
235
+ formatResponse: { classify: true }
231
236
  });
232
237
  }
233
238
 
@@ -258,6 +263,7 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
258
263
  return res;
259
264
  }, {} as { [mgmtId: string]: ProvCluster});
260
265
 
266
+ // Filter out mgmt clusters that don't have matching prov cluster and convert remaining to required format
261
267
  const _clustersNotPinned = res.notPinned
262
268
  .filter((mgmtCluster) => !!provClustersByMgmtId[mgmtCluster.id])
263
269
  .map((mgmtCluster) => this.convertToCluster(mgmtCluster, provClustersByMgmtId[mgmtCluster.id]));
@@ -274,6 +280,19 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
274
280
  this.cacheClusters();
275
281
  }
276
282
 
283
+ async destroy() {
284
+ this.clustersPinnedWrapper.onDestroy();
285
+ this.clustersOthersWrapper.onDestroy();
286
+ this.provClusterWrapper.onDestroy();
287
+ }
288
+
289
+ /**
290
+ * Helper function
291
+ *
292
+ * This extracts all the functionality previously in TopLevelMenu
293
+ *
294
+ * Construct SSP filter params
295
+ */
277
296
  private constructParams({
278
297
  pinnedIds,
279
298
  searchTerm,
@@ -289,7 +308,8 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
289
308
  includePinned?: boolean,
290
309
  excludePinned?: boolean,
291
310
  }): PaginationParam[] {
292
- const filters: PaginationParam[] = [...this.commonClusterFilters];
311
+ const commonClusterFilters = paginationFilterClusters({ getters: this.$store.getters });
312
+ const filters: PaginationParam[] = [...commonClusterFilters];
293
313
 
294
314
  if (pinnedIds) {
295
315
  if (includePinned) {
@@ -341,7 +361,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
341
361
  sort: DEFAULT_SORT,
342
362
  projectsOrNamespaces: []
343
363
  },
344
- classify: true,
345
364
  }).then((r) => r.data);
346
365
  }
347
366
 
@@ -362,7 +381,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
362
381
  sort: DEFAULT_SORT,
363
382
  projectsOrNamespaces: []
364
383
  },
365
- classify: true,
366
384
  }).then((r) => r.data);
367
385
  }
368
386
 
@@ -386,7 +404,6 @@ export class TopLevelMenuHelperPagination extends BaseTopLevelMenuHelper impleme
386
404
  sort: [],
387
405
  projectsOrNamespaces: []
388
406
  },
389
- classify: true,
390
407
  }).then((r) => r.data);
391
408
  }
392
409
  }
@@ -419,6 +436,10 @@ export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements
419
436
  this.cacheClusters();
420
437
  }
421
438
 
439
+ async destroy() {
440
+ // No-op
441
+ }
442
+
422
443
  /**
423
444
  * Filter mgmt clusters by
424
445
  * 1. Harvester type 1 (filterOnlyKubernetesClusters)
@@ -257,6 +257,13 @@ export default {
257
257
  });
258
258
 
259
259
  return appBar;
260
+ },
261
+
262
+ hideLocalCluster() {
263
+ const hideLocalSetting = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.HIDE_LOCAL_CLUSTER) || {};
264
+ const value = hideLocalSetting.value || hideLocalSetting.default || 'false';
265
+
266
+ return value === 'true';
260
267
  }
261
268
  },
262
269
 
@@ -309,6 +316,9 @@ export default {
309
316
  immediate: true,
310
317
  },
311
318
 
319
+ hideLocalCluster() {
320
+ this.updateClusters(this.pinnedIds, 'slow');
321
+ }
312
322
  },
313
323
 
314
324
  mounted() {
@@ -317,6 +327,7 @@ export default {
317
327
 
318
328
  beforeUnmount() {
319
329
  document.removeEventListener('keyup', this.handler);
330
+ this.helper?.destroy();
320
331
  },
321
332
 
322
333
  methods: {
@@ -64,7 +64,10 @@ export default {
64
64
  // If the route explicitly declares the nav path that should be highlighted, then use that
65
65
  if (routeMetaNav) {
66
66
  const cluster = this.$route.params?.cluster;
67
- const navPath = routeMetaNav.replace(':cluster', cluster);
67
+ const product = this.$route.params?.product;
68
+ const navPath = routeMetaNav
69
+ .replace(':cluster', cluster)
70
+ .replace(':product', product);
68
71
 
69
72
  if (navPath === typeFullPath) {
70
73
  return true;
@@ -0,0 +1,26 @@
1
+ import { Component } from 'vue';
2
+ import { useStore } from 'vuex';
3
+
4
+ export const useDrawer = () => {
5
+ const store = useStore();
6
+
7
+ const open = (component: Component, returnFocusSelector: string, options?: Record<string, any>) => {
8
+ store.commit('slideInPanel/open', {
9
+ component,
10
+ componentProps: {
11
+ ...(options || {}),
12
+ triggerFocusTrap: true,
13
+ returnFocusSelector
14
+ }
15
+ });
16
+ };
17
+
18
+ const close = () => {
19
+ store.commit('slideInPanel/close');
20
+ };
21
+
22
+ return {
23
+ open,
24
+ close
25
+ };
26
+ };
@@ -0,0 +1,63 @@
1
+ import { useResourceIdentifiers, useFetchResourceWithId } from '@shell/composables/resources';
2
+
3
+ const mockStore: any = {
4
+ getters: { 'cluster/schemaFor': jest.fn(() => ({ id: 'test-schema' })) },
5
+ dispatch: jest.fn()
6
+ };
7
+ const mockRoute: any = {
8
+ params: {
9
+ cluster: 'test-cluster',
10
+ namespace: 'test-namespace',
11
+ id: 'test-id',
12
+ },
13
+ };
14
+
15
+ jest.mock('vuex', () => ({ useStore: () => mockStore }));
16
+ jest.mock('vue-router', () => ({ useRoute: () => mockRoute }));
17
+
18
+ describe('resources', () => {
19
+ describe('useResourceIdentifiers', () => {
20
+ it('should return the correct value for a route with a namespace', async() => {
21
+ const { clusterId, id, schema } = useResourceIdentifiers('test-type');
22
+
23
+ expect(clusterId).toBe('test-cluster');
24
+ expect(id).toBe('test-namespace/test-id');
25
+ expect(schema).toStrictEqual({ id: 'test-schema' });
26
+ });
27
+
28
+ it('should return the correct value for a route without a namespace', async() => {
29
+ mockRoute.params.namespace = undefined;
30
+ const { clusterId, id, schema } = useResourceIdentifiers('test-type');
31
+
32
+ expect(clusterId).toBe('test-cluster');
33
+ expect(id).toBe('test-id');
34
+ expect(schema).toStrictEqual({ id: 'test-schema' });
35
+ });
36
+ });
37
+
38
+ describe('useFetchResourceWithId', () => {
39
+ it('should return the correct value given the correct arguments are passed to the dispatch method', async() => {
40
+ mockStore.dispatch.mockImplementation(() => Promise.resolve({ id: 'test-resource' }));
41
+ const resource = await useFetchResourceWithId('test-type', 'test-id');
42
+
43
+ expect(mockStore.dispatch).toHaveBeenCalledWith('cluster/find', { type: 'test-type', id: 'test-id' });
44
+ expect(resource).toStrictEqual({ id: 'test-resource' });
45
+ });
46
+
47
+ it('should dispatch a loadingError if a 404 occurs', async() => {
48
+ // eslint-disable-next-line prefer-promise-reject-errors
49
+ mockStore.dispatch.mockImplementationOnce(() => Promise.reject({ status: 404 }));
50
+ await useFetchResourceWithId('test-type', 'test-id');
51
+
52
+ expect(mockStore.dispatch).toHaveBeenCalledWith('loadingError', new Error('nav.failWhale.resourceIdNotFound-{"resource":"test-type","fqid":"test-id"}'));
53
+ });
54
+
55
+ it('should dispatch a loadingError if a 403 occurs', async() => {
56
+ // eslint-disable-next-line prefer-promise-reject-errors
57
+ mockStore.dispatch.mockImplementationOnce(() => Promise.reject({ status: 403 }));
58
+ await useFetchResourceWithId('test-type', 'test-id');
59
+
60
+ expect(mockStore.dispatch).toHaveBeenCalledWith('loadingError', new Error('nav.failWhale.resourceIdNotFound-{"resource":"test-type","fqid":"test-id"}'));
61
+ });
62
+ });
63
+ });
@@ -0,0 +1,38 @@
1
+ import { useI18n } from '@shell/composables/useI18n';
2
+ import { computed, Ref, toValue } from 'vue';
3
+ import { useRoute } from 'vue-router';
4
+ import { useStore } from 'vuex';
5
+
6
+ type ResourceType = string | Ref<string>;
7
+ type IdType = string | Ref<string>;
8
+
9
+ export const useResourceIdentifiers = (type: ResourceType) => {
10
+ const route = useRoute();
11
+ const store = useStore();
12
+
13
+ const typeValue = toValue(type);
14
+
15
+ const id = computed(() => route.params.namespace ? `${ route.params.namespace }/${ route.params.id }` : `${ route.params.id }`);
16
+ const schema = computed(() => store.getters['cluster/schemaFor'](typeValue));
17
+ const clusterId = computed(() => route.params.cluster as string);
18
+
19
+ return {
20
+ clusterId: clusterId.value, id: id.value, schema: schema.value
21
+ };
22
+ };
23
+
24
+ export const useFetchResourceWithId = async(type: ResourceType, id: IdType) => {
25
+ const store = useStore();
26
+ const i18n = useI18n(store);
27
+
28
+ const typeValue = toValue(type);
29
+ const idValue = toValue(id);
30
+
31
+ try {
32
+ return await store.dispatch('cluster/find', { type: typeValue, id: idValue });
33
+ } catch (ex: any) {
34
+ if (ex.status === 404 || ex.status === 403) {
35
+ store.dispatch('loadingError', new Error(i18n.t('nav.failWhale.resourceIdNotFound', { resource: type, fqid: id }, true)));
36
+ }
37
+ }
38
+ };
@@ -3,17 +3,6 @@ import { Store } from 'vuex';
3
3
  import { stringFor } from '@shell/plugins/i18n';
4
4
 
5
5
  let store: Store<any> | null = null;
6
-
7
- export const useI18n = (vuexStore: Store<any>): { t: typeof t } => {
8
- store = vuexStore;
9
-
10
- if (!store) {
11
- throw new Error('usI18n() must be called from setup()');
12
- }
13
-
14
- return { t };
15
- };
16
-
17
6
  /**
18
7
  * Allows for consuming i18n strings with the Vue composition API.
19
8
  * @param key - The key for the i18n string to translate.
@@ -24,3 +13,15 @@ export const useI18n = (vuexStore: Store<any>): { t: typeof t } => {
24
13
  const t = (key: string, args?: unknown, raw?: boolean): string => {
25
14
  return stringFor(store, key, args, raw);
26
15
  };
16
+
17
+ export type I18n = { t: typeof t };
18
+
19
+ export const useI18n = (vuexStore: Store<any>): I18n => {
20
+ store = vuexStore;
21
+
22
+ if (!store) {
23
+ throw new Error('usI18n() must be called from setup()');
24
+ }
25
+
26
+ return { t };
27
+ };
@@ -0,0 +1,17 @@
1
+ import { useRoute } from 'vue-router';
2
+ import { LEGACY } from '@shell/config/query-params';
3
+ import { computed } from 'vue';
4
+
5
+ const enabledByDefault = true;
6
+
7
+ export const useIsNewDetailPageEnabled = () => {
8
+ const route = useRoute();
9
+
10
+ return computed(() => {
11
+ if (enabledByDefault) {
12
+ return route?.query?.[LEGACY] !== 'true';
13
+ }
14
+
15
+ return route?.query?.[LEGACY] === 'false';
16
+ });
17
+ };
@@ -116,17 +116,20 @@ export const CATALOG = {
116
116
  };
117
117
 
118
118
  export const FLEET = {
119
- REPO_NAME: 'fleet.cattle.io/repo-name',
120
- CLUSTER_DISPLAY_NAME: 'management.cattle.io/cluster-display-name',
121
- CLUSTER_NAME: 'management.cattle.io/cluster-name',
122
- BUNDLE_ID: 'fleet.cattle.io/bundle-id',
123
- BUNDLE_NAME: 'fleet.cattle.io/bundle-name',
124
- BUNDLE_NAMESPACE: 'fleet.cattle.io/bundle-namespace',
125
- MANAGED: 'fleet.cattle.io/managed',
126
- CLUSTER_NAMESPACE: 'fleet.cattle.io/cluster-namespace',
127
- CLUSTER: 'fleet.cattle.io/cluster',
128
- CREATED_BY_USER_ID: 'fleet.cattle.io/created-by-user-id',
129
- CREATED_BY_USER_NAME: 'fleet.cattle.io/created-by-display-name',
119
+ REPO_NAME: 'fleet.cattle.io/repo-name',
120
+ HELM_NAME: 'fleet.cattle.io/fleet-helm-name',
121
+ CLUSTER_DISPLAY_NAME: 'management.cattle.io/cluster-display-name',
122
+ CLUSTER_NAME: 'management.cattle.io/cluster-name',
123
+ BUNDLE_ID: 'fleet.cattle.io/bundle-id',
124
+ BUNDLE_NAME: 'fleet.cattle.io/bundle-name',
125
+ BUNDLE_NAMESPACE: 'fleet.cattle.io/bundle-namespace',
126
+ MANAGED: 'fleet.cattle.io/managed',
127
+ CLUSTER_NAMESPACE: 'fleet.cattle.io/cluster-namespace',
128
+ CLUSTER: 'fleet.cattle.io/cluster',
129
+ CREATED_BY_USER_ID: 'fleet.cattle.io/created-by-user-id',
130
+ CREATED_BY_USER_NAME: 'fleet.cattle.io/created-by-display-name',
131
+ OCI_STORAGE_SECRET_DEFAULT: 'ui-default-oci-registry',
132
+ OCI_STORAGE_SECRET_GENERATED: 'fleet.cattle.io/bundle-internal-secret',
130
133
  };
131
134
 
132
135
  export const RBAC = { PRODUCT: 'management.cattle.io/ui-product' };
@@ -190,3 +193,9 @@ export const SYSTEM_LABELS = [
190
193
  ];
191
194
 
192
195
  export const CLOUD_CREDENTIALS = { EXPIRATION: 'rancher.io/expiration-timestamp' };
196
+
197
+ export const OIDC_CLIENT_SECRET_ANNOTATIONS = {
198
+ CREATE: 'cattle.io/oidc-client-secret-create',
199
+ REGEN: 'cattle.io/oidc-client-secret-regenerate',
200
+ REMOVE: 'cattle.io/oidc-client-secret-remove',
201
+ };