@rancher/shell 0.2.4 → 0.3.0

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 (493) hide show
  1. package/assets/styles/themes/_dark.scss +4 -0
  2. package/assets/styles/themes/_light.scss +5 -0
  3. package/assets/translations/en-us.yaml +14 -2
  4. package/assets/translations/zh-hans.yaml +7 -5
  5. package/chart/istio.vue +1 -1
  6. package/chart/monitoring/grafana/index.vue +1 -1
  7. package/chart/monitoring/index.vue +1 -1
  8. package/chart/monitoring/prometheus/index.vue +4 -4
  9. package/components/AlertTable.vue +1 -1
  10. package/components/AssignTo.vue +1 -1
  11. package/components/AsyncButton.vue +2 -2
  12. package/components/BrandImage.vue +1 -1
  13. package/components/ButtonGroup.vue +1 -1
  14. package/components/ClusterProviderIcon.vue +2 -2
  15. package/components/Collapse.vue +6 -2
  16. package/components/CollapsibleCard.vue +2 -2
  17. package/components/ConsumptionGauge.vue +4 -4
  18. package/components/ContainerResourceLimit.vue +1 -1
  19. package/components/CountBox.vue +1 -1
  20. package/components/CountGauge.vue +1 -1
  21. package/components/CruResource.vue +2 -1
  22. package/components/DashboardMetrics.vue +2 -2
  23. package/components/ExplorerProjectsNamespaces.vue +6 -6
  24. package/components/FixedBanner.vue +6 -6
  25. package/components/GlobalRoleBindings.vue +6 -6
  26. package/components/GradientBox.vue +2 -2
  27. package/components/IconMessage.vue +4 -4
  28. package/components/Import.vue +5 -5
  29. package/components/InputOrDisplay.vue +1 -1
  30. package/components/KeyValueView.vue +1 -1
  31. package/components/LabelValue.vue +1 -1
  32. package/components/ModalWithCard.vue +1 -1
  33. package/components/MoveModal.vue +1 -1
  34. package/components/PercentageBar.vue +2 -2
  35. package/components/PromptChangePassword.vue +1 -1
  36. package/components/PromptModal.vue +1 -1
  37. package/components/PromptRemove.vue +2 -2
  38. package/components/PromptRestore.vue +13 -13
  39. package/components/Questions/Question.js +1 -1
  40. package/components/ResourceCancelModal.vue +3 -3
  41. package/components/ResourceDetail/Masthead.vue +1 -1
  42. package/components/ResourceList/Masthead.vue +1 -1
  43. package/components/ResourceSummary.vue +4 -4
  44. package/components/RoleBindings.vue +19 -19
  45. package/components/SimpleBox.vue +5 -1
  46. package/components/SingleClusterInfo.vue +5 -5
  47. package/components/SortableTable/THead.vue +6 -2
  48. package/components/SortableTable/actions.js +4 -2
  49. package/components/SortableTable/index.vue +9 -9
  50. package/components/SortableTable/selection.js +2 -2
  51. package/components/TableSparkLine.vue +1 -1
  52. package/components/TypeDescription.vue +1 -1
  53. package/components/Wizard.vue +1 -1
  54. package/components/YamlEditor.vue +6 -6
  55. package/components/__tests__/ApplicationCard.test.ts +27 -0
  56. package/components/__tests__/Collapse.spec.ts +44 -0
  57. package/components/__tests__/CruResource.test.ts +3 -3
  58. package/components/__tests__/NamespaceFilter.test.ts +213 -0
  59. package/components/__tests__/SimpleBox.spec.ts +28 -0
  60. package/components/auth/RoleDetailEdit.vue +17 -15
  61. package/components/auth/SelectPrincipal.vue +9 -0
  62. package/components/auth/login/ldap.vue +3 -0
  63. package/components/cards/ApplicationCard.vue +10 -5
  64. package/components/fleet/FleetBundleResources.vue +8 -8
  65. package/components/fleet/FleetClusters.vue +10 -10
  66. package/components/fleet/FleetRepos.vue +5 -5
  67. package/components/fleet/FleetResources.vue +6 -6
  68. package/components/fleet/FleetSummary.vue +5 -5
  69. package/components/fleet/ResourcesSummary.vue +1 -1
  70. package/components/form/ArrayListGrouped.vue +1 -1
  71. package/components/form/ArrayListSelect.vue +3 -3
  72. package/components/form/BannerSettings.vue +6 -6
  73. package/components/form/ChangePassword.vue +3 -3
  74. package/components/form/Error.vue +2 -2
  75. package/components/form/FileSelector.vue +3 -3
  76. package/components/form/Footer.vue +1 -1
  77. package/components/form/GithubPicker.vue +4 -4
  78. package/components/form/KeyValue.vue +2 -2
  79. package/components/form/MatchExpressions.vue +1 -1
  80. package/components/form/Members/ClusterPermissionsEditor.vue +11 -11
  81. package/components/form/Members/MembershipEditor.vue +2 -2
  82. package/components/form/NodeAffinity.vue +1 -1
  83. package/components/form/Password.vue +3 -3
  84. package/components/form/PodAffinity.vue +1 -1
  85. package/components/form/ProjectMemberEditor.vue +1 -1
  86. package/components/form/ResourceQuota/shared.js +12 -12
  87. package/components/form/SecretSelector.vue +1 -1
  88. package/components/form/Security.vue +1 -1
  89. package/components/form/Select.vue +4 -0
  90. package/components/form/SimpleSecretSelector.vue +1 -1
  91. package/components/form/Taints.vue +1 -1
  92. package/components/form/UnitInput.vue +7 -7
  93. package/components/form/ValueFromResource.vue +1 -1
  94. package/components/form/WorkloadPorts.vue +1 -1
  95. package/components/formatter/AppSummaryGraph.vue +4 -4
  96. package/components/formatter/BadgeStateFormatter.vue +2 -2
  97. package/components/formatter/Checked.vue +1 -1
  98. package/components/formatter/ClusterLink.vue +3 -3
  99. package/components/formatter/Date.vue +1 -1
  100. package/components/formatter/DelayedValue.vue +1 -1
  101. package/components/formatter/Endpoints.vue +1 -1
  102. package/components/formatter/FleetSummaryGraph.vue +4 -4
  103. package/components/formatter/IconIsDefault.vue +1 -1
  104. package/components/formatter/IconText.vue +4 -4
  105. package/components/formatter/ImagePercentageBar.vue +4 -4
  106. package/components/formatter/IngressFullPath.vue +1 -1
  107. package/components/formatter/LinkDetail.vue +3 -3
  108. package/components/formatter/List.vue +1 -1
  109. package/components/formatter/ListLink.vue +1 -1
  110. package/components/formatter/ListLinkDetail.vue +1 -1
  111. package/components/formatter/LiveDate.vue +3 -3
  112. package/components/formatter/LivePodRestarts.vue +1 -1
  113. package/components/formatter/Number.vue +1 -1
  114. package/components/formatter/Percentage.vue +2 -2
  115. package/components/formatter/PercentageBar.vue +3 -3
  116. package/components/formatter/PodImages.vue +1 -1
  117. package/components/formatter/Principal.vue +1 -1
  118. package/components/formatter/PrincipalGroupBindings.vue +2 -2
  119. package/components/formatter/QualityText.vue +1 -1
  120. package/components/formatter/ReceiverIcons.vue +2 -2
  121. package/components/formatter/Scale.vue +1 -1
  122. package/components/formatter/ScanResult.vue +1 -1
  123. package/components/formatter/SecretData.vue +1 -1
  124. package/components/formatter/ServiceType.vue +1 -1
  125. package/components/formatter/Shortened.vue +1 -1
  126. package/components/formatter/VerticalScroll.vue +2 -2
  127. package/components/formatter/VirtualServiceGateways.vue +3 -3
  128. package/components/formatter/Weight.vue +2 -2
  129. package/components/formatter/WorkloadDetailEndpoints.vue +1 -1
  130. package/components/formatter/WorkloadHealthScale.vue +2 -2
  131. package/components/formatter/__tests__/Date.test.ts +60 -0
  132. package/components/formatter/__tests__/LinkDetail.test.ts +72 -0
  133. package/components/formatter/__tests__/LiveDate.test.ts +84 -0
  134. package/components/formatter/__tests__/Si.test.ts +35 -0
  135. package/components/graph/LinePlot.vue +1 -1
  136. package/components/graph/ProgressArc.vue +5 -5
  137. package/components/nav/GlobalLoading.vue +1 -1
  138. package/components/nav/Header.vue +1 -2
  139. package/components/nav/Jump.vue +3 -3
  140. package/components/nav/NamespaceFilter.vue +71 -22
  141. package/components/nav/TopLevelMenu.vue +4 -4
  142. package/components/nav/Type.vue +1 -1
  143. package/components/nav/WindowManager/ChartReadme.vue +1 -1
  144. package/components/nav/WindowManager/ContainerLogs.vue +3 -3
  145. package/components/nav/WindowManager/ContainerShell.vue +19 -0
  146. package/components/nav/WindowManager/KubectlShell.vue +6 -6
  147. package/components/nav/WindowManager/MachineSsh.vue +1 -1
  148. package/components/nav/WindowManager/index.vue +196 -25
  149. package/config/labels-annotations.js +19 -19
  150. package/config/product/apps.js +5 -5
  151. package/config/product/auth.js +20 -20
  152. package/config/product/cis.js +24 -24
  153. package/config/product/explorer.js +22 -21
  154. package/config/product/fleet.js +7 -7
  155. package/config/product/gatekeeper.js +7 -7
  156. package/config/product/harvester-manager.js +8 -8
  157. package/config/product/istio.js +7 -7
  158. package/config/product/legacy.js +21 -21
  159. package/config/product/logging.js +90 -90
  160. package/config/product/manager.js +14 -14
  161. package/config/product/monitoring.js +36 -36
  162. package/config/product/multi-cluster-apps.js +24 -24
  163. package/config/product/settings.js +42 -42
  164. package/config/settings.ts +16 -16
  165. package/config/table-headers.js +55 -48
  166. package/config/types.js +7 -7
  167. package/config/uiplugins.js +4 -4
  168. package/creators/app/app.package.json +4 -1
  169. package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
  170. package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
  171. package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
  172. package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
  173. package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
  174. package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
  175. package/creators/app/init +16 -17
  176. package/creators/app/package.json +7 -1
  177. package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
  178. package/creators/pkg/{index.ts → files/index.ts} +0 -0
  179. package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
  180. package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
  181. package/creators/pkg/init +1 -1
  182. package/creators/pkg/package.json +1 -1
  183. package/creators/update/init +56 -0
  184. package/creators/update/package.json +20 -0
  185. package/creators/update/upgrade +56 -0
  186. package/detail/cis.cattle.io.clusterscan.vue +6 -6
  187. package/detail/configmap.vue +1 -1
  188. package/detail/constraints.gatekeeper.sh.constraint.vue +1 -1
  189. package/detail/fleet.cattle.io.bundle.vue +5 -5
  190. package/detail/fleet.cattle.io.gitrepo.vue +5 -5
  191. package/detail/helm.cattle.io.projecthelmchart.vue +1 -1
  192. package/detail/management.cattle.io.user.vue +3 -3
  193. package/detail/namespace.vue +13 -13
  194. package/detail/node.vue +2 -2
  195. package/detail/pod.vue +1 -1
  196. package/detail/provisioning.cattle.io.cluster.vue +12 -1
  197. package/detail/secret.vue +2 -2
  198. package/detail/workload/index.vue +1 -1
  199. package/dialog/AddClusterMemberDialog.vue +1 -1
  200. package/dialog/AddCustomBadgeDialog.vue +4 -4
  201. package/dialog/AddProjectMemberDialog.vue +29 -22
  202. package/dialog/AddonConfigConfirmationDialog.vue +1 -1
  203. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  204. package/dialog/DrainNode.vue +12 -12
  205. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  206. package/dialog/GenericPrompt.vue +1 -1
  207. package/dialog/RollbackWorkloadDialog.vue +8 -8
  208. package/dialog/RotateCertificatesDialog.vue +4 -4
  209. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  210. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  211. package/dialog/ScaleMachineDownDialog.vue +1 -1
  212. package/edit/__tests__/management.cattle.io.setting.test.ts +1 -1
  213. package/edit/auth/azuread.vue +2 -2
  214. package/edit/auth/github.vue +2 -2
  215. package/edit/auth/ldap/index.vue +4 -4
  216. package/edit/auth/oidc.vue +3 -3
  217. package/edit/auth/saml.vue +4 -4
  218. package/edit/autoscaling.horizontalpodautoscaler/external-metric.vue +2 -2
  219. package/edit/autoscaling.horizontalpodautoscaler/metric-object-reference.vue +1 -1
  220. package/edit/autoscaling.horizontalpodautoscaler/object-metric.vue +2 -2
  221. package/edit/autoscaling.horizontalpodautoscaler/pod-metric.vue +2 -2
  222. package/edit/cis.cattle.io.clusterscan.vue +2 -2
  223. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -1
  224. package/edit/fleet.cattle.io.clustergroup.vue +3 -3
  225. package/edit/fleet.cattle.io.gitrepo.vue +9 -9
  226. package/edit/group.principal.vue +2 -2
  227. package/edit/helm.cattle.io.projecthelmchart.vue +3 -3
  228. package/edit/logging-flow/index.vue +1 -1
  229. package/edit/logging.banzaicloud.io.output/providers/datadog.vue +1 -1
  230. package/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue +1 -1
  231. package/edit/logging.banzaicloud.io.output/providers/gcs.vue +1 -1
  232. package/edit/logging.banzaicloud.io.output/providers/gelf.vue +1 -1
  233. package/edit/logging.banzaicloud.io.output/providers/kafka.vue +1 -1
  234. package/edit/logging.banzaicloud.io.output/providers/logz.vue +1 -1
  235. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -1
  236. package/edit/logging.banzaicloud.io.output/providers/opensearch.vue +213 -0
  237. package/edit/logging.banzaicloud.io.output/providers/redis.vue +142 -0
  238. package/edit/logging.banzaicloud.io.output/providers/s3.vue +1 -1
  239. package/edit/logging.banzaicloud.io.output/providers/splunkHec.vue +1 -1
  240. package/edit/logging.banzaicloud.io.output/providers/syslog.vue +1 -1
  241. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  242. package/edit/management.cattle.io.project.vue +3 -3
  243. package/edit/management.cattle.io.projectroletemplatebinding.vue +5 -5
  244. package/edit/management.cattle.io.setting.vue +1 -1
  245. package/edit/management.cattle.io.user.vue +4 -4
  246. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +15 -15
  247. package/edit/monitoring.coreos.com.alertmanagerconfig/tls.vue +1 -1
  248. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +4 -4
  249. package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +5 -5
  250. package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +3 -3
  251. package/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue +3 -3
  252. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +4 -4
  253. package/edit/monitoring.coreos.com.receiver/auth.vue +2 -2
  254. package/edit/monitoring.coreos.com.receiver/index.vue +1 -1
  255. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  256. package/edit/monitoring.coreos.com.receiver/types/opsgenie.vue +1 -1
  257. package/edit/monitoring.coreos.com.receiver/types/pagerduty.vue +1 -1
  258. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  259. package/edit/monitoring.coreos.com.route.vue +1 -1
  260. package/edit/networking.istio.io.destinationrule/LoadBalancer.vue +1 -1
  261. package/edit/networking.k8s.io.ingress/Certificates.vue +3 -3
  262. package/edit/networking.k8s.io.ingress/DefaultBackend.vue +2 -2
  263. package/edit/networking.k8s.io.ingress/IngressClass.vue +1 -1
  264. package/edit/networking.k8s.io.ingress/Rule.vue +1 -1
  265. package/edit/networking.k8s.io.ingress/RulePath.vue +5 -5
  266. package/edit/networking.k8s.io.ingress/Rules.vue +7 -7
  267. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +1 -1
  268. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +3 -3
  269. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -1
  270. package/edit/networking.k8s.io.networkpolicy/index.vue +5 -5
  271. package/edit/persistentvolume/index.vue +1 -1
  272. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +1 -1
  273. package/edit/persistentvolume/plugins/azureDisk.vue +1 -1
  274. package/edit/persistentvolume/plugins/azureFile.vue +1 -1
  275. package/edit/persistentvolume/plugins/cephfs.vue +2 -2
  276. package/edit/persistentvolume/plugins/cinder.vue +1 -1
  277. package/edit/persistentvolume/plugins/csi.vue +2 -2
  278. package/edit/persistentvolume/plugins/fc.vue +2 -2
  279. package/edit/persistentvolume/plugins/flexVolume.vue +2 -2
  280. package/edit/persistentvolume/plugins/flocker.vue +1 -1
  281. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +1 -1
  282. package/edit/persistentvolume/plugins/glusterfs.vue +1 -1
  283. package/edit/persistentvolume/plugins/hostPath.vue +1 -1
  284. package/edit/persistentvolume/plugins/iscsi.vue +2 -2
  285. package/edit/persistentvolume/plugins/local.vue +1 -1
  286. package/edit/persistentvolume/plugins/longhorn.vue +2 -2
  287. package/edit/persistentvolume/plugins/nfs.vue +1 -1
  288. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -1
  289. package/edit/persistentvolume/plugins/portworxVolume.vue +1 -1
  290. package/edit/persistentvolume/plugins/quobyte.vue +1 -1
  291. package/edit/persistentvolume/plugins/rbd.vue +2 -2
  292. package/edit/persistentvolume/plugins/scaleIO.vue +1 -1
  293. package/edit/persistentvolume/plugins/storageos.vue +1 -1
  294. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -1
  295. package/edit/persistentvolumeclaim.vue +2 -2
  296. package/edit/provisioning.cattle.io.cluster/DrainOptions.vue +1 -1
  297. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +1 -1
  298. package/edit/provisioning.cattle.io.cluster/S3Config.vue +1 -1
  299. package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.tests.ts +1 -1
  300. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  301. package/edit/provisioning.cattle.io.cluster/index.vue +2 -2
  302. package/edit/provisioning.cattle.io.cluster/rke2.vue +18 -12
  303. package/edit/resources.cattle.io.backup.vue +2 -2
  304. package/edit/secret/generic.vue +1 -0
  305. package/edit/storage.k8s.io.storageclass/index.vue +2 -2
  306. package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/no-provisioner.vue +1 -1
  307. package/edit/token.vue +1 -1
  308. package/edit/ui.cattle.io.navlink.vue +8 -8
  309. package/edit/workload/Job.vue +3 -3
  310. package/edit/workload/Upgrading.vue +1 -1
  311. package/edit/workload/VolumeClaimTemplate.vue +1 -1
  312. package/edit/workload/index.vue +3 -3
  313. package/edit/workload/mixins/workload.js +23 -23
  314. package/edit/workload/storage/ContainerMountPaths.vue +1 -1
  315. package/edit/workload/storage/Mount.vue +1 -1
  316. package/edit/workload/storage/azureDisk.vue +1 -1
  317. package/edit/workload/storage/azureFile.vue +1 -1
  318. package/edit/workload/storage/csi/index.vue +1 -1
  319. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  320. package/edit/workload/storage/gcePersistentDisk.vue +1 -1
  321. package/edit/workload/storage/hostPath.vue +1 -1
  322. package/edit/workload/storage/nfs.vue +1 -1
  323. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  324. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -1
  325. package/edit/workload/storage/secret.vue +1 -1
  326. package/edit/workload/storage/vsphereVolume.vue +1 -1
  327. package/layouts/default.vue +77 -16
  328. package/list/__tests__/workload.test.ts +50 -0
  329. package/list/fleet.cattle.io.gitrepo.vue +1 -1
  330. package/list/group.principal.vue +8 -8
  331. package/list/harvesterhci.io.management.cluster.vue +1 -1
  332. package/list/helm.cattle.io.projecthelmchart.vue +1 -1
  333. package/list/management.cattle.io.feature.vue +1 -1
  334. package/list/node.vue +1 -1
  335. package/list/provisioning.cattle.io.cluster.vue +3 -3
  336. package/machine-config/amazonec2.vue +1 -1
  337. package/machine-config/harvester.vue +4 -4
  338. package/mixins/__tests__/create-edit-view.test.ts +1 -1
  339. package/mixins/chart.js +14 -14
  340. package/mixins/create-edit-view/index.js +5 -5
  341. package/mixins/form-validation.js +1 -1
  342. package/mixins/labeled-form-element.ts +6 -6
  343. package/mixins/resource-fetch.js +3 -3
  344. package/mixins/resource-manager.js +1 -1
  345. package/models/autoscaling.horizontalpodautoscaler.js +5 -5
  346. package/models/batch.cronjob.js +15 -15
  347. package/models/batch.job.js +22 -0
  348. package/models/catalog.cattle.io.app.js +6 -6
  349. package/models/catalog.cattle.io.clusterrepo.js +7 -7
  350. package/models/catalog.cattle.io.operation.js +5 -5
  351. package/models/chart.js +4 -4
  352. package/models/cis.cattle.io.clusterscan.js +10 -10
  353. package/models/cluster/node.js +36 -36
  354. package/models/cluster.x-k8s.io.machine.js +13 -13
  355. package/models/constraints.gatekeeper.sh.constraint.js +1 -1
  356. package/models/etcdbackup.js +4 -4
  357. package/models/fleet.cattle.io.cluster.js +15 -15
  358. package/models/fleet.cattle.io.clustergroup.js +1 -1
  359. package/models/fleet.cattle.io.gitrepo.js +15 -15
  360. package/models/group.principal.js +1 -1
  361. package/models/logging.banzaicloud.io.clusterflow.js +2 -2
  362. package/models/logging.banzaicloud.io.flow.js +2 -2
  363. package/models/logging.banzaicloud.io.output.js +15 -3
  364. package/models/management.cattle.io.authconfig.js +4 -4
  365. package/models/management.cattle.io.cluster.js +9 -9
  366. package/models/management.cattle.io.clusterroletemplatebinding.js +8 -8
  367. package/models/management.cattle.io.globalrole.js +24 -3
  368. package/models/management.cattle.io.node.js +9 -9
  369. package/models/management.cattle.io.nodepool.js +3 -3
  370. package/models/management.cattle.io.nodetemplate.js +21 -21
  371. package/models/management.cattle.io.project.js +2 -2
  372. package/models/management.cattle.io.projectroletemplatebinding.js +6 -6
  373. package/models/management.cattle.io.roletemplate.js +54 -31
  374. package/models/management.cattle.io.user.js +4 -4
  375. package/models/monitoring.coreos.com.alertmanagerconfig.js +4 -4
  376. package/models/monitoring.coreos.com.receiver.js +7 -7
  377. package/models/monitoring.coreos.com.route.js +2 -2
  378. package/models/namespace.js +13 -0
  379. package/models/persistentvolumeclaim.js +4 -4
  380. package/models/pod.js +10 -10
  381. package/models/provisioning.cattle.io.cluster.js +29 -29
  382. package/models/rbac.authorization.k8s.io.role.js +4 -4
  383. package/models/rke.cattle.io.etcdsnapshot.js +4 -4
  384. package/models/service.js +15 -15
  385. package/models/storage.k8s.io.storageclass.js +8 -8
  386. package/models/workload.js +28 -28
  387. package/nuxt.config.js +32 -17
  388. package/package.json +2 -2
  389. package/pages/about.vue +1 -1
  390. package/pages/account/index.vue +1 -1
  391. package/pages/auth/login.vue +37 -7
  392. package/pages/auth/setup.vue +11 -11
  393. package/pages/c/_cluster/_product/_resource/_id.vue +2 -2
  394. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  395. package/pages/c/_cluster/apps/charts/index.vue +18 -18
  396. package/pages/c/_cluster/apps/charts/install.vue +14 -14
  397. package/pages/c/_cluster/auth/config/_id.vue +2 -2
  398. package/pages/c/_cluster/auth/roles/_resource/_id.vue +2 -2
  399. package/pages/c/_cluster/auth/roles/index.vue +4 -6
  400. package/pages/c/_cluster/explorer/EventsTable.vue +8 -8
  401. package/pages/c/_cluster/explorer/index.vue +14 -14
  402. package/pages/c/_cluster/explorer/tools/index.vue +4 -4
  403. package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +2 -2
  404. package/pages/c/_cluster/fleet/index.vue +10 -10
  405. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  406. package/pages/c/_cluster/legacy/index.vue +1 -1
  407. package/pages/c/_cluster/longhorn/index.vue +1 -1
  408. package/pages/c/_cluster/mcapps/index.vue +1 -1
  409. package/pages/c/_cluster/navlinks/_group.vue +1 -1
  410. package/pages/c/_cluster/neuvector/index.vue +1 -1
  411. package/pages/c/_cluster/settings/banners.vue +30 -30
  412. package/pages/c/_cluster/settings/brand.vue +9 -9
  413. package/pages/c/_cluster/settings/links.vue +6 -6
  414. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +1 -1
  415. package/pages/c/_cluster/uiplugins/InstallDialog.vue +1 -1
  416. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +25 -8
  417. package/pages/c/_cluster/uiplugins/index.vue +2 -2
  418. package/pages/prefs.vue +11 -11
  419. package/pages/rio/mesh.vue +4 -4
  420. package/pages/support/index.vue +7 -7
  421. package/pkg/vue.config.js +10 -1
  422. package/plugins/dashboard-store/mutations.js +6 -6
  423. package/plugins/dashboard-store/normalize.js +1 -1
  424. package/plugins/dashboard-store/resource-class.js +100 -100
  425. package/plugins/steve/subscribe.js +4 -4
  426. package/plugins/steve/web-worker.steve-sub-worker.js +3 -3
  427. package/promptRemove/management.cattle.io.project.vue +1 -1
  428. package/promptRemove/mixin/roleDeletionCheck.js +7 -7
  429. package/promptRemove/pod.vue +2 -2
  430. package/rancher-components/Card/Card.test.ts +39 -0
  431. package/rancher-components/Card/Card.vue +3 -3
  432. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +0 -1
  433. package/rancher-components/StringList/StringList.test.ts +420 -45
  434. package/rancher-components/StringList/StringList.vue +10 -1
  435. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +181 -0
  436. package/rancher-components/Utils/DraggableZone/index.ts +1 -0
  437. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  438. package/rancher-components/components/BadgeState/BadgeState.vue +111 -0
  439. package/rancher-components/components/BadgeState/index.ts +1 -0
  440. package/rancher-components/components/Banner/Banner.test.ts +13 -0
  441. package/rancher-components/components/Banner/Banner.vue +174 -0
  442. package/rancher-components/components/Banner/index.ts +1 -0
  443. package/rancher-components/components/Card/Card.test.ts +37 -0
  444. package/rancher-components/components/Card/Card.vue +166 -0
  445. package/rancher-components/components/Card/index.ts +1 -0
  446. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
  447. package/rancher-components/components/Form/Checkbox/Checkbox.vue +416 -0
  448. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  449. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +23 -0
  450. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +355 -0
  451. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  452. package/rancher-components/components/Form/Radio/RadioButton.vue +276 -0
  453. package/rancher-components/components/Form/Radio/RadioGroup.vue +253 -0
  454. package/rancher-components/components/Form/Radio/index.ts +2 -0
  455. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +169 -0
  456. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  457. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +94 -0
  458. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +149 -0
  459. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  460. package/rancher-components/components/Form/index.ts +5 -0
  461. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +152 -0
  462. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  463. package/rancher-components/components/StringList/StringList.test.ts +483 -0
  464. package/rancher-components/components/StringList/StringList.vue +605 -0
  465. package/rancher-components/components/StringList/index.ts +1 -0
  466. package/rancher-components/components/Utils/DraggableZone/DraggableZone.vue +181 -0
  467. package/rancher-components/components/Utils/DraggableZone/index.ts +1 -0
  468. package/scripts/publish-shell.sh +38 -5
  469. package/scripts/record-deps.js +37 -0
  470. package/scripts/test-plugins-build.sh +11 -7
  471. package/scripts/typegen.sh +84 -0
  472. package/store/action-menu.js +3 -3
  473. package/store/auth.js +4 -4
  474. package/store/aws.js +4 -4
  475. package/store/catalog.js +22 -22
  476. package/store/index.js +4 -4
  477. package/store/plugins.js +2 -2
  478. package/store/prefs.js +9 -1
  479. package/store/type-map.js +46 -31
  480. package/store/uiplugins.ts +2 -2
  481. package/store/wm.js +10 -0
  482. package/types/shell/index.d.ts +3059 -0
  483. package/types/vue-shim.d +20 -0
  484. package/utils/alertmanagerconfig.js +6 -6
  485. package/utils/gc/gc-types.ts +1 -1
  486. package/utils/object.js +2 -2
  487. package/utils/parse-externalid.js +5 -5
  488. package/utils/time.js +6 -0
  489. package/utils/validators/formRules/__tests__/index.test.ts +3 -3
  490. package/components/.DS_Store +0 -0
  491. package/components/__tests__/.DS_Store +0 -0
  492. package/creators/pkg/nuxt.config.js +0 -6
  493. package/creators/pkg/package-lock.json +0 -37
