@rancher/shell 0.3.14 → 0.3.15

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 (397) hide show
  1. package/assets/images/providers/nutanix.svg +1 -0
  2. package/assets/translations/en-us.yaml +83 -2
  3. package/chart/gatekeeper.vue +2 -2
  4. package/chart/monitoring/alerting/index.vue +3 -3
  5. package/chart/monitoring/index.vue +2 -2
  6. package/chart/monitoring/prometheus/index.vue +1 -1
  7. package/chart/rancher-backup/index.vue +2 -2
  8. package/cloud-credential/harvester.vue +2 -2
  9. package/components/AssignTo.vue +1 -1
  10. package/components/AwsComplianceBanner.vue +1 -1
  11. package/components/BackLink.vue +7 -0
  12. package/components/BrandImage.vue +3 -3
  13. package/components/ClusterProviderIcon.vue +1 -1
  14. package/components/CommunityLinks.vue +2 -2
  15. package/components/ConsumptionGauge.vue +17 -2
  16. package/components/CruResource.vue +2 -1
  17. package/components/DashboardMetrics.vue +8 -0
  18. package/components/DetailTop.vue +1 -1
  19. package/components/ExplorerMembers.vue +8 -8
  20. package/components/ExplorerProjectsNamespaces.vue +9 -9
  21. package/components/FixedBanner.vue +1 -1
  22. package/components/GlobalRoleBindings.vue +11 -11
  23. package/components/GrafanaDashboard.vue +7 -1
  24. package/components/GrowlManager.vue +1 -1
  25. package/components/HarvesterServiceAddOnConfig.vue +4 -3
  26. package/components/IconOrSvg.vue +10 -3
  27. package/components/LandingPagePreference.vue +2 -2
  28. package/components/MoveModal.vue +1 -1
  29. package/components/PodSecurityAdmission.vue +3 -3
  30. package/components/ProgressBarMulti.vue +2 -2
  31. package/components/PromptRemove.vue +52 -28
  32. package/components/PromptRestore.vue +3 -3
  33. package/components/Questions/index.vue +5 -5
  34. package/components/RelatedWorkloadsTable.vue +1 -1
  35. package/components/ResourceList/Masthead.vue +1 -1
  36. package/components/ResourceTable.vue +3 -3
  37. package/components/ResourceYaml.vue +1 -1
  38. package/components/RoleBindings.vue +2 -2
  39. package/components/SingleClusterInfo.vue +1 -1
  40. package/components/SortableTable/actions.js +3 -3
  41. package/components/SortableTable/advanced-filtering.js +7 -7
  42. package/components/SortableTable/filtering.js +1 -1
  43. package/components/SortableTable/index.vue +9 -9
  44. package/components/SortableTable/selection.js +5 -5
  45. package/components/SortableTable/sorting.js +5 -5
  46. package/components/Tabbed/index.vue +7 -7
  47. package/components/TableSparkLine.vue +1 -1
  48. package/components/Wizard.vue +11 -23
  49. package/components/__tests__/Collapse.spec.ts +1 -1
  50. package/components/__tests__/CruResource.test.ts +74 -0
  51. package/components/__tests__/SimpleBox.spec.ts +1 -1
  52. package/components/auth/RoleDetailEdit.vue +7 -3
  53. package/components/auth/SelectPrincipal.vue +3 -3
  54. package/components/fleet/FleetResources.vue +1 -1
  55. package/components/fleet/FleetStatus.vue +4 -4
  56. package/components/fleet/FleetSummary.vue +1 -1
  57. package/components/fleet/ForceDirectedTreeChart/chartIcons.js +1 -1
  58. package/components/fleet/ForceDirectedTreeChart/index.vue +1 -1
  59. package/components/form/ArrayList.vue +11 -3
  60. package/components/form/ArrayListSelect.vue +2 -2
  61. package/components/form/FileSelector.vue +6 -0
  62. package/components/form/GitPicker.vue +528 -0
  63. package/components/form/KeyValue.vue +82 -41
  64. package/components/form/LabeledSelect.vue +2 -2
  65. package/components/form/MatchExpressions.vue +2 -2
  66. package/components/form/Members/ClusterMembershipEditor.vue +1 -2
  67. package/components/form/Members/ClusterPermissionsEditor.vue +6 -5
  68. package/components/form/Members/MembershipEditor.vue +4 -4
  69. package/components/form/Members/ProjectMembershipEditor.vue +1 -2
  70. package/components/form/NameNsDescription.vue +13 -6
  71. package/components/form/Networking.vue +2 -2
  72. package/components/form/NodeScheduling.vue +1 -1
  73. package/components/form/PodAffinity.vue +1 -1
  74. package/components/form/ProjectMemberEditor.vue +4 -4
  75. package/components/form/ResourceQuota/Namespace.vue +2 -2
  76. package/components/form/ResourceQuota/NamespaceRow.vue +2 -2
  77. package/components/form/ResourceQuota/Project.vue +1 -1
  78. package/components/form/ResourceQuota/shared.js +2 -2
  79. package/components/form/ResourceSelector.vue +1 -1
  80. package/components/form/ResourceTabs/index.vue +1 -1
  81. package/components/form/RuleSelector.vue +1 -1
  82. package/components/form/SecretSelector.vue +4 -4
  83. package/components/form/Select.vue +2 -2
  84. package/components/form/SelectOrCreateAuthSecret.vue +3 -3
  85. package/components/form/ServiceNameSelect.vue +1 -1
  86. package/components/form/ServicePorts.vue +1 -1
  87. package/components/form/ShellInput.vue +1 -1
  88. package/components/form/SimpleSecretSelector.vue +4 -4
  89. package/components/form/Taints.vue +1 -1
  90. package/components/form/ValueFromResource.vue +3 -3
  91. package/components/form/WorkloadPorts.vue +8 -7
  92. package/components/form/__tests__/Error.test.ts +1 -1
  93. package/components/form/__tests__/KeyValue.test.ts +21 -0
  94. package/components/formatter/ClusterLink.vue +1 -1
  95. package/components/formatter/ClusterProvider.vue +13 -2
  96. package/components/formatter/Endpoints.vue +1 -1
  97. package/components/formatter/FleetSummaryGraph.vue +2 -2
  98. package/components/formatter/IngressTarget.vue +2 -2
  99. package/components/formatter/PodImages.vue +1 -1
  100. package/components/formatter/PrincipalGroupBindings.vue +1 -1
  101. package/components/formatter/ReceiverIcons.vue +3 -3
  102. package/components/formatter/ServiceType.vue +1 -1
  103. package/components/formatter/WorkloadDetailEndpoints.vue +1 -1
  104. package/components/formatter/WorkloadHealthScale.vue +1 -1
  105. package/components/formatter/__tests__/LiveDate.test.ts +1 -1
  106. package/components/graph/Bar.vue +1 -1
  107. package/components/graph/LinePlot.vue +3 -3
  108. package/components/nav/Group.vue +2 -2
  109. package/components/nav/Header.vue +5 -5
  110. package/components/nav/NamespaceFilter.vue +14 -14
  111. package/components/nav/TopLevelMenu.vue +76 -11
  112. package/components/nav/WindowManager/ContainerLogs.vue +2 -2
  113. package/components/nav/WindowManager/ContainerShell.vue +1 -1
  114. package/components/nav/WorkspaceSwitcher.vue +1 -1
  115. package/config/home-links.js +4 -4
  116. package/config/labels-annotations.js +8 -9
  117. package/config/pod-security-admission.ts +1 -1
  118. package/config/product/auth.js +4 -4
  119. package/config/product/explorer.js +14 -0
  120. package/config/router.js +5 -0
  121. package/config/store.js +2 -0
  122. package/config/table-headers.js +13 -13
  123. package/config/uiplugins.js +8 -1
  124. package/core/plugin-routes.ts +3 -2
  125. package/core/plugin.ts +3 -3
  126. package/core/plugins.js +7 -7
  127. package/creators/pkg/files/index.ts +1 -1
  128. package/detail/cis.cattle.io.clusterscan.vue +3 -3
  129. package/detail/fleet.cattle.io.bundle.vue +1 -1
  130. package/detail/helm.cattle.io.projecthelmchart.vue +16 -29
  131. package/detail/management.cattle.io.user.vue +12 -12
  132. package/detail/namespace.vue +4 -4
  133. package/detail/networking.k8s.io.ingress.vue +3 -3
  134. package/detail/node.vue +2 -2
  135. package/detail/provisioning.cattle.io.cluster.vue +9 -10
  136. package/detail/service.vue +1 -1
  137. package/detail/workload/index.vue +3 -3
  138. package/dialog/AddProjectMemberDialog.vue +2 -2
  139. package/dialog/DrainNode.vue +1 -1
  140. package/dialog/GenericPrompt.vue +9 -5
  141. package/dialog/RotateEncryptionKeyDialog.vue +2 -2
  142. package/dialog/ScaleMachineDownDialog.vue +2 -2
  143. package/edit/auth/azuread.vue +3 -3
  144. package/edit/autoscaling.horizontalpodautoscaler/index.vue +5 -5
  145. package/edit/cis.cattle.io.clusterscan.vue +5 -5
  146. package/edit/cloudcredential.vue +4 -4
  147. package/edit/constraints.gatekeeper.sh.constraint/NamespaceList.vue +1 -1
  148. package/edit/constraints.gatekeeper.sh.constraint/index.vue +4 -4
  149. package/edit/fleet.cattle.io.gitrepo.vue +6 -6
  150. package/edit/helm.cattle.io.projecthelmchart.vue +3 -3
  151. package/edit/logging-flow/index.vue +4 -4
  152. package/edit/logging.banzaicloud.io.output/index.vue +3 -3
  153. package/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue +1 -1
  154. package/edit/logging.banzaicloud.io.output/providers/forward.vue +1 -1
  155. package/edit/logging.banzaicloud.io.output/providers/logz.vue +1 -1
  156. package/edit/logging.banzaicloud.io.output/providers/opensearch.vue +1 -1
  157. package/edit/logging.banzaicloud.io.output/providers/redis.vue +1 -1
  158. package/edit/logging.banzaicloud.io.output/providers/splunkHec.vue +1 -1
  159. package/edit/management.cattle.io.clusterroletemplatebinding.vue +1 -1
  160. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +1 -1
  161. package/edit/management.cattle.io.project.vue +3 -3
  162. package/edit/management.cattle.io.projectroletemplatebinding.vue +2 -2
  163. package/edit/management.cattle.io.setting.vue +1 -1
  164. package/edit/management.cattle.io.user.vue +2 -2
  165. package/edit/monitoring.coreos.com.alertmanagerconfig/auth.vue +2 -2
  166. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  167. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +1 -1
  168. package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +3 -3
  169. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +5 -5
  170. package/edit/monitoring.coreos.com.prometheusrule/duration.js +1 -1
  171. package/edit/monitoring.coreos.com.receiver/auth.vue +2 -2
  172. package/edit/monitoring.coreos.com.receiver/tls.vue +3 -4
  173. package/edit/monitoring.coreos.com.receiver/types/__tests__/email.test.ts +53 -0
  174. package/edit/monitoring.coreos.com.receiver/types/email.vue +2 -0
  175. package/edit/monitoring.coreos.com.receiver/types/opsgenie.vue +3 -3
  176. package/edit/monitoring.coreos.com.receiver/types/webhook.add.vue +1 -1
  177. package/edit/monitoring.coreos.com.route.vue +2 -2
  178. package/edit/namespace.vue +21 -13
  179. package/edit/networking.k8s.io.ingress/Certificate.vue +2 -2
  180. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +2 -2
  181. package/edit/networking.k8s.io.ingress/RulePath.vue +2 -2
  182. package/edit/networking.k8s.io.ingress/Rules.vue +2 -2
  183. package/edit/networking.k8s.io.ingress/index.vue +4 -4
  184. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +3 -3
  185. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  186. package/edit/persistentvolume/index.vue +4 -4
  187. package/edit/persistentvolumeclaim.vue +3 -3
  188. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +1 -1
  189. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +2 -2
  190. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  191. package/edit/provisioning.cattle.io.cluster/index.vue +7 -7
  192. package/edit/provisioning.cattle.io.cluster/rke2.vue +28 -29
  193. package/edit/resources.cattle.io.backup.vue +2 -2
  194. package/edit/resources.cattle.io.restore.vue +3 -3
  195. package/edit/secret/generic.vue +1 -1
  196. package/edit/secret/index.vue +3 -3
  197. package/edit/service.vue +3 -21
  198. package/edit/serviceaccount.vue +2 -2
  199. package/edit/storage.k8s.io.storageclass/index.vue +4 -4
  200. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +1 -1
  201. package/edit/token.vue +5 -5
  202. package/edit/workload/index.vue +1 -1
  203. package/edit/workload/mixins/workload.js +8 -8
  204. package/edit/workload/storage/ContainerMountPaths.vue +9 -9
  205. package/edit/workload/storage/Mount.vue +2 -2
  206. package/edit/workload/storage/csi/index.vue +1 -1
  207. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  208. package/edit/workload/storage/index.vue +6 -6
  209. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +2 -2
  210. package/initialize/client.js +8 -8
  211. package/initialize/index.js +1 -4
  212. package/layouts/default.vue +38 -11
  213. package/list/catalog.cattle.io.clusterrepo.vue +9 -1
  214. package/list/cis.cattle.io.clusterscan.vue +1 -1
  215. package/list/fleet.cattle.io.cluster.vue +2 -2
  216. package/list/group.principal.vue +1 -1
  217. package/list/helm.cattle.io.projecthelmchart.vue +2 -2
  218. package/list/management.cattle.io.cluster.vue +1 -1
  219. package/list/management.cattle.io.feature.vue +1 -1
  220. package/list/management.cattle.io.user.vue +2 -2
  221. package/list/node.vue +5 -5
  222. package/list/provisioning.cattle.io.cluster.vue +4 -5
  223. package/machine-config/amazonec2.vue +2 -2
  224. package/machine-config/digitalocean.vue +4 -4
  225. package/machine-config/linode.vue +4 -4
  226. package/machine-config/vmwarevsphere.vue +12 -12
  227. package/middleware/authenticated.js +7 -6
  228. package/mixins/brand.js +1 -1
  229. package/mixins/chart.js +6 -6
  230. package/mixins/fetch.client.js +2 -2
  231. package/mixins/form-validation.js +7 -7
  232. package/mixins/resource-fetch-namespaced.js +1 -1
  233. package/mixins/resource-fetch.js +2 -2
  234. package/models/apps.statefulset.js +2 -2
  235. package/models/batch.cronjob.js +1 -1
  236. package/models/catalog.cattle.io.app.js +4 -4
  237. package/models/cis.cattle.io.clusterscan.js +1 -1
  238. package/models/cis.cattle.io.clusterscanbenchmark.js +1 -1
  239. package/models/cis.cattle.io.clusterscanreport.js +1 -1
  240. package/models/cloudcredential.js +1 -1
  241. package/models/cluster/node.js +5 -5
  242. package/models/cluster.x-k8s.io.machinedeployment.js +2 -2
  243. package/models/fleet.cattle.io.gitrepo.js +3 -3
  244. package/models/group.principal.js +4 -4
  245. package/models/helm.cattle.io.projecthelmchart.js +2 -2
  246. package/models/logging.banzaicloud.io.clusterflow.js +2 -2
  247. package/models/logging.banzaicloud.io.flow.js +5 -5
  248. package/models/logging.banzaicloud.io.output.js +2 -2
  249. package/models/management.cattle.io.cluster.js +10 -14
  250. package/models/management.cattle.io.globalrole.js +4 -4
  251. package/models/management.cattle.io.node.js +2 -2
  252. package/models/management.cattle.io.nodepool.js +3 -3
  253. package/models/management.cattle.io.nodetemplate.js +4 -4
  254. package/models/management.cattle.io.project.js +2 -2
  255. package/models/management.cattle.io.roletemplate.js +1 -1
  256. package/models/management.cattle.io.setting.js +1 -1
  257. package/models/management.cattle.io.user.js +5 -5
  258. package/models/monitoring.coreos.com.receiver.js +9 -9
  259. package/models/namespace.js +1 -1
  260. package/models/networking.k8s.io.ingress.js +5 -5
  261. package/models/persistentvolume.js +3 -3
  262. package/models/pod.js +3 -3
  263. package/models/provisioning.cattle.io.cluster.js +39 -27
  264. package/models/rbac.authorization.k8s.io.clusterrole.js +2 -2
  265. package/models/rbac.authorization.k8s.io.role.js +3 -3
  266. package/models/secret.js +1 -1
  267. package/models/service.js +2 -2
  268. package/models/storage.k8s.io.storageclass.js +2 -2
  269. package/models/token.js +1 -1
  270. package/models/workload.js +6 -6
  271. package/models/workload.service.js +5 -21
  272. package/package.json +2 -1
  273. package/pages/about.vue +9 -9
  274. package/pages/account/index.vue +2 -2
  275. package/pages/auth/login.vue +15 -12
  276. package/pages/auth/verify.vue +6 -0
  277. package/pages/c/_cluster/apps/charts/index.vue +4 -4
  278. package/pages/c/_cluster/apps/charts/install.vue +28 -20
  279. package/pages/c/_cluster/auth/roles/index.vue +9 -9
  280. package/pages/c/_cluster/explorer/index.vue +41 -16
  281. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  282. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +1 -1
  283. package/pages/c/_cluster/fleet/index.vue +11 -11
  284. package/pages/c/_cluster/monitoring/index.vue +1 -1
  285. package/pages/c/_cluster/settings/links.vue +3 -3
  286. package/pages/c/_cluster/settings/performance.vue +1 -1
  287. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +6 -6
  288. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +3 -3
  289. package/pages/c/_cluster/uiplugins/InstallDialog.vue +3 -3
  290. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  291. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +3 -3
  292. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +6 -6
  293. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +4 -4
  294. package/pages/c/_cluster/uiplugins/index.vue +22 -19
  295. package/pages/diagnostic.vue +6 -6
  296. package/pages/home.vue +3 -3
  297. package/pages/prefs.vue +2 -2
  298. package/pages/rio/mesh.vue +3 -3
  299. package/pages/support/index.vue +10 -1
  300. package/pkg/auto-import.js +1 -1
  301. package/pkg/tsconfig.json +1 -0
  302. package/pkg/vue.config.js +1 -1
  303. package/plugins/axios.js +1 -1
  304. package/plugins/clean-html-directive.js +1 -1
  305. package/plugins/dashboard-store/__tests__/mutations.spec.js +4 -4
  306. package/plugins/dashboard-store/actions.js +4 -4
  307. package/plugins/dashboard-store/getters.js +1 -1
  308. package/plugins/dashboard-store/index.js +1 -1
  309. package/plugins/dashboard-store/mutations.js +2 -2
  310. package/plugins/dashboard-store/resource-class.js +8 -8
  311. package/plugins/i18n.js +1 -1
  312. package/plugins/plugin.js +5 -1
  313. package/plugins/steve/actions.js +3 -3
  314. package/plugins/steve/getters.js +3 -3
  315. package/plugins/steve/hybrid-class.js +1 -1
  316. package/plugins/steve/mutations.js +1 -1
  317. package/plugins/steve/performanceTesting.js +1 -1
  318. package/plugins/steve/resourceWatcher.js +1 -1
  319. package/plugins/steve/subscribe.js +6 -6
  320. package/plugins/steve/worker/web-worker.basic.js +1 -1
  321. package/promptRemove/management.cattle.io.project.vue +3 -3
  322. package/promptRemove/mixin/roleDeletionCheck.js +4 -4
  323. package/promptRemove/pod.vue +1 -1
  324. package/rancher-components/StringList/StringList.vue +34 -50
  325. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +2 -2
  326. package/rancher-components/components/Form/Checkbox/Checkbox.vue +1 -1
  327. package/rancher-components/components/Form/Radio/RadioButton.test.ts +1 -1
  328. package/rancher-components/components/Form/Radio/RadioButton.vue +2 -2
  329. package/rancher-components/components/Form/Radio/RadioGroup.vue +2 -2
  330. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  331. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +1 -1
  332. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +7 -7
  333. package/rancher-components/components/StringList/StringList.test.ts +10 -9
  334. package/rancher-components/components/StringList/StringList.vue +5 -5
  335. package/scripts/extension/helm/charts/ui-plugin-server/Chart.yaml +1 -1
  336. package/store/action-menu.js +4 -4
  337. package/store/auth.js +40 -7
  338. package/store/aws.js +1 -1
  339. package/store/catalog.js +12 -11
  340. package/store/digitalocean.js +4 -4
  341. package/store/features.js +1 -0
  342. package/store/github.js +70 -213
  343. package/store/gitlab.js +159 -0
  344. package/store/growl.js +1 -1
  345. package/store/i18n.js +7 -7
  346. package/store/index.js +63 -22
  347. package/store/linode.js +1 -1
  348. package/store/plugins.js +5 -5
  349. package/store/pnap.js +1 -1
  350. package/store/prefs.js +6 -6
  351. package/store/resource-fetch.js +3 -3
  352. package/store/type-map.js +61 -42
  353. package/store/uiplugins.ts +2 -1
  354. package/store/wm.js +5 -4
  355. package/tsconfig.default.json +10 -0
  356. package/tsconfig.json +2 -9
  357. package/types/shell/index.d.ts +21 -13
  358. package/utils/__tests__/version.test.ts +28 -0
  359. package/utils/alertmanagerconfig.js +4 -4
  360. package/utils/array.ts +4 -4
  361. package/utils/async.ts +1 -1
  362. package/utils/auth.js +3 -3
  363. package/utils/axios.js +5 -5
  364. package/utils/cluster.js +4 -3
  365. package/utils/color.js +10 -0
  366. package/utils/create-yaml.js +4 -4
  367. package/utils/crypto/browserHashUtils.js +1 -1
  368. package/utils/crypto/browserMd5.js +1 -1
  369. package/utils/crypto/browserSha1.js +1 -1
  370. package/utils/crypto/browserSha256.js +1 -1
  371. package/utils/crypto/index.js +3 -3
  372. package/utils/favicon.js +2 -3
  373. package/utils/gatekeeper/util.js +3 -3
  374. package/utils/gc/gc.ts +2 -2
  375. package/utils/git.ts +92 -0
  376. package/utils/grafana.js +4 -4
  377. package/utils/monitoring.js +2 -2
  378. package/utils/nuxt.js +2 -2
  379. package/utils/object.js +5 -5
  380. package/utils/pod-security-admission.ts +1 -1
  381. package/utils/projectAndNamespaceFiltering.utils.ts +1 -1
  382. package/utils/select.js +2 -2
  383. package/utils/selector.js +2 -2
  384. package/utils/settings.ts +17 -2
  385. package/utils/socket.js +30 -6
  386. package/utils/sort.js +1 -1
  387. package/utils/string.js +1 -1
  388. package/utils/url.ts +1 -1
  389. package/utils/validators/formRules/index.ts +3 -3
  390. package/utils/validators/role-template.js +4 -4
  391. package/utils/version.js +14 -1
  392. package/vue.config.js +19 -13
  393. package/components/.DS_Store +0 -0
  394. package/components/__tests__/.DS_Store +0 -0
  395. package/components/form/GithubPicker.vue +0 -390
  396. package/creators/pkg/package-lock.json +0 -37
  397. package/yarn-error.log +0 -196
