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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (424) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/icons/document.svg +3 -0
  3. package/assets/images/key.svg +17 -0
  4. package/assets/images/vendor/cognito.svg +1 -0
  5. package/assets/styles/app.scss +1 -0
  6. package/assets/styles/base/_basic.scss +10 -0
  7. package/assets/styles/base/_spacing.scss +29 -0
  8. package/assets/styles/global/_form.scss +1 -1
  9. package/assets/styles/global/_labeled-input.scss +1 -1
  10. package/assets/styles/global/_layout.scss +1 -1
  11. package/assets/styles/themes/_dark.scss +28 -0
  12. package/assets/styles/themes/_light.scss +68 -0
  13. package/assets/styles/vendor/vue-select.scss +1 -1
  14. package/assets/translations/en-us.yaml +721 -83
  15. package/assets/translations/zh-hans.yaml +11 -9
  16. package/cloud-credential/gcp.vue +9 -1
  17. package/components/AppModal.vue +2 -0
  18. package/components/Certificates.vue +5 -0
  19. package/components/CodeMirror.vue +1 -1
  20. package/components/ConfigMapSettings/Settings.vue +377 -0
  21. package/components/ConfigMapSettings/index.vue +354 -0
  22. package/components/CruResource.vue +1 -2
  23. package/components/DetailText.vue +61 -11
  24. package/components/Drawer/Chrome.vue +116 -0
  25. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  26. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  27. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  28. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  29. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +82 -0
  30. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  31. package/components/Drawer/ResourceDetailDrawer/composables.ts +50 -0
  32. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  33. package/components/Drawer/ResourceDetailDrawer/index.vue +110 -0
  34. package/components/FilterPanel.vue +156 -0
  35. package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
  36. package/components/GrowlManager.vue +16 -15
  37. package/components/IconOrSvg.vue +19 -35
  38. package/components/KeyValueView.vue +1 -1
  39. package/components/LocaleSelector.vue +9 -1
  40. package/components/ProgressBarMulti.vue +1 -0
  41. package/components/PromptModal.vue +6 -1
  42. package/components/PromptRemove.vue +5 -1
  43. package/components/RelatedResources.vue +4 -12
  44. package/components/Resource/Detail/Additional.vue +46 -0
  45. package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
  46. package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
  47. package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
  48. package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
  49. package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
  50. package/components/Resource/Detail/Card/Scaler.vue +89 -0
  51. package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
  52. package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
  53. package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
  54. package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
  55. package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
  56. package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
  57. package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
  58. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
  59. package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
  60. package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
  61. package/components/Resource/Detail/Card/index.vue +56 -0
  62. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
  63. package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
  64. package/components/Resource/Detail/Metadata/Annotations/index.vue +31 -0
  65. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  66. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
  67. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +64 -0
  68. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +298 -0
  69. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +133 -0
  70. package/components/Resource/Detail/Metadata/KeyValue.vue +138 -0
  71. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
  72. package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
  73. package/components/Resource/Detail/Metadata/Labels/index.vue +31 -0
  74. package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
  75. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
  76. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
  77. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  78. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
  79. package/components/Resource/Detail/Metadata/composables.ts +78 -0
  80. package/components/Resource/Detail/Metadata/index.vue +73 -0
  81. package/components/Resource/Detail/Page.vue +37 -0
  82. package/components/Resource/Detail/PercentageBar.vue +40 -0
  83. package/components/Resource/Detail/ResourceRow.vue +138 -0
  84. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  85. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  86. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  87. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  88. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  89. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  90. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  91. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  92. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  93. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  94. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  95. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  96. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  97. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  98. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  99. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  100. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  101. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  102. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  103. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  104. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  105. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  106. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  107. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  108. package/components/Resource/Detail/SpacedRow.vue +14 -0
  109. package/components/Resource/Detail/StatusBar.vue +59 -0
  110. package/components/Resource/Detail/StatusRow.vue +61 -0
  111. package/components/Resource/Detail/TitleBar/Title.vue +14 -0
  112. package/components/Resource/Detail/TitleBar/Top.vue +14 -0
  113. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
  114. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
  115. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  116. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
  117. package/components/Resource/Detail/TitleBar/composables.ts +44 -0
  118. package/components/Resource/Detail/TitleBar/index.vue +196 -0
  119. package/components/Resource/Detail/Top/index.vue +34 -0
  120. package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
  121. package/components/Resource/Detail/composables.ts +45 -0
  122. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  123. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  124. package/components/ResourceDetail/Masthead/index.vue +65 -0
  125. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  126. package/components/ResourceDetail/__tests__/index.test.ts +135 -0
  127. package/components/ResourceDetail/index.vue +73 -557
  128. package/components/ResourceDetail/legacy.vue +562 -0
  129. package/components/ResourceList/Masthead.vue +6 -0
  130. package/components/ResourceTable.vue +41 -7
  131. package/components/ResourceYaml.vue +14 -1
  132. package/components/SlideInPanelManager.vue +117 -10
  133. package/components/SortableTable/index.vue +13 -2
  134. package/components/SortableTable/selection.js +21 -8
  135. package/components/StateDot/index.vue +28 -0
  136. package/components/StatusBadge.vue +6 -4
  137. package/components/SubtleLink.vue +25 -0
  138. package/components/Tabbed/index.vue +11 -15
  139. package/components/Wizard.vue +16 -3
  140. package/components/YamlEditor.vue +1 -1
  141. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  142. package/components/__tests__/FilterPanel.test.ts +81 -0
  143. package/components/__tests__/GrowlManager.test.ts +0 -25
  144. package/components/auth/AuthBanner.vue +2 -3
  145. package/components/auth/RoleDetailEdit.vue +45 -3
  146. package/components/auth/login/ldap.vue +1 -1
  147. package/components/auth/login/oidc.vue +6 -1
  148. package/components/fleet/FleetApplications.vue +174 -0
  149. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  150. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  151. package/components/fleet/FleetClusters.vue +25 -6
  152. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  153. package/components/fleet/FleetHelmOps.vue +123 -0
  154. package/components/fleet/FleetIntro.vue +58 -28
  155. package/components/fleet/FleetNoWorkspaces.vue +5 -1
  156. package/components/fleet/FleetOCIStorageSecret.vue +171 -0
  157. package/components/fleet/FleetRepos.vue +37 -80
  158. package/components/fleet/FleetResources.vue +53 -26
  159. package/components/fleet/FleetSummary.vue +26 -51
  160. package/components/fleet/FleetValuesFrom.vue +295 -0
  161. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  162. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  163. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
  164. package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
  165. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  166. package/components/fleet/dashboard/Empty.vue +73 -0
  167. package/components/fleet/dashboard/ResourceCard.vue +184 -0
  168. package/components/fleet/dashboard/ResourceCardSummary.vue +195 -0
  169. package/components/fleet/dashboard/ResourceDetails.vue +194 -0
  170. package/components/fleet/dashboard/ResourcePanel.vue +383 -0
  171. package/components/form/ArrayList.vue +19 -2
  172. package/components/form/ChangePassword.vue +3 -1
  173. package/components/form/Footer.vue +10 -4
  174. package/components/form/KeyValue.vue +81 -43
  175. package/components/form/LabeledSelect.vue +56 -16
  176. package/components/form/Labels.vue +90 -17
  177. package/components/form/MatchExpressions.vue +46 -5
  178. package/components/form/NameNsDescription.vue +1 -1
  179. package/components/form/ResourceSelector.vue +1 -0
  180. package/components/form/ResourceTabs/index.vue +5 -0
  181. package/components/form/SecretSelector.vue +9 -2
  182. package/components/form/Select.vue +57 -19
  183. package/components/form/SimpleSecretSelector.vue +17 -4
  184. package/components/form/Taints.vue +21 -2
  185. package/components/form/UnitInput.vue +8 -0
  186. package/components/form/ValueFromResource.vue +31 -19
  187. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  188. package/components/form/__tests__/Labels.test.ts +360 -0
  189. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  190. package/components/form/__tests__/Select.test.ts +5 -2
  191. package/components/formatter/FleetApplicationClustersReady.vue +77 -0
  192. package/components/formatter/FleetApplicationSource.vue +71 -0
  193. package/components/formatter/FleetSummaryGraph.vue +7 -0
  194. package/components/formatter/WorkloadHealthScale.vue +1 -1
  195. package/components/google/AccountAccess.vue +211 -0
  196. package/components/google/types/gcp.d.ts +136 -0
  197. package/components/google/types/index.d.ts +101 -0
  198. package/components/google/util/__mocks__/gcp.ts +465 -0
  199. package/components/google/util/formatter.ts +82 -0
  200. package/components/google/util/gcp.ts +134 -0
  201. package/components/google/util/index.d.ts +11 -0
  202. package/components/nav/Favorite.vue +1 -1
  203. package/components/nav/Group.vue +70 -47
  204. package/components/nav/Header.vue +13 -8
  205. package/components/nav/NamespaceFilter.vue +13 -1
  206. package/components/nav/NotificationCenter/Notification.vue +510 -0
  207. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  208. package/components/nav/NotificationCenter/index.vue +148 -0
  209. package/components/nav/TopLevelMenu.helper.ts +55 -34
  210. package/components/nav/TopLevelMenu.vue +11 -0
  211. package/components/nav/Type.vue +4 -1
  212. package/composables/drawer.ts +26 -0
  213. package/composables/resources.test.ts +63 -0
  214. package/composables/resources.ts +38 -0
  215. package/composables/useI18n.ts +12 -11
  216. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  217. package/config/labels-annotations.js +20 -11
  218. package/config/product/auth.js +17 -1
  219. package/config/product/{cis.js → compliance.js} +23 -26
  220. package/config/product/explorer.js +5 -1
  221. package/config/product/fleet.js +77 -17
  222. package/config/product/settings.js +22 -11
  223. package/config/query-params.js +6 -1
  224. package/config/roles.ts +2 -1
  225. package/config/router/navigation-guards/authentication.js +51 -2
  226. package/config/router/routes.js +45 -31
  227. package/config/secret.ts +15 -0
  228. package/config/settings.ts +24 -5
  229. package/config/store.js +2 -0
  230. package/config/system-namespaces.js +1 -1
  231. package/config/table-headers.js +53 -23
  232. package/config/types.js +17 -6
  233. package/core/plugin-helpers.ts +3 -2
  234. package/core/plugin.ts +32 -7
  235. package/core/types.ts +18 -1
  236. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  237. package/detail/fleet.cattle.io.cluster.vue +28 -15
  238. package/detail/fleet.cattle.io.gitrepo.vue +10 -1
  239. package/detail/fleet.cattle.io.helmop.vue +157 -0
  240. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  241. package/detail/management.cattle.io.oidcclient.vue +369 -0
  242. package/detail/node.vue +2 -2
  243. package/detail/pod.vue +2 -2
  244. package/detail/service.vue +10 -1
  245. package/detail/workload/index.vue +8 -2
  246. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  247. package/dialog/GenericPrompt.vue +1 -1
  248. package/dialog/HelmOpForceUpdateDialog.vue +132 -0
  249. package/dialog/ImportDialog.vue +8 -8
  250. package/dialog/OidcClientSecretDialog.vue +117 -0
  251. package/dialog/RedeployWorkloadDialog.vue +164 -0
  252. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  253. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +60 -68
  254. package/edit/auth/oidc.vue +159 -93
  255. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  256. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  257. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  258. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  259. package/edit/configmap.vue +4 -1
  260. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  261. package/edit/fleet.cattle.io.gitrepo.vue +70 -255
  262. package/edit/fleet.cattle.io.helmop.vue +772 -0
  263. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  264. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  265. package/edit/logging-flow/index.vue +1 -0
  266. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  267. package/edit/management.cattle.io.fleetworkspace.vue +44 -10
  268. package/edit/management.cattle.io.oidcclient.vue +162 -0
  269. package/edit/management.cattle.io.project.vue +4 -1
  270. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  271. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  272. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  273. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  274. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  275. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  276. package/edit/monitoring.coreos.com.route.vue +1 -0
  277. package/edit/namespace.vue +1 -0
  278. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  279. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  280. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  281. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  282. package/edit/node.vue +1 -0
  283. package/edit/persistentvolume/index.vue +4 -1
  284. package/edit/provisioning.cattle.io.cluster/rke2.vue +418 -382
  285. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +27 -27
  286. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  287. package/edit/resources.cattle.io.restore.vue +1 -1
  288. package/edit/secret/index.vue +1 -0
  289. package/edit/service.vue +4 -1
  290. package/edit/serviceaccount.vue +4 -1
  291. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  292. package/edit/workload/index.vue +5 -0
  293. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  294. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  295. package/list/fleet.cattle.io.helmop.vue +108 -0
  296. package/list/management.cattle.io.oidcclient.vue +108 -0
  297. package/list/namespace.vue +5 -2
  298. package/list/node.vue +2 -0
  299. package/machine-config/amazonec2.vue +3 -24
  300. package/machine-config/components/GCEImage.vue +374 -0
  301. package/machine-config/google.vue +617 -0
  302. package/mixins/__tests__/brand.spec.ts +170 -0
  303. package/mixins/auth-config.js +8 -1
  304. package/mixins/brand.js +16 -17
  305. package/mixins/create-edit-view/index.js +5 -0
  306. package/mixins/preset.js +100 -0
  307. package/mixins/resource-fetch-api-pagination.js +18 -0
  308. package/mixins/resource-fetch.js +1 -1
  309. package/mixins/resource-table-watch.js +45 -0
  310. package/mixins/vue-select-overrides.js +1 -0
  311. package/models/__tests__/chart.test.ts +273 -0
  312. package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  313. package/models/chart.js +144 -2
  314. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  315. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  316. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  317. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  318. package/models/fleet-application.js +314 -0
  319. package/models/fleet.cattle.io.bundle.js +9 -8
  320. package/models/fleet.cattle.io.cluster.js +11 -0
  321. package/models/fleet.cattle.io.gitrepo.js +41 -365
  322. package/models/fleet.cattle.io.helmop.js +198 -0
  323. package/models/management.cattle.io.authconfig.js +1 -0
  324. package/models/management.cattle.io.fleetworkspace.js +14 -1
  325. package/models/management.cattle.io.oidcclient.js +18 -0
  326. package/models/management.cattle.io.registration.js +3 -0
  327. package/models/provisioning.cattle.io.cluster.js +5 -5
  328. package/models/service.js +4 -0
  329. package/models/workload.js +19 -18
  330. package/package.json +2 -1
  331. package/pages/about.vue +4 -58
  332. package/pages/auth/login.vue +1 -1
  333. package/pages/auth/verify.vue +13 -1
  334. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +36 -0
  335. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
  336. package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
  337. package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
  338. package/pages/c/_cluster/apps/charts/index.vue +487 -465
  339. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  340. package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
  341. package/pages/c/_cluster/explorer/index.vue +3 -3
  342. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  343. package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
  344. package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
  345. package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
  346. package/pages/c/_cluster/fleet/application/create.vue +341 -0
  347. package/pages/c/_cluster/fleet/application/index.vue +139 -0
  348. package/pages/c/_cluster/fleet/graph/config.js +277 -0
  349. package/pages/c/_cluster/fleet/index.vue +809 -329
  350. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  351. package/pages/c/_cluster/longhorn/index.vue +5 -2
  352. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  353. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  354. package/pages/explorer/resource/detail/configmap.vue +42 -0
  355. package/pages/explorer/resource/detail/secret.vue +50 -0
  356. package/pages/home.vue +9 -55
  357. package/pages/support/index.vue +4 -6
  358. package/plugins/dashboard-store/actions.js +50 -14
  359. package/plugins/dashboard-store/getters.js +38 -21
  360. package/plugins/dashboard-store/mutations.js +51 -7
  361. package/plugins/dashboard-store/resource-class.js +30 -4
  362. package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
  363. package/plugins/steve/actions.js +3 -0
  364. package/plugins/steve/steve-pagination-utils.ts +17 -8
  365. package/plugins/steve/subscribe.js +235 -43
  366. package/rancher-components/BadgeState/BadgeState.vue +3 -1
  367. package/rancher-components/Banner/Banner.vue +13 -0
  368. package/rancher-components/Form/Checkbox/Checkbox.vue +11 -6
  369. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  370. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  371. package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
  372. package/rancher-components/RcItemCard/RcItemCard.vue +430 -0
  373. package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
  374. package/rancher-components/RcItemCard/index.ts +2 -0
  375. package/store/auth.js +3 -0
  376. package/store/catalog.js +85 -25
  377. package/store/growl.js +97 -8
  378. package/store/index.js +39 -14
  379. package/store/notifications.ts +426 -0
  380. package/store/prefs.js +0 -1
  381. package/store/slideInPanel.ts +6 -0
  382. package/store/type-map.js +19 -15
  383. package/store/uiplugins.ts +15 -1
  384. package/types/fleet.d.ts +59 -0
  385. package/types/notifications/index.ts +74 -0
  386. package/types/resources/settings.d.ts +19 -1
  387. package/types/shell/index.d.ts +388 -307
  388. package/types/store/dashboard-store.types.ts +33 -3
  389. package/types/store/pagination.types.ts +6 -1
  390. package/types/store/subscribe.types.ts +50 -0
  391. package/utils/__tests__/fleet.test.ts +148 -0
  392. package/utils/__tests__/object.test.ts +54 -1
  393. package/utils/__tests__/string.test.ts +273 -1
  394. package/utils/__tests__/time.test.ts +31 -0
  395. package/utils/auth.js +41 -5
  396. package/utils/crypto/encryption.ts +103 -0
  397. package/utils/cspAdaptor.ts +51 -0
  398. package/utils/fleet-types.ts +0 -0
  399. package/utils/fleet.ts +190 -2
  400. package/utils/object.js +36 -0
  401. package/utils/pagination-utils.ts +27 -2
  402. package/utils/pagination-wrapper.ts +132 -50
  403. package/utils/release-notes.ts +48 -0
  404. package/utils/selector-typed.ts +7 -2
  405. package/utils/settings.ts +4 -1
  406. package/utils/string.js +24 -0
  407. package/utils/style.ts +39 -0
  408. package/utils/{time.js → time.ts} +25 -6
  409. package/utils/uiplugins.ts +22 -0
  410. package/utils/validators/formRules/__tests__/index.test.ts +36 -3
  411. package/utils/validators/formRules/index.ts +13 -3
  412. package/utils/window.js +11 -7
  413. package/components/__tests__/ApplicationCard.test.ts +0 -27
  414. package/components/cards/ApplicationCard.vue +0 -145
  415. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
  416. package/config/product/legacy.js +0 -62
  417. package/config/secret.js +0 -14
  418. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
  419. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  420. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  421. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  422. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
  423. /package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +0 -0
  424. /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
