@rancher/shell 3.0.5-rc.5 → 3.0.5-rc.7

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 (361) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/key.svg +17 -0
  3. package/assets/styles/base/_spacing.scss +2 -2
  4. package/assets/styles/base/_variables.scss +17 -11
  5. package/assets/styles/global/_form.scss +1 -1
  6. package/assets/styles/global/_labeled-input.scss +1 -1
  7. package/assets/styles/themes/_dark.scss +5 -0
  8. package/assets/styles/themes/_light.scss +11 -2
  9. package/assets/styles/vendor/vue-select.scss +1 -1
  10. package/assets/translations/en-us.yaml +426 -64
  11. package/assets/translations/zh-hans.yaml +3 -4
  12. package/cloud-credential/gcp.vue +9 -1
  13. package/components/AppModal.vue +2 -0
  14. package/components/CodeMirror.vue +2 -2
  15. package/components/ConfigMapSettings/Settings.vue +377 -0
  16. package/components/ConfigMapSettings/index.vue +354 -0
  17. package/components/CruResource.vue +1 -2
  18. package/components/DetailText.vue +61 -11
  19. package/components/Drawer/Chrome.vue +115 -0
  20. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  21. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  22. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  23. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  24. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +106 -0
  25. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  26. package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
  27. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  28. package/components/Drawer/ResourceDetailDrawer/index.vue +111 -0
  29. package/components/GrowlManager.vue +16 -15
  30. package/components/IconOrSvg.vue +5 -0
  31. package/components/KeyValueView.vue +1 -1
  32. package/components/Loading.vue +1 -1
  33. package/components/LocaleSelector.vue +9 -1
  34. package/components/PaginatedResourceTable.vue +46 -1
  35. package/components/ProgressBarMulti.vue +1 -0
  36. package/components/PromptModal.vue +6 -1
  37. package/components/PromptRestore.vue +22 -44
  38. package/components/RelatedResources.vue +4 -12
  39. package/components/Resource/Detail/Additional.vue +46 -0
  40. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  41. package/components/Resource/Detail/Metadata/Annotations/index.vue +5 -0
  42. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  43. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +47 -256
  44. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
  45. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +34 -5
  46. package/components/Resource/Detail/Metadata/KeyValue.vue +32 -22
  47. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -1
  48. package/components/Resource/Detail/Metadata/Labels/index.vue +4 -0
  49. package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
  50. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +1 -1
  51. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +1 -1
  52. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  53. package/components/Resource/Detail/Metadata/composables.ts +60 -11
  54. package/components/Resource/Detail/Metadata/index.vue +12 -5
  55. package/components/Resource/Detail/Page.vue +15 -0
  56. package/components/Resource/Detail/ResourceRow.vue +37 -18
  57. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  58. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  59. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  60. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  61. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  62. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  63. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  64. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  65. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  66. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  67. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  68. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  69. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  70. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  71. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  72. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  73. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  74. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  75. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  76. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  77. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  78. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  79. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  80. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  81. package/components/Resource/Detail/SpacedRow.vue +1 -1
  82. package/components/Resource/Detail/TitleBar/Title.vue +2 -1
  83. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +1 -1
  84. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +1 -1
  85. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  86. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  87. package/components/Resource/Detail/TitleBar/composables.ts +45 -0
  88. package/components/Resource/Detail/TitleBar/index.vue +85 -13
  89. package/components/Resource/Detail/composables.ts +45 -0
  90. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  91. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  92. package/components/ResourceDetail/Masthead/index.vue +65 -0
  93. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  94. package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +1 -1
  95. package/components/ResourceDetail/__tests__/index.test.ts +26 -5
  96. package/components/ResourceDetail/index.vue +33 -17
  97. package/components/ResourceDetail/legacy.vue +18 -1
  98. package/components/ResourceList/Masthead.vue +6 -0
  99. package/components/ResourceList/index.vue +1 -0
  100. package/components/ResourceTable.vue +6 -1
  101. package/components/ResourceYaml.vue +15 -2
  102. package/components/RichTranslation.vue +106 -0
  103. package/components/SlideInPanelManager.vue +46 -11
  104. package/components/SortableTable/index.vue +1 -1
  105. package/components/SortableTable/selection.js +0 -1
  106. package/components/StateDot/index.vue +28 -0
  107. package/components/Tabbed/index.vue +17 -16
  108. package/components/Wizard.vue +4 -2
  109. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  110. package/components/__tests__/GrowlManager.test.ts +0 -25
  111. package/components/__tests__/PromptRestore.test.ts +1 -65
  112. package/components/__tests__/RichTranslation.test.ts +115 -0
  113. package/components/auth/login/ldap.vue +1 -1
  114. package/components/fleet/FleetApplications.vue +0 -7
  115. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  116. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  117. package/components/fleet/FleetClusters.vue +25 -6
  118. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  119. package/components/fleet/FleetHelmOps.vue +8 -0
  120. package/components/fleet/FleetRepos.vue +1 -6
  121. package/components/fleet/FleetResources.vue +4 -5
  122. package/components/fleet/FleetValuesFrom.vue +295 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  124. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  125. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +13 -13
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  127. package/components/fleet/dashboard/ResourceCard.vue +1 -0
  128. package/components/fleet/dashboard/ResourceCardSummary.vue +1 -5
  129. package/components/fleet/dashboard/ResourceDetails.vue +8 -10
  130. package/components/fleet/dashboard/ResourcePanel.vue +17 -9
  131. package/components/form/ArrayList.vue +13 -2
  132. package/components/form/ChangePassword.vue +3 -1
  133. package/components/form/FileImageSelector.vue +1 -1
  134. package/components/form/Footer.vue +10 -4
  135. package/components/form/KeyValue.vue +81 -43
  136. package/components/form/LabeledSelect.vue +56 -16
  137. package/components/form/Labels.vue +90 -17
  138. package/components/form/MatchExpressions.vue +46 -5
  139. package/components/form/NameNsDescription.vue +2 -1
  140. package/components/form/Networking.vue +24 -19
  141. package/components/form/ResourceLabeledSelect.vue +4 -3
  142. package/components/form/ResourceSelector.vue +1 -0
  143. package/components/form/ResourceTabs/index.vue +5 -0
  144. package/components/form/SecretSelector.vue +9 -2
  145. package/components/form/Select.vue +57 -19
  146. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  147. package/components/form/SimpleSecretSelector.vue +9 -2
  148. package/components/form/Taints.vue +21 -2
  149. package/components/form/UnitInput.vue +8 -0
  150. package/components/form/ValueFromResource.vue +1 -1
  151. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  152. package/components/form/__tests__/Labels.test.ts +360 -0
  153. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  154. package/components/form/__tests__/Networking.test.ts +116 -0
  155. package/components/form/__tests__/Select.test.ts +5 -2
  156. package/components/formatter/FleetApplicationSource.vue +1 -1
  157. package/components/formatter/PodImages.vue +1 -1
  158. package/components/formatter/WorkloadHealthScale.vue +1 -1
  159. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  160. package/components/google/AccountAccess.vue +209 -0
  161. package/components/google/types/gcp.d.ts +136 -0
  162. package/components/google/types/index.d.ts +101 -0
  163. package/components/google/util/__mocks__/gcp.ts +465 -0
  164. package/components/google/util/formatter.ts +82 -0
  165. package/components/google/util/gcp.ts +134 -0
  166. package/components/google/util/index.d.ts +11 -0
  167. package/components/nav/Favorite.vue +1 -1
  168. package/components/nav/Group.vue +71 -45
  169. package/components/nav/Header.vue +5 -1
  170. package/components/nav/NamespaceFilter.vue +13 -1
  171. package/components/nav/NotificationCenter/Notification.vue +510 -0
  172. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  173. package/components/nav/NotificationCenter/index.vue +148 -0
  174. package/composables/drawer.ts +26 -0
  175. package/composables/resources.test.ts +63 -0
  176. package/composables/resources.ts +38 -0
  177. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  178. package/config/labels-annotations.js +8 -0
  179. package/config/pagination-table-headers.js +8 -1
  180. package/config/product/auth.js +16 -1
  181. package/config/product/{cis.js → compliance.js} +23 -26
  182. package/config/product/explorer.js +32 -3
  183. package/config/product/fleet.js +7 -0
  184. package/config/product/manager.js +0 -1
  185. package/config/product/settings.js +22 -11
  186. package/config/query-params.js +13 -0
  187. package/config/roles.ts +1 -1
  188. package/config/router/navigation-guards/authentication.js +51 -2
  189. package/config/router/routes.js +47 -31
  190. package/config/settings.ts +21 -3
  191. package/config/store.js +2 -0
  192. package/config/system-namespaces.js +1 -1
  193. package/config/table-headers.js +32 -3
  194. package/config/types.js +16 -7
  195. package/config/version.js +1 -1
  196. package/core/plugin.ts +32 -7
  197. package/core/types.ts +18 -1
  198. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  199. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  200. package/detail/management.cattle.io.oidcclient.vue +369 -0
  201. package/detail/node.vue +2 -2
  202. package/detail/pod.vue +2 -2
  203. package/detail/provisioning.cattle.io.cluster.vue +3 -47
  204. package/detail/service.vue +10 -1
  205. package/detail/workload/index.vue +8 -2
  206. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  207. package/dialog/GenericPrompt.vue +1 -1
  208. package/dialog/ImportDialog.vue +8 -8
  209. package/dialog/OidcClientSecretDialog.vue +117 -0
  210. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  211. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  212. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +5 -2
  213. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  214. package/edit/auth/ldap/config.vue +24 -0
  215. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  216. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  217. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  218. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  219. package/edit/configmap.vue +8 -2
  220. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  221. package/edit/fleet.cattle.io.gitrepo.vue +44 -222
  222. package/edit/fleet.cattle.io.helmop.vue +44 -269
  223. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  224. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  225. package/edit/logging-flow/index.vue +1 -0
  226. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  227. package/edit/management.cattle.io.fleetworkspace.vue +1 -0
  228. package/edit/management.cattle.io.oidcclient.vue +162 -0
  229. package/edit/management.cattle.io.project.vue +4 -1
  230. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  231. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  232. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  233. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  234. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  235. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  236. package/edit/monitoring.coreos.com.route.vue +1 -0
  237. package/edit/namespace.vue +1 -0
  238. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  239. package/edit/networking.k8s.io.ingress/Certificate.vue +12 -12
  240. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
  241. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  242. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  243. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  244. package/edit/node.vue +1 -0
  245. package/edit/persistentvolume/index.vue +4 -1
  246. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
  247. package/edit/provisioning.cattle.io.cluster/rke2.vue +516 -426
  248. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
  249. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  250. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
  251. package/edit/resources.cattle.io.restore.vue +1 -1
  252. package/edit/secret/basic.vue +1 -0
  253. package/edit/secret/index.vue +127 -15
  254. package/edit/service.vue +4 -1
  255. package/edit/serviceaccount.vue +4 -1
  256. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  257. package/edit/workload/index.vue +5 -0
  258. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  259. package/list/management.cattle.io.oidcclient.vue +108 -0
  260. package/list/node.vue +2 -0
  261. package/list/projectsecret.vue +345 -0
  262. package/list/secret.vue +109 -0
  263. package/machine-config/amazonec2.vue +3 -24
  264. package/machine-config/components/GCEImage.vue +374 -0
  265. package/machine-config/google.vue +617 -0
  266. package/mixins/__tests__/brand.spec.ts +170 -0
  267. package/mixins/brand.js +16 -17
  268. package/mixins/create-edit-view/impl.js +10 -1
  269. package/mixins/create-edit-view/index.js +5 -0
  270. package/mixins/resource-fetch-api-pagination.js +24 -8
  271. package/mixins/resource-fetch.js +3 -1
  272. package/mixins/vue-select-overrides.js +1 -0
  273. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  274. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  275. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  276. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  277. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  278. package/models/fleet-application.js +8 -79
  279. package/models/fleet.cattle.io.cluster.js +13 -2
  280. package/models/fleet.cattle.io.gitrepo.js +2 -2
  281. package/models/fleet.cattle.io.helmop.js +9 -39
  282. package/models/management.cattle.io.fleetworkspace.js +2 -1
  283. package/models/management.cattle.io.oidcclient.js +18 -0
  284. package/models/management.cattle.io.registration.js +3 -0
  285. package/models/provisioning.cattle.io.cluster.js +29 -33
  286. package/models/secret.js +157 -2
  287. package/models/service.js +4 -0
  288. package/models/workload.js +5 -0
  289. package/package.json +2 -2
  290. package/pages/about.vue +4 -58
  291. package/pages/auth/login.vue +1 -1
  292. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +0 -1
  293. package/pages/c/_cluster/apps/charts/index.vue +296 -81
  294. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  295. package/pages/c/_cluster/explorer/index.vue +3 -3
  296. package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
  297. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  298. package/pages/c/_cluster/fleet/application/create.vue +3 -2
  299. package/pages/c/_cluster/fleet/index.vue +94 -57
  300. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  301. package/pages/c/_cluster/longhorn/index.vue +5 -2
  302. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  303. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  304. package/pages/explorer/resource/detail/configmap.vue +30 -7
  305. package/pages/explorer/resource/detail/projectsecret.vue +9 -0
  306. package/pages/explorer/resource/detail/secret.vue +63 -0
  307. package/pages/home.vue +9 -55
  308. package/pages/support/index.vue +4 -6
  309. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  310. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  311. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  312. package/plugins/dashboard-store/actions.js +19 -5
  313. package/plugins/dashboard-store/getters.js +4 -0
  314. package/plugins/dashboard-store/normalize.js +29 -17
  315. package/plugins/dashboard-store/resource-class.js +68 -19
  316. package/plugins/steve/steve-pagination-utils.ts +38 -19
  317. package/plugins/steve/subscribe.js +6 -1
  318. package/rancher-components/Banner/Banner.vue +13 -0
  319. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -4
  320. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  321. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  322. package/rancher-components/RcItemCard/RcItemCard.vue +8 -3
  323. package/store/auth.js +2 -0
  324. package/store/catalog.js +23 -1
  325. package/store/growl.js +97 -8
  326. package/store/index.js +6 -0
  327. package/store/notifications.ts +426 -0
  328. package/store/prefs.js +0 -1
  329. package/store/type-map.js +19 -16
  330. package/store/uiplugins.ts +15 -1
  331. package/types/fleet.d.ts +24 -0
  332. package/types/kube/kube-api.ts +12 -0
  333. package/types/notifications/index.ts +74 -0
  334. package/types/shell/index.d.ts +661 -589
  335. package/types/store/dashboard-store.types.ts +16 -0
  336. package/types/store/pagination.types.ts +16 -6
  337. package/utils/__tests__/create-yaml.test.ts +235 -0
  338. package/utils/__tests__/fleet.test.ts +148 -0
  339. package/utils/__tests__/object.test.ts +54 -1
  340. package/utils/__tests__/string.test.ts +273 -1
  341. package/utils/__tests__/time.test.ts +31 -0
  342. package/utils/auth.js +9 -2
  343. package/utils/create-yaml.js +103 -9
  344. package/utils/crypto/encryption.ts +103 -0
  345. package/utils/cspAdaptor.ts +51 -0
  346. package/utils/fleet.ts +54 -65
  347. package/utils/object.js +36 -0
  348. package/utils/pagination-utils.ts +19 -1
  349. package/utils/release-notes.ts +48 -0
  350. package/utils/selector-typed.ts +7 -2
  351. package/utils/string.js +24 -0
  352. package/utils/{time.js → time.ts} +25 -6
  353. package/utils/uiplugins.ts +22 -0
  354. package/utils/validators/formRules/index.ts +3 -0
  355. package/components/Resource/Detail/TitleBar/composable.ts +0 -31
  356. package/config/product/legacy.js +0 -62
  357. package/models/etcdbackup.js +0 -45
  358. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  359. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  360. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  361. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
