@rancher/shell 0.3.0 → 0.3.1

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 (322) hide show
  1. package/assets/styles/global/_button.scss +5 -1
  2. package/assets/styles/global/_columns.scss +4 -0
  3. package/assets/styles/global/_layout.scss +1 -2
  4. package/assets/styles/global/_select.scss +1 -4
  5. package/assets/styles/themes/_dark.scss +4 -4
  6. package/assets/styles/themes/_light.scss +4 -3
  7. package/assets/styles/themes/_suse.scss +1 -1
  8. package/assets/styles/vendor/vue-select.scss +4 -3
  9. package/assets/translations/en-us.yaml +669 -73
  10. package/assets/translations/zh-hans.yaml +547 -165
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/cloud-credential/azure.vue +23 -0
  13. package/cloud-credential/harvester.vue +25 -62
  14. package/cloud-credential/pnap.vue +80 -0
  15. package/components/.DS_Store +0 -0
  16. package/components/AdvancedSection.vue +9 -2
  17. package/components/Alert.vue +2 -2
  18. package/components/ButtonDropdown.vue +0 -2
  19. package/components/ButtonGroup.vue +1 -0
  20. package/components/CollapsibleCard.vue +0 -1
  21. package/components/CruResource.vue +41 -4
  22. package/components/DetailTop.vue +58 -3
  23. package/components/DisableAuthProviderModal.vue +106 -0
  24. package/{rancher-components/components/Utils/DraggableZone → components}/DraggableZone.vue +0 -0
  25. package/components/ExplorerMembers.vue +253 -30
  26. package/components/ExplorerProjectsNamespaces.vue +77 -33
  27. package/components/GrowlManager.vue +3 -3
  28. package/components/IconOrSvg.vue +149 -0
  29. package/components/LogItem.vue +69 -0
  30. package/components/PodSecurityAdmission.vue +302 -0
  31. package/components/PromptModal.vue +1 -0
  32. package/components/ResourceDetail/Masthead.vue +54 -2
  33. package/components/ResourceDetail/index.vue +12 -5
  34. package/components/ResourceList/Masthead.vue +11 -1
  35. package/components/ResourceList/ResourceLoadingIndicator.vue +12 -2
  36. package/components/ResourceList/index.vue +53 -12
  37. package/components/ResourceList/resource-list.config.js +7 -0
  38. package/components/ResourceTable.vue +31 -6
  39. package/components/SimpleBox.vue +1 -1
  40. package/components/SortableTable/THead.vue +15 -5
  41. package/components/SortableTable/index.vue +21 -10
  42. package/components/Tabbed/index.vue +20 -15
  43. package/components/__tests__/.DS_Store +0 -0
  44. package/components/__tests__/AsyncButton.test.ts +140 -0
  45. package/components/__tests__/BackLink.test.ts +33 -0
  46. package/components/__tests__/ButtonGroup.test.ts +124 -0
  47. package/components/__tests__/ClusterBadge.test.ts +32 -0
  48. package/components/__tests__/CollapsibleCard.test.ts +64 -0
  49. package/components/__tests__/ConsumptionGauge.test.ts +88 -0
  50. package/components/__tests__/CruResource.test.ts +3 -2
  51. package/components/__tests__/FixedBanner.test.ts +129 -0
  52. package/components/__tests__/GrowlManager.test.ts +147 -0
  53. package/components/__tests__/NamespaceFilter.test.ts +33 -25
  54. package/components/__tests__/PercentageBar.test.ts +32 -0
  55. package/components/__tests__/PodSecurityAdmission.test.ts +398 -0
  56. package/components/auth/AuthBanner.vue +20 -10
  57. package/components/auth/RoleDetailEdit.vue +26 -17
  58. package/components/auth/SelectPrincipal.vue +36 -5
  59. package/components/form/ArrayList.vue +3 -35
  60. package/components/form/ArrayListGrouped.vue +13 -4
  61. package/components/form/ArrayListSelect.vue +5 -5
  62. package/components/form/Error.vue +8 -0
  63. package/components/form/KeyValue.vue +39 -7
  64. package/components/form/LabeledSelect.vue +5 -2
  65. package/components/form/Labels.vue +46 -16
  66. package/components/form/Members/ClusterPermissionsEditor.vue +17 -17
  67. package/components/form/Members/MembershipEditor.vue +12 -12
  68. package/components/form/NameNsDescription.vue +1 -1
  69. package/components/form/NodeScheduling.vue +1 -1
  70. package/components/form/Probe.vue +3 -3
  71. package/components/form/ResourceQuota/Project.vue +6 -6
  72. package/components/form/ResourceTabs/index.vue +1 -6
  73. package/components/form/Security.vue +7 -6
  74. package/components/form/Select.vue +3 -2
  75. package/components/form/SelectOrCreateAuthSecret.vue +22 -29
  76. package/components/form/ServicePorts.vue +8 -0
  77. package/components/form/WorkloadPorts.vue +7 -1
  78. package/components/form/__tests__/ArrayList.test.ts +74 -0
  79. package/components/form/__tests__/ArrayListGrouped.test.ts +6 -4
  80. package/components/formatter/Checked.vue +1 -1
  81. package/components/formatter/ClusterLink.vue +5 -0
  82. package/components/formatter/IconIsDefault.vue +2 -2
  83. package/components/formatter/InternalExternalIP.vue +11 -8
  84. package/components/formatter/LiveDuration.vue +78 -0
  85. package/components/formatter/WorkloadHealthScale.vue +5 -3
  86. package/components/nav/Header.vue +6 -3
  87. package/components/nav/NamespaceFilter.vue +146 -63
  88. package/components/nav/TopLevelMenu.vue +22 -19
  89. package/components/nav/WindowManager/ContainerLogs.vue +83 -126
  90. package/components/nav/WindowManager/ContainerShell.vue +9 -7
  91. package/components/nav/WindowManager/Window.vue +2 -0
  92. package/components/nav/WindowManager/index.vue +10 -0
  93. package/config/elemental-types.js +9 -0
  94. package/config/features.js +2 -0
  95. package/config/home-links.js +4 -1
  96. package/config/pod-security-admission.ts +82 -0
  97. package/config/product/apps.js +1 -1
  98. package/config/product/auth.js +6 -5
  99. package/config/product/explorer.js +6 -6
  100. package/config/product/fleet.js +1 -1
  101. package/config/product/manager.js +6 -2
  102. package/config/secret.js +0 -1
  103. package/config/settings.ts +26 -9
  104. package/config/table-headers.js +22 -11
  105. package/config/types.js +4 -1
  106. package/content/docs/zh-hans/getting-started.md +113 -137
  107. package/content/docs/zh-hans/whats-new.md +8 -46
  108. package/creators/pkg/package-lock.json +37 -0
  109. package/creators/pkg/package.json +1 -1
  110. package/detail/catalog.cattle.io.app.vue +1 -1
  111. package/detail/pod.vue +1 -1
  112. package/detail/provisioning.cattle.io.cluster.vue +35 -9
  113. package/detail/service.vue +2 -9
  114. package/detail/workload/index.vue +0 -1
  115. package/dialog/AddClusterMemberDialog.vue +22 -28
  116. package/dialog/AddProjectMemberDialog.vue +53 -9
  117. package/dialog/DiagnosticTimingsDialog.vue +8 -7
  118. package/dialog/DrainNode.vue +44 -48
  119. package/dialog/ForceMachineRemoveDialog.vue +5 -7
  120. package/dialog/GenericPrompt.vue +15 -20
  121. package/dialog/RollbackWorkloadDialog.vue +15 -46
  122. package/dialog/RotateCertificatesDialog.vue +5 -7
  123. package/dialog/RotateEncryptionKeyDialog.vue +5 -9
  124. package/dialog/SaveAsRKETemplateDialog.vue +5 -13
  125. package/dialog/ScaleMachineDownDialog.vue +1 -1
  126. package/dialog/ScalePoolDownDialog.vue +121 -0
  127. package/edit/__tests__/management.cattle.io.setting.test.ts +3 -3
  128. package/edit/auth/azuread.vue +16 -16
  129. package/edit/auth/github.vue +8 -0
  130. package/edit/auth/googleoauth.vue +10 -1
  131. package/edit/auth/ldap/index.vue +10 -0
  132. package/edit/auth/oidc.vue +10 -0
  133. package/edit/auth/saml.vue +10 -0
  134. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -1
  135. package/edit/cloudcredential.vue +3 -7
  136. package/edit/logging-flow/Match.vue +39 -8
  137. package/edit/logging-flow/index.vue +27 -4
  138. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +107 -0
  139. package/edit/management.cattle.io.project.vue +8 -1
  140. package/edit/management.cattle.io.setting.vue +5 -2
  141. package/edit/management.cattle.io.user.vue +7 -1
  142. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +23 -7
  143. package/edit/monitoring.coreos.com.alertmanagerconfig/types/email.vue +2 -2
  144. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +14 -6
  145. package/edit/namespace.vue +18 -4
  146. package/edit/networking.k8s.io.ingress/Certificate.vue +1 -0
  147. package/edit/networking.k8s.io.ingress/IngressClass.vue +8 -6
  148. package/edit/networking.k8s.io.ingress/RulePath.vue +12 -6
  149. package/edit/networking.k8s.io.ingress/index.vue +8 -6
  150. package/edit/persistentvolume/index.vue +30 -27
  151. package/edit/persistentvolume/plugins/cephfs.vue +29 -29
  152. package/edit/persistentvolume/plugins/csi.vue +102 -62
  153. package/edit/persistentvolume/plugins/fc.vue +19 -19
  154. package/edit/persistentvolume/plugins/iscsi.vue +45 -45
  155. package/edit/persistentvolume/plugins/rbd.vue +39 -39
  156. package/edit/persistentvolumeclaim.vue +78 -75
  157. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +11 -7
  158. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +10 -1
  159. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +87 -27
  160. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -6
  161. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +93 -0
  162. package/edit/provisioning.cattle.io.cluster/import.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/index.vue +29 -6
  164. package/edit/provisioning.cattle.io.cluster/rke2.vue +440 -152
  165. package/edit/secret/index.vue +3 -7
  166. package/edit/service.vue +3 -1
  167. package/edit/storage.k8s.io.storageclass/index.vue +100 -16
  168. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +114 -0
  169. package/edit/workload/__tests__/index.test.ts +98 -0
  170. package/edit/workload/index.vue +58 -8
  171. package/edit/workload/mixins/workload.js +107 -70
  172. package/edit/workload/storage/ContainerMountPaths.vue +0 -10
  173. package/edit/workload/storage/emptyDir.vue +88 -0
  174. package/edit/workload/storage/ephemeralVolume/index.vue +1 -1
  175. package/edit/workload/storage/index.vue +8 -0
  176. package/edit/workload/storage/persistentVolumeClaim/index.vue +1 -1
  177. package/layouts/default.vue +57 -44
  178. package/list/__tests__/workload.test.ts +5 -2
  179. package/list/catalog.cattle.io.app.vue +1 -0
  180. package/list/cis.cattle.io.clusterscan.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +5 -6
  182. package/list/fleet.cattle.io.cluster.vue +6 -3
  183. package/list/fleet.cattle.io.clusterregistrationtoken.vue +5 -6
  184. package/list/fleet.cattle.io.gitrepo.vue +4 -9
  185. package/list/helm.cattle.io.projecthelmchart.vue +1 -5
  186. package/list/logging.banzaicloud.io.clusterflow.vue +4 -1
  187. package/list/logging.banzaicloud.io.flow.vue +6 -5
  188. package/list/management.cattle.io.cluster.vue +1 -0
  189. package/list/management.cattle.io.feature.vue +3 -4
  190. package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +47 -0
  191. package/list/management.cattle.io.setting.vue +2 -2
  192. package/list/management.cattle.io.user.vue +4 -10
  193. package/list/monitoring.coreos.com.alertmanagerconfig.vue +2 -7
  194. package/list/node.vue +8 -5
  195. package/list/persistentvolume.vue +3 -3
  196. package/list/persistentvolumeclaim.vue +3 -4
  197. package/list/provisioning.cattle.io.cluster.vue +18 -19
  198. package/list/service.vue +6 -14
  199. package/list/workload.vue +43 -38
  200. package/machine-config/azure.vue +429 -60
  201. package/machine-config/pnap.vue +288 -0
  202. package/mixins/auth-config.js +1 -3
  203. package/mixins/browser-tab-visibility.js +8 -14
  204. package/mixins/chart.js +1 -1
  205. package/mixins/create-edit-view/impl.js +4 -0
  206. package/mixins/create-edit-view/index.js +4 -2
  207. package/mixins/resource-fetch-namespaced.js +98 -0
  208. package/mixins/resource-fetch.js +79 -45
  209. package/mixins/resource-manager.js +1 -23
  210. package/models/apps.controllerrevision.js +7 -0
  211. package/models/apps.daemonset.js +18 -0
  212. package/models/apps.deployment.js +44 -0
  213. package/models/apps.replicaset.js +7 -0
  214. package/models/apps.statefulset.js +18 -0
  215. package/models/batch.job.js +7 -14
  216. package/models/cluster/node.js +10 -2
  217. package/models/cluster.x-k8s.io.machine.js +26 -4
  218. package/models/cluster.x-k8s.io.machinedeployment.js +12 -2
  219. package/models/event.js +7 -0
  220. package/models/logging.banzaicloud.io.flow.js +4 -0
  221. package/models/management.cattle.io.cluster.js +1 -1
  222. package/models/management.cattle.io.clusterroletemplatebinding.js +1 -1
  223. package/models/management.cattle.io.globalrole.js +2 -2
  224. package/models/management.cattle.io.node.js +37 -2
  225. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +4 -0
  226. package/models/management.cattle.io.project.js +30 -11
  227. package/models/management.cattle.io.setting.js +1 -1
  228. package/models/management.cattle.io.user.js +37 -1
  229. package/models/namespace.js +42 -5
  230. package/models/persistentvolume.js +14 -2
  231. package/models/pod.js +15 -0
  232. package/models/projectroletemplatebinding.js +7 -0
  233. package/models/provisioning.cattle.io.cluster.js +61 -10
  234. package/models/rke-machine.cattle.io.pnapmachinetemplate.js +15 -0
  235. package/models/service.js +14 -13
  236. package/models/storage.k8s.io.storageclass.js +33 -18
  237. package/models/workload.js +38 -7
  238. package/nuxt.config.js +27 -17
  239. package/package.json +7 -7
  240. package/pages/about.vue +14 -2
  241. package/pages/c/_cluster/apps/charts/index.vue +4 -3
  242. package/pages/c/_cluster/apps/charts/install.vue +59 -22
  243. package/pages/c/_cluster/auth/config/_id.vue +6 -0
  244. package/pages/c/_cluster/auth/config/index.vue +8 -6
  245. package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
  246. package/pages/c/_cluster/auth/roles/index.vue +1 -1
  247. package/pages/c/_cluster/explorer/index.vue +12 -6
  248. package/pages/c/_cluster/longhorn/index.vue +1 -1
  249. package/pages/c/_cluster/monitoring/alertmanagerconfig/_alertmanagerconfigid/receiver.vue +15 -4
  250. package/pages/c/_cluster/monitoring/index.vue +1 -1
  251. package/pages/c/_cluster/neuvector/index.vue +1 -1
  252. package/pages/c/_cluster/settings/performance.vue +48 -2
  253. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +34 -1
  254. package/pages/c/_cluster/uiplugins/index.vue +28 -2
  255. package/pages/diagnostic.vue +5 -4
  256. package/pages/home.vue +105 -30
  257. package/pages/prefs.vue +23 -12
  258. package/pages/rio/mesh.vue +1 -1
  259. package/pkg/dynamic-importer.lib.js +8 -0
  260. package/pkg/vue.config.js +4 -0
  261. package/plugins/dashboard-store/__tests__/mutations.spec.js +406 -0
  262. package/plugins/dashboard-store/actions.js +32 -25
  263. package/plugins/dashboard-store/getters.js +50 -33
  264. package/plugins/dashboard-store/mutations.js +134 -28
  265. package/plugins/dashboard-store/resource-class.js +21 -41
  266. package/plugins/steve/actions.js +30 -0
  267. package/plugins/steve/caches/resourceCache.js +60 -0
  268. package/plugins/steve/getters.js +44 -1
  269. package/plugins/steve/mutations.js +97 -36
  270. package/plugins/steve/resourceWatcher.js +277 -0
  271. package/plugins/steve/schema.utils.js +25 -0
  272. package/plugins/steve/subscribe.js +288 -115
  273. package/plugins/steve/worker/index.js +17 -0
  274. package/plugins/steve/worker/web-worker.advanced.js +302 -0
  275. package/plugins/steve/{web-worker.steve-sub-worker.js → worker/web-worker.basic.js} +3 -44
  276. package/rancher-components/Card/Card.vue +3 -3
  277. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +1 -0
  278. package/rancher-components/StringList/StringList.test.ts +45 -420
  279. package/rancher-components/StringList/StringList.vue +1 -10
  280. package/rancher-components/components/Banner/Banner.test.ts +44 -0
  281. package/rancher-components/components/Banner/Banner.vue +129 -61
  282. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +13 -22
  283. package/rancher-components/components/Form/Checkbox/Checkbox.vue +8 -6
  284. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +9 -9
  285. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +0 -1
  286. package/rancher-components/components/StringList/StringList.test.ts +7 -7
  287. package/rancher-components/components/StringList/StringList.vue +21 -15
  288. package/scripts/test-plugins-build.sh +8 -0
  289. package/static/loading-indicator.html +1 -1
  290. package/store/index.js +54 -3
  291. package/store/plugins.js +0 -17
  292. package/store/pnap.js +128 -0
  293. package/store/prefs.js +4 -2
  294. package/store/type-map.js +55 -13
  295. package/types/pod-security-admission.ts +36 -0
  296. package/types/shell/index.d.ts +496 -396
  297. package/utils/__tests__/object.test.ts +17 -1
  298. package/utils/__tests__/pod-security-admission.test.ts +61 -0
  299. package/utils/async.ts +36 -0
  300. package/utils/color.js +45 -0
  301. package/utils/crypto/browserHashUtils.js +18 -0
  302. package/utils/dynamic-importer.js +8 -0
  303. package/utils/install-redirect.js +1 -1
  304. package/utils/object.js +24 -0
  305. package/utils/pod-security-admission.ts +39 -0
  306. package/utils/socket.js +61 -24
  307. package/utils/string.js +2 -0
  308. package/utils/svg-filter.js +301 -0
  309. package/utils/time.js +49 -0
  310. package/utils/validators/cidr.js +4 -0
  311. package/utils/validators/formRules/__tests__/index.test.ts +23 -3
  312. package/utils/validators/formRules/index.ts +14 -0
  313. package/config/product/harvester-manager.js +0 -162
  314. package/edit/harvesterhci.io.management.cluster.vue +0 -153
  315. package/list/harvesterhci.io.management.cluster.vue +0 -241
  316. package/machine-config/harvester.vue +0 -693
  317. package/models/harvesterhci.io.management.cluster.js +0 -228
  318. package/pages/c/_cluster/harvesterManager/index.vue +0 -24
  319. package/rancher-components/Card/Card.test.ts +0 -39
  320. package/rancher-components/Utils/DraggableZone/DraggableZone.vue +0 -181
  321. package/rancher-components/Utils/DraggableZone/index.ts +0 -1
  322. package/rancher-components/components/Utils/DraggableZone/index.ts +0 -1