@@ -1,4 +1,5 @@
1
- import { PaginationArgs } from '@shell/types/store/pagination.types';
1
+ import { KubeLabelSelector } from '@shell/types/kube/kube-api';
2
+ import { PaginationArgs, StorePagination } from '@shell/types/store/pagination.types';
2
3
 
3
4
  /**
4
5
  * Properties on all findX actions
@@ -47,6 +48,11 @@ export interface ActionFindAllArgs extends ActionCoreFindArgs {
47
48
  depaginate?: boolean,
48
49
  }
49
50
 
51
+ export interface ActionFindPageTransientResult<T> {
52
+ pagination: StorePagination,
53
+ data: T[],
54
+ }
55
+
50
56
  /**
51
57
  * Args used for findPage action
52
58
  */
@@ -62,8 +68,32 @@ export interface ActionFindPageArgs extends ActionCoreFindArgs {
62
68
  */
63
69
  namespaced?: string,
64
70
  /**
65
- * Result of request is transient and not persisted to store
71
+ * Watch for changes
72
+ *
73
+ * false = no, all other values = yes
74
+ */
75
+ watch?: boolean,
76
+ /**
77
+ * Does this request stem from a list with manual refresh?
66
78
  */
67
- transient?: boolean,
68
79
  hasManualRefresh?: boolean,
80
+ /**
81
+ * If true don't persist the http response to the store, just pass it back
82
+ */
83
+ transient?: boolean,
84
+ }
85
+
86
+ export type ActionFindPageResponse<T = any> = {
87
+ data: T[],
88
+ pagination?: StorePagination
89
+ } | T[];
90
+
91
+ export interface ActionFindMatchingArgs extends ActionCoreFindArgs {
92
+ labelSelector: KubeLabelSelector,
93
+ namespaced?: string,
94
+ depaginate?: boolean
69
95
  }