@@ -1,12 +1,16 @@
1
1
  <script lang="ts">
2
- import BadgeState from '@pkg/rancher-components/src/components/BadgeState/BadgeState.vue';
3
- import { RouteLocationRaw } from 'vue-router';
2
+ import BadgeState from '@components/BadgeState/BadgeState.vue';
3
+ import { RouteLocationRaw, useRouter } from 'vue-router';
4
4
  import Title from '@shell/components/Resource/Detail/TitleBar/Title.vue';
5
5
  import Top from '@shell/components/Resource/Detail/TitleBar/Top.vue';
6
6
  import ActionMenu from '@shell/components/ActionMenuShell.vue';
7
7
  import { useStore } from 'vuex';
8
8
  import { useI18n } from '@shell/composables/useI18n';
9
- import RcButton from '~/pkg/rancher-components/src/components/RcButton/RcButton.vue';
9
+ import RcButton from '@components/RcButton/RcButton.vue';
10
+ import TabTitle from '@shell/components/TabTitle';
11
+ import { computed, ref, watch } from 'vue';
12
+ import { _CONFIG, _GRAPH, AS } from '@shell/config/query-params';
13
+ import ButtonGroup from '@shell/components/ButtonGroup';
10
14
 
11
15
  export interface Badge {
12
16
  color: 'bg-success' | 'bg-error' | 'bg-warning' | 'bg-info';
@@ -25,7 +29,10 @@ export interface TitleBarProps {
25
29
  // I don't have the time right now to swap this out though.
26
30
  actionMenuResource?: any;
27
31
 
28
- onShowConfiguration?: () => void;
32
+ // Please don't expand this pattern, this was a quick fix to resolve a conflict between the new masthead and fleet.
33
+ showViewOptions?: boolean;
34
+
35
+ onShowConfiguration?: (returnFocusSelector: string) => void;
29
36
  }
30
37
 
31
38
  const showConfigurationIcon = require(`@shell/assets/images/icons/document.svg`);
@@ -33,19 +40,50 @@ const showConfigurationIcon = require(`@shell/assets/images/icons/document.svg`)
33
40
 
34
41
  <script setup lang="ts">
35
42
  const {
36
- resourceTypeLabel, resourceTo, resourceName, description, badge, onShowConfiguration
43
+ resourceTypeLabel, resourceTo, resourceName, description, badge, showViewOptions, onShowConfiguration,
37
44
  } = defineProps<TitleBarProps>();
38
45
 
39
46
  const store = useStore();
40
47
  const i18n = useI18n(store);
48
+ const router = useRouter();
41
49
 
42
50
  const emit = defineEmits(['show-configuration']);
51
+ const showConfigurationDataTestId = 'show-configuration-cta';
52
+ const showConfigurationReturnFocusSelector = computed(() => `[data-testid="${ showConfigurationDataTestId }"]`);
53
+
54
+ const currentView = ref(router?.currentRoute?.value?.query?.as || _CONFIG);
55
+ const viewOptions = computed(() => {
56
+ if (!showViewOptions) {
57
+ return;
58
+ }
59
+
60
+ return [
61
+ {
62
+ labelKey: 'resourceDetail.masthead.config',
63
+ value: _CONFIG,
64
+ },
65
+ {
66
+ labelKey: 'resourceDetail.masthead.graph',
67
+ value: _GRAPH,
68
+ }
69
+ ];
70
+ });
71
+
72
+ watch(
73
+ () => currentView.value,
74
+ () => {
75
+ router.push({ query: { [AS]: currentView.value } });
76
+ }
77
+ );
43
78
  </script>
44
79
 
45
80
  <template>
46
81
  <div class="title-bar">
47
82
  <Top>
48
- <Title>
83
+ <Title class="title">
84
+ <TabTitle :show-child="false">
85
+ {{ resourceTypeLabel }}
86
+ </TabTitle>
49
87
  <router-link
50
88
  v-if="resourceTo"
51
89
  :to="resourceTo"
@@ -59,41 +97,50 @@ const emit = defineEmits(['show-configuration']);
59
97
  >
60
98
  {{ resourceTypeLabel }}:
61
99
  </span>
62
- <span class="resource-name">
100
+ <span class="resource-name masthead-resource-title">
63
101
  {{ resourceName }}
64
102
  </span>
65
103
  <BadgeState
66
104
  v-if="badge"
105
+ class="badge-state"
67
106
  :color="badge.color"
68
107
  :label="badge.label"
69
108
  />
70
109
  </Title>
71
110
  <div class="actions">
111
+ <!-- Please don't expand this pattern, this was a quick fix to resolve a conflict between the new masthead and fleet. -->
112
+ <ButtonGroup
113
+ v-if="viewOptions"
114
+ v-model:value="currentView"
115
+ :options="viewOptions"
116
+ />
72
117
  <RcButton
73
118
  v-if="onShowConfiguration"
119
+ :data-testid="showConfigurationDataTestId"
74
120
  class="show-configuration"
75
121
  :primary="true"
76
122
  :aria-label="i18n.t('component.resource.detail.titleBar.ariaLabel.showConfiguration', { resource: resourceName })"
77
- @click="emit('show-configuration')"
123
+ @click="() => emit('show-configuration', showConfigurationReturnFocusSelector)"
78
124
  >
79
125
  <img
80
126
  :src="showConfigurationIcon"
81
127
  class="mmr-3"
128
+ aria-hidden="true"
82
129
  >
83
130
  {{ i18n.t('component.resource.detail.titleBar.showConfiguration') }}
84
131
  </RcButton>
85
132
  <ActionMenu
86
133
  v-if="actionMenuResource"
87
- class="title-bar-action-menu"
88
134
  button-role="multiAction"
89
135
  :resource="actionMenuResource"
90
136
  data-testid="masthead-action-menu"
137
+ :button-aria-label="i18n.t('component.resource.detail.titleBar.ariaLabel.actionMenu', { resource: resourceName })"
91
138
  />
92
139
  </div>
93
140
  </Top>
94
141
  <div
95
142
  v-if="description"
96
- class="bottom description"
143
+ class="bottom description text-deemphasized"
97
144
  >
98
145
  {{ description }}
99
146
  </div>
@@ -102,13 +149,18 @@ const emit = defineEmits(['show-configuration']);
102
149
 
103
150
  <style lang="scss" scoped>
104
151
  .title-bar {
105
- &:deep() .badge-state {
152
+ min-width: 740px;
153
+
154
+ .badge-state {
106
155
  font-size: 16px;
107
- margin-left: 4px;
108
- top: -4px;
156
+ margin-left: 12px;
109
157
  position: relative;
110
158
  }
111
159
 
160
+ .show-configuration {
161
+ margin-left: 16px;
162
+ }
163
+
112
164
  &:deep() button[data-testid="masthead-action-menu"] {
113
165
  border-radius: 4px;
114
166
  width: 35px;
@@ -120,5 +172,25 @@ const emit = defineEmits(['show-configuration']);
120
172
  justify-content: center;
121
173
  align-items: center;
122
174
  }
175
+
176
+ .description {
177
+ max-width: 60%;
178
+ }
179
+
180
+ // This prevents the title from overlapping with the actions
181
+ .title {
182
+ max-width: calc(100% - 260px);
183
+ }
184
+
185
+ // We want the resource name to be what collaspes wh
186
+ .resource-name {
187
+ display: inline-block;
188
+ flex: 1;
189
+ white-space: nowrap;
190
+ overflow-x: hidden;
191
+ overflow-y: clip;
192
+ text-overflow: ellipsis;
193
+ margin-left: 4px;
194
+ }
123
195
  }
124
196
  </style>
@@ -0,0 +1,45 @@
1
+ import { computed, Ref, toValue } from 'vue';
2
+ import { useStore } from 'vuex';
3
+ import { Props as BannerProps } from '@components/Banner/Banner.vue';
4
+ import { useI18n } from '@shell/composables/useI18n';
5
+
6
+ export const useResourceDetailBannerProps = (resource: any): Ref<BannerProps | undefined> => {
7
+ const store = useStore();
8
+ const i18n = useI18n(store);
9
+ const resourceValue = toValue(resource);
10
+
11
+ return computed(() => {
12
+ const options = store.getters[`type-map/optionsFor`](resourceValue.type);
13
+
14
+ if (options.hideBanner) {
15
+ return;
16
+ }
17
+
18
+ if (resourceValue?.stateObj?.error) {
19
+ const defaultErrorMessage = i18n.t('resourceDetail.masthead.defaultBannerMessage.error', undefined, true);
20
+
21
+ return {
22
+ color: 'error',
23
+ label: resourceValue.stateObj.message || defaultErrorMessage
24
+ };
25
+ }
26
+
27
+ if (resourceValue?.spec?.paused) {
28
+ return {
29
+ color: 'info',
30
+ label: i18n.t('asyncButton.pause.description')
31
+ };
32
+ }
33
+
34
+ if (resourceValue?.stateObj?.transitioning) {
35
+ const defaultTransitioningMessage = i18n.t('resourceDetail.masthead.defaultBannerMessage.transitioning', undefined, true);
36
+
37
+ return {
38
+ color: 'info',
39
+ label: resourceValue.stateObj.message || defaultTransitioningMessage
40
+ };
41
+ }
42
+
43
+ return undefined;
44
+ });
45
+ };
@@ -0,0 +1,70 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { _VIEW } from '@shell/config/query-params';
3
+ import Index from '@shell/components/ResourceDetail/Masthead/index.vue';
4
+ import * as PageEnabled from '@shell/composables/useIsNewDetailPageEnabled';
5
+ import { computed } from 'vue';
6
+
7
+ jest.mock('@shell/composables/useIsNewDetailPageEnabled');
8
+ jest.mock('@shell/components/ResourceDetail/Masthead/latest.vue', () => ({
9
+ name: 'Latest',
10
+ template: `<div>Latest</div>`,
11
+ props: ['value', 'resourceSubtype']
12
+ }));
13
+ jest.mock('@shell/components/ResourceDetail/Masthead/legacy.vue', () => ({
14
+ name: 'Legacy',
15
+ template: `<div>Legacy</div>`
16
+ }));
17
+
18
+ describe('component: Masthead/index', () => {
19
+ const useIsNewDetailPageEnabledSpy = jest.spyOn(PageEnabled, 'useIsNewDetailPageEnabled');
20
+
21
+ beforeEach(() => {
22
+ jest.clearAllMocks();
23
+ });
24
+
25
+ it('should render Latest if useIsNewDetailPageEnabled is true and mode is _VIEW', () => {
26
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => true));
27
+ const props = {
28
+ value: { type: 'VALUE' },
29
+ mode: _VIEW,
30
+ resourceSubtype: 'SUBTYPE'
31
+ };
32
+
33
+ const wrapper = mount(Index, { props });
34
+
35
+ const component = wrapper.getComponent({ name: 'Latest' });
36
+
37
+ expect(component.props('value')).toStrictEqual(props.value);
38
+ expect(component.props('resourceSubtype')).toStrictEqual(props.resourceSubtype);
39
+ });
40
+
41
+ it('should render Legacy if useIsNewDetailPageEnabled is false and mode is _VIEW', () => {
42
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
43
+ const props = {
44
+ value: { type: 'VALUE' },
45
+ mode: _VIEW,
46
+ resourceSubtype: 'SUBTYPE'
47
+ };
48
+
49
+ const wrapper = mount(Index, { props });
50
+
51
+ const component = wrapper.getComponent({ name: 'Legacy' });
52
+
53
+ expect(component).toBeDefined();
54
+ });
55
+
56
+ it('should render Legacy if useIsNewDetailPageEnabled is true and mode is not _VIEW', () => {
57
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => true));
58
+ const props = {
59
+ value: { type: 'VALUE' },
60
+ mode: 'ANYTHING',
61
+ resourceSubtype: 'SUBTYPE'
62
+ };
63
+
64
+ const wrapper = mount(Index, { props });
65
+
66
+ const component = wrapper.getComponent({ name: 'Legacy' });
67
+
68
+ expect(component).toBeDefined();
69
+ });
70
+ });
@@ -1,6 +1,6 @@
1
1
  import { mount, RouterLinkStub } from '@vue/test-utils';