@@ -11,8 +11,8 @@ export default {
11
11
  },
12
12
  },
13
13
  computed: {
14
- showBoth() {
15
- return this.row.internalIp !== this.row.externalIp;
14
+ internalSameAsExternal() {
15
+ return this.row.internalIp === this.row.externalIp;
16
16
  },
17
17
  ...mapGetters({ t: 'i18n/t' })
18
18
  },
@@ -35,12 +35,15 @@ export default {
35
35
  />
36
36
  </template>
37
37
  <template v-else>
38
- {{ t('generic.none') }}
38
+ -
39
39
  </template>
40
-
41
- <template v-if="showBoth">
42
- <template v-if="isIp(row.internalIp)">
43
- / {{ row.internalIp }} <CopyToClipboard
40
+ /
41
+ <template>
42
+ <template v-if="internalSameAsExternal && isIp(row.internalIp)">
43
+ {{ t('tableHeaders.internalIpSameAsExternal') }}
44
+ </template>
45
+ <template v-else-if="isIp(row.internalIp)">
46
+ {{ row.internalIp }}<CopyToClipboard
44
47
  label-as="tooltip"
45
48
  :text="row.internalIp"
46
49
  class="icon-btn"
@@ -48,7 +51,7 @@ export default {
48
51
  />
49
52
  </template>
50
53
  <template v-else>
51
- {{ t('generic.none') }}
54
+ -
52
55
  </template>
53
56
  </template>
54
57
  </span>
@@ -0,0 +1,78 @@
1
+ <script>
2
+ import day from 'dayjs';
3
+ import { elapsedTime } from '@shell/utils/time';
4
+
5
+ export default {
6
+ props: {
7
+ value: {
8
+ type: Object,
9
+ default: () => {}
10
+ },
11
+ },
12
+
13
+ mounted() {
14
+ // Set initial value;
15
+ if (this.value.startTime) {
16
+ this.liveUpdate(day());
17
+ }
18
+ },
19
+
20
+ data() {
21
+ return { label: '-' };
22
+ },
23
+
24
+ computed: {
25
+ dayValue() {
26
+ if (!this.value.startTime) {
27
+ return null;
28
+ }
29
+
30
+ return day(this.value.startTime);
31
+ }
32
+ },
33
+
34
+ watch: {
35
+ value() {
36
+ if (this.value.startTime) {
37
+ this.liveUpdate(day());
38
+ }
39
+ }
40
+ },
41
+
42
+ methods: {
43
+ liveUpdate(now) {
44
+ if (!this.dayValue) {
45
+ this.label = '-';
46
+
47
+ return 300;
48
+ }
49
+
50
+ const { label, diff } = this.getDuration(this.dayValue, now);
51
+
52
+ this.label = label;
53
+
54
+ return diff;
55
+ },
56
+ getDuration(value, from) {
57
+ const now = day();
58
+
59
+ from = from || now;
60
+ const seconds = Math.abs(value.diff(now, 'seconds'));
61
+
62
+ return elapsedTime(seconds);
63
+ },
64
+ }
65
+ };
66
+ </script>
67
+
68
+ <template>
69
+ <span v-if="value.staticValue">
70
+ {{ value.staticValue }}
71
+ </span>
72
+ <span
73
+ v-else
74
+ class="live-date"
75
+ >
76
+ {{ label }}
77
+ </span>
78
+ </template>
@@ -261,15 +261,17 @@ $width: 150px;
261
261
  }
262
262
  }
263
263
 
264
+ $icon-width: 21px;
265
+
264
266
  .health {
265
- width: $width - $height; // height is width of icon;
267
+ width: $width - $icon-width;
266
268
  margin-left: 5px;
267
269
  }
268
270
  .icon {
269
- font-size: $height;
270
- width: $height;
271
+ width: $icon-width;
271
272
  color: var(--primary);
272
273
  margin-top: 1px;
274
+ padding: 0 5px 0 3px; // It would be better to display flex here... but the icon looks a pixel off to the right
273
275
  }
274
276
  }