@@ -0,0 +1,159 @@
1
+ import { isArray } from '@shell/utils/array';
2
+
3
+ const API_VERSION = 'v4';
4
+ const GITLAB_BASE_API = 'https://gitlab.com/api';
5
+ const TOKEN = '';
6
+ const MAX_RESULTS = 100; // max number of results is 100
7
+
8
+ const getResponse = (endpoint) => fetch(`${ GITLAB_BASE_API }/${ API_VERSION }/${ endpoint }${ TOKEN }`);
9
+
10
+ function fetchUserOrOrganization(endpoint) {
11
+ return Promise.all([
12
+ getResponse(`users/${ endpoint }`),
13
+ getResponse(`groups/${ endpoint }`),
14
+ ]).then((responses) => {
15
+ const found = responses.find((r) => r.ok);
16
+
17
+ if (!found) {
18
+ throw responses[0];
19
+ }
20
+
21
+ return found.json();
22
+ });
23
+ }
24
+
25
+ const fetchGitLabAPI = async(endpoint) => {
26
+ const response = await getResponse(endpoint);
27
+
28
+ // If rate-limit is exceeded, we should wait until the rate limit is reset
29
+ if (response.status === 403) {
30
+ const resetTime = new Date(response.headers.get('X-RateLimit-Reset') * 1000);
31
+
32
+ throw new Error(`Rate limit exceeded. Try again at ${ resetTime }`);
33
+ }
34
+
35
+ if (!response.ok) {
36
+ throw response;
37
+ }
38
+
39
+ return await response.json();
40
+ };
41
+
42
+ export const getters = {};
43
+
44
+ export const actions = {
45
+ async apiList(ctx, {
46
+ username, email, endpoint, repo, branch
47
+ }) {
48
+ try {
49
+ switch (endpoint) {
50
+ case 'branches': {
51
+ return await fetchGitLabAPI(`projects/${ username }%2F${ repo }/repository/branches?per_page=${ MAX_RESULTS }`);
52
+ }
53
+ case 'repo': {
54
+ return await fetchGitLabAPI(`projects/${ username }%2F${ repo }`);
55
+ }
56
+ case 'commits': {
57
+ return await fetchGitLabAPI(`projects/${ username }%2F${ repo }/repository/commits?ref_name=${ branch }&order_by=updated_at&per_page=${ MAX_RESULTS }`);
58
+ }
59
+ case 'recentRepos': {
60
+ return await fetchUserOrOrganization(`${ username }/projects?order_by=name&sort=asc&per_page=${ MAX_RESULTS }`);
61
+ }
62
+ case 'avatar': {
63
+ return await fetchGitLabAPI(`avatar?email=${ email }`);
64
+ }
65
+ case 'search': {
66
+ // Fetch for a specific branches
67
+ if (username && repo && branch) {
68
+ const response = await fetchGitLabAPI(`projects/${ repo }/repository/branches/${ branch }`);
69
+
70
+ return [response];
71
+ }
72
+
73
+ // Fetch for repos
74
+ const response = await fetchGitLabAPI(`search/repositories?q=repo:${ username }/${ repo }`);
75
+
76
+ if (response) {
77
+ return response.items;
78
+ }
79
+ }
80
+ }
81
+ } catch (error) {
82
+ throw await error.json() ?? Error(`Error fetching ${ endpoint }`);
83
+ }
84
+ },
85
+
86
+ async fetchRecentRepos({ commit, dispatch }, { username } = {}) {
87
+ const res = await dispatch('apiList', { username, endpoint: 'recentRepos' });
88
+
89
+ return res;
90
+ },
91
+
92
+ async fetchRepoDetails({ commit, dispatch }, { username, repo } = {}) {
93
+ const res = await dispatch('apiList', {
94
+ username, endpoint: 'repo', repo: repo.name
95
+ });
96
+
97
+ return res;
98
+ },
99
+
100
+ async fetchBranches({ commit, dispatch }, { repo, username }) {
101
+ const res = await dispatch('apiList', {
102
+ username, endpoint: 'branches', repo: repo.name
103
+ });
104
+
105
+ return res;
106
+ },
107
+
108
+ async fetchCommits(ctx, { repo, username, branch }) {
109
+ const { dispatch } = ctx;
110
+
111
+ const res = await dispatch('apiList', {
112
+ username, endpoint: 'commits', repo: repo.name, branch: branch.name
113
+ });
114
+
115
+ let commits = [];
116
+
117
+ // Get and cache Avatar URLs
118
+ if (res) {
119
+ commits = isArray(res) ? res : [res];
120
+
121
+ const avatars = {};
122
+
123
+ for (const c of commits) {
124
+ const found = avatars[c.author_email];
125
+
126
+ if (found) {
127
+ c.avatar_url = found;
128
+ } else {
129
+ const newAvatar = await dispatch('apiList', {
130
+ username, endpoint: 'avatar', email: c.author_email
131
+ });
132
+
133
+ c.avatar_url = newAvatar?.avatar_url;
134
+ avatars[c.author_email] = c.avatar_url;
135
+ }
136
+ }
137
+ }
138
+
139
+ return commits;
140
+ },
141
+
142
+ async search({ dispatch }, { repo, username, branch }) {
143
+ try {
144
+ const res = await dispatch('apiList', {
145
+ username, endpoint: 'search', repo: repo?.id, branch: branch?.name
146
+ });
147
+
148
+ return {
149
+ ...res,
150
+ hasError: false,
151
+ };
152
+ } catch (error) {
153
+ return {
154
+ message: error.message,
155
+ hasError: true
156
+ };
157
+ }
158
+ }
159
+ };
package/store/growl.js CHANGED
@@ -11,7 +11,7 @@ export const state = function() {
11
11
  };