2
2
  import { _VIEW } from '@shell/config/query-params';
3
- import Masthead from '@shell/components/ResourceDetail/Masthead.vue';
3
+ import Legacy from '@shell/components/ResourceDetail/Masthead/legacy.vue';
4
4
  import { createStore } from 'vuex';
5
5
 
6
6
  const mockedStore = () => {
@@ -30,7 +30,7 @@ const requiredSetup = () => {
30
30
  };
31
31
  };
32
32
 
33
- describe('component: Masthead', () => {
33
+ describe('component: Masthead/legacy', () => {
34
34
  it.each([
35
35
  ['hidden', '', false, { displayName: 'admin', location: { id: 'resource-id' } }, false, false],
36
36
  ['plain-text', 'admin', true, { displayName: 'admin', location: null }, false, true],
@@ -43,7 +43,7 @@ describe('component: Masthead', () => {
43
43
  showLink,
44
44
  showPlainText,
45
45
  ) => {
46
- const wrapper = mount(Masthead, {
46
+ const wrapper = mount(Legacy, {
47
47
  props: {
48
48
  mode: _VIEW,
49
49
  value: {
@@ -0,0 +1,65 @@
1
+ <script lang="ts">
2
+ import { _VIEW, _YAML } from '@shell/config/query-params';
3
+ import Latest from '@shell/components/ResourceDetail/Masthead/latest.vue';
4
+ import Legacy from '@shell/components/ResourceDetail/Masthead/legacy.vue';
5
+ import { useIsNewDetailPageEnabled } from '@shell/composables/useIsNewDetailPageEnabled';
6
+ import { computed } from 'vue';
7
+
8
+ export interface Props {
9
+ value?: Object;
10
+ mode?: string;
11
+ realMode?: string;
12
+ as?: string;
13
+ hasGraph?: boolean;
14
+ hasDetail?: boolean;
15
+ hasEdit?: boolean;
16
+ storeOverride?: string;
17
+ resource?: string;
18
+ resourceSubtype?: string;
19
+ parentRouteOverride?: string;
20
+ canViewYaml?: boolean;
21
+ }
22
+
23
+ </script>
24
+ <script lang="ts" setup>
25
+
26
+ const props = withDefaults(defineProps<Props>(), {
27
+ value: () => ({}),
28
+ mode: 'create',
29
+ realMode: 'create',
30
+ as: _YAML,
31
+ hasGraph: false,
32
+ hasDetail: false,
33
+ hasEdit: false,
34
+ storeOverride: undefined,
35
+ resource: undefined,
36
+ resourceSubtype: undefined,
37
+ parentRouteOverride: undefined,
38
+ canViewYaml: false
39
+ });
40
+
41
+ const isNewDetailPageEnabled = useIsNewDetailPageEnabled();
42
+ const isView = computed(() => props.mode === _VIEW);
43
+ const showLatestMasthead = computed(() => isNewDetailPageEnabled.value && isView.value );
44
+ </script>
45
+
46
+ <template>
47
+ <Latest
48
+ v-if="showLatestMasthead"
49
+ :value="props.value"
50
+ :resourceSubtype="props.resourceSubtype"
51
+ />
52
+ <Legacy
53
+ v-else
54
+ v-bind="props"
55
+ >
56
+ <slot name="default" />
57
+ </Legacy>
58
+ </template>
59
+
60
+ <style lang="scss" scoped>
61
+ .new.state-banner {
62
+ margin: 0;
63
+ margin-top: 16px;
64
+ }
65
+ </style>
@@ -0,0 +1,44 @@
1
+ <script lang="ts">
2
+ import { Banner } from '@components/Banner';
3
+ import TitleBar from '@shell/components/Resource/Detail/TitleBar/index.vue';
4
+ import { useDefaultTitleBarProps } from '@shell/components/Resource/Detail/TitleBar/composables';
5
+ import Metadata from '@shell/components/Resource/Detail/Metadata/index.vue';
6
+ import { useDefaultMetadataForLegacyPagesProps } from '@shell/components/Resource/Detail/Metadata/composables';
7
+ import { useResourceDetailBannerProps } from '@shell/components/Resource/Detail/composables';
8
+ import { computed } from 'vue';
9
+
10
+ export interface Props {
11
+ value?: Object;
12
+ resourceSubtype?: string;
13
+ }
14
+
15
+ </script>
16
+
17
+ <script lang="ts" setup>
18
+ const props = withDefaults(defineProps<Props>(), { value: () => ({}), resourceSubtype: undefined });
19
+
20
+ const resourceSubtype = computed(() => props.resourceSubtype);
21
+ const titleBarProps = useDefaultTitleBarProps(props.value, resourceSubtype);
22
+ const metadataProps = useDefaultMetadataForLegacyPagesProps(props.value);
23
+ const bannerProps = useResourceDetailBannerProps(props.value);
24
+ </script>
25
+
26
+ <template>
27
+ <TitleBar v-bind="titleBarProps" />
28
+ <Banner
29
+ v-if="bannerProps"
30
+ class="new state-banner"
31
+ v-bind="bannerProps"
32
+ />
33
+ <Metadata
34
+ v-bind="metadataProps"
35
+ class="mmt-4"
36
+ />
37
+ </template>
38
+
39
+ <style lang="scss" scoped>
40
+ .new.state-banner {
41
+ margin: 0;
42
+ margin-top: 16px;
43
+ }
44
+ </style>
@@ -645,10 +645,10 @@ export default {
645
645
 
646
646
  h1 {
647
647
  margin: 0 0 0 -5px;
648
- overflow-x: hidden;
649
648
  display: flex;
650
649
  flex-direction: row;
651
650
  align-items: center;
651
+ overflow: hidden;
652
652
 
653
653
  .masthead-resource-title {
654
654
  text-overflow: ellipsis;
@@ -1,8 +1,9 @@
1
1
  import { mount } from '@vue/test-utils';
2
-
3
2
  import ResourceDetail from '@shell/components/ResourceDetail/index.vue';
4
3
  import { _EDIT, _VIEW, LEGACY, MODE } from '@shell/config/query-params';
4
+ import * as pageEnabled from '@shell/composables/useIsNewDetailPageEnabled';
5
5
  import flushPromises from 'flush-promises';
6
+ import { computed } from 'vue';
6
7
 
7
8
  const mockQuery: any = {};
8
9
  const mockParams: any = {};
@@ -30,13 +31,22 @@ jest.mock('vue-router', () => ({
30
31
  })
31
32
  }));
32
33
 
34
+ jest.mock('@shell/composables/useIsNewDetailPageEnabled');
35
+
33
36
  describe('component: ResourceDetail/index', () => {
34
37
  const resourceName = 'configmap';
38
+ const useIsNewDetailPageEnabledSpy = jest.spyOn(pageEnabled, 'useIsNewDetailPageEnabled');
39
+
40
+ beforeEach(() => {
41
+ jest.clearAllMocks();
42
+ });
35
43
 
36
- it('should render legacy component with default props if LEGACY=false is not present', async() => {
44
+ it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false', async() => {
37
45
  mockParams.resource = resourceName;
38
46
  mockQuery[MODE] = _VIEW;
39
47
 
48
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
49
+
40
50
  const wrapper = mount(ResourceDetail, { });
41
51
  const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
42
52
 
@@ -46,26 +56,33 @@ describe('component: ResourceDetail/index', () => {
46
56
  expect(legacyComponent.props('resourceOverride')).toBeUndefined();
47
57
  expect(legacyComponent.props('parentRouteOverride')).toBeUndefined();
48
58
  expect(legacyComponent.props('errorsMap')).toBeUndefined();
59
+ expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
49
60
  });
50
61
 
51
- it('should render legacy component with default props if LEGACY=false is present but resourceName has not been added to our mapping', async() => {
62
+ it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false but resourceName has not been added to our mapping', async() => {
52
63
  mockParams.resource = 'notMapped';
53
64
  mockQuery[MODE] = _VIEW;
54
65
 
66
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
67
+
55
68
  const wrapper = mount(ResourceDetail, {});
56
69
  const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
57
70
 
58
71
  expect(legacyComponent.exists()).toBeTruthy();
72
+ expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
59
73
  });
60
74
 
61
- it('should render legacy component with default props if LEGACY=false is present but mode is not VIEW', async() => {
75
+ it('should render legacy component with default props if useIsNewDetailPageEnabledSpy is false but mode is not VIEW', async() => {
62
76
  mockParams.resource = resourceName;
63
77
  mockQuery[MODE] = _EDIT;
64
78
 
79
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => false));
80
+
65
81
  const wrapper = mount(ResourceDetail, {});
66
82
  const legacyComponent = wrapper.findComponent<any>({ name: 'Legacy' });
67
83
 
68
84
  expect(legacyComponent.exists()).toBeTruthy();
85
+ expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
69
86
  });
70
87
 
71
88
  it('should render legacy component while forwarding props', async() => {
@@ -99,16 +116,20 @@ describe('component: ResourceDetail/index', () => {
99
116
  expect(legacyComponent.props('errorsMap')).toStrictEqual(errorsMap);
100
117
  });
101
118
 
102
- it('should render new component if LEGACY=false is present', async() => {
119
+ it('should render new component if useIsNewDetailPageEnabledSpy is true', async() => {
103
120
  mockParams.resource = resourceName;
121
+ mockParams.id = 'ID';
104
122
  mockQuery[MODE] = _VIEW;
105
123
  mockQuery[LEGACY] = 'false';
106
124
 
125
+ useIsNewDetailPageEnabledSpy.mockReturnValue(computed(() => true));
126
+
107
127
  const wrapper = mount(ResourceDetail);
108
128
 
109
129
  await flushPromises();
110
130
  const configmapComponent = wrapper.findComponent<any>({ name: 'configmap' });
111
131
 
112
132
  expect(configmapComponent.exists()).toBeTruthy();
133
+ expect(useIsNewDetailPageEnabledSpy).toHaveBeenCalledTimes(1);
113
134
  });
114
135
  });
@@ -2,9 +2,11 @@
2
2
  import { useRoute } from 'vue-router';
3
3
  import { computed, defineAsyncComponent } from 'vue';
4
4
 
5
- import { MODE, _VIEW, LEGACY } from '@shell/config/query-params';
5
+ import { MODE, _VIEW } from '@shell/config/query-params';
6
6
  import Legacy from '@shell/components/ResourceDetail/legacy.vue';
7
7
  import Loading from '@shell/components/Loading.vue';
8
+ import { useIsNewDetailPageEnabled } from '@shell/composables/useIsNewDetailPageEnabled';
9
+ import { VIRTUAL_TYPES } from '@shell/config/types';
8
10
 
9
11
  export interface Props {
10
12
  flexContent?: boolean;
@@ -22,19 +24,21 @@ export interface Props {
22
24
  // I could also dynamically check for and import these pages but I wanted this to be easier
23
25
  // to be explicit and easier to search for.
24
26
  const resourceToPage: any = {
25
- // 'apps.daemonset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.daemonset.vue')),
26
- // 'apps.deployment': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.deployment.vue')),
27
- // 'apps.statefulset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.statefulset.vue')),
28
- // 'batch.cronjob': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.cronjob.vue')),
29
- // 'batch.job': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.job.vue')),
30
- // 'cluster-dashboard': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/cluster-dashboard.vue')),
31
- configmap: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/configmap.vue')),
27
+ // 'apps.daemonset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.daemonset.vue')),
28
+ // 'apps.deployment': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.deployment.vue')),
29
+ // 'apps.statefulset': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/apps.statefulset.vue')),
30
+ // 'batch.cronjob': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.cronjob.vue')),
31
+ // 'batch.job': defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/batch.job.vue')),
32
+ configmap: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/configmap.vue')),
32
33
  // namespace: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/namespace.vue')),
33
34
  // node: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/node.vue')),
34
35
  // pod: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/pod.vue')),
35
- // secret: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/secret.vue')),
36
+ secret: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/secret.vue')),
37
+ [VIRTUAL_TYPES.PROJECT_SECRETS]: defineAsyncComponent(() => import('@shell/pages/explorer/resource/detail/projectsecret.vue')),
36
38
  };
37
39
 
40
+ defineOptions({ inheritAttrs: false });
41
+
38
42
  const route = useRoute();
39
43
  const props = withDefaults(defineProps<Props>(), {
40
44
  flexContent: false,
@@ -45,14 +49,26 @@ const props = withDefaults(defineProps<Props>(), {
45
49
  errorsMap: undefined
46
50
  });
47
51
 
48
- const currentResourceName = computed<string>(() => route.params.resource as string);
49
- const mode = computed(() => route.query[MODE]);
50
- const isView = computed(() => !mode.value || mode.value === _VIEW);
51
- // We're defaulting to legacy being on, we'll switch this once we want to enable the new detail page by default
52
- const isLegacy = computed(() => route.query[LEGACY] !== 'false');
53
- const page = computed(() => resourceToPage[currentResourceName.value]);
52
+ const currentResourceName = computed(() => {
53
+ const resource = props.resourceOverride || route?.params?.resource;
54
+
55
+ if (!resource) {
56
+ return;
57
+ }
54
58
 
55
- const useLatest = computed(() => !!(!isLegacy.value && isView.value && page.value));
59
+ if (typeof resource === 'string') {
60
+ return resource;
61
+ }
62
+
63
+ // This should never occur, just satisfying the types
64
+ return resource[0];
65
+ });
66
+ const mode = computed(() => route?.query?.[MODE]);
67
+ const isView = computed(() => route?.params?.id && (!mode.value || mode.value === _VIEW));
68
+ // We're defaulting to legacy being on, we'll switch this once we want to enable the new detail page by default
69
+ const iseNewDetailPageEnabled = useIsNewDetailPageEnabled();
70
+ const page = computed(() => currentResourceName.value ? resourceToPage[currentResourceName.value] : undefined);
71
+ const useLatest = computed(() => !!(iseNewDetailPageEnabled.value && isView.value && page.value));
56
72
  </script>
57
73
 
58
74
  <template>
@@ -66,6 +82,6 @@ const useLatest = computed(() => !!(!isLegacy.value && isView.value && page.valu
66
82
  </Suspense>
67
83
  <Legacy
68
84
  v-else
69
- v-bind="props"
85
+ v-bind="{...$attrs, ...props}"
70
86
  />
71
87
  </template>
@@ -379,6 +379,16 @@ export default {
379
379
  closeError(index) {
380
380
  this.errors = this.errors.filter((_, i) => i !== index);
381
381
  },
382
+ onYamlError(err) {
383
+ this.errors = [];
384
+ const errors = Array.isArray(err) ? err : [err];
385
+
386
+ errors.forEach((e) => {
387
+ if (this.errors.indexOf(e) === -1) {
388
+ this.errors.push(e);
389
+ }
390
+ });
391
+ },
382
392
  /**
383
393
  * Initializes the resource components based on the provided user and
384
394
  * resource override.
@@ -483,8 +493,9 @@ export default {
483
493
  :offer-preview="offerPreview"
484
494
  :done-route="doneRoute"
485
495
  :done-override="value ? value.doneOverride : null"
496
+ :show-errors="false"
486
497
  @update:value="$emit('input', $event)"
487
- @error="e=>errors.push(e)"
498
+ @error="onYamlError"
488
499
  />
489
500
 
490
501
  <component
@@ -542,4 +553,10 @@ export default {
542
553
  flex-direction: column;
543
554
  flex-grow: 1;
544
555
  }
556
+ .cru__errors {
557
+ position: sticky;
558
+ top: 0;
559
+ z-index: 1;
560
+ background-color: var(--header-bg);
561
+ }
545
562
  </style>