275
277
 
@@ -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
 
@@ -671,8 +671,6 @@ export default {
671
671
 
672
672
  .vs__dropdown-toggle .vs__actions:after {
673
673
  color: var(--body-text) !important;
674
- font-size: 1.5rem;
675
- padding-right: 4px;
676
674
  }
677
675
 
678
676
  .vs__dropdown-toggle {
@@ -816,6 +814,11 @@ export default {
816
814
  background-color: var(--success);
817
815
  color: var(--success-text);
818
816
  }
817
+
818
+ img {
819
+ height: 20px;
820
+ width: 20px;
821
+ }
819
822
  }
820
823
  }
821
824
 
@@ -19,16 +19,17 @@ import { KEY } from '@shell/utils/platform';
19
19
  export default {
20
20
  data() {
21
21
  return {
22
- isOpen: false,
23
- filter: '',
24
- hidden: 0,
25
- total: 0,
26
- activeElement: null,
22
+ isOpen: false,
23
+ filter: '',
24
+ hidden: 0,
25
+ total: 0,
26
+ activeElement: null,
27
+ cachedFiltered: [],
27
28
  };
28
29
  },
29
30
 
30
31
  computed: {
31
- ...mapGetters(['currentProduct']),
32
+ ...mapGetters(['currentProduct', 'namespaceFilterMode']),
32
33
 
33
34
  hasFilter() {
34
35
  return this.filter.length > 0;
@@ -37,11 +38,26 @@ export default {
37
38
  filtered() {
38
39
  let out = this.options;
39
40
 
40
- // Filter by the current filter
41
- if (this.hasFilter) {
42
- out = out.filter((item) => {
41
+ out = out.filter((item) => {
42
+ // Filter out anything not applicable to singleton selection
43
+ if (this.namespaceFilterMode) {
44
+ // We always show dividers, projects and namespaces
45
+ if (!['divider', 'project', this.namespaceFilterMode].includes(item.kind)) {
46
+ // Hide any invalid option that's not selected
47
+ return this.value.findIndex(v => v.id === item.id) >= 0;
48
+ }
49
+ }
50
+
51
+ // Filter by the current filter
52
+ if (this.hasFilter) {
43
53
  return item.kind !== SPECIAL && item.label.toLowerCase().includes(this.filter.toLowerCase());
44
- });
54
+ }
55
+
56
+ return true;
57
+ });
58
+
59
+ if (out?.[0]?.kind === 'divider') {
60
+ out.splice(0, 1);
45
61
  }
46
62
 
47
63
  const mapped = this.value.reduce((m, v) => {
@@ -54,6 +70,8 @@ export default {
54
70
  out.forEach((i) => {
55
71
  i.selected = !!mapped[i.id] || (i.id === ALL && this.value && this.value.length === 0);
56
72
  i.elementId = (i.id || '').replace('://', '_');
73
+ // Are we in singleton resource type mode, if so is this an allowed type?
74
+ i.enabled = !this.namespaceFilterMode || i.kind === this.namespaceFilterMode;
57
75
  });
58
76
 
59
77
  return out;
@@ -326,6 +344,21 @@ export default {
326
344
  watch: {
327
345
  value(neu) {
328
346
  this.layout();
347
+ },
348
+
349
+ /**
350
+ * When there are thousands of entries certain actions (drop down opened, selection changed, etc) take a long time to complete (upwards
351
+ * of 5 seconds)
352
+ *
353
+ * This is caused by churn of the filtered and options computed properties causing multiple renders for each action.
354
+ *
355
+ * To break this multiple-render per cycle behaviour detatch `filtered` from the value used in `v-for`.
356
+ *
357
+ */
358
+ filtered(neu) {
359
+ if (!!neu) {
360
+ this.cachedFiltered = neu;
361
+ }
329
362
  }
330
363
  },
331
364
 
@@ -427,7 +460,10 @@ export default {
427
460
  e.preventDefault();
428
461
  e.stopPropagation();
429
462
  this.up();
430
- } else if (e.keyCode === KEY.SPACE) {
463
+ } else if (e.keyCode === KEY.SPACE || e.keyCode === KEY.CR) {
464
+ if (this.namespaceFilterMode && !opt.enabled) {
465
+ return;
466
+ }
431
467
  e.preventDefault();
432
468
  e.stopPropagation();
433
469
  this.selectOption(opt);
@@ -545,9 +581,22 @@ export default {
545
581
 
546
582
  const current = this.value;
547
583
  const exists = current.findIndex(v => v.id === option.id);
584
+ const optionIsSelected = exists !== -1;
585
+
586
+ // Any type of mode means only a single resource can be selected. So clear out any stale
587
+ // values (multiple selected in another context OR a single one selected in this context)
588
+ if (this.namespaceFilterMode) {
589
+ if (current.length === 1 && optionIsSelected) {
590
+ // Don't deselect the only selected option
591
+ return;
592
+ }
593
+ current.length = 0;
594
+ }
548
595
 
549
- // Remove if it exists, add if it does not
550
- if (exists !== -1) {
596
+ const remove = !this.namespaceFilterMode && optionIsSelected;
597
+
598
+ // Remove if it exists (or always add if in singleton mode - we've reset the list above)
599
+ if (remove) {
551
600
  current.splice(exists, 1);
552
601
  } else {
553
602
  current.push(option);
@@ -559,6 +608,14 @@ export default {
559
608
  document.activeElement.blur();
560
609
  }
561
610
  },
611
+ handleValueMouseDown(ns, event) {
612
+ this.removeOption(ns, event);
613
+
614
+ if (this.value.length === 0) {
615
+ this.open();
616
+ }
617
+ },
618
+
562
619
  removeOption(ns, event) {
563
620
  this.selectOption(ns);
564
621
  event.preventDefault();
@@ -634,9 +691,11 @@ export default {
634
691
  >
635
692
  <div>{{ ns.label }}</div>
636
693
  <i
694
+ v-if="!namespaceFilterMode"
637
695
  class="icon icon-close"
638
696
  :data-testid="`namespaces-values-close-${j}`"
639
697
  @click="removeOption(ns, $event)"
698
+ @mousedown="handleValueMouseDown(ns, $event)"
640
699
  />
641
700
  </div>
642
701
  </div>
@@ -686,7 +745,19 @@ export default {
686
745
  @click="filter = ''"
687
746
  />
688
747
  </div>
689
- <div class="ns-clear">
748
+ <div
749
+ v-if="namespaceFilterMode"
750
+ class="ns-singleton-info"
751
+ >
752
+ <i
753
+ v-tooltip="t('resourceList.nsFilterToolTip', { mode: namespaceFilterMode})"
754
+ class="icon icon-info"
755
+ />
756
+ </div>
757
+ <div
758
+ v-else
759
+ class="ns-clear"
760
+ >
690
761
  <i
691
762
  class="icon icon-close"
692
763
  @click="clear()"
@@ -700,18 +771,19 @@ export default {
700
771
  role="list"
701
772
  >
702
773
  <div
703
- v-for="(opt, i) in filtered"
774
+ v-for="(opt, i) in cachedFiltered"
704
775
  :id="opt.elementId"
705
776
  :key="opt.id"
706
777
  tabindex="0"
707
778
  class="ns-option"
779
+ :disabled="!opt.enabled"
708
780
  :class="{
709
781
  'ns-selected': opt.selected,
710
- 'ns-single-match': filtered.length === 1 && !opt.selected,
782
+ 'ns-single-match': cachedFiltered.length === 1 && !opt.selected,
711
783
  }"
712
784
  :data-testid="`namespaces-option-${i}`"
713
- @click="selectOption(opt)"
714
- @mouseover="mouseOver($event)"
785
+ @click="opt.enabled && selectOption(opt)"
786
+ @mouseover="opt.enabled && mouseOver($event)"
715
787
  @keydown="itemKeyHandler($event, opt)"
716
788
  >
717
789
  <div
@@ -734,7 +806,7 @@ export default {
734
806
  </div>
735
807
  </div>
736
808
  <div
737
- v-if="filtered.length === 0"
809
+ v-if="cachedFiltered.length === 0"
738
810
  class="ns-none"
739
811
  data-testid="namespaces-option-none"
740
812
  >
@@ -775,16 +847,17 @@ export default {
775
847
  }
776
848
 
777
849
  .ns-clear {
850
+ &:hover {
851
+ color: var(--primary);
852
+ cursor: pointer;
853
+ }
854
+ }
855
+
856
+ .ns-singleton-info, .ns-clear {
778
857
  align-items: center;
779
858
  display: flex;
780
859
  > i {
781
- font-size: 24px;
782
- padding: 0 5px;
783
- }
784
-
785
- &:hover {
786
- color: var(--link);
787
- cursor: pointer;
860
+ padding-right: 5px;
788
861
  }
789
862
  }
790
863
 
@@ -803,7 +876,6 @@ export default {
803
876
  position: absolute;
804
877
  right: 10px;
805
878
  top: 5px;
806
- font-size: 16px;
807
879
  line-height: 24px;
808
880
  text-align: center;
809
881
  width: 24px;
@@ -811,7 +883,7 @@ export default {
811
883
 
812
884
  .ns-dropdown-menu {
813
885
  background-color: var(--header-bg);
814
- border: 1px solid var(--link-border);
886
+ border: 1px solid var(--primary-border);
815
887
  border-bottom-left-radius: var(--border-radius);
816
888
  border-bottom-right-radius: var(--border-radius);
817
889
  color: var(--header-btn-text);
@@ -837,12 +909,49 @@ export default {
837
909
  padding-bottom: 10px;
838
910
  }
839
911
 
840
- .ns-option:focus {
841
- background-color: var(--dropdown-hover-bg);
842
- color: var(--dropdown-hover-text);
843
- }
844
-
845
912
  .ns-option {
913
+
914
+ &[disabled] {
915
+ cursor: default;
916
+ }
917
+
918
+ &:not([disabled]) {
919
+ &:focus {
920
+ background-color: var(--dropdown-hover-bg);
921
+ color: var(--dropdown-hover-text);
922
+ }
923
+ .ns-item {
924
+ &:hover, &:focus {
925
+ background-color: var(--dropdown-hover-bg);
926
+ color: var(--dropdown-hover-text);
927
+ cursor: pointer;
928
+
929
+ > i {
930
+ color: var(--dropdown-hover-text);
931
+ }
932
+ }
933
+ }
934
+
935
+ &.ns-selected {
936
+ &:hover,&:focus {
937
+ .ns-item {
938
+ > * {
939
+ background-color: var(--dropdown-hover-bg);
940
+ color: var(--dropdown-hover-text);
941
+ }
942
+ }
943
+ }
944
+ }
945
+
946
+ &.ns-selected:not(:hover) {
947
+ .ns-item {
948
+ > * {
949
+ color: var(--dropdown-hover-bg);
950
+ }
951
+ }
952
+ }
953
+ }
954
+
846
955
  .ns-item {
847
956
  align-items: center;
848
957
  display: flex;
@@ -862,33 +971,8 @@ export default {
862
971
  white-space: nowrap;
863
972
  }
864
973
 
865
- &:hover, &:focus {
866
- background-color: var(--dropdown-hover-bg);
867
- color: var(--dropdown-hover-text);
868
- cursor: pointer;
869
-
870
- > i {
871
- color: var(--dropdown-hover-text);
872
- }
873
- }
874
- }
875
- &.ns-selected:not(:hover) {
876
- .ns-item {
877
- > * {
878
- color: var(--dropdown-hover-bg);
879
- }
880
- }
881
- }
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
974
  }
975
+
892
976
  &.ns-single-match {
893
977
  .ns-item {
894
978
  background-color: var(--dropdown-hover-bg);
@@ -915,7 +999,7 @@ export default {
915
999
  &.ns-open {
916
1000
  border-bottom-left-radius: 0;
917
1001
  border-bottom-right-radius: 0;
918
- border-color: var(--link-border);
1002
+ border-color: var(--primary-border);
919
1003
  }
920
1004
 
921
1005
  > .ns-values {
@@ -924,14 +1008,13 @@ export default {
924
1008
 
925
1009
  &:hover {
926
1010
  > i {
927
- color: var(--link);
1011
+ color: var(--primary);
928
1012
  }
929
1013
  }
930
1014
 
931
1015
  > i {
932
1016
  height: $ns_dropdown_size;
933
1017
  width: $ns_dropdown_size;
934
- font-size: 20px;
935
1018
  cursor: pointer;
936
1019
  text-align: center;
937
1020
  line-height: $ns_dropdown_size;
@@ -963,7 +1046,7 @@ export default {
963
1046
  margin-left: 5px;
964
1047
 
965
1048
  &:hover {
966
- color: var(--link);
1049
+ color: var(--primary);
967
1050
  };
968
1051
  }
969
1052
 
@@ -1,6 +1,7 @@
1
1
  <script>
2
2
  import BrandImage from '@shell/components/BrandImage';
3
3
  import ClusterProviderIcon from '@shell/components/ClusterProviderIcon';
4
+ import IconOrSvg from '../IconOrSvg';
4
5
  import { mapGetters } from 'vuex';
5
6
  import $ from 'jquery';
6
7
  import { CAPI, MANAGEMENT } from '@shell/config/types';
@@ -14,13 +15,13 @@ import { SETTING } from '@shell/config/settings';
14
15
  import { filterOnlyKubernetesClusters, filterHiddenLocalCluster } from '@shell/utils/cluster';
15
16
  import { isRancherPrime } from '@shell/config/version';
16
17
 
17
- const UNKNOWN = 'unknown';
18
- const UI_VERSION = process.env.VERSION || UNKNOWN;
19
- const UI_COMMIT = process.env.COMMIT || UNKNOWN;
20
-
21
18
  export default {
22
19
 
23
- components: { BrandImage, ClusterProviderIcon },
20
+ components: {
21
+ BrandImage,
22
+ ClusterProviderIcon,
23
+ IconOrSvg
24
+ },
24
25
 
25
26
  data() {
26
27
  const { displayVersion, fullVersion } = getVersionInfo(this.$store);
@@ -30,8 +31,6 @@ export default {
30
31
  shown: false,
31
32
  displayVersion,
32
33
  fullVersion,
33
- uiCommit: UI_COMMIT,
34
- uiVersion: UI_VERSION,
35
34
  clusterFilter: '',
36
35
  hasProvCluster,
37
36
  };
@@ -145,6 +144,7 @@ export default {
145
144
  return {
146
145
  label: this.$store.getters['i18n/withFallback'](`product."${ p.name }"`, null, ucFirst(p.name)),
147
146
  icon: `icon-${ p.icon || 'copy' }`,
147
+ svg: p.svg,
148
148
  value: p.name,
149
149
  removable: p.removable !== false,
150
150
  inStore: p.inStore || 'cluster',
@@ -347,9 +347,9 @@ export default {
347
347
  class="option"
348
348
  :to="a.to"
349
349
  >
350
- <i
351
- class="icon group-icon"
352
- :class="a.icon"
350
+ <IconOrSvg
351
+ :icon="a.icon"
352
+ :src="a.svg"
353
353
  />
354
354
  <div>{{ a.label }}</div>
355
355
  </nuxt-link>
@@ -368,9 +368,9 @@ export default {
368
368
  class="option"
369
369
  :to="a.to"
370
370
  >
371
- <i
372
- class="icon group-icon"
373
- :class="a.icon"
371
+ <IconOrSvg
372
+ :icon="a.icon"
373
+ :src="a.svg"
374
374
  />
375
375
  <div>{{ a.label }}</div>
376
376
  </nuxt-link>
@@ -389,9 +389,9 @@ export default {
389
389
  class="option"
390
390
  :to="a.to"
391
391
  >
392
- <i
393
- class="icon group-icon"
394
- :class="a.icon"
392
+ <IconOrSvg
393
+ :icon="a.icon"
394
+ :src="a.svg"
395
395
  />
396
396
  <div>{{ a.label }}</div>
397
397
  </nuxt-link>
@@ -410,11 +410,11 @@ export default {
410
410
  </div>
411
411
  <div @click="hide()">
412
412
  <nuxt-link
413
- v-tooltip="{ content: fullVersion, classes: 'footer-tooltip' }"
414
413
  :to="{ name: 'about' }"
415
414
  class="version"
416
- v-html="displayVersion"
417
- />
415
+ >
416
+ {{ t('about.title') }}
417
+ </nuxt-link>
418
418
  </div>
419
419
  </div>
420
420
  </div>
@@ -505,6 +505,9 @@ export default {
505
505
  margin-right: 8px;
506
506
  fill: var(--link);
507
507
  }
508
+ img {
509
+ margin-right: 8px;
510
+ }
508
511
 
509
512
  > div {
510
513
  color: var(--link);