96
+
97
+ export type ActionFindMatchingResponse<T = any> = ActionFindPageResponse<T>
98
+
99
+ export type ActionFindLabelSelectorArgs = ActionFindPageArgs | ActionFindMatchingArgs;
@@ -451,7 +451,12 @@ export interface StorePaginationRequest {
451
451
  /**
452
452
  * The set of pagination args used to create the request
453
453
  */
454
- pagination: PaginationArgs
454
+ pagination: PaginationArgs,
455
+
456
+ /**
457
+ * Does this request stem from a list with manual refresh?
458
+ */
459
+ hasManualRefresh?: boolean,
455
460
  }
456
461
 
457
462
  /**
@@ -0,0 +1,50 @@
1
+ /* eslint-disable no-unused-vars */
2
+ export enum STEVE_WATCH_MODE {
3
+ DEFAULT = '',
4
+ RESOURCE_CHANGES = 'resource.changes'
5
+ }
6
+ /* eslint-enable no-unused-vars */
7
+
8
+ /* eslint-disable no-unused-vars */
9
+ export enum STEVE_WATCH_EVENT {
10
+ START = 'resource.start',
11
+ CREATE = 'resource.create',
12
+ CHANGE = 'resource.change',
13
+ CHANGES = 'resource.changes',
14
+ REMOVE = 'resource.resource.remove',
15
+ ERROR = 'resource.error',
16
+ STOP = 'resource.stop',
17
+ }
18
+ /* eslint-enable no-unused-vars */
19
+
20
+ export interface STEVE_WATCH_PARAMS {
21
+ type: string,
22
+ selector?: string,
23
+ id?: string,
24
+ revision?: string,
25
+ namespace?: string,
26
+ stop?: boolean,
27
+ force?: boolean,
28
+ mode?: STEVE_WATCH_MODE
29
+ }
30
+
31
+ export type STEVE_WATCH_EVENT_LISTENER_CALLBACK = () => void
32
+ export interface STEVE_WATCH_EVENT_LISTENER {
33
+ params: STEVE_WATCH_PARAMS,
34
+ callbacks: { [id: string]: STEVE_WATCH_EVENT_LISTENER_CALLBACK},
35
+ }
36
+
37
+ export interface STEVE_WATCH_EVENT_PARAMS_COMMON {
38
+ event: STEVE_WATCH_EVENT,
39
+ id: string,
40
+ /**
41
+ * of type @STEVE_WATCH_PARAMS
42
+ */
43
+ params: STEVE_WATCH_PARAMS,
44
+ }
45
+
46
+ export interface STEVE_WATCH_EVENT_PARAMS extends STEVE_WATCH_EVENT_PARAMS_COMMON {
47
+ callback: STEVE_WATCH_EVENT_LISTENER_CALLBACK,
48
+ }
49
+
50
+ export type STEVE_UNWATCH_EVENT_PARAMS = STEVE_WATCH_EVENT_PARAMS_COMMON
@@ -0,0 +1,148 @@
1
+ import { Target } from '@shell/types/fleet';
2
+ import FleetUtils from '@shell/utils/fleet';
3
+
4
+ describe('fx: util.getTargetMode', () => {
5
+ const util = FleetUtils.Application;
6
+
7
+ it('should return "all" when targets contain excludeHarvesterRule and namespace is not fleet-local', () => {
8
+ const targets = [{
9
+ clusterSelector: {
10
+ matchExpressions: [{
11
+ key: 'provider.cattle.io',
12
+ operator: 'NotIn',
13
+ values: ['harvester'],
14
+ }],
15
+ },
16
+ }];
17
+ const namespace = 'ws1';
18
+
19
+ expect(util.getTargetMode(targets, namespace)).toBe('all');
20
+ });
21
+
22
+ it('should return "clusters" when targets include clusterName and clusterSelector', () => {
23
+ const targets = [{ clusterName: 'fleet-5-france' }, { clusterSelector: { matchLabels: { foo: 'true' } } }];
24
+ const namespace = 'ws1';
25
+
26
+ expect(util.getTargetMode(targets, namespace)).toBe('clusters');
27
+ });
28
+
29
+ it('should return "clusters" when targets only include multiple clusterSelectors', () => {
30
+ const targets: Target[] = [{ clusterSelector: { matchLabels: { foo: 'true' } } }, { clusterSelector: { matchLabels: { hci: 'true' } } }];
31
+ const namespace = 'ws1';
32
+
33
+ expect(util.getTargetMode(targets, namespace)).toBe('clusters');
34
+ });
35
+
36
+ it('should return "advanced" when a target contains clusterGroupSelector', () => {
37
+ const targets = [{ clusterGroupSelector: {} }];
38
+ const namespace = 'ws1';
39
+
40
+ expect(util.getTargetMode(targets, namespace)).toBe('advanced');
41
+ });
42
+
43
+ it('should return "advanced" when any target contains clusterGroup or clusterGroupSelector', () => {
44
+ const targets = [{
45
+ clusterGroup: 'cg1',
46
+ clusterGroupSelector: {
47
+ matchExpressions: [{
48
+ key: 'string',
49
+ operator: 'string',
50
+ values: ['string']
51
+ }],
52
+ matchLabels: { foo: 'bar' }
53
+ },
54
+ clusterName: 'pippo',
55
+ clusterSelector: {
56
+ matchExpressions: [{
57
+ key: 'string',
58
+ operator: 'string',
59
+ values: ['vvv']
60
+ }],
61
+ matchLabels: { foo: 'bar' }
62
+ },
63
+ name: 'tt1',
64
+ }, {
65
+ clusterGroup: 'cg2',
66
+ clusterGroupSelector: {
67
+ matchExpressions: [{
68
+ key: 'string',
69
+ operator: 'string',
70
+ values: ['string']
71
+ }],
72
+ matchLabels: { foo: 'bar' }
73
+ },
74
+ clusterName: 'pippo',
75
+ clusterSelector: {
76
+ matchExpressions: [{
77
+ key: 'string',
78
+ operator: 'string',
79
+ values: ['vvv']
80
+ }],
81
+ matchLabels: { foo: 'bar' }
82
+ },
83
+ name: 'tt1',
84
+ }];
85
+ const namespace = 'ws1';
86
+
87
+ expect(util.getTargetMode(targets, namespace)).toBe('advanced');
88
+ });
89
+
90
+ it('should return "none" when targets is an empty array', () => {
91
+ const targets: Target[] = [];
92
+ const namespace = 'ws1';
93
+
94
+ expect(util.getTargetMode(targets, namespace)).toBe('none');
95
+ });
96
+
97
+ it('should return "local" when namespace is "fleet-local" regardless of targets', () => {
98
+ const targets: Target[] = [{ clusterSelector: { matchLabels: { foo: 'true' } } }, { clusterSelector: { matchLabels: { hci: 'true' } } }];
99
+ const namespace = 'fleet-local';
100
+
101
+ expect(util.getTargetMode(targets, namespace)).toBe('local');
102
+ });
103
+
104
+ it('should return "all" if no specific target type (clusterName, clusterSelector, clusterGroup, clusterGroupSelector) is present', () => {
105
+ const targets = [{ name: 'target1' }];
106
+ const namespace = 'ws1';
107
+
108
+ expect(util.getTargetMode(targets, namespace)).toBe('all');
109
+ });
110
+
111
+ it('should return "clusters" if multiple targets include only clusterName', () => {
112
+ const targets = [{ clusterName: 'cluster-a' }, { clusterName: 'cluster-b' }];
113
+ const namespace = 'ws1';
114
+
115
+ expect(util.getTargetMode(targets, namespace)).toBe('clusters');
116
+ });
117
+
118
+ it('should return "clusters" if a mix of clusterName and empty clusterSelector is present', () => {
119
+ const targets = [{ clusterName: 'cluster-c' }, { clusterSelector: {} },
120
+ ];
121
+ const namespace = 'ws1';
122
+
123
+ expect(util.getTargetMode(targets, namespace)).toBe('clusters');
124
+ });
125
+
126
+ it('should return "advanced" if one target has clusterGroup but others have clusterName or clusterSelector', () => {
127
+ const targets = [{ clusterName: 'cluster-x' }, { clusterGroup: 'my-group' }, { clusterSelector: { matchLabels: { env: 'prod' } } }];
128
+ const namespace = 'ws1';
129
+
130
+ expect(util.getTargetMode(targets, namespace)).toBe('advanced');
131
+ });
132
+
133
+ it('should return "all" when targets contain excludeHarvesterRule along with other irrelevant properties', () => {
134
+ const targets = [{
135
+ clusterSelector: {
136
+ matchExpressions: [{
137
+ key: 'provider.cattle.io',
138
+ operator: 'NotIn',
139
+ values: ['harvester'],
140
+ }],
141
+ },
142
+ name: 'some-other-name'
143
+ }];
144
+ const namespace = 'ws1';
145
+
146
+ expect(util.getTargetMode(targets, namespace)).toBe('all');
147
+ });
148
+ });
@@ -1,6 +1,6 @@
1
1
  import { reactive, isReactive } from 'vue';
