@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
@@ -408,10 +408,12 @@ export default {
408
408
  *
409
409
  * @param {*} ctx
410
410
  * @param { {type: string, opt: ActionFindPageArgs} } opt
411
+ * @returns @ActionFindPageResponse
411
412
  */
412
413
  async findPage(ctx, { type, opt }) {
413
414
  const { getters, commit, dispatch } = ctx;
414
415
 
416
+ // of type @ActionFindPageArgs
415
417
  opt = opt || {};
416
418
 
417
419
  if (!opt.pagination) {
@@ -443,7 +445,7 @@ export default {
443
445
  return findAllGetter(getters, type, opt);
444
446
  }
445
447
 
446
- console.log(`Find Page: [${ ctx.state.config.namespace }] ${ type }. Page: ${ opt.pagination.page }. Size: ${ opt.pagination.pageSize }`); // eslint-disable-line no-console
448
+ console.log(`Find Page: [${ ctx.state.config.namespace }] ${ type }. Page: ${ opt.pagination.page }. Size: ${ opt.pagination.pageSize }. Sort: ${ opt.pagination.sort.map((s) => s.field).join(', ') }`); // eslint-disable-line no-console
447
449
  opt = opt || {};
448
450
  opt.url = getters.urlFor(type, null, opt);
449
451
 
@@ -512,6 +514,9 @@ export default {
512
514
  * b) Pagination Disabled - use the old 'native kube api' - findMatching
513
515
  *
514
516
  * Filter is defined via the kube labelSelector object (see KubeLabelSelector)
517
+ *
518
+ * opt: @ActionFindLabelSelectorArgs
519
+ * @returns @ActionFindMatchingResponse (resources[], or if transient { data: resources[], pagination: StorePagination })
515
520
  */
516
521
  async findLabelSelector(ctx, {
517
522
  type,
@@ -528,6 +533,8 @@ export default {
528
533
  context,
529
534
  };
530
535
 
536
+ opt = opt || {};
537
+
531
538
  if (getters[`paginationEnabled`]?.(args)) {
532
539
  if (isLabelSelectorEmpty(labelSelector)) {
533
540
  throw new Error(`labelSelector must not be empty when using findLabelSelector (avoid fetching all resources)`);
@@ -537,21 +544,28 @@ export default {
537
544
  return dispatch('findPage', {
538
545
  type,
539
546
  opt: {
540
- ...(opt || {}),
547
+ ...opt,
541
548
  namespaced: namespace,
542
549
  pagination: new FilterArgs({ labelSelector }),
550
+ transient: opt?.transient !== undefined ? opt.transient : false // Call this out explicitly here, as by default findX methods ar eusually be cached AND watched
543
551
  }
544
552
  });
545
553
  }
546
554
 
547
- return dispatch('findMatching', {
555
+ // opt of type ActionFindPageArgs
556
+ const findMatching = await dispatch('findMatching', {
548
557
  type,
549
558
  selector: labelSelectorToSelector(labelSelector),
550
559
  opt,
551
560
  namespace,
552
561
  });
562
+
563
+ return opt.transient ? { data: findMatching } : findMatching;
553
564
  },
554
565
 
566
+ /**
567
+ * opt: @ActionFindMatchingArgs
568
+ */
555
569
  async findMatching(ctx, {
556
570
  type,
557
571
  selector,
@@ -796,9 +810,9 @@ export default {
796
810
 
797
811
  // Forget a type in the store
798
812
  // Remove all entries for that type and stop watching it
799
- forgetType({ commit, dispatch, state }, type) {
813
+ forgetType({ commit, dispatch, state }, type, compareWatches) {
800
814
  state.started
801
- .filter((entry) => entry.type === type)
815
+ .filter((entry) => compareWatches ? compareWatches(entry) : entry.type === type)
802
816
  .forEach((entry) => dispatch('unwatch', entry));
803
817
 
804
818
  commit('forgetType', type);
@@ -152,6 +152,10 @@ export default {
152
152
  return getters.all(type);
153
153
  }
154
154
 
155
+ if (getters['havePage'](type)) {
156
+ return getters.all(type);
157
+ }
158
+
155
159
  // Does the store have all and we can pretend like it contains a result of a labelSelector?
156
160
  if (getters['haveAll'](type)) {
157
161
  return getters.matching( type, selector, namespace );
@@ -17,28 +17,40 @@ export function normalizeType(type) {
17
17
  return type;
18
18
  }
19
19
 
20
- // Detect and resolve conflicts from a 409 response.
21
- // If they are resolved, return a false-y value
22
- // Else they can't be resolved, return an array of errors to show to the user.
23
- export async function handleConflict(initialValueJSON, value, liveValue, rootGetters, store, storeNamespace) {
24
- const orig = await store.dispatch(`${ storeNamespace }/cleanForDiff`, initialValueJSON, { root: true });
25
- const user = await store.dispatch(`${ storeNamespace }/cleanForDiff`, value.toJSON(), { root: true });
26
- const cur = await store.dispatch(`${ storeNamespace }/cleanForDiff`, liveValue.toJSON(), { root: true });
27
-
28
- const bgChange = changeset(orig, cur);
29
- const userChange = changeset(orig, user);
30
- const actualConflicts = changesetConflicts(bgChange, userChange);
31
-
32
- console.log('Background Change', bgChange); // eslint-disable-line no-console
33
- console.log('User Change', userChange); // eslint-disable-line no-console
20
+ /**
21
+ * Detect and resolve conflicts from a 409 response.
22
+ *
23
+ * @param {*} initialValue the initial value before changes
24
+ * @param {*} userValue the value containing the local changes. this function will intentionally mutate this to contain changes made from the server
25
+ * @param {*} serverValue the very latest value from the server
26
+ * @returns If `value` has been successfully updated return a false-y value. Else they can't be resolved, return an array of errors to show the user.
27
+ */
28
+ export async function handleConflict(initialValue, userValue, serverValue, store, storeNamespace, toJSON = (x) => x.toJSON()) {
29
+ // initial value
30
+ const initial = await store.dispatch(`${ storeNamespace }/cleanForDiff`, toJSON(initialValue), { root: true });
31
+ // changed value (user edits)
32
+ const user = await store.dispatch(`${ storeNamespace }/cleanForDiff`, toJSON(userValue), { root: true });
33
+ // server value
34
+ const server = await store.dispatch(`${ storeNamespace }/cleanForDiff`, toJSON(serverValue), { root: true });
35
+
36
+ // changes made to the server value
37
+ const serverChanges = changeset(initial, server);
38
+ // changes made locally
39
+ const userChanges = changeset(initial, user);
40
+ // Any incompatibilities between changes made locally and the server?
41
+ const actualConflicts = changesetConflicts(serverChanges, userChanges);
42
+
43
+ console.log('Background Change', serverChanges); // eslint-disable-line no-console
44
+ console.log('User Change', userChanges); // eslint-disable-line no-console
34
45
  console.log('Conflicts', actualConflicts); // eslint-disable-line no-console
35
46
 
36
- value.metadata.resourceVersion = liveValue.metadata.resourceVersion;
37
- applyChangeset(value, bgChange);
47
+ userValue.metadata.resourceVersion = serverValue.metadata.resourceVersion;
48
+ // Apply changes made on the server to the changed (user) value
49
+ applyChangeset(userValue, serverChanges);
38
50
 
39
51
  if ( actualConflicts.length ) {
40
52
  // Stop the save and let the user inspect and continue editing
41
- const out = [rootGetters['i18n/t']('validation.conflict', { fields: actualConflicts.join(', '), fieldCount: actualConflicts.length })];
53
+ const out = [store.getters['i18n/t']('validation.conflict', { fields: actualConflicts.join(', '), fieldCount: actualConflicts.length })];
42
54
 
43
55
  return out;
44
56
  } else {
@@ -32,6 +32,7 @@ import isFunction from 'lodash/isFunction';
32
32
  import isString from 'lodash/isString';
33
33
  import { markRaw } from 'vue';
34
34
 
35
+ import { handleConflict } from '@shell/plugins/dashboard-store/normalize';
35
36
  import { ExtensionPoint, ActionLocation } from '@shell/core/types';
36
37
  import { getApplicableExtensionEnhancements } from '@shell/core/plugin-helpers';
37
38
  import { parse } from '@shell/utils/selector';
@@ -736,6 +737,17 @@ export default class Resource {
736
737
  );
737
738
  }
738
739
 
740
+ get stateColorPair() {
741
+ return {
742
+ state: this.stateDisplay,
743
+ color: this.stateSimpleColor
744
+ };
745
+ }
746
+
747
+ get stateSimpleColor() {
748
+ return this.stateColor.replace('text-', '');
749
+ }
750
+
739
751
  get stateBackground() {
740
752
  return this.stateColor.replace('text-', 'bg-');
741
753
  }
@@ -1332,9 +1344,7 @@ export default class Resource {
1332
1344
  this.currentRouter().push(location);
1333
1345
  }
1334
1346
 
1335
- goToEdit(moreQuery = {}) {
1336
- const location = this.detailLocation;
1337
-
1347
+ goToEdit(moreQuery = {}, location = this.detailLocation) {
1338
1348
  location.query = {
1339
1349
  ...location.query,
1340
1350
  [MODE]: _EDIT,
@@ -1517,11 +1527,11 @@ export default class Resource {
1517
1527
  }
1518
1528
  }
1519
1529
 
1520
- async saveYaml(yaml) {
1521
- await this._saveYaml(yaml);
1530
+ async saveYaml(yaml, initialYaml) {
1531
+ await this._saveYaml(yaml, initialYaml);
1522
1532
  }
1523
1533
 
1524
- async _saveYaml(yaml) {
1534
+ async _saveYaml(yaml, initialYaml, depth = 0) {
1525
1535
  /* Multipart support, but need to know the right cluster and work for management store
1526
1536
  and "apply" seems to only work for create, not update.
1527
1537
 
@@ -1559,20 +1569,56 @@ export default class Resource {
1559
1569
  data: yaml
1560
1570
  });
1561
1571
  } else {
1562
- res = await this.followLink('update', {
1563
- method: 'PUT',
1564
- headers,
1565
- data: yaml
1566
- });
1572
+ try {
1573
+ res = await this.followLink('update', {
1574
+ method: 'PUT',
1575
+ headers,
1576
+ data: yaml
1577
+ });
1578
+ } catch (err) {
1579
+ const IS_ERR_409 = err.status === 409 || err._status === 409;
1580
+
1581
+ // Conflict, the resource being edited has changed since starting editing
1582
+ if (IS_ERR_409 && depth === 0 && initialYaml) {
1583
+ const inStore = this.$rootGetters['currentStore'](this.type);
1584
+
1585
+ const initialValue = jsyaml.load(initialYaml);
1586
+ const value = jsyaml.load(yaml);
1587
+ const liveValue = this.$rootGetters[`${ inStore }/byId`](this.type, this.id);
1588
+
1589
+ const handledConflictErr = await handleConflict(
1590
+ initialValue,
1591
+ value,
1592
+ liveValue,
1593
+ {
1594
+ dispatch: this.$dispatch,
1595
+ getters: this.$rootGetters
1596
+ },
1597
+ this.$rootGetters['currentStore'](this.type),
1598
+ (v) => v.toJSON ? v.toJSON() : v
1599
+ );
1600
+
1601
+ if (handledConflictErr === false) {
1602
+ // It was automatically figured out, save again
1603
+ await this._saveYaml(jsyaml.dump(value), null, depth + 1);
1604
+ } else {
1605
+ throw handledConflictErr;
1606
+ }
1607
+ } else {
1608
+ throw err;
1609
+ }
1610
+ }
1567
1611
  }
1568
1612
 
1569
- await this.$dispatch(`load`, {
1570
- data: res,
1571
- existing: (isCreate ? this : undefined)
1572
- });
1613
+ if (res) {
1614
+ await this.$dispatch(`load`, {
1615
+ data: res,
1616
+ existing: (isCreate ? this : undefined)
1617
+ });
1573
1618
 
1574
- if (this.isSpoofed) {
1575
- await this.$dispatch('cluster/findAll', { type: this.type, opt: { force: true } }, { root: true });
1619
+ if (this.isSpoofed) {
1620
+ await this.$dispatch('cluster/findAll', { type: this.type, opt: { force: true } }, { root: true });
1621
+ }
1576
1622
  }
1577
1623
  }
1578
1624
 
@@ -1868,10 +1914,13 @@ export default class Resource {
1868
1914
  namespace,
1869
1915
  labelSelector: { matchExpressions: parse(selector) }
1870
1916
  },
1871
- opts: opt
1917
+ opts: {
1918
+ transient: true,
1919
+ ...opt,
1920
+ },
1872
1921
  });
1873
1922
 
1874
- addObjects(out, matching);
1923
+ addObjects(out, matching.data);
1875
1924
  }
1876
1925
 
1877
1926
  // Find all the resources that match the required id's
@@ -15,7 +15,9 @@ import {
15
15
  HPA,
16
16
  SECRET
17
17
  } from '@shell/config/types';
18
- import { CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE } from '@shell/config/labels-annotations';
18
+ import {
19
+ CAPI as CAPI_LAB_AND_ANO, CATTLE_PUBLIC_ENDPOINTS, STORAGE, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY
20
+ } from '@shell/config/labels-annotations';
19
21
  import { Schema } from '@shell/plugins/steve/schema';
20
22
  import { PaginationSettingsStore } from '@shell/types/resources/settings';
21
23
  import paginationUtils from '@shell/utils/pagination-utils';
@@ -184,6 +186,10 @@ class StevePaginationUtils extends NamespaceProjectFilters {
184
186
  [CONFIG_MAP]: [
185
187
  { field: 'metadata.labels[harvesterhci.io/cloud-init-template]' }
186
188
  ],
189
+ [SECRET]: [
190
+ { field: `metadata.labels[${ UI_PROJECT_SECRET }]` },
191
+ { field: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]` },
192
+ ],
187
193
  [NAMESPACE]: [
188
194
  { field: 'metadata.labels[field.cattle.io/projectId]' }
189
195
  ],
@@ -454,7 +460,6 @@ class StevePaginationUtils extends NamespaceProjectFilters {
454
460
 
455
461
  // First check in our hardcoded list of supported filters
456
462
  if (
457
- process.env.NODE_ENV === 'dev' &&
458
463
  !!schema &&
459
464
  [
460
465
  StevePaginationUtils.VALID_FIELDS[''], // Global
@@ -500,16 +505,29 @@ class StevePaginationUtils extends NamespaceProjectFilters {
500
505
  // Check if the API supports filtering by this field
501
506
  this.validateField(validateFields, schema, field.field);
502
507
 
503
- const value = encodeURIComponent(field.value);
508
+ // we're just checking that the field exists, so there's no value
509
+ if (field.exists) {
510
+ return field.field;
511
+ }
512
+ const encodedValue = encodeURIComponent(field.value || '');
504
513
 
505
514
  // = exact match (equals + exact)
506
515
  // ~ partial match (equals + !exact)
507
516
  // != not exact match (!equals + exact)
508
517
  // !~ not partial match (!equals + !exact)
509
518
  const operator = `${ field.equals ? '' : '!' }${ field.exact ? '=' : '~' }`;
510
- const quotedValue = StevePaginationUtils.VALID_FIELD_VALUE_REGEX.test(value) ? value : `"${ value }"`;
511
-
512
- return `${ this.convertArrayPath(field.field) }${ operator }${ quotedValue }`;
519
+ let safeValue;
520
+
521
+ if (StevePaginationUtils.VALID_FIELD_VALUE_REGEX.test(field.value || '')) {
522
+ // Does not contain any protected characters, send as is
523
+ safeValue = encodedValue;
524
+ } else {
525
+ // Contains protected characters, wrap in quotes to ensure backend doesn't fail
526
+ // - replace reserver `"`/`%22` with empty string - see https://github.com/rancher/dashboard/issues/14549 for improvement
527
+ safeValue = `"${ encodedValue.replaceAll('%22', '') }"`;
528
+ }
529
+
530
+ return `${ this.convertArrayPath(field.field) }${ operator }${ safeValue }`;
513
531
  }
514
532
 
515
533
  return field.value;
@@ -658,19 +676,20 @@ export const PAGINATION_SETTINGS_STORE_DEFAULTS: PaginationSettingsStore = {
658
676
  }
659
677
  }
660
678
  },
661
- // Disabled due to https://github.com/rancher/dashboard/issues/14493
662
- // management: {
663
- // resources: {
664
- // enableAll: false,
665
- // enableSome: {
666
- // enabled: [
667
- // { resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] },
668
- // { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] },
669
- // ],
670
- // generic: false,
671
- // }
672
- // }
673
- // }
679
+ management: {
680
+ resources: {
681
+ enableAll: false,
682
+ enableSome: {
683
+ enabled: [
684
+ // { resource: CAPI.RANCHER_CLUSTER, context: ['home', 'side-bar'] }, // Disabled due to https://github.com/rancher/dashboard/issues/14493
685
+ // { resource: MANAGEMENT.CLUSTER, context: ['side-bar'] }, // Disabled due to https://github.com/rancher/dashboard/issues/14493
686
+ { resource: CATALOG.APP, context: ['branding'] },
687
+ SECRET
688
+ ],
689
+ generic: false,
690
+ }
691
+ }
692
+ }
674
693
  };
675
694
 
676
695
  export default new StevePaginationUtils();
@@ -544,6 +544,9 @@ const sharedActions = {
544
544
  return dispatch('send', msg);
545
545
  },
546
546
 
547
+ /**
548
+ * @param {STEVE_WATCH_PARAMS} params
549
+ */
547
550
  unwatch(ctx, {
548
551
  type, id, namespace, selector, all, mode
549
552
  }) {
@@ -577,7 +580,7 @@ const sharedActions = {
577
580
  dispatch('watch', obj); // Ask the backend to stop watching the type
578
581
  } else if (all) {
579
582
  getters['watchesOfType'](type).forEach((obj) => {
580
- unwatch(obj);
583
+ unwatch({ ...obj, stop: true });
581
584
  });
582
585
  } else if (getters['watchStarted'](obj)) {
583
586
  unwatch(obj);
@@ -752,6 +755,7 @@ const defaultActions = {
752
755
  if (mode === STEVE_WATCH_MODE.RESOURCE_CHANGES) {
753
756
  // Other findX use options (id/ns/selector) from the messages received over socket.
754
757
  // However paginated requests have more complex params so grab them from store from the store.
758
+ // of type @StorePagination
755
759
  const storePagination = getters['havePage'](resourceType);
756
760
 
757
761
  if (!!storePagination) {
@@ -766,6 +770,7 @@ const defaultActions = {
766
770
  type: resourceType,
767
771
  opt: {
768
772
  ...opt,
773
+ namespaced: namespace,
769
774
  // This brings in page, page size, filter, etc
770
775
  ...storePagination.request
771
776
  }
@@ -3,6 +3,19 @@ import { defineComponent } from 'vue';
3
3
  import { nlToBr, generateRandomAlphaString } from '@shell/utils/string';
4
4
  import { stringify } from '@shell/utils/error';
5
5
 
6
+ /**
7
+ * These should eventually be used when making this component use the composable api but I need the props elsewhere so I'm defining them here.
8
+ */
9
+ export interface Props {
10
+ color?: string;
11
+ label?: string | Error | Object;
12
+ labelKey?: string;
13
+ icon?: string;
14
+ closable?: boolean;
15
+ stacked?: boolean;
16
+ disabled?: boolean;
17
+ }
18
+
6
19
  export default defineComponent({
7
20
  props: {
8
21
  /**
@@ -305,12 +305,15 @@ export default defineComponent({
305
305
  :class="{ 'checkbox-primary': primary }"
306
306
  >
307
307
  <slot name="label">
308
- <t
308
+ <span
309
309
  v-if="labelKey"
310
310
  :id="idForLabel"
311
- :k="labelKey"
312
- :raw="true"
313
- />
311
+ >
312
+ <t
313
+ :k="labelKey"
314
+ :raw="true"
315
+ />
316
+ </span>
314
317
  <span
315
318
  v-else-if="label"
316
319
  :id="idForLabel"
@@ -322,6 +325,7 @@ export default defineComponent({
322
325
  class="checkbox-info icon icon-info icon-lg"
323
326
  :data-testid="componentTestid + '-info-icon'"
324
327
  :tabindex="isDisabled ? -1 : 0"
328
+ role="tooltip"
325
329
  />
326
330
  <i
327
331
  v-else-if="tooltip"
@@ -330,6 +334,7 @@ export default defineComponent({
330
334
  class="checkbox-info icon icon-info icon-lg"
331
335
  :data-testid="componentTestid + '-info-icon'"
332
336
  :tabindex="isDisabled ? -1 : 0"
337
+ role="tooltip"
333
338
  />
334
339
  </slot>
335
340
  </span>
@@ -407,7 +407,7 @@ export default defineComponent({
407
407
  :id="inputId"
408
408
  ref="value"
409
409
  v-stripped-aria-label="!hasLabel && ariaLabel ? ariaLabel : undefined"
410
- role="textbox"
410
+ :role="type === 'number' ? undefined : 'textbox'"
411
411
  :class="{ 'no-label': !hasLabel }"
412
412
  v-bind="$attrs"
413
413
  :maxlength="_maxlength"
@@ -73,6 +73,7 @@ export default defineComponent({
73
73
  class="icon status-icon"
74
74
  tabindex="0"
75
75
  :data-testid="componentTestid"
76
+ role="tooltip"
76
77
  />
77
78
  </template>
78
79
  <template v-else>
@@ -80,7 +80,7 @@ interface RcItemCardProps {
80
80
  image?: Image;
81
81
 
82
82
  /** Optional actions that will be displayed inside an action-menu */
83
- actions?: DropdownOption;
83
+ actions?: DropdownOption[];
84
84
 
85
85
  /** Text content inside the card body. A slot is available for it too #item-card-content */
86
86
  content?: Label;
@@ -149,6 +149,10 @@ const cardMeta = computed(() => ({
149
149
  <div
150
150
  ref="cardEl"
151
151
  class="item-card"
152
+ :class="{
153
+ 'clickable':
154
+ clickable
155
+ }"
152
156
  :role="cardMeta.role"
153
157
  :tabindex="cardMeta.tabIndex"
154
158
  :aria-label="cardMeta.ariaLabel"
@@ -288,7 +292,7 @@ $image-medium-box-width: 48px;
288
292
  border: 1px solid var(--border);
289
293
  background: var(--body-bg);
290
294
 
291
- &:hover {
295
+ &.clickable:hover {
292
296
  border-color: var(--primary);
293
297
  }
294
298
 
@@ -329,10 +333,11 @@ $image-medium-box-width: 48px;
329
333
 
330
334
  &-left {
331
335
  flex-grow: 1;
336
+ min-width: 0;
332
337
  }
333
338
 
334
339
  &-title {
335
- max-width: 60%;
340
+ max-width: 80%;
336
341
  font-size: 18px;
337
342
  font-weight: 600;
338
343
  margin-bottom: 0px;
package/store/auth.js CHANGED
@@ -356,6 +356,8 @@ export const actions = {
356
356
 
357
357
  commit('loggedOut');
358
358
  dispatch('onLogout', null, { root: true });
359
+
360
+ dispatch('uiplugins/setReady', false, { root: true });
359
361
  },
360
362
 
361
363
  async logout({ dispatch, getters, rootState }, options = {}) {
package/store/catalog.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CATALOG, EXPERIMENTAL, DEPRECATED } from '@shell/config/types';
1
+ import { CATALOG, EXPERIMENTAL, DEPRECATED, CATALOG_SORT_OPTIONS } from '@shell/config/types';
2
2
  import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
3
3
  import { addParams } from '@shell/utils/url';
4
4
  import { allHash, allHashSettled } from '@shell/utils/promise';
@@ -536,6 +536,7 @@ function addChart(ctx, map, chart, repo) {
536
536
  chartNameDisplay: chart.annotations?.[CATALOG_ANNOTATIONS.DISPLAY_NAME] || chart.name,
537
537
  chartDescription: chart.description,
538
538
  featured: chart.annotations?.[CATALOG_ANNOTATIONS.FEATURED],
539
+ featuredIndex: chart.annotations?.[CATALOG_ANNOTATIONS.FEATURED] ? Number(chart.annotations?.[CATALOG_ANNOTATIONS.FEATURED]) : Number.MAX_SAFE_INTEGER,
539
540
  repoKey: repo._key,
540
541
  versions: [],
541
542
  categories: filterCategories(chart.keywords),
@@ -565,6 +566,10 @@ function addChart(ctx, map, chart, repo) {
565
566
  }
566
567
 
567
568
  obj.versions.push(chart);
569
+
570
+ if (!obj.durationSinceRelease) {
571
+ obj.durationSinceRelease = Date.now() - new Date(obj.versions[0].created).getTime();
572
+ }
568
573
  }
569
574
 
570
575
  function preferSameRepo(matching, repoType, repoName) {
@@ -648,6 +653,7 @@ export function filterAndArrangeCharts(charts, {
648
653
  category,
649
654
  tag,
650
655
  searchQuery,
656
+ sort,
651
657
  showDeprecated = false,
652
658
  showHidden = false,
653
659
  showPrerelease = true,
@@ -700,5 +706,21 @@ export function filterAndArrangeCharts(charts, {
700
706
  return true;
701
707
  });
702
708
 
709
+ if (sort === CATALOG_SORT_OPTIONS.RECOMMENDED) {
710
+ return sortBy(out, ['featuredIndex', 'certifiedSort', 'repoName', 'chartNameDisplay']);
711
+ }
712
+
713
+ if (sort === CATALOG_SORT_OPTIONS.LAST_UPDATED_DESC) {
714
+ return sortBy(out, ['durationSinceRelease', 'featuredIndex', 'certifiedSort', 'repoName', 'chartNameDisplay']);
715
+ }
716
+
717
+ if (sort === CATALOG_SORT_OPTIONS.ALPHABETICAL_ASC) {
718
+ return sortBy(out, ['chartNameDisplay', 'featuredIndex', 'certifiedSort', 'repoName']);
719
+ }
720
+
721
+ if (sort === CATALOG_SORT_OPTIONS.ALPHABETICAL_DESC) {
722
+ return sortBy(out, ['chartNameDisplay'], true);
723
+ }
724
+
703
725
  return sortBy(out, ['certifiedSort', 'repoName', 'chartNameDisplay']);
704
726
  }