@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,70 +1,152 @@
1
1
  import paginationUtils from '@shell/utils/pagination-utils';
2
- import { PaginationArgs, PaginationResourceContext, StorePagination } from '@shell/types/store/pagination.types';
2
+ import { PaginationArgs, PaginationResourceContext } from '@shell/types/store/pagination.types';
3
3
  import { VuexStore } from '@shell/types/store/vuex';
4
- import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
4
+ import { ActionFindPageArgs, ActionFindPageTransientResult } from '@shell/types/store/dashboard-store.types';
5
+ import {
6
+ STEVE_WATCH_EVENT_LISTENER_CALLBACK, STEVE_UNWATCH_EVENT_PARAMS, STEVE_WATCH_EVENT, STEVE_WATCH_EVENT_PARAMS, STEVE_WATCH_EVENT_PARAMS_COMMON, STEVE_WATCH_MODE
7
+ } from '@shell/types/store/subscribe.types';
8
+ import { Reactive, reactive } from 'vue';
5
9
 
6
- interface Result<T> {
7
- data: Array<T>
8
- pagination: StorePagination
10
+ interface Args {
11
+ $store: VuexStore,
12
+ /**
13
+ * Unique ID for this request. Used for watch purposes
14
+ */
15
+ id: string,
16
+ /**
17
+ * Args used when determining if this resource type supports SSP
18
+ */
19
+ enabledFor: PaginationResourceContext,
20
+ /**
21
+ * Callback called when the resource is changed (notified by socket)
22
+ */
23
+ onChange?: () => void,
24
+
25
+ formatResponse?: {
26
+ /**
27
+ * Convert the response into a model class instance
28
+ */
29
+ classify?: boolean,
30
+ reactive?: boolean,
31
+ }
32
+ }
33
+
34
+ interface Result<T> extends Omit<ActionFindPageTransientResult<T>, 'data'> {
35
+ data: Reactive<T[]>
9
36
  }
10
37
 
11
38
  /**
12
- * This is a helper class that will assist in fetching a resource
13
- * - Handle if the resource can be fetched by the new pagination api
14
- * - Make a request to get a page (including classify)
15
- * - Provide updates when the resource changes
39
+ * This is a helper class that will assist in fetching a resource via the new Server-Side Pagination API
16
40
  *
17
41
  * This is designed to work in places where we don't/can't store the resource in the store
18
42
  * - There already exists a resource we don't want to overwrite
19
- * - We're transient and want something nicer than just cluster/request
43
+ * - We're transient and want something nicer than just `cluster/request` + all the trimmings
44
+ *
45
+ * It ...
46
+ * - Handles if the resource can be fetched by the new pagination api
47
+ * - Makes a request to get a page (including optional classify & reactive)
48
+ * - Provide updates when the resource changes
20
49
  */
21
- class PaginationWrapper<T = any> {
22
- private $store: VuexStore;
23
- private enabledFor: PaginationResourceContext;
24
-
25
- // Blocked on https://github.com/rancher/rancher/issues/40773 / https://github.com/rancher/dashboard/issues/12734
26
- private onUpdate: (out: Result<T>) => void;
27
-
28
- public isEnabled: boolean;
29
-
30
- constructor({
31
- $store,
32
- enabledFor,
33
- onUpdate,
34
- }: {
35
- $store: VuexStore,
36
- onUpdate: (res: Result<T>) => void,
37
- enabledFor: PaginationResourceContext,
38
- }) {
39
- this.$store = $store;
40
- this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters }, enabledFor);
41
- this.enabledFor = enabledFor;
42
- this.onUpdate = onUpdate;
50
+ class PaginationWrapper<T extends object> {
51
+ private $store: VuexStore;
52
+ private enabledFor: PaginationResourceContext;
53
+ private onChange?: STEVE_WATCH_EVENT_LISTENER_CALLBACK;
54
+ private id: string;
55
+ private classify: boolean;
56
+ private reactive: boolean;
57
+
58
+ public isEnabled: boolean;
59
+ private steveWatchParams: STEVE_WATCH_EVENT_PARAMS_COMMON | undefined;
60
+
61
+ constructor(args: Args) {
62
+ const {
63
+ $store, id, enabledFor, onChange, formatResponse
64
+ } = args;
65
+
66
+ this.$store = $store;
67
+ this.id = id;
68
+ this.enabledFor = enabledFor;
69
+ this.onChange = onChange;
70
+ this.classify = formatResponse?.classify || false;
71
+ this.reactive = formatResponse?.reactive || false;
72
+
73
+ this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters }, enabledFor);
74
+ }
75
+
76
+ async request(args: {
77
+ pagination: PaginationArgs,
78
+ }): Promise<Result<T>> {
79
+ if (!this.isEnabled) {
80
+ throw new Error(`Wrapper for type '${ this.enabledFor.store }/${ this.enabledFor.resource?.id }' in context '${ this.enabledFor.resource?.context }' not supported`);
81
+ }
82
+ const { pagination } = args;
83
+ const opt: ActionFindPageArgs = {
84
+ watch: false,
85
+ pagination,
86
+ transient: true,
87
+ };
88
+
89
+ // Fetch
90
+ const out: ActionFindPageTransientResult<T> = await this.$store.dispatch(`${ this.enabledFor.store }/findPage`, { opt, type: this.enabledFor.resource?.id });
91
+
92
+ // Watch
93
+ if (this.onChange && !this.steveWatchParams) {
94
+ this.steveWatchParams = {
95
+ event: STEVE_WATCH_EVENT.CHANGES,
96
+ id: this.id,
97
+ params: {
98
+ type: this.enabledFor.resource?.id as string,
99
+ mode: STEVE_WATCH_MODE.RESOURCE_CHANGES,
100
+ }
101
+ };
102
+
103
+ this.watch();
43
104
  }
44
105
 
45
- async request(args: {
46
- pagination: PaginationArgs,
47
- classify?: boolean,
48
- }): Promise<Result<T>> {
49
- if (!this.isEnabled) {
50
- throw new Error(`Wrapper for type '${ this.enabledFor.store }/${ this.enabledFor.resource?.id }' in context '${ this.enabledFor.resource?.context }' not supported`);
51
- }
52
- const { pagination, classify: doClassify } = args;
53
- const opt: ActionFindPageArgs = {
54
- transient: true,
55
- pagination
106
+ // Convert Response
107
+ if (this.classify) {
108
+ out.data = await this.$store.dispatch(`${ this.enabledFor.store }/createMany`, out.data);
109
+ }
110
+
111
+ if (this.reactive) {
112
+ return {
113
+ ...out,
114
+ data: reactive(out.data)
56
115
  };
116
+ }
57
117
 
58
- const out: Result<T> = await this.$store.dispatch(`${ this.enabledFor.store }/findPage`, { opt, type: this.enabledFor.resource?.id });
118
+ return out;
119
+ }
59
120
 
60
- if (doClassify) {
61
- for (let i = 0; i < out.data.length; i++) {
62
- out.data[i] = await this.$store.dispatch(`${ this.enabledFor.store }/create`, out.data[i]);
63
- }
64
- }
121
+ private async watch() {
122
+ if (!this.steveWatchParams) {
123
+ console.error('Calling watch but no watch params created'); // eslint-disable-line no-console
65
124
 
66
- return out;
125
+ return;
67
126
  }
127
+ const watchParams: STEVE_WATCH_EVENT_PARAMS = {
128
+ ...this.steveWatchParams,
129
+ callback: this.onChange as STEVE_WATCH_EVENT_LISTENER_CALLBACK, // we must have it by now
130
+ };
131
+
132
+ await this.$store.dispatch(`${ this.enabledFor.store }/watchEvent`, watchParams);
133
+ }
134
+
135
+ private async unWatch() {
136
+ if (!this.steveWatchParams) {
137
+ console.error('Calling unWatch but no watch params created'); // eslint-disable-line no-console
138
+
139
+ return;
140
+ }
141
+
142
+ const unWatchParams: STEVE_UNWATCH_EVENT_PARAMS = { ...this.steveWatchParams };
143
+
144
+ await this.$store.dispatch(`${ this.enabledFor.store }/unwatchEvent`, unWatchParams);
145
+ }
146
+
147
+ async onDestroy() {
148
+ await this.unWatch();
149
+ }
68
150
  }
69
151
 
70
152
  export default PaginationWrapper;
@@ -0,0 +1,48 @@
1
+ import { getVersionData } from '@shell/config/version';
2
+ import { READ_WHATS_NEW } from '@shell/store/prefs';
3
+ import { NotificationLevel } from '@shell/types/notifications';
4
+
5
+ export async function addReleaseNotesNotification(dispatch: any, getters: any) {
6
+ const rancherVersion = getVersionData().Version.split('-')[0];
7
+ const prefix = 'release-notes-';
8
+ const id = `${ prefix }${ rancherVersion }`;
9
+ let found = false;
10
+ const all = getters['notifications/all'];
11
+ const lastReadVersion = getters['prefs/get'](READ_WHATS_NEW) || '';
12
+ const t = getters['i18n/t'];
13
+ const releaseNotesUrl = getters['releaseNotesUrl'];
14
+
15
+ // Delete notification(s) for old release notes
16
+ for (let i = 0; i < all.length; i++) {
17
+ const notification = all[i];
18
+
19
+ if (notification.id.startsWith(prefix)) {
20
+ if (notification.id === id) {
21
+ found = true;
22
+ } else {
23
+ await dispatch('notifications/delete', notification.id);
24
+ }
25
+ }
26
+ }
27
+
28
+ // Also use pref, so if we expired it, we don't add it back
29
+ if (!found && lastReadVersion !== rancherVersion) {
30
+ // Register notification
31
+ const notification = {
32
+ id,
33
+ level: NotificationLevel.Info,
34
+ title: t('landing.whatsNew.title', { version: rancherVersion }),
35
+ message: t('landing.whatsNew.message'),
36
+ preference: {
37
+ key: READ_WHATS_NEW,
38
+ value: rancherVersion
39
+ },
40
+ primaryAction: {
41
+ label: t('landing.whatsNew.link'),
42
+ target: releaseNotesUrl
43
+ }
44
+ };
45
+
46
+ await dispatch('notifications/add', notification);
47
+ }
48
+ }
@@ -34,7 +34,7 @@ export async function matching({
34
34
  $store,
35
35
  inScopeCount = undefined,
36
36
  namespace = undefined,
37
- transient = false,
37
+ transient = true,
38
38
  }: {
39
39
  /**
40
40
  * Standard kube label selector object.
@@ -101,7 +101,12 @@ export async function matching({
101
101
  const filterByNamespaceButNoNamespace = isNamespaced && !!namespace && (!safeNamespaces || safeNamespaces.length === 0);
102
102
  const explicityNullLabelSelector = labelSelector === null || (labelSelector?.matchLabels === null && !labelSelector.matchExpressions === null);
103
103
 
104
- if (noCandidates || filterByNamespaceButNoNamespace || explicityNullLabelSelector) {
104
+ // If we have matchLabels or matchExpression entries they must have a key
105
+ const matchLabelKeys = Object.keys(labelSelector.matchLabels || {});
106
+ const invalidMatchLabelKeys = matchLabelKeys.length && matchLabelKeys.filter((k) => !k).length;
107
+ const invalidMatchExpressionKeys = labelSelector?.matchExpressions?.length && labelSelector.matchExpressions.filter((me) => !me.key).length;
108
+
109
+ if (noCandidates || filterByNamespaceButNoNamespace || explicityNullLabelSelector || invalidMatchLabelKeys || invalidMatchExpressionKeys) {
105
110
  return generateMatchingResponse([], inScopeCount || 0);
106
111
  }
107
112
 
package/utils/settings.ts CHANGED
@@ -59,7 +59,10 @@ export const fetchInitialSettings = async(store: Store<any>): Promise<any> => {
59
59
  // We're authed, we will always get the full list
60
60
  return await store.dispatch('management/findAll', {
61
61
  type: MANAGEMENT.SETTING,
62
- opt: { url: `/v1/${ pluralize(MANAGEMENT.SETTING) }` }
62
+ opt: {
63
+ url: `/v1/${ pluralize(MANAGEMENT.SETTING) }`,
64
+ watch: false, // Watch requires FF and Settings, see `loadManagement` to see how this is handled
65
+ }
63
66
  } );
64
67
  }
65
68
 
package/utils/string.js CHANGED
@@ -358,3 +358,27 @@ export function isBase64(value) {
358
358
  export function generateRandomAlphaString(length) {
359
359
  return Array.from({ length }, () => String.fromCharCode(97 + Math.random() * 26 | 0)).join('');
360
360
  }
361
+
362
+ /**
363
+ * Generate a key-value nested object from a list of paths that represents a directory tree.
364
+ *
365
+ * Each key is a subpath
366
+ * Each value contains the children of the subpath
367
+ */
368
+ export function pathArrayToTree(paths) {
369
+ const result = [];
370
+ const level = { result };
371
+
372
+ paths.forEach((path) => {
373
+ path?.split('/').reduce((r, name) => {
374
+ if (!r[name]) {
375
+ r[name] = { result: [] };
376
+ r.result.push({ name, children: r[name].result });
377
+ }
378
+
379
+ return r[name];
380
+ }, level);
381
+ });
382
+
383
+ return result;
384
+ }
package/utils/style.ts ADDED
@@ -0,0 +1,39 @@
1
+ export type StateColor = 'success' | 'warning' | 'error' | 'info' | 'disabled';
2
+ export const ALL_STATE_COLORS: StateColor[] = ['success', 'warning', 'error', 'info', 'disabled'];
3
+
4
+ export function stateColorCssVar(color: StateColor) {
5
+ return `var(--${ color })`;
6
+ }
7
+
8
+ export function toBgColor(color?: StateColor) {
9
+ const withDefaultColor = color || 'info';
10
+
11
+ return `bg-${ withDefaultColor }`;
12
+ }
13
+
14
+ /**
15
+ * Checks if 'a' is considered a higher alert than 'b'
16
+ * @param a target
17
+ * @param b comparison
18
+ * @returns true if 'a' is a higher alert than 'b' and false otherwise.
19
+ */
20
+ export function isHigherAlert(a: StateColor, b: StateColor) {
21
+ const order: StateColor[] = ['info', 'success', 'warning', 'error'];
22
+
23
+ const aIndex = order.indexOf(a);
24
+ const bIndex = order.indexOf(b);
25
+
26
+ return aIndex > bIndex;
27
+ }
28
+
29
+ export function getHighestAlertColor(colors: StateColor[]) {
30
+ let highestAlert: StateColor = 'info';
31
+
32
+ for (const color of colors) {
33
+ if (isHigherAlert(color, highestAlert)) {
34
+ highestAlert = color;
35
+ }
36
+ }
37
+
38
+ return highestAlert;
39
+ }
@@ -1,4 +1,7 @@
1
1
  import day from 'dayjs';
2
+ import { escapeHtml } from '@shell/utils/string';
3
+ import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
4
+ import { type Store } from 'vuex';
2
5
 
3
6
  const FACTORS = [60, 60, 24];
4
7
  const LABELS = ['sec', 'min', 'hour', 'day'];
@@ -6,7 +9,7 @@ const LABELS = ['sec', 'min', 'hour', 'day'];
6
9
  // Diff two dates and return an object with values for presentation
7
10
  // If 't' is also passed, 'string' property is set on the return object with the diff formatted as a string
8
11
  // e.g. formats a date difference to return '1 day', '20 hours' etc
9
- export function diffFrom(value, from, t) {
12
+ export function diffFrom(value: any, from: any, t: any) {
10
13
  const now = day();
11
14
 
12
15
  from = from || now;
@@ -15,7 +18,7 @@ export function diffFrom(value, from, t) {
15
18
  let absDiff = Math.abs(diff);
16
19
 
17
20
  let next = 1;
18
- let label = '?';
21
+ let label: any = '?';
19
22
 
20
23
  let i = 0;
21
24
 
@@ -30,7 +33,7 @@ export function diffFrom(value, from, t) {
30
33
  } else {
31
34
  label = Math.floor(absDiff);
32
35
  }
33
- const ret = {
36
+ const ret: any = {
34
37
  diff,
35
38
  absDiff,
36
39
  label,
@@ -47,7 +50,7 @@ export function diffFrom(value, from, t) {
47
50
  return ret;
48
51
  }
49
52
 
50
- export function safeSetTimeout(timeout, callback, that) {
53
+ export function safeSetTimeout(timeout: any, callback: any, that: any) {
51
54
  if (timeout <= 2147483647) {
52
55
  // Max value setTimeout can take is max 32 bit int (about 24.9 days)
53
56
  return setTimeout(() => {
@@ -56,7 +59,7 @@ export function safeSetTimeout(timeout, callback, that) {
56
59
  }
57
60
  }
58
61
 
59
- export function getSecondsDiff(startDate, endDate) {
62
+ export function getSecondsDiff(startDate: any, endDate: any) {
60
63
  return Math.round(
61
64
  Math.abs(Date.parse(endDate) - Date.parse(startDate)) / 1000
62
65
  );
@@ -68,7 +71,7 @@ export function getSecondsDiff(startDate, endDate) {
68
71
  * diff: update frequency in seconds
69
72
  * label: content of the cell's column
70
73
  */
71
- export function elapsedTime(seconds) {
74
+ export function elapsedTime(seconds: any) {
72
75
  if (!seconds) {
73
76
  return {};
74
77
  }
@@ -119,3 +122,19 @@ export function elapsedTime(seconds) {
119
122
  label: `${ hours }h${ minutes - (hours * 60) }m`,
120
123
  };
121
124
  }
125
+
126
+ /**
127
+ * Format date and time using user preferences
128
+ * @param value Date string to format
129
+ * @returns Formatted date string
130
+ */
131
+ export const dateTimeFormat = (value: string | undefined, store: Store<any>): string => {
132
+ if (!value) return '';
133
+
134
+ const dateFormat = escapeHtml( store.getters['prefs/get'](DATE_FORMAT));
135
+ const timeFormat = escapeHtml( store.getters['prefs/get'](TIME_FORMAT));
136
+
137
+ const format = `${ dateFormat } ${ timeFormat }`;
138
+
139
+ return day(value).format(format);
140
+ };
@@ -321,3 +321,25 @@ export async function getHelmChart(store: any, repository: any, chartName: strin
321
321
  await new Promise((resolve) => setTimeout(resolve, RETRY_WAIT));
322
322
  }
323
323
  }
324
+
325
+ export async function onExtensionsReady(store: any) {
326
+ const alreadyReady = store.getters['uiplugins/ready'];
327
+
328
+ if (alreadyReady) {
329
+ return;
330
+ }
331
+
332
+ const extensions = store.getters['uiplugins/plugins'] || [];
333
+
334
+ for (let i = 0; i < extensions.length; i++) {
335
+ const ext = extensions[i];
336
+
337
+ try {
338
+ await ext.onLogIn(store);
339
+ } catch (e) {
340
+ console.error(`Exception caught in onReady for extension ${ ext.name }`, e); // eslint-disable-line no-console
341
+ }
342
+ }
343
+
344
+ await store.dispatch('uiplugins/setReady', true);
345
+ }
@@ -96,8 +96,8 @@ describe('formRules', () => {
96
96
  );
97
97
  });
98
98
 
99
- describe('gitRepository', () => {
100
- const message = JSON.stringify({ message: 'validation.git.repository' });
99
+ describe('urlRepository', () => {
100
+ const message = JSON.stringify({ message: 'validation.git.url' });
101
101
  const testCases = [
102
102
  // Valid HTTP(s)
103
103
  ['https://github.com/rancher/dashboard.git', undefined],
@@ -128,7 +128,40 @@ describe('formRules', () => {
128
128
  it.each(testCases)(
129
129
  'should return undefined or correct message based on the provided Git url: %p',
130
130
  (url, expected) => {
131
- const formRuleResult = formRules.gitRepository(url);
131
+ const formRuleResult = formRules.urlRepository(url);
132
+
133
+ expect(formRuleResult).toStrictEqual(expected);
134
+ }
135
+ );
136
+ });
137
+
138
+ describe('ociRegistry', () => {
139
+ const message = JSON.stringify({ message: 'validation.oci.url' });
140
+ const testCases = [
141
+ // Valid
142
+ ['oci://bucket/object', undefined],
143
+ ['oci://region.objectstorage.example.com/n', undefined],
144
+ ['oci://a', undefined],
145
+ ['oci://UPPERCASE/path', undefined],
146
+
147
+ // Invalid
148
+ ['http://example.com/oci', message],
149
+ ['https://oci.cloud.com', message],
150
+ ['ftp://oci.server.net', message],
151
+ ['/path/to/oci', message],
152
+ ['oci:/missing/slash', message],
153
+ ['oci:', message],
154
+ ['oci://', message],
155
+ ['oci://space between', message],
156
+ ['oci://resource multiple spaces', message],
157
+ ['', message],
158
+ [undefined, message],
159
+ ];
160
+
161
+ it.each(testCases)(
162
+ 'should return undefined or correct message based on the provided OCI url: %p',
163
+ (url, expected) => {
164
+ const formRuleResult = formRules.ociRegistry(url);
132
165
 
133
166
  expect(formRuleResult).toStrictEqual(expected);
134
167
  }
@@ -170,19 +170,27 @@ export default function(
170
170
 
171
171
  const url: Validator = (val: string) => val && !isUrl(val) ? t('validation.setting.serverUrl.url') : undefined;
172
172
 
173
- const gitRepository: Validator = (url: string) => {
173
+ const genericUrl: Validator = (val: string) => val && !isUrl(val) ? t('validation.genericUrl') : undefined;
174
+
175
+ const urlRepository: Validator = (url: string) => {
174
176
  const regexPart1 = /^((http|git|ssh|http(s)|file|\/?)|(git@[\w\.]+))(:(\/\/)?)/gm;
175
177
  const regexPart2 = /^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(.git){0,1}(\/)?$/gm;
176
178
 
177
179
  if (url) {
178
180
  const urlPart2 = url.replaceAll(regexPart1, '');
179
181
 
180
- return !urlPart2 || url === urlPart2 || !regexPart2.test(urlPart2.replaceAll('%20', '')) ? t('validation.git.repository') : undefined;
182
+ return !urlPart2 || url === urlPart2 || !regexPart2.test(urlPart2.replaceAll('%20', '')) ? t('validation.git.url') : undefined;
181
183
  }
182
184
 
183
185
  return undefined;
184
186
  };
185
187
 
188
+ const ociRegistry: Validator = (url: string) => {
189
+ const regex = /^oci:\/\/\S+$/gm;
190
+
191
+ return !regex.test(url) ? t('validation.oci.url') : undefined;
192
+ };
193
+
186
194
  const alphanumeric: Validator = (val: string) => val && !/^[a-zA-Z0-9]+$/.test(val) ? t('validation.alphanumeric', { key }) : undefined;
187
195
 
188
196
  const interval: Validator = (val: string) => !/^\d+[hms]$/.test(val) ? t('validation.monitoring.route.interval', { key }) : undefined;
@@ -527,7 +535,7 @@ export default function(
527
535
  dnsLabelRestricted,
528
536
  externalName,
529
537
  fileRequired,
530
- gitRepository,
538
+ urlRepository,
531
539
  groupsAreValid,
532
540
  hostname,
533
541
  imageUrl,
@@ -536,12 +544,14 @@ export default function(
536
544
  localhost,
537
545
  trailingForwardSlash,
538
546
  url,
547
+ genericUrl,
539
548
  matching,
540
549
  maxLength,
541
550
  maxValue,
542
551
  minLength,
543
552
  minValue,
544
553
  noUpperCase,
554
+ ociRegistry,
545
555
  portNumber,
546
556
  registryUrl,
547
557
  required,
package/utils/window.js CHANGED
@@ -28,7 +28,7 @@ export class Popup {
28
28
  this.popup = null;
29
29
  }
30
30
 
31
- open(url, name, opt) {
31
+ open(url, name, opt, doNotPollForClosure) {
32
32
  this.onOpen();
33
33
  this.popup = open(url, name, opt);
34
34
 
@@ -36,11 +36,15 @@ export class Popup {
36
36
  throw new Error('Please disable your popup blocker for this site');
37
37
  }
38
38
 
39
- const timer = setInterval(() => {
40
- if (this.popup.closed) {
41
- clearInterval(timer);
42
- this.onClose();
43
- }
44
- }, 500);
39
+ // In some cases, for example, if the origin policy does not allow, we will think the window has closed
40
+ // when it has not - we will see it as closed, because we don't have access
41
+ if (!doNotPollForClosure) {
42
+ const timer = setInterval(() => {
43
+ if (this.popup.closed) {
44
+ clearInterval(timer);
45
+ this.onClose();
46
+ }
47
+ }, 500);
48
+ }
45
49
  }
46
50
  }
@@ -1,27 +0,0 @@
1
- import { mount } from '@vue/test-utils';
2
- import ApplicationCard from '@shell/components/cards/ApplicationCard.vue';
3
-
4
- describe('component: ApplicationCard', () => {
5
- const wrapper = mount(ApplicationCard, {
6
- slots: {
7
- cardIcon: '<i class="icon icon-fw icon-epinio"></i>',
8
- 'top-left': '<h1>Routes</h1> <ul><li> <a target="_blank" rel="noopener noreferrer nofollow"> route1 </a> </li> <li><a target="_blank" rel="noopener noreferrer nofollow"> route1 </a></li> </ul>',
9
- }
10
- });
11
-
12
- it.each([
13
- 'cardIcon',
14
- 'top-left',
15
- 'top-right',
16
- 'resourcesCount',
17
- ])('should have a populated %p slot', (slot) => {
18
- const content = '<div>text</div>';
19
- const ele = mount(ApplicationCard, { slots: { [slot]: content } });
20
-
21
- expect(ele.find(`[data-testid="${ slot }-section"`).find('div').html()).toContain(content);
22
- });
23
-
24
- it('should have card-icon slot with an icon', () => {
25
- expect(wrapper.find('[data-testid="cardIcon-section"]').find('i').classes()).toContain('icon-epinio');
26
- });
27
- });