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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/key.svg +17 -0
  3. package/assets/styles/base/_spacing.scss +2 -2
  4. package/assets/styles/base/_variables.scss +17 -11
  5. package/assets/styles/global/_form.scss +1 -1
  6. package/assets/styles/global/_labeled-input.scss +1 -1
  7. package/assets/styles/themes/_dark.scss +5 -0
  8. package/assets/styles/themes/_light.scss +11 -2
  9. package/assets/styles/vendor/vue-select.scss +1 -1
  10. package/assets/translations/en-us.yaml +426 -64
  11. package/assets/translations/zh-hans.yaml +3 -4
  12. package/cloud-credential/gcp.vue +9 -1
  13. package/components/AppModal.vue +2 -0
  14. package/components/CodeMirror.vue +2 -2
  15. package/components/ConfigMapSettings/Settings.vue +377 -0
  16. package/components/ConfigMapSettings/index.vue +354 -0
  17. package/components/CruResource.vue +1 -2
  18. package/components/DetailText.vue +61 -11
  19. package/components/Drawer/Chrome.vue +115 -0
  20. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  21. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  22. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  23. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  24. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +106 -0
  25. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  26. package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
  27. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  28. package/components/Drawer/ResourceDetailDrawer/index.vue +111 -0
  29. package/components/GrowlManager.vue +16 -15
  30. package/components/IconOrSvg.vue +5 -0
  31. package/components/KeyValueView.vue +1 -1
  32. package/components/Loading.vue +1 -1
  33. package/components/LocaleSelector.vue +9 -1
  34. package/components/PaginatedResourceTable.vue +46 -1
  35. package/components/ProgressBarMulti.vue +1 -0
  36. package/components/PromptModal.vue +6 -1
  37. package/components/PromptRestore.vue +22 -44
  38. package/components/RelatedResources.vue +4 -12
  39. package/components/Resource/Detail/Additional.vue +46 -0
  40. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  41. package/components/Resource/Detail/Metadata/Annotations/index.vue +5 -0
  42. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  43. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +47 -256
  44. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
  45. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +34 -5
  46. package/components/Resource/Detail/Metadata/KeyValue.vue +32 -22
  47. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -1
  48. package/components/Resource/Detail/Metadata/Labels/index.vue +4 -0
  49. package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
  50. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +1 -1
  51. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +1 -1
  52. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  53. package/components/Resource/Detail/Metadata/composables.ts +60 -11
  54. package/components/Resource/Detail/Metadata/index.vue +12 -5
  55. package/components/Resource/Detail/Page.vue +15 -0
  56. package/components/Resource/Detail/ResourceRow.vue +37 -18
  57. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  58. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  59. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  60. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  61. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  62. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  63. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  64. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  65. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  66. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  67. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  68. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  69. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  70. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  71. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  72. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  73. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  74. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  75. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  76. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  77. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  78. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  79. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  80. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  81. package/components/Resource/Detail/SpacedRow.vue +1 -1
  82. package/components/Resource/Detail/TitleBar/Title.vue +2 -1
  83. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +1 -1
  84. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +1 -1
  85. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  86. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  87. package/components/Resource/Detail/TitleBar/composables.ts +45 -0
  88. package/components/Resource/Detail/TitleBar/index.vue +85 -13
  89. package/components/Resource/Detail/composables.ts +45 -0
  90. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  91. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  92. package/components/ResourceDetail/Masthead/index.vue +65 -0
  93. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  94. package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +1 -1
  95. package/components/ResourceDetail/__tests__/index.test.ts +26 -5
  96. package/components/ResourceDetail/index.vue +33 -17
  97. package/components/ResourceDetail/legacy.vue +18 -1
  98. package/components/ResourceList/Masthead.vue +6 -0
  99. package/components/ResourceList/index.vue +1 -0
  100. package/components/ResourceTable.vue +6 -1
  101. package/components/ResourceYaml.vue +15 -2
  102. package/components/RichTranslation.vue +106 -0
  103. package/components/SlideInPanelManager.vue +46 -11
  104. package/components/SortableTable/index.vue +1 -1
  105. package/components/SortableTable/selection.js +0 -1
  106. package/components/StateDot/index.vue +28 -0
  107. package/components/Tabbed/index.vue +17 -16
  108. package/components/Wizard.vue +4 -2
  109. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  110. package/components/__tests__/GrowlManager.test.ts +0 -25
  111. package/components/__tests__/PromptRestore.test.ts +1 -65
  112. package/components/__tests__/RichTranslation.test.ts +115 -0
  113. package/components/auth/login/ldap.vue +1 -1
  114. package/components/fleet/FleetApplications.vue +0 -7
  115. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  116. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  117. package/components/fleet/FleetClusters.vue +25 -6
  118. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  119. package/components/fleet/FleetHelmOps.vue +8 -0
  120. package/components/fleet/FleetRepos.vue +1 -6
  121. package/components/fleet/FleetResources.vue +4 -5
  122. package/components/fleet/FleetValuesFrom.vue +295 -0
  123. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  124. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  125. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +13 -13
  126. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  127. package/components/fleet/dashboard/ResourceCard.vue +1 -0
  128. package/components/fleet/dashboard/ResourceCardSummary.vue +1 -5
  129. package/components/fleet/dashboard/ResourceDetails.vue +8 -10
  130. package/components/fleet/dashboard/ResourcePanel.vue +17 -9
  131. package/components/form/ArrayList.vue +13 -2
  132. package/components/form/ChangePassword.vue +3 -1
  133. package/components/form/FileImageSelector.vue +1 -1
  134. package/components/form/Footer.vue +10 -4
  135. package/components/form/KeyValue.vue +81 -43
  136. package/components/form/LabeledSelect.vue +56 -16
  137. package/components/form/Labels.vue +90 -17
  138. package/components/form/MatchExpressions.vue +46 -5
  139. package/components/form/NameNsDescription.vue +2 -1
  140. package/components/form/Networking.vue +24 -19
  141. package/components/form/ResourceLabeledSelect.vue +4 -3
  142. package/components/form/ResourceSelector.vue +1 -0
  143. package/components/form/ResourceTabs/index.vue +5 -0
  144. package/components/form/SecretSelector.vue +9 -2
  145. package/components/form/Select.vue +57 -19
  146. package/components/form/SelectOrCreateAuthSecret.vue +6 -3
  147. package/components/form/SimpleSecretSelector.vue +9 -2
  148. package/components/form/Taints.vue +21 -2
  149. package/components/form/UnitInput.vue +8 -0
  150. package/components/form/ValueFromResource.vue +1 -1
  151. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  152. package/components/form/__tests__/Labels.test.ts +360 -0
  153. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  154. package/components/form/__tests__/Networking.test.ts +116 -0
  155. package/components/form/__tests__/Select.test.ts +5 -2
  156. package/components/formatter/FleetApplicationSource.vue +1 -1
  157. package/components/formatter/PodImages.vue +1 -1
  158. package/components/formatter/WorkloadHealthScale.vue +1 -1
  159. package/components/formatter/__tests__/LiveDate.test.ts +10 -2
  160. package/components/google/AccountAccess.vue +209 -0
  161. package/components/google/types/gcp.d.ts +136 -0
  162. package/components/google/types/index.d.ts +101 -0
  163. package/components/google/util/__mocks__/gcp.ts +465 -0
  164. package/components/google/util/formatter.ts +82 -0
  165. package/components/google/util/gcp.ts +134 -0
  166. package/components/google/util/index.d.ts +11 -0
  167. package/components/nav/Favorite.vue +1 -1
  168. package/components/nav/Group.vue +71 -45
  169. package/components/nav/Header.vue +5 -1
  170. package/components/nav/NamespaceFilter.vue +13 -1
  171. package/components/nav/NotificationCenter/Notification.vue +510 -0
  172. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  173. package/components/nav/NotificationCenter/index.vue +148 -0
  174. package/composables/drawer.ts +26 -0
  175. package/composables/resources.test.ts +63 -0
  176. package/composables/resources.ts +38 -0
  177. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  178. package/config/labels-annotations.js +8 -0
  179. package/config/pagination-table-headers.js +8 -1
  180. package/config/product/auth.js +16 -1
  181. package/config/product/{cis.js → compliance.js} +23 -26
  182. package/config/product/explorer.js +32 -3
  183. package/config/product/fleet.js +7 -0
  184. package/config/product/manager.js +0 -1
  185. package/config/product/settings.js +22 -11
  186. package/config/query-params.js +13 -0
  187. package/config/roles.ts +1 -1
  188. package/config/router/navigation-guards/authentication.js +51 -2
  189. package/config/router/routes.js +47 -31
  190. package/config/settings.ts +21 -3
  191. package/config/store.js +2 -0
  192. package/config/system-namespaces.js +1 -1
  193. package/config/table-headers.js +32 -3
  194. package/config/types.js +16 -7
  195. package/config/version.js +1 -1
  196. package/core/plugin.ts +32 -7
  197. package/core/types.ts +18 -1
  198. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  199. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  200. package/detail/management.cattle.io.oidcclient.vue +369 -0
  201. package/detail/node.vue +2 -2
  202. package/detail/pod.vue +2 -2
  203. package/detail/provisioning.cattle.io.cluster.vue +3 -47
  204. package/detail/service.vue +10 -1
  205. package/detail/workload/index.vue +8 -2
  206. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  207. package/dialog/GenericPrompt.vue +1 -1
  208. package/dialog/ImportDialog.vue +8 -8
  209. package/dialog/OidcClientSecretDialog.vue +117 -0
  210. package/dialog/RotateEncryptionKeyDialog.vue +10 -30
  211. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  212. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +5 -2
  213. package/edit/auth/ldap/__tests__/config.test.ts +14 -0
  214. package/edit/auth/ldap/config.vue +24 -0
  215. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  216. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  217. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  218. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  219. package/edit/configmap.vue +8 -2
  220. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  221. package/edit/fleet.cattle.io.gitrepo.vue +44 -222
  222. package/edit/fleet.cattle.io.helmop.vue +44 -269
  223. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  224. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  225. package/edit/logging-flow/index.vue +1 -0
  226. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  227. package/edit/management.cattle.io.fleetworkspace.vue +1 -0
  228. package/edit/management.cattle.io.oidcclient.vue +162 -0
  229. package/edit/management.cattle.io.project.vue +4 -1
  230. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  231. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  232. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  233. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  234. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  235. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  236. package/edit/monitoring.coreos.com.route.vue +1 -0
  237. package/edit/namespace.vue +1 -0
  238. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  239. package/edit/networking.k8s.io.ingress/Certificate.vue +12 -12
  240. package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
  241. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  242. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  243. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  244. package/edit/node.vue +1 -0
  245. package/edit/persistentvolume/index.vue +4 -1
  246. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
  247. package/edit/provisioning.cattle.io.cluster/rke2.vue +516 -426
  248. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
  249. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  250. package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
  251. package/edit/resources.cattle.io.restore.vue +1 -1
  252. package/edit/secret/basic.vue +1 -0
  253. package/edit/secret/index.vue +127 -15
  254. package/edit/service.vue +4 -1
  255. package/edit/serviceaccount.vue +4 -1
  256. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  257. package/edit/workload/index.vue +5 -0
  258. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  259. package/list/management.cattle.io.oidcclient.vue +108 -0
  260. package/list/node.vue +2 -0
  261. package/list/projectsecret.vue +345 -0
  262. package/list/secret.vue +109 -0
  263. package/machine-config/amazonec2.vue +3 -24
  264. package/machine-config/components/GCEImage.vue +374 -0
  265. package/machine-config/google.vue +617 -0
  266. package/mixins/__tests__/brand.spec.ts +170 -0
  267. package/mixins/brand.js +16 -17
  268. package/mixins/create-edit-view/impl.js +10 -1
  269. package/mixins/create-edit-view/index.js +5 -0
  270. package/mixins/resource-fetch-api-pagination.js +24 -8
  271. package/mixins/resource-fetch.js +3 -1
  272. package/mixins/vue-select-overrides.js +1 -0
  273. package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
  274. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  275. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  276. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  277. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  278. package/models/fleet-application.js +8 -79
  279. package/models/fleet.cattle.io.cluster.js +13 -2
  280. package/models/fleet.cattle.io.gitrepo.js +2 -2
  281. package/models/fleet.cattle.io.helmop.js +9 -39
  282. package/models/management.cattle.io.fleetworkspace.js +2 -1
  283. package/models/management.cattle.io.oidcclient.js +18 -0
  284. package/models/management.cattle.io.registration.js +3 -0
  285. package/models/provisioning.cattle.io.cluster.js +29 -33
  286. package/models/secret.js +157 -2
  287. package/models/service.js +4 -0
  288. package/models/workload.js +5 -0
  289. package/package.json +2 -2
  290. package/pages/about.vue +4 -58
  291. package/pages/auth/login.vue +1 -1
  292. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +0 -1
  293. package/pages/c/_cluster/apps/charts/index.vue +296 -81
  294. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  295. package/pages/c/_cluster/explorer/index.vue +3 -3
  296. package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
  297. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  298. package/pages/c/_cluster/fleet/application/create.vue +3 -2
  299. package/pages/c/_cluster/fleet/index.vue +94 -57
  300. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  301. package/pages/c/_cluster/longhorn/index.vue +5 -2
  302. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  303. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  304. package/pages/explorer/resource/detail/configmap.vue +30 -7
  305. package/pages/explorer/resource/detail/projectsecret.vue +9 -0
  306. package/pages/explorer/resource/detail/secret.vue +63 -0
  307. package/pages/home.vue +9 -55
  308. package/pages/support/index.vue +4 -6
  309. package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
  310. package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
  311. package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
  312. package/plugins/dashboard-store/actions.js +19 -5
  313. package/plugins/dashboard-store/getters.js +4 -0
  314. package/plugins/dashboard-store/normalize.js +29 -17
  315. package/plugins/dashboard-store/resource-class.js +68 -19
  316. package/plugins/steve/steve-pagination-utils.ts +38 -19
  317. package/plugins/steve/subscribe.js +6 -1
  318. package/rancher-components/Banner/Banner.vue +13 -0
  319. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -4
  320. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  321. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  322. package/rancher-components/RcItemCard/RcItemCard.vue +8 -3
  323. package/store/auth.js +2 -0
  324. package/store/catalog.js +23 -1
  325. package/store/growl.js +97 -8
  326. package/store/index.js +6 -0
  327. package/store/notifications.ts +426 -0
  328. package/store/prefs.js +0 -1
  329. package/store/type-map.js +19 -16
  330. package/store/uiplugins.ts +15 -1
  331. package/types/fleet.d.ts +24 -0
  332. package/types/kube/kube-api.ts +12 -0
  333. package/types/notifications/index.ts +74 -0
  334. package/types/shell/index.d.ts +661 -589
  335. package/types/store/dashboard-store.types.ts +16 -0
  336. package/types/store/pagination.types.ts +16 -6
  337. package/utils/__tests__/create-yaml.test.ts +235 -0
  338. package/utils/__tests__/fleet.test.ts +148 -0
  339. package/utils/__tests__/object.test.ts +54 -1
  340. package/utils/__tests__/string.test.ts +273 -1
  341. package/utils/__tests__/time.test.ts +31 -0
  342. package/utils/auth.js +9 -2
  343. package/utils/create-yaml.js +103 -9
  344. package/utils/crypto/encryption.ts +103 -0
  345. package/utils/cspAdaptor.ts +51 -0
  346. package/utils/fleet.ts +54 -65
  347. package/utils/object.js +36 -0
  348. package/utils/pagination-utils.ts +19 -1
  349. package/utils/release-notes.ts +48 -0
  350. package/utils/selector-typed.ts +7 -2
  351. package/utils/string.js +24 -0
  352. package/utils/{time.js → time.ts} +25 -6
  353. package/utils/uiplugins.ts +22 -0
  354. package/utils/validators/formRules/index.ts +3 -0
  355. package/components/Resource/Detail/TitleBar/composable.ts +0 -31
  356. package/config/product/legacy.js +0 -62
  357. package/models/etcdbackup.js +0 -45
  358. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  359. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  360. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  361. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