@@ -6,7 +6,7 @@ export default {
6
6
 
7
7
  props: {
8
8
  value: {
9
- type: Number,
9
+ type: Number,
10
10
  default: 0,
11
11
  },
12
12
  row: {
@@ -14,7 +14,7 @@ export default {
14
14
  required: true
15
15
  },
16
16
  col: {
17
- type: Object,
17
+ type: Object,
18
18
  default: () => {}
19
19
  },
20
20
  },
@@ -5,7 +5,7 @@ import Tag from '@shell/components/Tag';
5
5
  export default {
6
6
  props: {
7
7
  value: {
8
- type: [Array, String],
8
+ type: [Array, String],
9
9
  default: null,
10
10
  },
11
11
  },
@@ -52,7 +52,7 @@ export default {
52
52
  },
53
53
  },
54
54
 
55
- methods: {
55
+ methods: {
56
56
  liveUpdate() {
57
57
  if (this.loading) {
58
58
  return 5;
@@ -144,7 +144,7 @@ export default {
144
144
  top: 0,
145
145
  left: 0,
146
146
  right: window.innerWidth || document.documentElement.clientWidth,
147
- bottom: window.innerHeight || document.documentElement.clientHeight,
147
+ bottom: window.innerHeight || document.documentElement.clientHeight,
148
148
  });
149
149
 
150
150
  if (insideWindow) {
@@ -0,0 +1,60 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import Date from '@shell/components/formatter/Date.vue';
3
+ import dayjs from 'dayjs';
4
+
5
+ describe('component: Date formatter', () => {
6
+ it.each([
7
+ 'ddd, MMM D YYYY',
8
+ 'MMM YYYY'
9
+ ])('should use date format pref', async(dateFormat) => {
10
+ const inputTime = dayjs().toString();
11
+ const expectedDate = dayjs(inputTime).format(dateFormat);
12
+ const wrapper = await mount(Date, {
13
+ propsData: { value: inputTime, showTime: false },
14
+ mocks: { $store: { getters: { 'prefs/get': () => dateFormat } } }
15
+ });
16
+ const element = wrapper.find('span');
17
+
18
+ expect(element.text()).toBe(expectedDate);
19
+ });
20
+
21
+ it.each([
22
+ 'h:mm:ss a',
23
+ 'hh:mm'
24
+ ])('should use time format pref', async(timeFormat) => {
25
+ const inputTime = dayjs().toString();
26
+ const expectedDate = dayjs(inputTime).format(timeFormat);
27
+ const wrapper = await mount(Date, {
28
+ propsData: { value: inputTime, showDate: false },
29
+ mocks: { $store: { getters: { 'prefs/get': () => timeFormat } } }
30
+ });
31
+ const element = wrapper.find('span');
32
+
33
+ expect(element.text()).toBe(expectedDate);
34
+ });
35
+
36
+ it.each([
37
+ 'div',
38
+ 'hr'
39
+ ])('use custom tag provided by tagName prop', async(tagName) => {
40
+ const wrapper = await mount(Date, {
41
+ propsData: { value: dayjs().toString(), tagName },
42
+ mocks: { $store: { getters: { 'prefs/get': jest.fn() } } }
43
+ });
44
+ const element = wrapper.find(tagName);
45
+
46
+ expect(element).toBeDefined();
47
+ });
48
+
49
+ it.each([
50
+ true,
51
+ false
52
+ ])('should render day and time on different lines if configured', async(multiline) => {
53
+ const wrapper = await mount(Date, {
54
+ propsData: { value: dayjs().toString(), multiline },
55
+ mocks: { $store: { getters: { 'prefs/get': jest.fn() } } }
56
+ });
57
+
58
+ expect(wrapper.find('br').exists()).toBe(multiline);
59
+ });
60
+ });
@@ -0,0 +1,72 @@
1
+ import { mount, RouterLinkStub } from '@vue/test-utils';
2
+ import LinkDetail from '@shell/components/formatter/LinkDetail.vue';
3
+
4
+ describe('component: LinkDetail', () => {
5
+ it('should display the value', async() => {
6
+ const location = 'route-somewhere';
7
+ const wrapper = await mount(LinkDetail, {
8
+ propsData: { row: { detailLocation: location }, value: 'test-name' },
9
+ stubs: { nLink: RouterLinkStub }
10
+ });
11
+
12
+ const link = wrapper.findComponent(RouterLinkStub);
13
+
14
+ expect(link.text()).toBe('test-name');
15
+ });
16
+
17
+ it('should use rows detailLocation to render a link', async() => {
18
+ const location = 'route-somewhere';
19
+ const wrapper = await mount(LinkDetail, {
20
+ propsData: { row: { detailLocation: location } },
21
+ stubs: { nLink: RouterLinkStub }
22
+ });
23
+
24
+ const link = wrapper.findComponent(RouterLinkStub);
25
+
26
+ expect(link.props().to).toBe(location);
27
+ });
28
+
29
+ it('should render the value in a span if no location is provided', async() => {
30
+ const wrapper = await mount(LinkDetail, {
31
+ propsData: {
32
+ row: { detailLocation: null }, value: 'test-name', col: { }
33
+ },
34
+ stubs: { nLink: RouterLinkStub }
35
+ });
36
+ const span = wrapper.find('span span');
37
+
38
+ const link = wrapper.findComponent(RouterLinkStub);
39
+
40
+ expect(link.exists()).toBe(false);
41
+
42
+ expect(span.element.innerHTML).toContain('test-name');
43
+ });
44
+
45
+ it('should use getCustomDetailLink if defined', async() => {
46
+ const location = 'route-somewhere';
47
+ const wrapper = await mount(LinkDetail, {
48
+ propsData: {
49
+ row: { detailLocation: location }, value: 'test-name', col: { }, getCustomDetailLink: () => 'custom-link'
50
+ },
51
+ stubs: { nLink: RouterLinkStub }
52
+ });
53
+
54
+ const link = wrapper.findComponent(RouterLinkStub);
55
+
56
+ expect(link.props().to).toBe('custom-link');
57
+ });
58
+
59
+ it('should use reference to find location if defined', async() => {
60
+ const location = 'route-somewhere';
61
+ const wrapper = await mount(LinkDetail, {
62
+ propsData: {
63
+ row: { detailLocation: location, otherKey: 'other-location' }, value: 'test-name', col: { }, reference: 'otherKey'
64
+ },
65
+ stubs: { nLink: RouterLinkStub }
66
+ });
67
+
68
+ const link = wrapper.findComponent(RouterLinkStub);
69
+
70
+ expect(link.props().to).toBe('other-location');
71
+ });
72
+ });
@@ -0,0 +1,84 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import LiveDate from '@shell/components/formatter/LiveDate.vue';
3
+ import dayjs from 'dayjs';
4
+ import { ExtendedVue, Vue } from 'vue/types/vue';
5
+ import { DefaultProps } from 'vue/types/options';
6
+
7
+ const defaultMock = {
8
+ $store: {
9
+ getters: {
10
+ 'prefs/get': jest.fn(),
11
+ 'i18n/t': ( unitKey: string, { count }: any) => unitKey.split('.')[1] + (count > 1 ? 's' : ''),
12
+ 'i18n/exists': () => false,
13
+
14
+ }
15
+ },
16
+ };
17
+
18
+ describe('component: LiveDate', () => {
19
+ it('should show a dash if no date is provided', () => {
20
+ const wrapper = mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, { mocks: defaultMock });
21
+ const element = wrapper.find('span');
22
+
23
+ expect(element.text()).toBe('-');
24
+ });
25
+
26
+ it('should say just now when the time provided is the current time', async() => {
27
+ const wrapper = await mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
28
+ mocks: defaultMock,
29
+ propsData: { value: dayjs().toString() }
30
+ });
31
+
32
+ const element = wrapper.find('span');
33
+
34
+ expect(element.text()).toContain('Just now');
35
+ });
36
+
37
+ it('should display difference between value and current time', async() => {
38
+ const wrapper = await mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, { mocks: defaultMock, propsData: { value: Date.now() - 5000 } });
39
+
40
+ const element = wrapper.find('span');
41
+
42
+ expect(element.text()).toContain('5 secs');
43
+ });
44
+
45
+ // this test calls a component method directly: we're testing this because it's how 'live' formatters are used in sortabletable
46
+ it('should recompute and update the displayed value when prompted', async() => {
47
+ const wrapper = await mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
48
+ mocks: defaultMock,
49
+ propsData: { value: dayjs().toString() }
50
+ });
51
+
52
+ let element = wrapper.find('span');
53
+
54
+ expect(element.text()).toContain('Just now');
55
+ await new Promise(resolve => setTimeout(resolve, 1000));
56
+ await wrapper.vm.liveUpdate(Date.now());
57
+
58
+ element = wrapper.find('span');
59
+ expect(element.text()).toContain('1 sec');
60
+ });
61
+
62
+ it('should include ago suffix if enabled', async() => {
63
+ const wrapper = await mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, { mocks: defaultMock, propsData: { value: Date.now() - 5000, addSuffix: true } });
64
+
65
+ const element = wrapper.find('span');
66
+
67
+ expect(element.text()).toContain('5 secs ago');
68
+ });
69
+
70
+ it.each([
71
+ [86400000, '1 day'],
72
+ [82800000, '23 hours'],
73
+ [3540000, '59 mins']
74
+ ])('should use the largest sensible time unit', async(msAgo, displayValue) => {
75
+ const wrapper = await mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, {
76
+ mocks: defaultMock,
77
+ propsData: { value: Date.now() - msAgo }
78
+ });
79
+
80
+ const element = wrapper.find('span');
81
+
82
+ expect(element.text()).toContain(displayValue);
83
+ });
84
+ });
@@ -0,0 +1,35 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import Si from '@shell/components/formatter/Si.vue';
3
+
4
+ describe('component: Si formatter', () => {
5
+ it('should format integers as Bytes', async() => {
6
+ const wrapper = await mount(Si, { propsData: { value: 13 } });
7
+
8
+ const element = wrapper.find('span');
9
+
10
+ expect(element.text()).toBe('13 B');
11
+ });
12
+
13
+ it.each([
14
+ ['1024 Mi', '1 GiB'],
15
+ ['1024', '1 KiB'],
16
+ ['2048 GiB', '2 TiB']
17
+ ])('should parse and re-format Si input strings', async(input, out) => {
18
+ const wrapper = await mount(Si, { propsData: { value: input, needParseSi: true } });
19
+
20
+ const element = wrapper.find('span');
21
+
22
+ expect(element.text()).toBe(out);
23
+ });
24
+
25
+ it('should allow additional si formatting opts', async() => {
26
+ const wrapper = await mount(Si, {
27
+ propsData: {
28
+ value: '1 TiB', needParseSi: true, opts: { maxExponent: 3 }
29
+ }
30
+ });
31
+ const element = wrapper.find('span');
32
+
33
+ expect(element.text()).toBe('1024 GiB');
34
+ });
35
+ });
@@ -2,7 +2,7 @@
2
2
  import * as d3 from 'd3';