12
12
 
13
13
  export const getters = {
14
- find: state => ({ key, val }) => {
14
+ find: (state) => ({ key, val }) => {
15
15
  return findBy(state.stack, key, val);
16
16
  }
17
17
  };
package/store/i18n.js CHANGED
@@ -58,7 +58,7 @@ export const getters = {
58
58
  return out;
59
59
  },
60
60
 
61
- t: state => (key, args, language) => {
61
+ t: (state) => (key, args, language) => {
62
62
  if (state.selected === NONE && !language) {
63
63
  return `%${ key }%`;
64
64
  }
@@ -110,7 +110,7 @@ export const getters = {
110
110
  }
111
111
  },
112
112
 
113
- exists: state => (key, language) => {
113
+ exists: (state) => (key, language) => {
114
114
  const locale = language || state.selected;
115
115
  const cacheKey = `${ locale }/${ key }`;
116
116
 
@@ -131,11 +131,11 @@ export const getters = {
131
131
  return false;
132
132
  },
133
133
 
134
- current: state => () => {
134
+ current: (state) => () => {
135
135
  return state.selected;
136
136
  },
137
137
 
138
- default: state => () => {
138
+ default: (state) => () => {
139
139
  return state.default;
140
140
  },
141
141
 
@@ -191,7 +191,7 @@ export const mutations = {
191
191
 
192
192
  // Add a locale to the list of available locales
193
193
  addLocale(state, { locale, label }) {
194
- const hasLocale = state.available.find(l => l === locale);
194
+ const hasLocale = state.available.find((l) => l === locale);
195
195
 
196
196
  if (!hasLocale) {
197
197
  state.available.push(locale);
@@ -203,7 +203,7 @@ export const mutations = {
203
203
 
204
204
  // Remove locale
205
205
  removeLocale(state, locale) {
206
- const index = state.available.findIndex(l => l === locale);
206
+ const index = state.available.findIndex((l) => l === locale);
207
207
 
208
208
  if (index !== -1) {
209
209
  state.available.splice(index, 1);
@@ -222,7 +222,7 @@ export const actions = {
222
222
  let selected = rootGetters['prefs/get']('locale');
223
223
 
224
224
  // We might be using a locale that is loaded by a plugin that is no longer loaded
225
- const exists = !!state.available.find(loc => loc === selected);
225
+ const exists = !!state.available.find((loc) => loc === selected);
226
226
 
227
227
  if ( !selected || !exists) {
228
228
  selected = state.default;
package/store/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  FLEET,
10
10
  MANAGEMENT,
11
11
  NAMESPACE, NORMAN,
12
- UI, VIRTUAL_HARVESTER_PROVIDER
12
+ UI, VIRTUAL_HARVESTER_PROVIDER, HCI
13
13
  } from '@shell/config/types';
14
14
  import { BY_TYPE } from '@shell/plugins/dashboard-store/classify';
15
15
  import Steve from '@shell/plugins/steve';
@@ -133,11 +133,11 @@ const getActiveSingleNamespaces = (getters, filters) => {
133
133
  const getReadOnlyActiveNamespaces = (namespaces, activeNamespaces) => {
134
134
  const readonlyNamespaces = Object
135
135
  .values(namespaces)
136
- .filter(ns => !!ns.links.update)
136
+ .filter((ns) => !!ns.links.update)
137
137
  .map(({ id }) => id);
138
138
 
139
139
  return Object.keys(activeNamespaces)
140
- .filter(ns => readonlyNamespaces.includes(ns))
140
+ .filter((ns) => readonlyNamespaces.includes(ns))
141
141
  .reduce((acc, ns) => ({
142
142
  ...acc,
143
143
  [ns]: true
@@ -179,12 +179,12 @@ const getActiveNamespaces = (state, getters, readonly = false) => {
179
179
  const allNamespaces = hasNamespaces ? state.allNamespaces : getters[`${ inStore }/all`](NAMESPACE);
180
180
 
181
181
  const allowedNamespaces = allNamespaces
182
- .filter(ns => state.prefs.data['all-namespaces'] ? true : !ns.isObscure) // Filter out Rancher system namespaces
183
- .filter(ns => product.hideSystemResources ? !ns.isSystem : true); // Filter out Fleet system namespaces
182
+ .filter((ns) => state.prefs.data['all-namespaces'] ? true : !ns.isObscure) // Filter out Rancher system namespaces
183
+ .filter((ns) => product.hideSystemResources ? !ns.isSystem : true); // Filter out Fleet system namespaces
184
184
 
185
185
  // Retrieve all the filters selected by the user
186
186
  const filters = state.namespaceFilters.filter(
187
- filters => !!filters && !`${ filters }`.startsWith(NAMESPACED_PREFIX)
187
+ (filters) => !!filters && !`${ filters }`.startsWith(NAMESPACED_PREFIX)
188
188
  );
189
189
 
190
190
  const activeNamespaces = {
@@ -211,7 +211,7 @@ const updateActiveNamespaceCache = (state, activeNamespaceCache) => {
211
211
  let cacheKey = '';
212
212
 
213
213
  for (const key in activeNamespaceCache) {
214
- // I though array.join would be faster than string concatenation, but in places like this where the array must first be constructed it's
214
+ // I thought array.join would be faster than string concatenation, but in places like this where the array must first be constructed it's
215
215
  // slower.
216
216
  cacheKey += key + activeNamespaceCache[key];
217
217
  }
@@ -242,6 +242,8 @@ export const state = () => {
242
242
  serverVersion: null,
243
243
  systemNamespaces: [],
244
244
  isSingleProduct: undefined,
245
+ isRancherInHarvester: false,
246
+ targetRoute: null
245
247
  };
246
248
  };
247
249
 
@@ -307,7 +309,7 @@ export const getters = {
307
309
  getStoreNameByProductId(state) {
308
310
  const products = state['type-map']?.products;
309
311
 
310
- return (products.find(p => p.name === state.productId) || {})?.inStore || 'cluster';
312
+ return (products.find((p) => p.name === state.productId) || {})?.inStore || 'cluster';
311
313
  },
312
314
 
313
315
  currentStore(state, getters) {
@@ -342,7 +344,7 @@ export const getters = {
342
344
 
343
345
  const desired = getters['prefs/get'](CLUSTER_PREF);
344
346
 
345
- if ( clusters.find(x => x.id === desired) ) {
347
+ if ( clusters.find((x) => x.id === desired) ) {
346
348
  return desired;
347
349
  } else if ( clusters.length ) {
348
350
  return clusters[0].id;
@@ -366,7 +368,7 @@ export const getters = {
366
368
  return true;
367
369
  }
368
370
 
369
- return state.namespaceFilters.filter(x => !`${ x }`.startsWith(NAMESPACED_PREFIX)).length === 0;
371
+ return state.namespaceFilters.filter((x) => !`${ x }`.startsWith(NAMESPACED_PREFIX)).length === 0;
370
372
  },
371
373
 
372
374
  isMultipleNamespaces(state, getters) {
@@ -394,7 +396,7 @@ export const getters = {
394
396
  },
395
397
 
396
398
  namespaceFilters(state) {
397
- const filters = state.namespaceFilters.filter(x => !!x && !`${ x }`.startsWith(NAMESPACED_PREFIX));
399
+ const filters = state.namespaceFilters.filter((x) => !!x && !`${ x }`.startsWith(NAMESPACED_PREFIX));
398
400
 
399
401
  return filters;
400
402
  },
@@ -475,7 +477,7 @@ export const getters = {
475
477
  const inStore = product.inStore;
476
478
  const filteredMap = getters['activeNamespaceCache'];
477
479
  const isAll = getters['isAllNamespaces'];
478
- const all = getters[`${ inStore }/all`](NAMESPACE).map(x => x.id);
480
+ const all = getters[`${ inStore }/all`](NAMESPACE).map((x) => x.id);
479
481
  let out;
480
482
 
481
483
  function isOk() {
@@ -550,12 +552,27 @@ export const getters = {
550
552
  return false;
551
553
  },
552
554
 
555
+ isRancherInHarvester(state) {
556
+ return state.isRancherInHarvester;
557
+ },
558
+
553
559
  isVirtualCluster(state, getters) {
554
560
  const cluster = getters['currentCluster'];
555
561
 
556
562
  return cluster?.status?.provider === VIRTUAL_HARVESTER_PROVIDER;
557
563
  },
558
564
 
565
+ isStandaloneHarvester(state, getters) {
566
+ const clusters = getters['management/all'](MANAGEMENT.CLUSTER);
567
+ const cluster = clusters.find((c) => c.id === 'local') || {};
568
+
569
+ return getters['isSingleProduct'] && cluster.isHarvester && !getters['isRancherInHarvester'];
570
+ },
571
+
572
+ targetRoute(state) {
573
+ return state.targetRoute;
574
+ },
575
+
559
576
  ...gcGetters
560
577
  };
561
578
 
@@ -568,13 +585,16 @@ export const mutations = {
568
585
  state.clusterReady = ready;
569
586
  },
570
587
 
588
+ isRancherInHarvester(state, neu) {
589
+ state.isRancherInHarvester = neu;
590
+ },
591
+
571
592
  updateNamespaces(state, { filters, all }) {
572
- state.namespaceFilters = filters.filter(x => !!x);
593
+ state.namespaceFilters = filters.filter((x) => !!x);
573
594
 
574
595
  if ( all ) {
575
596
  state.allNamespaces = all;
576
597
  }
577
-
578
598
  // Create map that can be used to efficiently check if a
579
599
  // resource should be displayed
580
600
  getActiveNamespaces(state, getters);
@@ -648,6 +668,9 @@ export const mutations = {
648
668
  state.isSingleProduct = isSingleProduct;
649
669
  },
650
670
 
671
+ targetRoute(state, route) {
672
+ state.targetRoute = route;
673
+ }
651
674
  };
652
675
 
653
676
  export const actions = {
@@ -713,9 +736,20 @@ export const actions = {
713
736
  dispatch('i18n/init');
714
737
  const isMultiCluster = getters['isMultiCluster'];
715
738
 
716
- const pl = res.settings?.find(x => x.id === 'ui-pl')?.value;
717
- const brand = res.settings?.find(x => x.id === SETTING.BRAND)?.value;
718
- const systemNamespaces = res.settings?.find(x => x.id === SETTING.SYSTEM_NAMESPACES);
739
+ // If the local cluster is a Harvester cluster and 'rancher-manager-support' is true, it means that the embedded Rancher is being used.
740
+ const localCluster = res.clusters?.find((c) => c.id === 'local');
741
+
742
+ if (localCluster?.isHarvester) {
743
+ const harvesterSetting = await dispatch('cluster/findAll', { type: HCI.SETTING, opt: { url: `/v1/harvester/${ HCI.SETTING }s` } });
744
+ const rancherManagerSupport = harvesterSetting.find((setting) => setting.id === 'rancher-manager-support');
745
+ const isRancherInHarvester = (rancherManagerSupport?.value || rancherManagerSupport?.default) === 'true';
746
+
747
+ commit('isRancherInHarvester', isRancherInHarvester);
748
+ }
749
+
750
+ const pl = res.settings?.find((x) => x.id === 'ui-pl')?.value;
751
+ const brand = res.settings?.find((x) => x.id === SETTING.BRAND)?.value;
752
+ const systemNamespaces = res.settings?.find((x) => x.id === SETTING.SYSTEM_NAMESPACES);
719
753
 
720
754
  if ( pl ) {
721
755
  setVendor(pl);
@@ -750,8 +784,9 @@ export const actions = {
750
784
  async loadCluster({
751
785
  state, commit, dispatch, getters
752
786
  }, {
753
- id, product, oldProduct, oldPkg, newPkg
787
+ id, product, oldProduct, oldPkg, newPkg, targetRoute
754
788
  }) {
789
+ commit('targetRoute', targetRoute);
755
790
  const sameCluster = state.clusterId && state.clusterId === id;
756
791
  const samePackage = oldPkg?.name === newPkg?.name;
757
792
  const isMultiCluster = getters['isMultiCluster'];
@@ -763,14 +798,14 @@ export const actions = {
763
798
  }
764
799
 
765
800
  const oldPkgClusterStore = oldPkg?.stores.find(
766
- s => getters[`${ s.storeName }/isClusterStore`]
801
+ (s) => getters[`${ s.storeName }/isClusterStore`]
767
802
  )?.storeName;
768
803
 
769
804
  const newPkgClusterStore = newPkg?.stores.find(
770
- s => getters[`${ s.storeName }/isClusterStore`]
805
+ (s) => getters[`${ s.storeName }/isClusterStore`]
771
806
  )?.storeName;
772
807
 
773
- const productConfig = state['type-map']?.products?.find(p => p.name === product);
808
+ const productConfig = state['type-map']?.products?.find((p) => p.name === product);
774
809
  const forgetCurrentCluster = ((state.clusterId && id) || !samePackage) && !productConfig?.inExplorer;
775
810
 
776
811
  // Should we leave/forget the current cluster? Only if we're going from an existing cluster to a new cluster, or the package has changed
@@ -902,12 +937,17 @@ export const actions = {
902
937
  await dispatch('cleanNamespaces');
903
938
 
904
939
  const filters = getters['prefs/get'](NAMESPACE_FILTERS)?.[id];
940
+ const allNamespaces = res.namespaces;
905
941
 
906
942
  commit('updateNamespaces', {
907
943
  filters: filters || [ALL_USER],
908
- all: res.namespaces,
944
+ all: allNamespaces,
909
945
  });
910
946
 
947
+ if (getters['currentCluster'] && getters['currentCluster'].isHarvester) {
948
+ await dispatch('cluster/findAll', { type: HCI.SETTING });
949
+ }
950
+
911
951
  commit('clusterReady', true);
912
952
 
913
953
  console.log('Done loading cluster.'); // eslint-disable-line no-console
@@ -923,6 +963,7 @@ export const actions = {
923
963
  [key]: ids
924
964
  }
925
965
  });
966
+
926
967
  commit('updateNamespaces', { filters: ids });
927
968
  },
928
969
 
package/store/linode.js CHANGED
@@ -21,7 +21,7 @@ export const mutations = {
21
21
  };
22
22
 
23
23
  export const getters = {
24
- fromCache: state => ({ credentialId, key }) => {
24
+ fromCache: (state) => ({ credentialId, key }) => {
25
25
  return state.cache[credentialId]?.[key];
26
26
  },
27
27
  };
package/store/plugins.js CHANGED
@@ -72,12 +72,12 @@ export const likelyFields = [
72
72
  'token', 'apikey',
73
73
  'secret',
74
74
  'clientid', 'clientsecret', 'subscriptionid', 'tenantid',
75
- ].map(x => simplify(x));
75
+ ].map((x) => simplify(x));
76
76
 
77
77
  // Machine driver fields that are maaaaybe a credential field
78
78
  export const iffyFields = [
79
79
  'location', 'region',
80
- ].map(x => simplify(x));
80
+ ].map((x) => simplify(x));
81
81
 
82
82
  // Machine driver fields that are safe to display the whole value
83
83
  export const fullFields = [
@@ -85,18 +85,18 @@ export const fullFields = [
85
85
  'accesskey',
86
86
  'accesskeyid',
87
87
  'clientid'
88
- ].map(x => simplify(x));
88
+ ].map((x) => simplify(x));
89
89
 
90
90
  // Machine driver fields that are safe to display the beginning of
91
91
  export const prefixFields = [
92
92
  'token',
93
93
  'apikey',
94
94
  'secret',
95
- ].map(x => simplify(x));
95
+ ].map((x) => simplify(x));
96
96
 
97
97
  // Machine driver fields that are safe to display the end of
98
98
  export const suffixFields = [
99
- ].map(x => simplify(x));
99
+ ].map((x) => simplify(x));
100
100
 
101
101
  // Machine driver to cloud provider mapping
102
102
  const driverToCloudProviderMap = {
package/store/pnap.js CHANGED
@@ -21,7 +21,7 @@ export const mutations = {
21
21
  };
22
22
 
23
23
  export const getters = {
24
- fromCache: state => ({ credentialId, key }) => {
24
+ fromCache: (state) => ({ credentialId, key }) => {
25
25
  return state.cache[credentialId]?.[key];
26
26
  },
27
27
  };
package/store/prefs.js CHANGED
@@ -60,8 +60,8 @@ export const THEME = create('theme', 'auto', {
60
60
  options: ['light', 'auto', 'dark'],
61
61
  asCookie,
62
62
  parseJSON,
63
- mangleRead: x => x.replace(/^ui-/, ''),
64
- mangleWrite: x => `ui-${ x }`,
63
+ mangleRead: (x) => x.replace(/^ui-/, ''),
64
+ mangleWrite: (x) => `ui-${ x }`,
65
65
  });
66
66
  export const PREFERS_SCHEME = create('pcs', '', { asCookie, asUserPreference: false });
67
67
  export const LOCALE = create('locale', 'en-us', { asCookie });
@@ -141,7 +141,7 @@ export const state = function() {
141
141
  };
142
142
 
143
143
  export const getters = {
144
- get: state => (key) => {
144
+ get: (state) => (key) => {
145
145
  const definition = state.definitions[key];
146
146
 
147
147
  if (!definition) {
@@ -159,7 +159,7 @@ export const getters = {
159
159
  return def;
160
160
  },
161
161
 
162
- defaultValue: state => (key) => {
162
+ defaultValue: (state) => (key) => {
163
163
  const definition = state.definitions[key];
164
164
 
165
165
  if (!definition) {
@@ -169,7 +169,7 @@ export const getters = {
169
169
  return clone(definition.def);
170
170
  },
171
171
 
172
- options: state => (key) => {
172
+ options: (state) => (key) => {
173
173
  const definition = state.definitions[key];
174
174
 
175
175
  if (!definition) {
@@ -531,7 +531,7 @@ function getLoginRoute(route) {
531
531
  const routeParams = route.params || {};
532
532
 
533
533
  // Find the 'resource' part of the route, if it is there
534
- const index = parts.findIndex(p => p === 'resource');
534
+ const index = parts.findIndex((p) => p === 'resource');
535
535
 
536
536
  if (index >= 0) {
537
537
  parts = parts.slice(0, index);
@@ -7,9 +7,9 @@ export const state = function() {
7
7
  };
8
8
 
9
9
  export const getters = {
10
- isTooManyItemsToAutoUpdate: state => state.isTooManyItemsToAutoUpdate,
11
- refreshFlag: state => state.refreshFlag,
12
- manualRefreshIsLoading: state => state.manualRefreshIsLoading
10
+ isTooManyItemsToAutoUpdate: (state) => state.isTooManyItemsToAutoUpdate,
11
+ refreshFlag: (state) => state.refreshFlag,
12
+ manualRefreshIsLoading: (state) => state.manualRefreshIsLoading
13
13
  };
14
14
 
15
15
  export const mutations = {