@@ -0,0 +1,510 @@
1
+ <script setup lang="ts">
2
+ import day from 'dayjs';
3
+ import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
4
+ import { escapeHtml } from '@shell/utils/string';
5
+ import { computed, inject, ref } from 'vue';
6
+ import { useStore } from 'vuex';
7
+ import { useRouter } from 'vue-router';
8
+ import { useI18n } from '@shell/composables/useI18n';
9
+ import { NotificationAction, NotificationLevel, StoredNotification } from '@shell/types/notifications';
10
+ import { DropdownContext, defaultContext } from '@components/RcDropdown/types';
11
+ import { useDropdownItem } from '@components/RcDropdown/useDropdownItem';
12
+
13
+ const CLASSES = {
14
+ [NotificationLevel.Announcement]: 'icon-notify-announcement text-info',
15
+ [NotificationLevel.Error]: 'icon-notify-error text-error',
16
+ [NotificationLevel.Info]: 'icon-notify-info text-info',
17
+ [NotificationLevel.Task]: 'icon-notify-busy text-info',
18
+ [NotificationLevel.Warning]: 'icon-notify-warning text-warning',
19
+ [NotificationLevel.Success]: 'icon-notify-tick text-success',
20
+ };
21
+
22
+ const emits = defineEmits(['didFocus']);
23
+
24
+ const props = defineProps<{item: StoredNotification}>();
25
+ const { dropdownItems } = inject<DropdownContext>('dropdownContext') || defaultContext;
26
+
27
+ const store = useStore();
28
+ const { t } = useI18n(store);
29
+ const router = useRouter();
30
+ const unreadCount = computed<number>(() => store.getters['notifications/unreadCount']);
31
+ const dateFormat = escapeHtml( store.getters['prefs/get'](DATE_FORMAT));
32
+ const timeFormat = escapeHtml( store.getters['prefs/get'](TIME_FORMAT));
33
+
34
+ const { close } = useDropdownItem();
35
+
36
+ // Outer element for the notification
37
+ const dropdownMenuItem = ref<HTMLElement>();
38
+
39
+ // Refs to the 3 buttons that can be in the notification
40
+ const readButton = ref<HTMLElement>();
41
+ const primaryActionButton = ref<HTMLElement>();
42
+ const secondaryActionButton = ref<HTMLElement>();
43
+
44
+ // These are the buttons in the notification that can be tabbed between when in the focus trap
45
+ const tabItems = computed(() => {
46
+ const items: HTMLElement[] = [];
47
+
48
+ if (readButton.value) {
49
+ items.push(readButton.value);
50
+ }
51
+
52
+ if (props.item.primaryAction && primaryActionButton.value) {
53
+ items.push(primaryActionButton.value);
54
+ }
55
+
56
+ if (props.item.secondaryAction && secondaryActionButton.value) {
57
+ items.push(secondaryActionButton.value);
58
+ }
59
+
60
+ return items;
61
+ });
62
+
63
+ // Ensure the aria label changes when read/unread is toggled
64
+ const toggleLabel = computed(() => {
65
+ return props.item.read ? t('notificationCenter.markRead') : t('notificationCenter.markUnread');
66
+ });
67
+
68
+ const age = computed(() => {
69
+ const created = day(props.item?.created);
70
+ const diff = created.diff(day(), 'day');
71
+ let date = created.format(dateFormat);
72
+
73
+ if (diff === 0 ) {
74
+ date = t('notificationCenter.dates.today');
75
+ } else if (diff === 1) {
76
+ date = t('notificationCenter.dates.yesterday');
77
+ }
78
+
79
+ return `${ date }, ${ created.format(timeFormat) }`;
80
+ });
81
+
82
+ const clz = computed(() => CLASSES[props.item.level]);
83
+
84
+ // Invoke action on either the primary or secondary buttons
85
+ // This can open a URL in a new tab OR navigate to an application route
86
+ const action = (action: NotificationAction) => {
87
+ if (action.target) {
88
+ window.open(action.target, '_blank');
89
+ } else if (action.route) {
90
+ try {
91
+ router.push(action.route);
92
+ } catch (e) {
93
+ console.error('Error navigating to route for the notification action', e); // eslint-disable-line no-console
94
+ }
95
+ close();
96
+ } else {
97
+ console.error('Notification action must either specify a "target" or a "route"'); // eslint-disable-line no-console
98
+ }
99
+ };
100
+
101
+ const toggleRead = (e: MouseEvent | KeyboardEvent, fromKeyboard = false) => {
102
+ if (props.item.read) {
103
+ store.dispatch('notifications/markUnread', props.item.id);
104
+ } else {
105
+ store.dispatch('notifications/markRead', props.item.id);
106
+ }
107
+
108
+ if (fromKeyboard) {
109
+ e.preventDefault();
110
+ e.stopPropagation();
111
+ }
112
+ };
113
+
114
+ // User presses enter or space on the notification, so enter the focus trap
115
+ const enterFocusTrap = (e: MouseEvent | KeyboardEvent) => {
116
+ const elementToFocus = tabItems.value[0];
117
+
118
+ elementToFocus.focus();
119
+
120
+ e.preventDefault();
121
+ e.stopPropagation();
122
+ };
123
+
124
+ // Inner focus next
125
+ // Move the tab between the buttons within the notification when it is in a focus trap
126
+ const innerFocusNext = (e: KeyboardEvent) => {
127
+ const index = tabItems.value.indexOf(e.target as HTMLElement);
128
+
129
+ // Sanity check - shouldn't happen
130
+ if (index < 0) {
131
+ return;
132
+ }
133
+
134
+ let nextIndex = e.shiftKey ? index - 1 : index + 1;
135
+
136
+ if (nextIndex < 0) {
137
+ nextIndex = tabItems.value.length - 1;
138
+ } else if (nextIndex === tabItems.value.length) {
139
+ nextIndex = 0;
140
+ }
141
+
142
+ const nextElement = tabItems.value[nextIndex] as HTMLElement;
143
+
144
+ nextElement.focus();
145
+
146
+ e.stopPropagation();
147
+ e.preventDefault();
148
+ };
149
+
150
+ // Exit inner focus - this is the state when the notification has a focus trap and you are tabbing between
151
+ // the controls in the notification - this function is typically called when the user presses ESCape
152
+ // and we want to exit this focus trap
153
+ const exitFocusTrap = (e: MouseEvent | KeyboardEvent) => {
154
+ // Return focus to the outer notification div
155
+ dropdownMenuItem.value?.focus();
156
+
157
+ e.stopPropagation();
158
+ e.preventDefault();
159
+ };
160
+
161
+ const gotFocus = () => {
162
+ const activeItem = document.activeElement;
163
+ const activeIndex = dropdownItems.value.indexOf(activeItem || new HTMLElement());
164
+
165
+ // Let the scroll container decide if it needs to adjust the scroll to show the item fully
166
+ emits('didFocus', activeIndex, dropdownItems.value.length);
167
+ };
168
+
169
+ const handleKeydown = (e: KeyboardEvent) => {
170
+ const activeItem = document.activeElement;
171
+ const activeIndex = dropdownItems.value.indexOf(activeItem || new HTMLElement());
172
+
173
+ if (activeIndex < 0) {
174
+ return;
175
+ }
176
+
177
+ const shouldAdvance = e.key === 'ArrowDown';
178
+ const newIndex = findNewIndex(shouldAdvance, activeIndex, dropdownItems.value);
179
+
180
+ if (dropdownItems.value[newIndex] instanceof HTMLElement) {
181
+ dropdownItems.value[newIndex].focus();
182
+ }
183
+ };
184
+
185
+ /**
186
+ * This allows the user to press up/down while in the focus trap for a notification and exit the focus trap and move to the next/previous notification
187
+ */
188
+ const handleKeydownFocusTrap = (e: KeyboardEvent) => {
189
+ exitFocusTrap(e);
190
+ handleKeydown(e);
191
+ };
192
+
193
+ /**
194
+ * Finds the new index for the dropdown item based on the key pressed.
195
+ * @param shouldAdvance - Whether to advance to the next or previous item.
196
+ * @param activeIndex - Current active index.
197
+ * @param itemsArr - Array of dropdown items.
198
+ * @returns The new index.
199
+ */
200
+ const findNewIndex = (shouldAdvance: boolean, activeIndex: number, itemsArr: Element[]) => {
201
+ const newIndex = shouldAdvance ? activeIndex + 1 : activeIndex - 1;
202
+
203
+ if (!shouldAdvance && activeIndex === 1 && unreadCount.value === 0) {
204
+ // Special case
205
+ // We are the top notification, there are no unread and the uses has pressed up
206
+ // We want to skip the notification header, as this won't have the 'Mark all as read' button
207
+ return itemsArr.length - 1;
208
+ }
209
+
210
+ if (newIndex > itemsArr.length - 1) {
211
+ return 0;
212
+ }
213
+
214
+ if (newIndex < 0) {
215
+ return itemsArr.length - 1;
216
+ }
217
+
218
+ return newIndex;
219
+ };
220
+
221
+ /**
222
+ * Ensure we scroll the item into view smoothly
223
+ * @param event FocusIn Event
224
+ */
225
+ const scrollIntoView = (event: Event) => {
226
+ const target = event.target;
227
+
228
+ if (target instanceof HTMLElement) {
229
+ const t = target as HTMLElement;
230
+
231
+ // If a button was clicked, then do not scroll into view, as this will scroll to make the button
232
+ // visible and the click will be ignored - so just return, so that the click works as expected
233
+ if (t.tagName === 'BUTTON') {
234
+ return;
235
+ }
236
+ }
237
+
238
+ if (target instanceof HTMLElement) {
239
+ target?.scrollIntoView({
240
+ behavior: 'smooth',
241
+ block: 'center',
242
+ inline: 'nearest',
243
+ });
244
+ }
245
+ };
246
+ </script>
247
+
248
+ <template>
249
+ <div
250
+ ref="dropdownMenuItem"
251
+ dropdown-menu-item
252
+ tabindex="-1"
253
+ role="menuitem"
254
+ data-testid="notifications-center-item"
255
+ :aria-label="t('notificationCenter.ariaLabel', { title: item.title })"
256
+ :class="{ 'notification-unread': !item.read }"
257
+ @keydown.up.down.stop.prevent="handleKeydown"
258
+ @focusin="scrollIntoView"
259
+ @focus.stop="gotFocus"
260
+ @click.stop
261
+ @keydown.enter.space.stop="enterFocusTrap"
262
+ >
263
+ <div
264
+ class="notification"
265
+ :data-testid="`notifications-center-item-${ item.id }`"
266
+ >
267
+ <div class="sep" />
268
+ <div class="top">
269
+ <div class="icon">
270
+ <i
271
+ class="icon"
272
+ :class="clz"
273
+ />
274
+ </div>
275
+ <div class="item-title">
276
+ {{ item.title }}
277
+ </div>
278
+ <button
279
+ ref="readButton"
280
+ v-clean-tooltip="item.read ? t('notificationCenter.markUnread') : t('notificationCenter.markRead')"
281
+ class="read-indicator"
282
+ role="button"
283
+ :aria-label="toggleLabel"
284
+ @keydown.enter.space.stop="toggleRead($event, true)"
285
+ @keydown.tab.stop="innerFocusNext($event)"
286
+ @keydown.escape.stop="exitFocusTrap"
287
+ @keydown.up.down.prevent.stop="handleKeydownFocusTrap"
288
+ @click.stop="toggleRead($event, false)"
289
+ >
290
+ <div>
291
+ <div
292
+ class="read-icon"
293
+ :class="{ 'unread': !item.read }"
294
+ />
295
+ </div>
296
+ </button>
297
+ </div>
298
+ <div class="bottom">
299
+ <div class="created text-muted">
300
+ {{ age }}
301
+ </div>
302
+ <div
303
+ v-if="item.message"
304
+ class="message"
305
+ >
306
+ {{ item.message }}
307
+ </div>
308
+ <div
309
+ v-if="item.level === NotificationLevel.Task && typeof item.progress === 'number'"
310
+ class="progress"
311
+ >
312
+ <div class="progress-bar">
313
+ <div class="pb-background" />
314
+ <div
315
+ :style="{width: `${item.progress}%`}"
316
+ class="pb-foreground"
317
+ />
318
+ </div>
319
+ <div class="progress-percent text-muted">
320
+ {{ item.progress }}%
321
+ </div>
322
+ </div>
323
+ <div
324
+ v-if="item.primaryAction || item.secondaryAction"
325
+ class="notification-actions"
326
+ >
327
+ <button
328
+ v-if="item.primaryAction"
329
+ ref="primaryActionButton"
330
+ role="button"
331
+ class="btn btn-sm role-primary"
332
+ @keydown.enter.space.stop="action(item.primaryAction)"
333
+ @keydown.tab.stop="innerFocusNext($event)"
334
+ @keydown.escape.stop="exitFocusTrap"
335
+ @click.stop.prevent="action(item.primaryAction)"
336
+ @keydown.up.down.prevent.stop="handleKeydownFocusTrap"
337
+ >
338
+ {{ item.primaryAction.label }}
339
+ </button>
340
+ <button
341
+ v-if="item.secondaryAction"
342
+ ref="secondaryActionButton"
343
+ role="button"
344
+ class="btn btn-sm role-secondary"
345
+ @keydown.enter.space.stop="action(item.secondaryAction)"
346
+ @keydown.tab.stop="innerFocusNext($event)"
347
+ @keydown.escape.stop="exitFocusTrap"
348
+ @click.stop.prevent="action(item.secondaryAction)"
349
+ @keydown.up.down.prevent.stop="handleKeydownFocusTrap"
350
+ >
351
+ {{ item.secondaryAction.label }}
352
+ </button>
353
+ </div>
354
+ </div>
355
+ </div>
356
+ </div>
357
+ </template>
358
+
359
+ <style lang="scss" scoped>
360
+ [dropdown-menu-item] {
361
+ display: flex;
362
+ gap: 8px;
363
+ align-items: center;
364
+ padding: 12px;
365
+ margin: 0 3px;
366
+
367
+ &.notification-unread {
368
+ background-color: var(--notification-unread-bg);
369
+ }
370
+
371
+ &:focus-visible, &:focus {
372
+ @include focus-outline;
373
+ outline-offset: 0;
374
+ }
375
+
376
+ .notification {
377
+ width: 400px;
378
+ display: flex;
379
+ flex-direction: column;
380
+
381
+ .top {
382
+ align-items: center;
383
+ display: flex;
384
+ padding: 0;
385
+
386
+ .icon {
387
+ display: flex;
388
+ text-align: center;
389
+ vertical-align: middle;
390
+ width: 32px;
391
+ }
392
+
393
+ .item-title {
394
+ flex: 1;
395
+ font-weight: 700;
396
+ white-space: nowrap;
397
+ overflow: hidden;
398
+ text-overflow: ellipsis;
399
+ }
400
+
401
+ button.read-indicator {
402
+ line-height: normal;
403
+ min-height: auto;
404
+ padding: 8px;
405
+ margin-left: 16px;
406
+ background-color: unset;
407
+ display: flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+
411
+ &:disabled {
412
+ cursor: default;
413
+ }
414
+
415
+ &:focus-visible {
416
+ @include focus-outline;
417
+ outline-offset: 2px;
418
+ }
419
+
420
+ .read-icon {
421
+ border: 2px solid var(--primary);
422
+ border-radius: 50%;
423
+ width: 8px;
424
+ height: 8px;
425
+
426
+ &.unread {
427
+ background-color: var(--primary);
428
+ }
429
+ }
430
+
431
+ // Add subtle effect when hovering over the unread button
432
+ &:hover .read-icon.unread {
433
+ opacity: 0.5;
434
+ }
435
+ }
436
+ }
437
+
438
+ .bottom {
439
+ margin-left: 32px; // 20px icon + 12px spacing
440
+
441
+ .created {
442
+ font-size: 13px;
443
+ }
444
+
445
+ .message {
446
+ line-height: 20px;
447
+ padding: 6px 0;
448
+ }
449
+
450
+ .progress {
451
+ display: flex;
452
+ margin-top: 6px;
453
+
454
+ .progress-bar {
455
+ align-items: center;
456
+ display: flex;
457
+ position: relative;
458
+ flex: 1;
459
+
460
+ .pb-foreground, .pb-background {
461
+ position: absolute;
462
+ height: 6px;
463
+ border-radius: 5px;
464
+ background-color: var(--primary);
465
+ transition: width 0.1s ease-in;
466
+ }
467
+
468
+ .pb-background {
469
+ opacity: 0.5;
470
+ width: 100%;
471
+ }
472
+ }
473
+
474
+ .progress-percent {
475
+ font-size: 13px;
476
+ margin-left: 16px;
477
+ min-width: 40px;
478
+ text-align: right;
479
+ }
480
+ }
481
+
482
+ .notification-actions {
483
+ display: flex;
484
+ margin-top: 12px;
485
+
486
+ > button:not(:first-child) {
487
+ margin-left: 12px;
488
+ }
489
+ }
490
+ }
491
+
492
+ .icon {
493
+ font-size: 20px;
494
+ width: 32px;
495
+ }
496
+
497
+ .content {
498
+ flex: 1;
499
+ display: flex;
500
+ flex-direction: column;
501
+ align-content: flex-start;
502
+
503
+ .item-title {
504
+ font-weight: bold;
505
+ margin-bottom: 4px;
506
+ }
507
+ }
508
+ }
509
+ }
510
+ </style>
@@ -0,0 +1,112 @@
1
+ <script setup lang="ts">
2
+ import { useStore } from 'vuex';
3
+ import { computed, inject, ref } from 'vue';
4
+ import { DropdownContext, defaultContext } from '@components/RcDropdown/types';
5
+
6
+ const { dropdownItems } = inject<DropdownContext>('dropdownContext') || defaultContext;
7
+ const store = useStore();
8
+ const unreadCount = computed<number>(() => store.getters['notifications/unreadCount']);
9
+ const markAllReadButton = ref<HTMLElement>();
10
+
11
+ const markAllRead = (keyboard: boolean) => {
12
+ store.dispatch('notifications/markAllRead');
13
+
14
+ // If we have focus, then move to the next item if activated by the keyboard
15
+ if (keyboard && document.activeElement === markAllReadButton?.value) {
16
+ moveFocus(true);
17
+ }
18
+ };
19
+
20
+ /**
21
+ * Handles keydown events to navigate between dropdown items.
22
+ * @param {KeyboardEvent} e - The keydown event.
23
+ */
24
+ const handleKeydown = (e: KeyboardEvent) => {
25
+ const shouldAdvance = e.key === 'ArrowDown';
26
+
27
+ moveFocus(shouldAdvance);
28
+ };
29
+
30
+ // User pressed up/down - move focus to the correct notification item
31
+ // Header should always be the first item
32
+ const moveFocus = (shouldAdvance: Boolean) => {
33
+ if (dropdownItems.value.length > 1) {
34
+ const newIndex = shouldAdvance ? 1 : dropdownItems.value.length - 1;
35
+
36
+ if (dropdownItems.value[newIndex] instanceof HTMLElement) {
37
+ dropdownItems.value[newIndex].focus();
38
+ }
39
+ }
40
+ };
41
+
42
+ const gotFocus = (e: Event) => {
43
+ // If no unread items, then there is no button to focus, so move to the next item
44
+ if (unreadCount.value === 0) {
45
+ moveFocus(true);
46
+ }
47
+
48
+ // When the header gets focus, pass the focus onto the 'mark all read' button
49
+ markAllReadButton?.value?.focus();
50
+ };
51
+ </script>
52
+
53
+ <template>
54
+ <div
55
+ dropdown-menu-item
56
+ tabindex="-1"
57
+ role="menuitem"
58
+ class="notification-header"
59
+ @click.stop
60
+ @keydown.up.down.stop.prevent="handleKeydown"
61
+ @focus="gotFocus"
62
+ >
63
+ <div class="notification-header">
64
+ <div class="notification-title">
65
+ {{ t('notificationCenter.title') }}
66
+ </div>
67
+ <div v-if="unreadCount !== 0">
68
+ <a
69
+ ref="markAllReadButton"
70
+ role="button"
71
+ tabindex="-1"
72
+ href="#"
73
+ data-testid="notifications-center-markall-read"
74
+ @keydown.up.down.stop.prevent="handleKeydown"
75
+ @keydown.enter.space.stop="markAllRead(true)"
76
+ @click="markAllRead(false)"
77
+ >
78
+ {{ t('notificationCenter.markAllRead') }}
79
+ </a>
80
+ </div>
81
+ </div>
82
+ <div class="notification-border" />
83
+ </div>
84
+ </template>
85
+
86
+ <style lang="scss" scoped>
87
+ [dropdown-menu-item] {
88
+ display: flex;
89
+ flex-direction: column;
90
+
91
+ .notification-border {
92
+ border-bottom: 1px solid var(--border);
93
+ margin-left: -16px;
94
+ width: calc(100% + 32px);
95
+ }
96
+
97
+ .notification-header {
98
+ display: flex;
99
+ flex: 1;
100
+ padding: 6px 16px 16px 16px; // already 10px at the top of the dropdown
101
+
102
+ .notification-title {
103
+ font-weight: bold;
104
+ flex: 1;
105
+ }
106
+
107
+ A {
108
+ color: var(--link);
109
+ }
110
+ }
111
+ }
112
+ </style>