2
2
  import {
3
- clone, get, getter, isEmpty, toDictionary, remove, diff, definedKeys, deepToRaw, mergeWithReplace
3
+ clone, get, getter, isEmpty, toDictionary, remove, diff, definedKeys, deepToRaw, mergeWithReplace, convertKVToString, convertStringToKV
4
4
  } from '@shell/utils/object';
5
5
 
6
6
  describe('fx: get', () => {
@@ -441,3 +441,56 @@ describe('fx: mergeWithReplace', () => {
441
441
  expect(result).toStrictEqual(expected);
442
442
  });
443
443
  });
444
+
445
+ describe('fx: convertKVToString', () => {
446
+ it.each([
447
+ [{}, ''],
448
+ [{ foo: 'bar' }, 'foo,bar'],
449
+ [{ foo: 'bar', baz: 'bang' }, 'foo,bar,baz,bang'],
450
+ [{ foo: 'bar', baz: null }, 'foo,bar,baz,null'],
451
+ [{ ' spaced ': ' value ' }, ' spaced , value '], // preserves raw keys/values
452
+ [{ 0: 42, truthy: true }, '0,42,truthy,true'],
453
+ ])('should convert %p -> "%s"', (input, expected) => {
454
+ const result = convertKVToString(input);
455
+
456
+ expect(result).toBe(expected);
457
+ });
458
+
459
+ it('should produce a string with an even number of comma-separated parts', () => {
460
+ const str = convertKVToString({
461
+ a: 1, b: 2, c: 3
462
+ });
463
+ const parts = str.split(',');
464
+
465
+ expect(parts.length % 2).toBe(0);
466
+ });
467
+ });
468
+
469
+ describe('fx: convertStringToKV', () => {
470
+ it.each([
471
+ ['', {}],
472
+ ['foo,bar', { foo: 'bar' }],
473
+ ['foo,bar,baz,bang', { foo: 'bar', baz: 'bang' }],
474
+ [' foo , bar ', { foo: 'bar' }], // trims whitespace
475
+ ['foo,bar,baz', { foo: 'bar' }], // dangling key ignored
476
+ ['foo,bar,,bang', { foo: 'bar', '': 'bang' }], // empty key retained when present
477
+ ])('should convert "%s" -> %p', (input, expected) => {
478
+ const result = convertStringToKV(input);
479
+
480
+ expect(result).toStrictEqual(expected);
481
+ });
482
+ });
483
+
484
+ describe('fx: convertStringToKV to convertKVToString and back (round-trip)', () => {
485
+ it.each([
486
+ '',
487
+ 'foo,bar',
488
+ 'foo,bar,baz,bang',
489
+ 'answer,42,truthy,true,falsy,false',
490
+ ])('should round-trip %p without loss', (input) => {
491
+ const asObj = convertStringToKV(input);
492
+ const backToString = convertKVToString(asObj);
493
+
494
+ expect(backToString).toStrictEqual(input);
495
+ });
496
+ });
@@ -1,4 +1,4 @@
1
- import { decodeHtml, resourceNames } from '@shell/utils/string';
1
+ import { decodeHtml, resourceNames, pathArrayToTree } from '@shell/utils/string';
2
2
 
