@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
package/store/growl.js CHANGED
@@ -1,8 +1,11 @@
1
1
  import { clear, findBy, removeObject } from '@shell/utils/array';
2
2
  import { stringify } from '@shell/utils/error';
3
+ import { NotificationLevel } from '@shell/types/notifications';
3
4
 
4
5
  const DEFAULT_TIMEOUT = 5000;
5
6
 
7
+ const MAX_GROWLS = 5;
8
+
6
9
  export const state = function() {
7
10
  return {
8
11
  nextId: 1,
@@ -13,18 +16,28 @@ export const state = function() {
13
16
  export const getters = {
14
17
  find: (state) => ({ key, val }) => {
15
18
  return findBy(state.stack, key, val);
19
+ },
20
+
21
+ // findBy is slow, so more efficient getter for id
22
+ byId: (state) => (id) => {
23
+ return state.stack.find((item) => item.id === id);
16
24
  }
17
25
  };
18
26
 
19
27
  export const mutations = {
20
28
  add(state, data) {
29
+ if (state.stack.length === MAX_GROWLS) {
30
+ // Remove the last one
31
+ state.stack.pop();
32
+ }
33
+
21
34
  state.stack = [
22
- ...state.stack,
23
35
  {
24
36
  id: state.nextId++,
25
37
  started: (new Date().getTime()),
26
38
  ...data
27
- }
39
+ },
40
+ ...state.stack
28
41
  ];
29
42
  },
30
43
 
@@ -50,11 +63,29 @@ export const actions = {
50
63
  commit('remove', id);
51
64
  },
52
65
 
53
- success({ commit }, data) {
66
+ async close({ commit, dispatch, getters }, id ) {
67
+ const growl = getters.byId(id);
68
+
69
+ commit('remove', id);
70
+
71
+ // If the growl has a notification, mark it as read if the user dismisses the growl
72
+ if (growl.notification) {
73
+ await dispatch('notifications/markRead', growl.notification, { root: true });
74
+ }
75
+ },
76
+
77
+ async success({ commit, dispatch }, data) {
78
+ // Send a notification for the growl
79
+ const notification = await dispatch('notifications/fromGrowl', {
80
+ ...data,
81
+ level: NotificationLevel.Success
82
+ }, { root: true });
83
+
54
84
  commit('add', {
55
85
  color: 'success',
56
86
  icon: 'checkmark',
57
87
  timeout: DEFAULT_TIMEOUT,
88
+ notification,
58
89
  ...data
59
90
  });
60
91
  },
@@ -68,31 +99,89 @@ export const actions = {
68
99
  });
69
100
  },
70
101
 
71
- warning({ commit }, data) {
102
+ async warning({ commit, dispatch }, data) {
103
+ // Send a notification for the growl
104
+ const notification = await dispatch('notifications/fromGrowl', {
105
+ ...data,
106
+ level: NotificationLevel.Warning
107
+ }, { root: true });
108
+
72
109
  commit('add', {
73
110
  color: 'warning',
74
111
  icon: 'warning',
75
112
  timeout: DEFAULT_TIMEOUT,
113
+ notification,
76
114
  ...data
77
115
  });
78
116
  },
79
117
 
80
- error({ commit }, data) {
118
+ async error({ commit, dispatch }, data) {
119
+ // Send a notification for the growl
120
+ const notification = await dispatch('notifications/fromGrowl', {
121
+ ...data,
122
+ level: NotificationLevel.Error
123
+ }, { root: true });
124
+
81
125
  commit('add', {
82
126
  color: 'error',
83
127
  icon: 'error',
84
- timeout: 0, // Errors don't timeout
128
+ timeout: DEFAULT_TIMEOUT, // Errors timeout since they will be available as a notification
129
+ notification,
85
130
  ...data
86
131
  });
87
132
  },
88
133
 
89
- fromError({ commit }, { title, err }) {
134
+ async fromError({ commit, dispatch }, { title, err }) {
135
+ // Send a notification for the growl
136
+ const notification = await dispatch('notifications/fromGrowl', {
137
+ title,
138
+ message: stringify(err),
139
+ level: NotificationLevel.Error
140
+ }, { root: true });
141
+
90
142
  commit('add', {
91
143
  color: 'error',
92
144
  icon: 'error',
93
- timeout: 0, // Errors don't timeout
145
+ timeout: DEFAULT_TIMEOUT, // Errors timeout since they will be available as a notification
146
+ notification,
94
147
  title,
95
148
  message: stringify(err),
96
149
  });
150
+ },
151
+
152
+ /**
153
+ * Used to create a growl when a notification is sent
154
+ *
155
+ * Growls are only shown for Success, Warning and Error notifications
156
+ */
157
+ notification({ commit }, notification) {
158
+ const growl = {
159
+ title: notification.title,
160
+ message: notification.message,
161
+ notification: notification.id,
162
+ timeout: DEFAULT_TIMEOUT,
163
+ };
164
+
165
+ switch (notification.level) {
166
+ case NotificationLevel.Success:
167
+ growl.color = 'success';
168
+ growl.icon = 'checkmark';
169
+ break;
170
+ case NotificationLevel.Warning:
171
+ growl.color = 'warning';
172
+ growl.icon = 'warning';
173
+ break;
174
+ case NotificationLevel.Error:
175
+ growl.color = 'error';
176
+ growl.icon = 'error';
177
+ break;
178
+ default:
179
+ growl.skip = true;
180
+ }
181
+
182
+ // We don't show growls for info, announcement, task
183
+ if (!growl.skip) {
184
+ commit('add', growl);
185
+ }
97
186
  }
98
187
  };
package/store/index.js CHANGED
@@ -39,6 +39,7 @@ import { STORE, BLANK_CLUSTER } from '@shell/store/store-types';
39
39
  import { isDevBuild } from '@shell/utils/version';
40
40
  import { markRaw } from 'vue';
41
41
  import paginationUtils from '@shell/utils/pagination-utils';
42
+ import { addReleaseNotesNotification } from '@shell/utils/release-notes';
42
43
 
43
44
  // Disables strict mode for all store instances to prevent warning about changing state outside of mutations
44
45
  // because it's more efficient to do that sometimes.
@@ -896,6 +897,11 @@ export const actions = {
896
897
  setBrand(brand);
897
898
  }
898
899
 
900
+ // Add the notification for the release notes
901
+ if (isRancher) {
902
+ await addReleaseNotesNotification(dispatch, getters);
903
+ }
904
+
899
905
  if (systemNamespaces) {
900
906
  const namespace = (systemNamespaces.value || systemNamespaces.default)?.split(',');
901
907
 
@@ -0,0 +1,426 @@
1
+ import { md5 } from '@shell/utils/crypto';
2
+ import { randomStr } from '@shell/utils/string';
3
+ import { EncryptedNotification, Notification, StoredNotification } from '@shell/types/notifications';
4
+ import { encrypt, decrypt, deriveKey } from '@shell/utils/crypto/encryption';
5
+
6
+ /**
7
+ * Key used to store notifications in the browser's local storage
8
+ */
9
+ const LOCAL_STORAGE_KEY_PREFIX = 'rancher-notifications-';
10
+
11
+ /**
12
+ * Expire notifications in seconds (14 days)
13
+ */
14
+ const EXPIRY = 14 * 24 * 60 * 60;
15
+
16
+ /**
17
+ * Maximum number of notifications that will be kept
18
+ */
19
+ const MAX_NOTIFICATIONS = 50;
20
+
21
+ /**
22
+ * Broadcast channel name to send changes across tabs
23
+ */
24
+ const NOTIFICATION_CHANNEL_NAME = 'rancher-notification-sync';
25
+
26
+ /**
27
+ * Store for the UI Notification Centre
28
+ */
29
+ interface NotificationsStore {
30
+ localStorageKey: string,
31
+ userId: string;
32
+ notifications: StoredNotification[],
33
+ encryptionKey: CryptoKey | undefined,
34
+ }
35
+
36
+ export const state = function(): NotificationsStore {
37
+ const notifications: StoredNotification[] = [];
38
+
39
+ return {
40
+ localStorageKey: '',
41
+ userId: '',
42
+ encryptionKey: undefined,
43
+ notifications,
44
+ };
45
+ };
46
+
47
+ let bc: BroadcastChannel;
48
+
49
+ /**
50
+ * Sync notifications to other tabs using the broadcast channel. Send the user id, to cover corner case
51
+ * where a stale login exists for a different user in another tab.
52
+ */
53
+ function sync(userId: string, operation: string, param?: any) {
54
+ bc?.postMessage({
55
+ userId,
56
+ operation,
57
+ param
58
+ });
59
+ }
60
+
61
+ async function saveEncryptedNotification(getters: any, notification: Notification) {
62
+ const toEncrypt: EncryptedNotification = {
63
+ title: notification.title,
64
+ message: notification.message,
65
+ level: notification.level,
66
+ primaryAction: notification.primaryAction,
67
+ secondaryAction: notification.secondaryAction,
68
+ };
69
+
70
+ const localStorageKey = getters['localStorageKey'];
71
+ const encryptionKey = getters['encryptionKey'];
72
+
73
+ try {
74
+ const data = JSON.stringify(toEncrypt);
75
+ const enc = await encrypt(data, encryptionKey);
76
+
77
+ window.localStorage.setItem(`${ localStorageKey }-${ notification.id }`, JSON.stringify(enc));
78
+ } catch (e) {
79
+ console.error('Unable to save notification to local storage', e); // eslint-disable-line no-console
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Sync the notifications index to local storage.
85
+ *
86
+ * We only store the non-sensitive data about the notifications in the index - the other data is stored in individual entries which are encrypted.
87
+ */
88
+ function syncIndex(state: NotificationsStore) {
89
+ const localStorageKey = state.localStorageKey;
90
+
91
+ // We just want the id, created, read and progress properties for the index
92
+ const index = state.notifications.map((n) => ({
93
+ id: n.id,
94
+ created: n.created,
95
+ read: n.read,
96
+ progress: n.progress,
97
+ }));
98
+
99
+ try {
100
+ window.localStorage.setItem(localStorageKey, JSON.stringify(index));
101
+ } catch (e) {
102
+ console.error('Unable to save notifications index to local storage', e); // eslint-disable-line no-console
103
+ }
104
+ }
105
+
106
+ export const getters = {
107
+ all: (state: NotificationsStore) => {
108
+ return state.notifications;
109
+ },
110
+
111
+ item: (state: NotificationsStore) => {
112
+ return (id: string) => {
113
+ return state.notifications.find((i) => i.id === id);
114
+ };
115
+ },
116
+
117
+ // Count of unread notifications
118
+ unreadCount: (state: NotificationsStore) => {
119
+ return state.notifications.filter((n) => !n.read).length;
120
+ },
121
+
122
+ /**
123
+ * Local storage key includes the user key
124
+ */
125
+ localStorageKey: (state: NotificationsStore) => {
126
+ return state.localStorageKey;
127
+ },
128
+
129
+ userId: (state: NotificationsStore) => {
130
+ return state.userId;
131
+ },
132
+
133
+ encryptionKey: (state: NotificationsStore) => {
134
+ return state.encryptionKey;
135
+ },
136
+ };
137
+
138
+ export const mutations = {
139
+ add(state: NotificationsStore, notification: Notification) {
140
+ if (!notification.id) {
141
+ notification.id = randomStr();
142
+ } else {
143
+ // Check that there is not already a notification with this id
144
+ const index = state.notifications.findIndex((n) => n.id === notification.id);
145
+
146
+ if (index !== -1) {
147
+ console.error(`Can not add a notification with the same id as an existing notification (${ notification.id })`); // eslint-disable-line no-console
148
+
149
+ return;
150
+ }
151
+ }
152
+
153
+ const stored = {
154
+ ...notification,
155
+ read: false,
156
+ created: new Date()
157
+ };
158
+
159
+ // Add to top of list
160
+ state.notifications.unshift(stored);
161
+
162
+ // Check that we have not exceeded the maximum number of notifications
163
+ if (state.notifications.length > MAX_NOTIFICATIONS) {
164
+ const removed = state.notifications.pop();
165
+
166
+ if (removed) {
167
+ // Remove the encrypted data for the notification that we just removed
168
+ window.localStorage.removeItem(`${ state.localStorageKey }-${ removed.id }`);
169
+ }
170
+ }
171
+
172
+ syncIndex(state);
173
+ },
174
+
175
+ markRead(state: NotificationsStore, id: string) {
176
+ const notification = state.notifications.find((n) => n.id === id);
177
+
178
+ if (notification && !notification.read) {
179
+ notification.read = true;
180
+ }
181
+
182
+ syncIndex(state);
183
+ },
184
+
185
+ markUnread(state: NotificationsStore, id: string) {
186
+ const notification = state.notifications.find((n) => n.id === id);
187
+
188
+ if (notification && notification.read) {
189
+ notification.read = false;
190
+ }
191
+
192
+ syncIndex(state);
193
+ },
194
+
195
+ markAllRead(state: NotificationsStore) {
196
+ state.notifications.forEach((notification) => {
197
+ if (!notification.read) {
198
+ notification.read = true;
199
+ }
200
+ });
201
+
202
+ syncIndex(state);
203
+ },
204
+
205
+ update(state: NotificationsStore, notification: Partial<Notification>) {
206
+ if (notification?.id) {
207
+ const index = state.notifications.findIndex((n) => n.id === notification.id);
208
+
209
+ if (index >= 0) {
210
+ state.notifications[index] = {
211
+ ...state.notifications[index],
212
+ ...notification
213
+ };
214
+ }
215
+ }
216
+
217
+ syncIndex(state);
218
+ },
219
+
220
+ clearAll(state: NotificationsStore) {
221
+ // Remove the encrypted data for each notification
222
+ state.notifications.forEach((n) => {
223
+ window.localStorage.removeItem(`${ state.localStorageKey }-${ n.id }`);
224
+ });
225
+
226
+ state.notifications = [];
227
+ syncIndex(state);
228
+ },
229
+
230
+ remove(state: NotificationsStore, id: string) {
231
+ // Remove the encrypted data for the notification
232
+ window.localStorage.removeItem(`${ state.localStorageKey }-${ id }`);
233
+
234
+ state.notifications = state.notifications.filter((n) => n.id !== id);
235
+ syncIndex(state);
236
+ },
237
+
238
+ load(state: NotificationsStore, notifications: StoredNotification[]) {
239
+ state.notifications = notifications;
240
+ },
241
+
242
+ localStorageKey(state: NotificationsStore, userKey: string) {
243
+ state.localStorageKey = `${ LOCAL_STORAGE_KEY_PREFIX }${ userKey }`;
244
+ },
245
+
246
+ userId(state: NotificationsStore, userId: string) {
247
+ state.userId = userId;
248
+ },
249
+
250
+ encryptionKey(state: NotificationsStore, encryptionKey: CryptoKey) {
251
+ state.encryptionKey = encryptionKey;
252
+ },
253
+ };
254
+
255
+ export const actions = {
256
+ async add( { commit, dispatch, getters }: any, notification: Notification) {
257
+ // We encrypt the notification on add - this is the only time we will encrypt it
258
+ if (!notification.id) {
259
+ notification.id = randomStr();
260
+ }
261
+
262
+ // Need to save the encrypted notification to local storage
263
+ await saveEncryptedNotification(getters, notification);
264
+
265
+ commit('add', notification);
266
+ sync(getters['userId'], 'add', notification);
267
+
268
+ // Show a growl for the notification if necessary
269
+ dispatch('growl/notification', notification, { root: true });
270
+ },
271
+
272
+ async fromGrowl( { commit, getters }: any, notification: Notification) {
273
+ notification.id = randomStr();
274
+
275
+ // Need to save the encrypted notification to local storage
276
+ await saveEncryptedNotification(getters, notification);
277
+
278
+ commit('add', notification);
279
+ sync(getters['userId'], 'add', notification);
280
+
281
+ return notification.id;
282
+ },
283
+
284
+ update({ commit, getters }: any, notification: Notification) {
285
+ commit('update', notification);
286
+ sync(getters['userId'], 'update', notification);
287
+ },
288
+
289
+ async markRead({ commit, dispatch, getters }: any, id: string) {
290
+ commit('markRead', id);
291
+ sync(getters['userId'], 'markRead', id);
292
+
293
+ const notification = getters.item(id);
294
+
295
+ if (notification?.preference) {
296
+ await dispatch('prefs/set', notification.preference, { root: true });
297
+ }
298
+ },
299
+
300
+ async markUnread({ commit, dispatch, getters }: any, id: string) {
301
+ commit('markUnread', id);
302
+ sync(getters['userId'], 'markUnread', id);
303
+
304
+ const notification = getters.item(id) as Notification;
305
+
306
+ if (notification?.preference) {
307
+ await dispatch('prefs/set', {
308
+ key: notification.preference.key,
309
+ value: notification.preference.unsetValue || '',
310
+ }, { root: true });
311
+ }
312
+ },
313
+
314
+ async markAllRead({ commit, dispatch, getters }: any) {
315
+ commit('markAllRead');
316
+ sync(getters['userId'], 'markAllRead');
317
+
318
+ // For all notifications that have a preference, set the preference, since they are now read
319
+ const withPreference = getters.all.filter((n: Notification) => !!n.preference);
320
+
321
+ for (let i = 0; i < withPreference.length; i++) {
322
+ await dispatch('prefs/set', withPreference[i].preference, { root: true });
323
+ }
324
+ },
325
+
326
+ remove({ commit, getters }: any, id: string) {
327
+ commit('remove', id);
328
+ sync(getters['userId'], 'remove', id);
329
+ },
330
+
331
+ clearAll({ commit, getters }: any) {
332
+ commit('clearAll');
333
+ sync(getters['userId'], 'clearAll');
334
+ },
335
+
336
+ /**
337
+ * Initialize the notifications store and load the notifications from local storage
338
+ */
339
+ async init({ commit, getters } : any, userData: any) {
340
+ const userKey = userData.id;
341
+ const userId = userData.v3User?.uuid;
342
+
343
+ if (!userKey || !userId) {
344
+ console.error('Unable to initialize notifications - required user info not available'); // eslint-disable-line no-console
345
+
346
+ return;
347
+ }
348
+
349
+ // Notifications are stored under a key for the current user, so set the local storage key based on the user id
350
+ commit('localStorageKey', md5(userKey, 'hex'));
351
+ commit('userId', userId);
352
+
353
+ let index: StoredNotification[] = [];
354
+ let notifications: StoredNotification[] = [];
355
+ const localStorageKey = getters['localStorageKey'];
356
+
357
+ let encryptionKey;
358
+
359
+ try {
360
+ encryptionKey = await deriveKey(userId);
361
+ } catch (e) {
362
+ console.error('Unable to generate encryption key for notifications', e); // eslint-disable-line no-console
363
+
364
+ return;
365
+ }
366
+
367
+ // Store the encryption key
368
+ commit('encryptionKey', encryptionKey);
369
+
370
+ // Load the notifications from local storage
371
+ // We store the index of notifications in local storage, and the actual notification data is stored in individual entries which are encrypted
372
+ try {
373
+ const data = window.localStorage.getItem(localStorageKey) || '[]';
374
+
375
+ index = JSON.parse(data) as StoredNotification[];
376
+ } catch (e) {
377
+ console.error('Unable to read notifications from local storage', e); // eslint-disable-line no-console
378
+ }
379
+
380
+ for (let i = 0; i < index.length; i++) {
381
+ const n = index[i];
382
+
383
+ try {
384
+ const data = window.localStorage.getItem(`${ localStorageKey }-${ n.id }`);
385
+ const parsedData = data ? JSON.parse(data) : '{}';
386
+ const decryptedString = await decrypt(parsedData, encryptionKey);
387
+ const decrypted = JSON.parse(decryptedString) as EncryptedNotification;
388
+
389
+ // Overlay the decrypted data onto the notification
390
+ notifications.push({
391
+ ...n,
392
+ ...decrypted
393
+ });
394
+ } catch (e) {
395
+ console.error('Unable to decrypt notification data', e); // eslint-disable-line no-console
396
+ }
397
+ }
398
+
399
+ // Expire old notifications
400
+ const now = new Date();
401
+
402
+ notifications = notifications.filter((n: StoredNotification) => {
403
+ // Try ... catch in case the date parsing fails
404
+ try {
405
+ const created = new Date(n.created);
406
+ const diff = (now.getTime() - created.getTime()) / 1000; // Diff in seconds
407
+
408
+ return diff < EXPIRY;
409
+ } catch (e) {}
410
+
411
+ return true;
412
+ });
413
+
414
+ commit('load', notifications);
415
+
416
+ // Set up broadcast listener to listen for updates from other tabs
417
+ bc = new BroadcastChannel(NOTIFICATION_CHANNEL_NAME);
418
+
419
+ bc.onmessage = (msgEvent: any) => {
420
+ // Ignore events where the user id does not match (corner case of stale login in another tab)
421
+ if (msgEvent?.data?.operation && msgEvent?.data?.userId === userId) {
422
+ commit(msgEvent.data.operation, msgEvent.data.param);
423
+ }
424
+ };
425
+ }
426
+ };
package/store/prefs.js CHANGED
@@ -74,7 +74,6 @@ export const HIDE_REPOS = create('hide-repos', [], { parseJSON });
74
74
  export const HIDE_DESC = create('hide-desc', [], { parseJSON });
75
75
  export const HIDE_SENSITIVE = create('hide-sensitive', true, { options: [true, false], parseJSON });
76
76
  export const SHOW_PRE_RELEASE = create('show-pre-release', false, { options: [false, true], parseJSON });
77
- export const SHOW_CHART_MODE = create('chart-mode', 'featured', { parseJSON });
78
77
 
79
78
  export const DATE_FORMAT = create('date-format', 'ddd, MMM D YYYY', {
80
79
  options: [
package/store/type-map.js CHANGED
@@ -512,21 +512,22 @@ export const getters = {
512
512
 
513
513
  optionsFor(state, getters, rootState, rootGetters) {
514
514
  const def = {
515
- isCreatable: true,
516
- isEditable: true,
517
- isRemovable: true,
518
- showState: true,
519
- showAge: true,
520
- canYaml: true,
521
- namespaced: null,
522
- listGroups: [],
523
- listGroupsWillOverride: false,
524
- listMandatorySort: null,
525
- depaginate: false,
526
- customRoute: undefined,
527
- resourceEditMasthead: true,
528
- custom: {},
529
- subTypes: [],
515
+ listCreateButtonLabelKey: undefined,
516
+ isCreatable: true,
517
+ isEditable: true,
518
+ isRemovable: true,
519
+ showState: true,
520
+ showAge: true,
521
+ canYaml: true,
522
+ namespaced: null,
523
+ listGroups: [],
524
+ listGroupsWillOverride: false,
525
+ listMandatorySort: null,
526
+ depaginate: false,
527
+ customRoute: undefined,
528
+ resourceEditMasthead: true,
529
+ custom: {},
530
+ subTypes: [],
530
531
  };
531
532
 
532
533
  return (schemaOrType, pagination) => {
@@ -754,11 +755,13 @@ export const getters = {
754
755
  let group = findBy(tree.children, 'name', name);
755
756
 
756
757
  if ( !group ) {
758
+ const groupDefaultTypeFor = getters.groupDefaultTypeFor(name);
759
+
757
760
  group = {
758
761
  name,
759
762
  label,
760
763
  weight: getters.groupWeightFor(name, forBasic),
761
- defaultType: getters.groupDefaultTypeFor(name),
764
+ defaultType: typeof groupDefaultTypeFor === 'function' ? groupDefaultTypeFor() : groupDefaultTypeFor,
762
765
  };
763
766
 
764
767
  tree.children.push(group);