3
3
  export default {
4
4
  props: {
5
- graphWidth: {
5
+ graphWidth: {
6
6
  type: Number,
7
7
  required: true
8
8
  },
@@ -6,7 +6,7 @@ export default {
6
6
  type: Number,
7
7
  default: 0
8
8
  },
9
- graphWidth: {
9
+ graphWidth: {
10
10
  type: Number,
11
11
  required: true
12
12
  },
@@ -37,10 +37,10 @@ export default {
37
37
  const arc = d3.arc();
38
38
 
39
39
  return arc({
40
- innerRadius: vm.innerRadius,
41
- outerRadius: vm.outerRadius,
42
- endAngle: 2 * (Math.PI),
43
- startAngle: 0
40
+ innerRadius: vm.innerRadius,
41
+ outerRadius: vm.outerRadius,
42
+ endAngle: 2 * (Math.PI),
43
+ startAngle: 0
44
44
  });
45
45
  },
46
46
  arc() {
@@ -6,7 +6,7 @@ export default {
6
6
 
7
7
  data: () => ({ loading: false }),
8
8
 
9
- methods: {
9
+ methods: {
10
10
  start() {
11
11
  this.loading = true;
12
12
  },
@@ -49,7 +49,7 @@ export default {
49
49
  searchShortcut,
50
50
  shellShortcut,
51
51
  LOGGED_OUT,
52
- navHeaderRight: null
52
+ navHeaderRight: null
53
53
  };
54
54
  },
55
55
 
@@ -296,7 +296,6 @@ export default {
296
296
  <template>
297
297
  <header
298
298
  ref="header"
299
- class="header-layout"
300
299
  >
301
300
  <div>
302
301
  <TopLevelMenu v-if="isMultiCluster || !isSingleProduct" />
@@ -10,8 +10,8 @@ export default {
10
10
  data() {
11
11
  return {
12
12
  isMac,
13
- value: '',
14
- groups: null,
13
+ value: '',
14
+ groups: null,
15
15
  };
16
16
  },
17
17
 
@@ -91,7 +91,7 @@ export default {
91
91
  </template>
92
92
 
93
93
  <style lang="scss" scoped>
94
- .search, .search:hover, search:focus {
94
+ .search, .search:hover, .search:focus {
95
95
  position: relative;
96
96
  background-color: var(--dropdown-bg);
97
97
  border-radius: 0;
@@ -87,7 +87,8 @@ export default {
87
87
  const t = this.$store.getters['i18n/t'];
88
88
  let out = [];
89
89
 
90
- if (this.currentProduct.customNamespaceFilter) {
90
+ // TODO: Add return info
91
+ if (this.currentProduct?.customNamespaceFilter && this.currentProduct?.inStore) {
91
92
  // Sometimes the component can show before the 'currentProduct' has caught up, so access the product via the getter rather
92
93
  // than caching it in the `fetch`
93
94
  return this.$store.getters[`${ this.currentProduct.inStore }/namespaceFilterOptions`]({
@@ -96,6 +97,7 @@ export default {
96
97
  });
97
98
  }
98
99
 
100
+ // TODO: Add return info
99
101
  if (!this.currentProduct?.hideSystemResources) {
100
102
  out = [
101
103
  {
@@ -129,6 +131,11 @@ export default {
129
131
  }
130
132
 
131
133
  const inStore = this.$store.getters['currentStore'](NAMESPACE);
134
+
135
+ if (!inStore) {
136
+ return out;
137
+ }
138
+
132
139
  let namespaces = sortBy(
133
140
  this.$store.getters[`${ inStore }/all`](NAMESPACE),
134
141
  ['nameDisplay']
@@ -249,19 +256,21 @@ export default {
249
256
 
250
257
  value: {
251
258
  get() {
259
+ // Use last picked filter from user preferences
252
260
  const prefs = this.$store.getters['prefs/get'](NAMESPACE_FILTERS);
253
- const prefDefault = this.currentProduct.customNamespaceFilter ? [] : [ALL_USER];
254
- const values = prefs[this.key] || prefDefault;
261
+
262
+ const prefDefault = this.currentProduct?.customNamespaceFilter ? [] : [ALL_USER];
263
+ const values = prefs && prefs[this.key] ? prefs[this.key] : prefDefault;
255
264
  const options = this.options;
256
265
 
257
266
  // Remove values that are not valid options
258
- const out = values
267
+ const filters = values
259
268
  .map((value) => {
260
269
  return findBy(options, 'id', value);
261
270
  })
262
271
  .filter(x => !!x);
263
272
 
264
- return out;
273
+ return filters;
265
274
  },
266
275
 
267
276
  set(neu) {
@@ -291,7 +300,7 @@ export default {
291
300
  // If there was something selected and you remove it, go back to user by default
292
301
  // Unless it was user or all
293
302
  if (neu.length === 0 && !hadUser && !hadAll) {
294
- ids = this.currentProduct.customNamespaceFilter ? [] : [ALL_USER];
303
+ ids = this.currentProduct?.customNamespaceFilter ? [] : [ALL_USER];
295
304
  } else {
296
305
  ids = neu.map(x => x.id);
297
306
  }
@@ -426,14 +435,23 @@ export default {
426
435
  }
427
436
  },
428
437
  inputKeyHandler(e) {
429
- if (e.keyCode === KEY.DOWN ) {
438
+ switch (e.keyCode) {
439
+ case KEY.DOWN:
430
440
  e.preventDefault();
431
441
  e.stopPropagation();
432
442
  this.down(true);
433
- } else if (e.keyCode === KEY.TAB) {
443
+ break;
444
+ case KEY.TAB:
434
445
  // Tab out of the input box
435
446
  this.close();
436
447
  e.target.blur();
448
+ break;
449
+ case KEY.CR:
450
+ if (this.filtered.length === 1) {
451
+ this.selectOption(this.filtered[0]);
452
+ this.filter = '';
453
+ }
454
+ break;
437
455
  }
438
456
  },
439
457
  mouseOver(event) {
@@ -553,6 +571,7 @@ export default {
553
571
  <template>
554
572
  <div
555
573
  class="ns-filter"
574
+ data-testid="namespaces-filter"
556
575
  tabindex="0"
557
576
  @focus="open()"
558
577
  >
@@ -561,53 +580,68 @@ export default {
561
580
  class="ns-glass"
562
581
  @click="close()"
563
582
  />
564
- <!-- Dropdown control -->
583
+
584
+ <!-- Select Dropdown control -->
565
585
  <div
566
586
  ref="dropdown"
567
587
  class="ns-dropdown"
588
+ data-testid="namespaces-dropdown"
568
589
  :class="{ 'ns-open': isOpen }"
569
590
  @click="toggle()"
570
591
  >
592
+ <!-- No filters found or available -->
571
593
  <div
572
594
  v-if="value.length === 0"
573
595
  ref="values"
596
+ data-testid="namespaces-values-none"
574
597
  class="ns-values"
575
598
  >
576
599
  {{ t('nav.ns.all') }}
577
600
  </div>
601
+
602
+ <!-- Filtered by set with custom label E.g. "All namespaces" -->
578
603
  <div
579
604
  v-else-if="isSingleSpecial"
580
605
  ref="values"
606
+ data-testid="namespaces-values-label"
581
607
  class="ns-values"
582
608
  >
583
609
  {{ value[0].label }}
584
610
  </div>
611
+
612
+ <!-- All the selected namespaces -->
585
613
  <div
586
614
  v-else
587
615
  ref="values"
588
616
  v-tooltip="tooltip"
617
+ data-testid="namespaces-values"
589
618
  class="ns-values"
590
619
  >
591
620
  <div
592
621
  v-if="total"
593
622
  ref="total"
623
+ data-testid="namespaces-values-total"
594
624
  class="ns-value ns-abs"
595
625
  >
596
626
  {{ t('namespaceFilter.selected.label', { total }) }}
597
627
  </div>
598
628
  <div
599
- v-for="ns in value"
629
+ v-for="(ns, j) in value"
600
630
  ref="value"
601
631
  :key="ns.id"
632
+ :data-testid="`namespaces-value-${j}`"
602
633
  class="ns-value"
603
634
  >
604
635
  <div>{{ ns.label }}</div>
605
636
  <i
606
637
  class="icon icon-close"
638
+ :data-testid="`namespaces-values-close-${j}`"
607
639
  @click="removeOption(ns, $event)"
608
640
  />
609
641
  </div>
610
642
  </div>
643
+
644
+ <!-- Inform user if more namespaces are selected -->
611
645
  <div
612
646
  v-if="hidden > 0"
613
647
  ref="more"
@@ -630,9 +664,12 @@ export default {
630
664
  class="hide"
631
665
  @shortkey="open()"
632
666
  />
667
+
668
+ <!-- Dropdown menu -->
633
669
  <div
634
670
  v-if="isOpen"
635
671
  class="ns-dropdown-menu"
672
+ data-testid="namespaces-menu"
636
673
  >
637
674
  <div class="ns-controls">
638
675
  <div class="ns-input">
@@ -663,12 +700,16 @@ export default {
663
700
  role="list"
664
701
  >
665
702
  <div
666
- v-for="opt in filtered"
703
+ v-for="(opt, i) in filtered"
667
704
  :id="opt.elementId"
668
705
  :key="opt.id"
669
706
  tabindex="0"
670
707
  class="ns-option"
671
- :class="{'ns-selected': opt.selected}"
708
+ :class="{
709
+ 'ns-selected': opt.selected,
710
+ 'ns-single-match': filtered.length === 1 && !opt.selected,
711
+ }"
712
+ :data-testid="`namespaces-option-${i}`"
672
713
  @click="selectOption(opt)"
673
714
  @mouseover="mouseOver($event)"
674
715
  @keydown="itemKeyHandler($event, opt)"
@@ -695,6 +736,7 @@ export default {
695
736
  <div
696
737
  v-if="filtered.length === 0"
697
738
  class="ns-none"
739
+ data-testid="namespaces-option-none"
698
740
  >
699
741
  {{ t('namespaceFilter.noMatchingOptions') }}
700
742
  </div>
@@ -830,25 +872,32 @@ export default {
830
872
  }
831
873
  }
832
874
  }
833
- &.ns-selected:not(:hover) {
834
- .ns-item {
835
- > * {
836
- color: var(--dropdown-hover-bg);
875
+ &.ns-selected:not(:hover) {
876
+ .ns-item {
877
+ > * {
878
+ color: var(--dropdown-hover-bg);
879
+ }
837
880
  }
838
881
  }
839
- }
840
- &.ns-selected {
841
- &:hover,&:focus {
882
+ &.ns-selected {
883
+ &:hover,&:focus {
884
+ .ns-item {
885
+ > * {
886
+ background-color: var(--dropdown-hover-bg);
887
+ color: var(--dropdown-hover-text);
888
+ }
889
+ }
890
+ }
891
+ }
892
+ &.ns-single-match {
842
893
  .ns-item {
894
+ background-color: var(--dropdown-hover-bg);
843
895
  > * {
844
- background-color: var(--dropdown-hover-bg);
845
896
  color: var(--dropdown-hover-text);
846
897
  }
847
898
  }
848
899
  }
849
900
  }
850
-
851
- }
852
901
  }
853
902
 
854
903
  .ns-dropdown {
@@ -27,12 +27,12 @@ export default {
27
27
  const hasProvCluster = this.$store.getters[`management/schemaFor`](CAPI.RANCHER_CLUSTER);
28
28
 
29
29
  return {
30
- shown: false,
30
+ shown: false,
31
31
  displayVersion,
32
32
  fullVersion,
33
- uiCommit: UI_COMMIT,
34
- uiVersion: UI_VERSION,
35
- clusterFilter: '',
33
+ uiCommit: UI_COMMIT,
34
+ uiVersion: UI_VERSION,
35
+ clusterFilter: '',
36
36
  hasProvCluster,
37
37
  };
38
38
  },
@@ -8,7 +8,7 @@ export default {
8
8
 
9
9
  components: { Favorite },
10
10
 
11
- props: {
11
+ props: {
12
12
  type: {
13
13
  type: Object,
14
14
  required: true
@@ -5,7 +5,7 @@ import Window from './Window';
5
5
  export default {
6
6
  components: { Window, ChartReadme },
7
7
 
8
- props: {
8
+ props: {
9
9
  // The definition of the tab itself
10
10
  tab: {
11
11
  type: Object,