3
3
  describe('fx: decodeHtml', () => {
4
4
  it('should decode HTML values from escaped string into valid markup', () => {
@@ -89,3 +89,275 @@ describe('fx: resourceNames', () => {
89
89
  });
90
90
  });
91
91
  });
92
+
93
+ describe('fx: pathArrayToTree', () => {
94
+ interface TreeNode {
95
+ name: string;
96
+ children: TreeNode[];
97
+ }
98
+
99
+ function sortTree(nodes: TreeNode[]): void {
100
+ if (!nodes) return;
101
+ nodes.sort((a, b) => a.name.localeCompare(b.name));
102
+ nodes.forEach((node) => {
103
+ if (node.children && node.children.length > 0) {
104
+ sortTree(node.children);
105
+ }
106
+ });
107
+ }
108
+
109
+ it('should return an empty array for an empty input array', () => {
110
+ const paths: string[] = [];
111
+
112
+ expect(pathArrayToTree(paths)).toStrictEqual([]);
113
+ });
114
+
115
+ it('should convert simple single-level paths correctly', () => {
116
+ const paths: string[] = [
117
+ 'file1.txt',
118
+ 'folderA',
119
+ 'itemB'
120
+ ];
121
+ const expected: TreeNode[] = [
122
+ { name: 'file1.txt', children: [] },
123
+ { name: 'folderA', children: [] },
124
+ { name: 'itemB', children: [] },
125
+ ];
126
+ const actual = pathArrayToTree(paths);
127
+
128
+ sortTree(actual); // Sort the actual output for deterministic comparison
129
+ expect(actual).toStrictEqual(expected);
130
+ });
131
+
132
+ it('should convert two-level nested paths correctly', () => {
133
+ const paths: string[] = [
134
+ 'folderA/file1.txt',
135
+ 'folderC/file3.txt'
136
+ ];
137
+ const expected: TreeNode[] = [
138
+ {
139
+ name: 'folderA',
140
+ children: [
141
+ { name: 'file1.txt', children: [] },
142
+ ]
143
+ },
144
+ {
145
+ name: 'folderC',
146
+ children: [
147
+ { name: 'file3.txt', children: [] }
148
+ ]
149
+ },
150
+ ];
151
+ const actual = pathArrayToTree(paths);
152
+
153
+ sortTree(actual);
154
+ expect(actual).toStrictEqual(expected);
155
+ });
156
+
157
+ it('should handle deep nesting and common prefixes correctly', () => {
158
+ const paths: string[] = [
159
+ 'root/level1/level2/file.doc',
160
+ 'root/level1/another_file.txt',
161
+ 'root/diff_level1/config.json'
162
+ ];
163
+ const expected: TreeNode[] = [
164
+ {
165
+ name: 'root',
166
+ children: [
167
+ {
168
+ name: 'diff_level1',
169
+ children: [
170
+ { name: 'config.json', children: [] }
171
+ ]
172
+ },
173
+ {
174
+ name: 'level1',
175
+ children: [
176
+ { name: 'another_file.txt', children: [] },
177
+ {
178
+ name: 'level2',
179
+ children: [
180
+ { name: 'file.doc', children: [] }
181
+ ]
182
+ }
183
+ ]
184
+ }
185
+ ]
186
+ }
187
+ ];
188
+ const actual = pathArrayToTree(paths);
189
+
190
+ sortTree(actual);
191
+ expect(actual).toStrictEqual(expected);
192
+ });
193
+
194
+ it('should handle leading/trailing/multiple slashes by treating them as path segments', () => {
195
+ const paths: string[] = [
196
+ '/path/to/file.txt', // Starts with a slash
197
+ 'path/to/another.txt/', // Ends with a slash (adds an empty segment)
198
+ '//root/item//subitem//', // Multiple slashes (adds empty segments)
199
+ 'root/item/another_subitem'
200
+ ];
201
+ const expected: TreeNode[] = [
202
+ {
203
+ name: '',
204
+ children: [
205
+ {
206
+ name: '',
207
+ children: [
208
+ {
209
+ name: 'root',
210
+ children: [
211
+ {
212
+ name: 'item',
213
+ children: [
214
+ {
215
+ name: '',
216
+ children: [
217
+ {
218
+ name: 'subitem',
219
+ children: [
220
+ {
221
+ name: '',
222
+ children: [
223
+ {
224
+ name: '',
225
+ children: [
226
+ ],
227
+ },
228
+ ],
229
+ },
230
+ ],
231
+ },
232
+ ],
233
+ },
234
+ ],
235
+ },
236
+ ],
237
+ },
238
+ ],
239
+ },
240
+ {
241
+ name: 'path',
242
+ children: [
243
+ {
244
+ name: 'to',
245
+ children: [
246
+ {
247
+ name: 'file.txt',
248
+ children: [
249
+ ],
250
+ },
251
+ ],
252
+ },
253
+ ],
254
+ },
255
+ ],
256
+ },
257
+ {
258
+ name: 'path',
259
+ children: [
260
+ {
261
+ name: 'to',
262
+ children: [
263
+ {
264
+ name: 'another.txt',
265
+ children: [
266
+ {
267
+ name: '',
268
+ children: [
269
+ ],
270
+ },
271
+ ],
272
+ },
273
+ ],
274
+ },
275
+ ],
276
+ },
277
+ {
278
+ name: 'root',
279
+ children: [
280
+ {
281
+ name: 'item',
282
+ children: [
283
+ {
284
+ name: 'another_subitem',
285
+ children: [
286
+ ],
287
+ },
288
+ ],
289
+ },
290
+ ],
291
+ },
292
+ ];
293
+ const actual = pathArrayToTree(paths);
294
+
295
+ sortTree(actual);
296
+ expect(actual).toStrictEqual(expected);
297
+ });
298
+
299
+ it('should produce the same structure regardless of input order', () => {
300
+ const paths1: string[] = ['a/b', 'a/c'];
301
+ const paths2: string[] = ['a/c', 'a/b'];
302
+
303
+ const actual1 = pathArrayToTree(paths1);
304
+
305
+ sortTree(actual1);
306
+ const actual2 = pathArrayToTree(paths2);
307
+
308
+ sortTree(actual2);
309
+
310
+ expect(actual1).toStrictEqual(actual2);
311
+ });
312
+
313
+ it('should handle names with special characters (not slashes) correctly', () => {
314
+ const paths: string[] = [
315
+ 'my-folder/file_name.1.txt',
316
+ 'another folder/item with spaces'
317
+ ];
318
+ const expected: TreeNode[] = [
319
+ {
320
+ name: 'another folder',
321
+ children: [
322
+ { name: 'item with spaces', children: [] }
323
+ ]
324
+ },
325
+ {
326
+ name: 'my-folder',
327
+ children: [
328
+ { name: 'file_name.1.txt', children: [] }
329
+ ]
330
+ }
331
+ ];
332
+ const actual = pathArrayToTree(paths);
333
+
334
+ sortTree(actual);
335
+ expect(actual).toStrictEqual(expected);
336
+ });
337
+
338
+ it('should handle duplicate paths correctly, only adding unique structure', () => {
339
+ const paths: string[] = [
340
+ 'folder/file.txt',
341
+ 'folder/file.txt', // Duplicate
342
+ 'other_folder/another_file.txt'
343
+ ];
344
+ const expected: TreeNode[] = [
345
+ {
346
+ name: 'folder',
347
+ children: [
348
+ { name: 'file.txt', children: [] }
349
+ ]
350
+ },
351
+ {
352
+ name: 'other_folder',
353
+ children: [
354
+ { name: 'another_file.txt', children: [] }
355
+ ]
356
+ }
357
+ ];
358
+ const actual = pathArrayToTree(paths);
359
+
360
+ sortTree(actual);
361
+ expect(actual).toStrictEqual(expected);
362
+ });
363
+ });
@@ -0,0 +1,31 @@
1
+ import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
2
+ import { dateTimeFormat } from '@shell/utils/time';
3
+ import { type Store } from 'vuex';
4
+
5
+ describe('function: dateTimeFormat', () => {
6
+ jest.useFakeTimers()
7
+ .setSystemTime(new Date('21-10-2010 4:29:00'));
8
+ const store = {
9
+ getters: {
10
+ 'prefs/get': (key: string) => {
11
+ return {
12
+ [DATE_FORMAT]: 'ddd, MMM D YYYY',
13
+ [TIME_FORMAT]: 'h:mm:ss a',
14
+ }[key];
15
+ },
16
+ },
17
+ } as Store<any>;
18
+
19
+ it('should format date and time correctly', () => {
20
+ const date = new Date('2010-10-21T04:29:00Z');
21
+ const formattedDate = dateTimeFormat(date.toISOString(), store);
22
+
23
+ expect(formattedDate).toBe('Thu, Oct 21 2010 4:29:00 am');
24
+ });
25
+
26
+ it('should return empty string for undefined value', () => {
27
+ const formattedDate = dateTimeFormat(undefined, store);
28
+
29
+ expect(formattedDate).toBe('');
30
+ });
31
+ });