@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/utils/fleet.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { isEmpty, isEqual } from 'lodash';
1
2
  import {
2
3
  BundleDeploymentResource,
3
4
  BundleResourceKey,
@@ -6,10 +7,10 @@ import {
6
7
  Condition,
7
8
  } from '@shell/types/resources/fleet';
8
9
  import { mapStateToEnum, STATES_ENUM, STATES } from '@shell/plugins/dashboard-store/resource-class';
9
- import { FLEET as FLEET_LABELS } from '@shell/config/labels-annotations';
10
+ import { FLEET as FLEET_LABELS, CAPI } from '@shell/config/labels-annotations';
10
11
  import { NAME as EXPLORER_NAME } from '@shell/config/product/explorer';
11
- import { FleetDashboardState, FleetResourceState } from '@shell/types/fleet';
12
- import { FLEET } from '@shell/config/types';
12
+ import { FleetDashboardState, FleetResourceState, Target, TargetMode } from '@shell/types/fleet';
13
+ import { FLEET, VIRTUAL_HARVESTER_PROVIDER } from '@shell/config/types';
13
14
 
14
15
  interface Resource extends BundleDeploymentResource {
15
16
  state: string,
@@ -19,17 +20,6 @@ type Labels = {
19
20
  [key: string]: string,
20
21
  }
21
22
 
22
- interface KeyRef {
23
- key: string;
24
- name: string;
25
- namespace?: string;
26
- }
27
-
28
- interface ValueFrom {
29
- configMapKeyRef?: KeyRef;
30
- secretKeyRef?: KeyRef;
31
- }
32
-
33
23
  function resourceKey(r: BundleResourceKey): string {
34
24
  return `${ r.kind }/${ r.namespace }/${ r.name }`;
35
25
  }
@@ -42,64 +32,63 @@ function conditionIsTrue(conditions: Condition[] | undefined, type: string): boo
42
32
  return !!conditions.find((c) => c.type === type && c.status.toLowerCase() === 'true');
43
33
  }
44
34
 
45
- class HelmOp {
46
- fromValuesFrom(data: ValueFrom[]): { valueFrom: ValueFrom }[] {
47
- return (data || []).map((elem) => {
48
- const out = {} as any;
35
+ class Application {
36
+ excludeHarvesterRule = {
37
+ clusterSelector: {
38
+ matchExpressions: [{
39
+ key: CAPI.PROVIDER,
40
+ operator: 'NotIn',
41
+ values: [
42
+ VIRTUAL_HARVESTER_PROVIDER
43
+ ],
44
+ }],
45
+ },
46
+ };
47
+
48
+ getTargetMode(targets: Target[], namespace: string): TargetMode {
49
+ if (namespace === 'fleet-local') {
50
+ return 'local';
51
+ }
49
52
 
50
- const cm = elem.configMapKeyRef;
53
+ if (!targets.length) {
54
+ return 'none';
55
+ }
51
56
 
52
- if (cm) {
53
- out.valueFrom = {
54
- configMapKeyRef: {
55
- key: cm.key || '',
56
- name: cm.name || '',
57
- }
58
- };
57
+ let mode: TargetMode = 'all';
58
+
59
+ for (const target of targets) {
60
+ const {
61
+ clusterName,
62
+ clusterSelector,
63
+ clusterGroup,
64
+ clusterGroupSelector,
65
+ } = target;
66
+
67
+ if (clusterGroup || clusterGroupSelector) {
68
+ return 'advanced';
59
69
  }
60
70
 
61
- const sc = elem.secretKeyRef;
71
+ if (clusterName) {
72
+ mode = 'clusters';
73
+ }
62
74
 
63
- if (sc) {
64
- out.valueFrom = {
65
- secretKeyRef: {
66
- key: sc.key || '',
67
- name: sc.name || '',
68
- }
69
- };
75
+ if (!isEmpty(clusterSelector)) {
76
+ mode = 'clusters';
70
77
  }
78
+ }
71
79
 
72
- return out;
80
+ const normalized = [...targets].map((target) => {
81
+ delete target.name;
82
+
83
+ return target;
73
84
  });
74
- }
75
85
 
76
- toValuesFrom(data: { valueFrom: ValueFrom }[], namespace: string): ValueFrom[] {
77
- return (data || [])
78
- .filter((f) => f.valueFrom?.configMapKeyRef || f.valueFrom?.secretKeyRef)
79
- .map(({ valueFrom }) => {
80
- const cm = valueFrom.configMapKeyRef;
81
- const sc = valueFrom.secretKeyRef;
82
-
83
- const out = {} as ValueFrom;
84
-
85
- if (cm?.name) {
86
- out.configMapKeyRef = {
87
- key: cm.key,
88
- name: cm.name,
89
- namespace
90
- };
91
- }
92
-
93
- if (sc?.name) {
94
- out.secretKeyRef = {
95
- key: sc.key,
96
- name: sc.name,
97
- namespace
98
- };
99
- }
100
-
101
- return out;
102
- });
86
+ // Check if targets contains only harvester rule after name normalizing
87
+ if (isEqual(normalized, [this.excludeHarvesterRule])) {
88
+ mode = 'all';
89
+ }
90
+
91
+ return mode;
103
92
  }
104
93
  }
105
94
 
@@ -142,14 +131,14 @@ class Fleet {
142
131
  {
143
132
  index: 3,
144
133
  id: 'info',
145
- label: 'InProgress',
134
+ label: 'Pending',
146
135
  color: '#3d98d3',
147
136
  icon: 'icon icon-warning',
148
137
  stateBackground: 'bg-info'
149
138
  },
150
139
  ];
151
140
 
152
- HelmOp = new HelmOp();
141
+ Application = new Application();
153
142
 
154
143
  GIT_HTTPS_REGEX = /^https?:\/\/github\.com\/(.*?)(\.git)?\/*$/;
155
144
  GIT_SSH_REGEX = /^git@github\.com:.*\.git$/;
package/utils/object.js CHANGED
@@ -527,3 +527,39 @@ export function mergeWithReplace(
527
527
  }
528
528
  });
529
529
  }
530
+ /**
531
+ * Converts Object into a string of a format "key1, val1, key2, val2"
532
+ * @param {Object} input - KV object to convert
533
+ * @returns string
534
+ */
535
+ export const convertKVToString = (input) => {
536
+ if (!input || typeof input !== 'object') return '';
537
+
538
+ return Object.entries(input)
539
+ .flatMap(([key, value]) => [key, String(value)])
540
+ .join(',');
541
+ };
542
+
543
+ /**
544
+ * Converts kv string into object
545
+ * @param {string} input - a string of a format "key1, val1, key2, val2"
546
+ * @returns
547
+ */
548
+ export const convertStringToKV = ( input ) => {
549
+ if (!input?.trim()) return {};
550
+
551
+ const parts = input.split(',').map((part) => part.trim());
552
+ const result = {};
553
+
554
+ for (let i = 0; i < parts.length - 1; i += 2) {
555
+ const key = parts[i];
556
+ const value = parts[i + 1];
557
+
558
+ // Accept empty keys but ignore undefined values
559
+ if (typeof key === 'string') {
560
+ result[key] = value ?? '';
561
+ }
562
+ }
563
+
564
+ return result;
565
+ };
@@ -15,6 +15,7 @@ import { isEqual } from '@shell/utils/object';
15
15
  import { STEVE_CACHE } from '@shell/store/features';
16
16
  import { getPerformanceSetting } from '@shell/utils/settings';
17
17
  import { PAGINATION_SETTINGS_STORE_DEFAULTS } from '@shell/plugins/steve/steve-pagination-utils';
18
+ import { MANAGEMENT } from '@shell/config/types';
18
19
 
19
20
  /**
20
21
  * Helper functions for server side pagination
@@ -23,7 +24,7 @@ class PaginationUtils {
23
24
  /**
24
25
  * In places where we're using paginated features but not in a page... this is what the max results should be
25
26
  */
26
- readonly defaultPageSize = 10000;
27
+ readonly defaultPageSize = 100000;
27
28
  /**
28
29
  * When a ns filter isn't one or more projects/namespaces... what are the valid values?
29
30
  *
@@ -54,6 +55,23 @@ class PaginationUtils {
54
55
  return rootGetters['features/get']?.(STEVE_CACHE);
55
56
  }
56
57
 
58
+ /**
59
+ * Determine if the downstream cluster has vai enabled
60
+ *
61
+ * Almost all the time the downstream cluster vai state will align with upstream (it manages it)
62
+ * ... unless it's harvester then weird things happen
63
+ */
64
+ async isDownstreamSteveCacheEnabled({ dispatch }: any, clusterId: string): Promise<boolean> {
65
+ const url = `/k8s/clusters/${ clusterId }/v1/${ MANAGEMENT.FEATURE }s/${ STEVE_CACHE }`;
66
+ const entry = await dispatch('cluster/request', { url });
67
+
68
+ if (entry.status.lockedValue !== null) {
69
+ return entry.status.lockedValue;
70
+ }
71
+
72
+ return (entry.spec.value !== null) ? entry.spec.value : entry.status.default;
73
+ }
74
+
57
75
  /**
58
76
  * Is pagination enabled at a global level or for a specific resource
59
77
  */
@@ -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/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
+ }
@@ -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
+ }
@@ -170,6 +170,8 @@ 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 genericUrl: Validator = (val: string) => val && !isUrl(val) ? t('validation.genericUrl') : undefined;
174
+
173
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;
@@ -542,6 +544,7 @@ export default function(
542
544
  localhost,
543
545
  trailingForwardSlash,
544
546
  url,
547
+ genericUrl,
545
548
  matching,
546
549
  maxLength,
547
550
  maxValue,
@@ -1,31 +0,0 @@
1
- import { TitleBarProps } from '@shell/components/Resource/Detail/TitleBar/index.vue';
2
- import { computed, Ref, toValue } from 'vue';
3
- import { useRoute } from 'vue-router';
4
- import { useStore } from 'vuex';
5
-
6
- export const useDefaultTitleBarData = (resource: any): Ref<TitleBarProps> => {
7
- const route = useRoute();
8
- const store = useStore();
9
-
10
- const resourceValue = toValue(resource);
11
-
12
- return computed(() => ({
13
- resourceTypeLabel: store.getters['type-map/labelFor']({ id: resourceValue.type }),
14
- resourceTo: {
15
- name: 'c-cluster-product-resource',
16
- params: {
17
- product: 'explorer',
18
- cluster: route.params.cluster,
19
- namespace: resourceValue.namespace,
20
- resource: resourceValue.type
21
- }
22
- },
23
- resourceName: resourceValue.nameDisplay,
24
- actionMenuResource: resourceValue,
25
- badge: {
26
- color: resourceValue.stateBackground,
27
- label: resourceValue.stateDisplay
28
- },
29
- onShowConfiguration: () => resourceValue.goToEdit()
30
- }));
31
- };
@@ -1,62 +0,0 @@
1
- import { LEGACY } from '@shell/store/features';
2
- import { DSL, IF_HAVE } from '@shell/store/type-map';
3
-
4
- export const NAME = 'legacy';
5
-
6
- export function init(store) {
7
- const {
8
- product,
9
- basicType,
10
- virtualType,
11
- setGroupDefaultType,
12
- } = DSL(store, NAME);
13
-
14
- product({
15
- weight: 80,
16
- ifFeature: LEGACY,
17
- showNamespaceFilter: true,
18
- });
19
-
20
- virtualType({
21
- ifHave: IF_HAVE.NO_PROJECT,
22
- labelKey: 'legacy.project.label',
23
- namespaced: true,
24
- name: 'v1-project-overview',
25
- weight: 105,
26
- route: { name: 'c-cluster-legacy-project' },
27
- exact: true,
28
- overview: false,
29
- });
30
-
31
- basicType(['v1-project-overview']);
32
-
33
- // Project Pages
34
-
35
- virtualType({
36
- ifHave: IF_HAVE.PROJECT,
37
- labelKey: 'legacy.secrets',
38
- namespaced: true,
39
- name: 'project-secrets',
40
- weight: 104,
41
- route: { name: 'c-cluster-legacy-project-page', params: { page: 'secrets' } },
42
- exact: true,
43
- overview: false,
44
- });
45
-
46
- virtualType({
47
- ifHave: IF_HAVE.PROJECT,
48
- labelKey: 'legacy.configMaps',
49
- namespaced: true,
50
- name: 'project-config-maps',
51
- weight: 104,
52
- route: { name: 'c-cluster-legacy-project-page', params: { page: 'config-maps' } },
53
- exact: true,
54
- overview: false,
55
- });
56
-
57
- basicType([
58
- 'project-config-maps',
59
- 'project-secrets',
60
- ], 'Project');
61
- setGroupDefaultType('project-config-maps', 'Project');
62
- }
@@ -1,45 +0,0 @@
1
- import NormanModel from '@shell/plugins/steve/norman-class';
2
- import { STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
3
-
4
- export default class Rke1EtcdBackup extends NormanModel {
5
- get _availableActions() {
6
- const restore = {
7
- action: 'promptRestore',
8
- enabled: this.state === STATES_ENUM.ACTIVE,
9
- icon: 'icon icon-fw icon-backup-restore',
10
- label: 'Restore'
11
- };
12
-
13
- const baseActions = super._availableActions;
14
- const actions = [
15
- restore
16
- ];
17
-
18
- if (baseActions.length) {
19
- actions.push({ divider: true });
20
- actions.push(...baseActions);
21
- }
22
-
23
- return actions;
24
- }
25
-
26
- promptRestore() {
27
- this.$dispatch('promptRestore', [this]);
28
- }
29
-
30
- get createdAt() {
31
- return this.created;
32
- }
33
-
34
- get rke2() {
35
- return false;
36
- }
37
-
38
- get nameDisplay() {
39
- return this.name;
40
- }
41
-
42
- get backupLocation() {
43
- return !!this.backupConfig.s3BackupConfig ? this.t('cluster.snapshot.rke1.s3') : this.t('cluster.snapshot.rke1.local');
44
- }
45
- }
@@ -1,29 +0,0 @@
1
- <script>
2
- import EmberPage from '@shell/components/EmberPage';
3
-
4
- const PAGES = {
5
- monitoring: 'monitoring/cluster-setting',
6
- cis: 'cis/scan',
7
- istio: 'istio/cluster-setting',
8
- snapshots: 'backups',
9
- };
10
-
11
- export default {
12
- components: { EmberPage },
13
-
14
- data() {
15
- const cluster = this.$store.getters['currentCluster'];
16
- const page = this.$route.params.page;
17
- const p = PAGES[page] || page;
18
-
19
- return { src: `/k/${ cluster.id }/${ p }` };
20
- }
21
- };
22
- </script>
23
-
24
- <template>
25
- <EmberPage
26
- v-if="src"
27
- :src="src"
28
- />
29
- </template>