@rancher/shell 3.0.5-rc.1 → 3.0.5-rc.3

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 (280) hide show
  1. package/assets/data/aws-regions.json +2 -0
  2. package/assets/images/providers/sks.svg +1 -0
  3. package/assets/styles/base/_helpers.scss +4 -0
  4. package/assets/styles/base/_variables.scss +1 -0
  5. package/assets/styles/global/_layout.scss +0 -1
  6. package/assets/translations/en-us.yaml +92 -34
  7. package/assets/translations/zh-hans.yaml +4 -13
  8. package/chart/monitoring/index.vue +4 -2
  9. package/components/ActionDropdownShell.vue +71 -0
  10. package/components/AppModal.vue +18 -4
  11. package/components/AsyncButton.vue +2 -0
  12. package/components/CodeMirror.vue +3 -3
  13. package/components/CommunityLinks.vue +3 -58
  14. package/components/CruResource.vue +109 -16
  15. package/components/ExplorerProjectsNamespaces.vue +19 -6
  16. package/components/FixedBanner.vue +19 -5
  17. package/components/GlobalRoleBindings.vue +5 -1
  18. package/components/GrowlManager.vue +1 -0
  19. package/components/LandingPagePreference.vue +2 -0
  20. package/components/LocaleSelector.vue +1 -1
  21. package/components/ModalManager.vue +55 -0
  22. package/components/PaginatedResourceTable.vue +7 -0
  23. package/components/PromptModal.vue +47 -8
  24. package/components/ResourceDetail/Masthead.vue +38 -13
  25. package/components/ResourceDetail/__tests__/Masthead.test.ts +5 -1
  26. package/components/ResourceDetail/index.vue +47 -12
  27. package/components/ResourceList/index.vue +2 -1
  28. package/components/ResourceTable.vue +54 -19
  29. package/components/SideNav.vue +5 -1
  30. package/components/SlideInPanelManager.vue +125 -0
  31. package/components/SortableTable/THead.vue +5 -2
  32. package/components/SortableTable/actions.js +1 -1
  33. package/components/SortableTable/index.vue +54 -40
  34. package/components/SortableTable/paging.js +16 -19
  35. package/components/SortableTable/selection.js +1 -12
  36. package/components/Tabbed/index.vue +6 -0
  37. package/components/Wizard.vue +2 -2
  38. package/components/__tests__/AsyncButton.test.ts +39 -0
  39. package/components/__tests__/CruResource.test.ts +63 -0
  40. package/components/__tests__/ModalManager.spec.ts +176 -0
  41. package/components/__tests__/PromptModal.test.ts +146 -0
  42. package/components/__tests__/SlideInPanelManager.spec.ts +166 -0
  43. package/components/auth/AuthBanner.vue +13 -11
  44. package/components/auth/Principal.vue +1 -0
  45. package/components/auth/login/ldap.vue +1 -1
  46. package/components/fleet/FleetResources.vue +21 -6
  47. package/components/form/ArrayList.vue +138 -118
  48. package/components/form/BannerSettings.vue +149 -85
  49. package/components/form/ColorInput.vue +35 -6
  50. package/components/form/EnvVars.vue +1 -0
  51. package/components/form/KeyValue.vue +10 -7
  52. package/components/form/LabeledSelect.vue +25 -23
  53. package/components/form/MatchExpressions.vue +9 -2
  54. package/components/form/NameNsDescription.vue +6 -2
  55. package/components/form/NotificationSettings.vue +15 -1
  56. package/components/form/Password.vue +1 -0
  57. package/components/form/Probe.vue +1 -0
  58. package/components/form/ResourceSelector.vue +26 -23
  59. package/components/form/ResourceTabs/index.vue +2 -1
  60. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +15 -34
  61. package/components/form/SSHKnownHosts/index.vue +14 -11
  62. package/components/form/Select.vue +8 -15
  63. package/components/form/UnitInput.vue +13 -0
  64. package/components/form/ValueFromResource.vue +12 -12
  65. package/components/form/__tests__/ArrayList.test.ts +34 -2
  66. package/components/form/__tests__/ColorInput.test.ts +35 -0
  67. package/components/form/__tests__/KeyValue.test.ts +36 -0
  68. package/components/form/__tests__/LabeledSelect.test.ts +73 -0
  69. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -2
  70. package/components/form/__tests__/Select.test.ts +34 -1
  71. package/components/form/__tests__/UnitInput.test.ts +23 -1
  72. package/components/formatter/ClusterLink.vue +5 -8
  73. package/components/formatter/Description.vue +30 -0
  74. package/components/formatter/__tests__/ClusterLink.test.ts +2 -32
  75. package/components/nav/Group.vue +12 -4
  76. package/components/nav/Header.vue +16 -43
  77. package/components/nav/NamespaceFilter.vue +134 -86
  78. package/components/nav/TopLevelMenu.vue +4 -5
  79. package/components/nav/WindowManager/ContainerLogs.vue +87 -61
  80. package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
  81. package/components/nav/WindowManager/index.vue +1 -0
  82. package/components/templates/default.vue +6 -3
  83. package/components/templates/home.vue +6 -0
  84. package/components/templates/plain.vue +6 -3
  85. package/composables/focusTrap.ts +12 -4
  86. package/config/product/explorer.js +16 -13
  87. package/config/product/manager.js +1 -28
  88. package/config/settings.ts +11 -13
  89. package/config/store.js +4 -0
  90. package/config/table-headers.js +7 -5
  91. package/config/uiplugins.js +5 -1
  92. package/core/types.ts +7 -6
  93. package/detail/catalog.cattle.io.app.vue +5 -1
  94. package/detail/fleet.cattle.io.bundle.vue +70 -6
  95. package/detail/fleet.cattle.io.gitrepo.vue +1 -1
  96. package/detail/namespace.vue +0 -3
  97. package/detail/node.vue +17 -13
  98. package/detail/provisioning.cattle.io.cluster.vue +85 -9
  99. package/detail/service.vue +0 -1
  100. package/detail/workload/index.vue +21 -34
  101. package/dialog/AddCustomBadgeDialog.vue +0 -1
  102. package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
  103. package/dialog/AssignToDialog.vue +176 -0
  104. package/dialog/ChangePasswordDialog.vue +106 -0
  105. package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
  106. package/dialog/DisableAuthProviderDialog.vue +101 -0
  107. package/dialog/DrainNode.vue +1 -1
  108. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
  109. package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +83 -65
  110. package/dialog/FeatureFlagListDialog.vue +288 -0
  111. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  112. package/{components/Import.vue → dialog/ImportDialog.vue} +0 -5
  113. package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
  114. package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -62
  115. package/dialog/MoveNamespaceDialog.vue +157 -0
  116. package/dialog/ScalePoolDownDialog.vue +1 -1
  117. package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
  118. package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
  119. package/dialog/WechatDialog.vue +57 -0
  120. package/edit/__tests__/service.test.ts +2 -1
  121. package/edit/auth/azuread.vue +1 -1
  122. package/edit/auth/github.vue +1 -1
  123. package/edit/auth/googleoauth.vue +1 -1
  124. package/edit/auth/ldap/index.vue +1 -1
  125. package/edit/auth/oidc.vue +1 -1
  126. package/edit/auth/saml.vue +1 -1
  127. package/edit/cloudcredential.vue +24 -10
  128. package/edit/management.cattle.io.user.vue +28 -3
  129. package/edit/namespace.vue +1 -4
  130. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -14
  131. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +57 -62
  132. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +3 -14
  133. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.test.ts +72 -41
  134. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +17 -1
  135. package/edit/networking.k8s.io.networkpolicy/index.vue +18 -30
  136. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +4 -1
  137. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +26 -10
  138. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +8 -8
  139. package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
  140. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +66 -0
  141. package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
  142. package/edit/provisioning.cattle.io.cluster/index.vue +21 -73
  143. package/edit/provisioning.cattle.io.cluster/rke2.vue +24 -7
  144. package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
  145. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +4 -1
  146. package/edit/service.vue +13 -28
  147. package/initialize/install-plugins.js +2 -1
  148. package/list/harvesterhci.io.management.cluster.vue +4 -1
  149. package/list/management.cattle.io.feature.vue +4 -288
  150. package/list/workload.vue +6 -1
  151. package/machine-config/azure.vue +16 -4
  152. package/mixins/resource-fetch-api-pagination.js +55 -43
  153. package/mixins/resource-fetch.js +14 -5
  154. package/mixins/vue-select-overrides.js +0 -4
  155. package/models/__tests__/workload.test.ts +1 -0
  156. package/models/cluster/node.js +1 -0
  157. package/models/cluster.js +32 -2
  158. package/models/fleet.cattle.io.cluster.js +8 -2
  159. package/models/fleet.cattle.io.gitrepo.js +8 -34
  160. package/models/management.cattle.io.cluster.js +0 -20
  161. package/models/management.cattle.io.feature.js +7 -1
  162. package/models/management.cattle.io.node.js +7 -22
  163. package/models/management.cattle.io.nodepool.js +12 -0
  164. package/models/namespace.js +12 -1
  165. package/models/provisioning.cattle.io.cluster.js +18 -64
  166. package/models/service.js +24 -9
  167. package/models/workload.js +70 -31
  168. package/package.json +1 -1
  169. package/pages/about.vue +13 -3
  170. package/pages/account/index.vue +12 -5
  171. package/pages/auth/login.vue +7 -4
  172. package/pages/auth/setup.vue +1 -0
  173. package/pages/auth/verify.vue +9 -7
  174. package/pages/c/_cluster/apps/charts/install.vue +25 -26
  175. package/pages/c/_cluster/auth/config/index.vue +10 -12
  176. package/pages/c/_cluster/explorer/EventsTable.vue +38 -33
  177. package/pages/c/_cluster/explorer/index.vue +28 -15
  178. package/pages/c/_cluster/istio/index.vue +2 -2
  179. package/pages/c/_cluster/longhorn/index.vue +3 -3
  180. package/pages/c/_cluster/monitoring/index.vue +1 -1
  181. package/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue +4 -2
  182. package/pages/c/_cluster/monitoring/monitor/create.vue +4 -2
  183. package/pages/c/_cluster/monitoring/route-receiver/_id.vue +4 -2
  184. package/pages/c/_cluster/monitoring/route-receiver/create.vue +5 -2
  185. package/pages/c/_cluster/neuvector/index.vue +1 -1
  186. package/pages/c/_cluster/settings/banners.vue +60 -5
  187. package/pages/c/_cluster/settings/performance.vue +7 -26
  188. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +8 -10
  189. package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
  190. package/pages/c/_cluster/uiplugins/index.vue +98 -55
  191. package/pages/diagnostic.vue +12 -9
  192. package/pages/fail-whale.vue +8 -5
  193. package/pages/home.vue +11 -52
  194. package/pages/prefs.vue +7 -6
  195. package/plugins/clean-html.js +2 -0
  196. package/plugins/dashboard-store/__tests__/actions.test.ts +4 -1
  197. package/plugins/dashboard-store/actions.js +122 -21
  198. package/plugins/dashboard-store/getters.js +74 -3
  199. package/plugins/dashboard-store/mutations.js +10 -5
  200. package/plugins/dashboard-store/resource-class.js +23 -3
  201. package/plugins/internal-api/index.ts +37 -0
  202. package/plugins/internal-api/shared/base-api.ts +13 -0
  203. package/plugins/internal-api/shell/shell.api.ts +108 -0
  204. package/plugins/steve/__tests__/getters.test.ts +18 -11
  205. package/plugins/steve/__tests__/steve-class.test.ts +1 -0
  206. package/plugins/steve/actions.js +34 -24
  207. package/plugins/steve/getters.js +39 -10
  208. package/plugins/steve/steve-class.js +5 -0
  209. package/plugins/steve/steve-pagination-utils.ts +199 -37
  210. package/plugins/steve/worker/web-worker.advanced.js +3 -1
  211. package/public/index.html +1 -0
  212. package/rancher-components/Banner/Banner.test.ts +51 -3
  213. package/rancher-components/Banner/Banner.vue +28 -6
  214. package/rancher-components/Card/Card.vue +1 -1
  215. package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
  216. package/rancher-components/Form/Checkbox/Checkbox.vue +27 -3
  217. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +51 -0
  218. package/rancher-components/Form/LabeledInput/LabeledInput.vue +20 -2
  219. package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
  220. package/rancher-components/Form/Radio/RadioButton.vue +20 -4
  221. package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
  222. package/rancher-components/Form/Radio/RadioGroup.vue +75 -35
  223. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +17 -0
  224. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +26 -1
  225. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +10 -1
  226. package/rancher-components/RcButton/RcButton.vue +2 -1
  227. package/rancher-components/RcButton/types.ts +1 -0
  228. package/rancher-components/RcDropdown/RcDropdown.vue +17 -6
  229. package/rancher-components/RcDropdown/RcDropdownItem.vue +3 -56
  230. package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +68 -0
  231. package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +92 -0
  232. package/rancher-components/RcDropdown/index.ts +2 -0
  233. package/rancher-components/RcDropdown/useDropdownItem.ts +63 -0
  234. package/scripts/extension/bundle +20 -0
  235. package/scripts/extension/helm/charts/ui-plugin-server/templates/cr.yaml +2 -1
  236. package/scripts/extension/helm/charts/ui-plugin-server/values.yaml +2 -0
  237. package/scripts/extension/helmpatch +44 -31
  238. package/scripts/extension/publish +12 -13
  239. package/scripts/typegen.sh +2 -4
  240. package/store/action-menu.js +26 -56
  241. package/store/features.js +0 -1
  242. package/store/index.js +5 -0
  243. package/store/modal.ts +71 -0
  244. package/store/slideInPanel.ts +47 -0
  245. package/store/type-map.js +8 -1
  246. package/store/type-map.utils.ts +49 -6
  247. package/types/fleet.d.ts +1 -1
  248. package/types/global-vue.d.ts +5 -0
  249. package/types/internal-api/shell/growl.d.ts +25 -0
  250. package/types/internal-api/shell/modal.d.ts +77 -0
  251. package/types/internal-api/shell/slideIn.d.ts +15 -0
  252. package/types/kube/kube-api.ts +22 -0
  253. package/types/resources/fleet.d.ts +0 -14
  254. package/types/resources/settings.d.ts +0 -4
  255. package/types/shell/index.d.ts +375 -306
  256. package/types/store/dashboard-store.types.ts +24 -1
  257. package/types/store/pagination.types.ts +19 -2
  258. package/types/vue-shim.d.ts +4 -1
  259. package/utils/__mocks__/tabbable.js +13 -0
  260. package/utils/__tests__/object.test.ts +38 -4
  261. package/utils/cluster.js +24 -20
  262. package/utils/fleet.ts +15 -73
  263. package/utils/grafana.js +1 -0
  264. package/utils/object.js +36 -5
  265. package/utils/pagination-utils.ts +6 -2
  266. package/utils/perf-setting.utils.ts +28 -0
  267. package/utils/selector-typed.ts +205 -0
  268. package/utils/selector.js +29 -6
  269. package/utils/uiplugins.ts +10 -6
  270. package/utils/v-sphere.ts +5 -1
  271. package/utils/validators/formRules/__tests__/index.test.ts +10 -1
  272. package/utils/validators/formRules/index.ts +27 -3
  273. package/components/AssignTo.vue +0 -199
  274. package/components/DisableAuthProviderModal.vue +0 -115
  275. package/components/MoveModal.vue +0 -167
  276. package/components/PromptChangePassword.vue +0 -123
  277. package/components/fleet/FleetBundleResources.vue +0 -86
  278. package/components/formatter/RKETemplateName.vue +0 -37
  279. package/dialog/SaveAsRKETemplateDialog.vue +0 -139
  280. package/types/vue-shim.d +0 -20
@@ -20,11 +20,15 @@ import { KEY } from '@shell/utils/platform';
20
20
  import pAndNFiltering from '@shell/plugins/steve/projectAndNamespaceFiltering.utils';
21
21
  import { SETTING } from '@shell/config/settings';
22
22
  import paginationUtils from '@shell/utils/pagination-utils';
23
+ import { randomStr } from '@shell/utils/string';
24
+ import { RcButton } from '@components/RcButton';
23
25
 
24
26
  const forcedNamespaceValidTypes = [NAMESPACE_FILTER_KINDS.DIVIDER, NAMESPACE_FILTER_KINDS.PROJECT, NAMESPACE_FILTER_KINDS.NAMESPACE];
25
27
 
26
28
  export default {
27
29
 
30
+ components: { RcButton },
31
+
28
32
  data() {
29
33
  return {
30
34
  isOpen: false,
@@ -35,6 +39,7 @@ export default {
35
39
  cachedFiltered: [],
36
40
  NAMESPACE_FILTER_KINDS,
37
41
  namespaceFilterMode: undefined,
42
+ containerId: `dropdown-${ randomStr() }`,
38
43
  };
39
44
  },
40
45
 
@@ -381,10 +386,6 @@ export default {
381
386
  }
382
387
  },
383
388
 
384
- beforeUnmount() {
385
- this.removeCloseKeyHandler();
386
- },
387
-
388
389
  mounted() {
389
390
  this.layout();
390
391
  },
@@ -477,28 +478,25 @@ export default {
477
478
  }
478
479
  });
479
480
  },
480
- addCloseKeyHandler() {
481
- document.addEventListener('keyup', this.closeKeyHandler);
482
- },
483
- removeCloseKeyHandler() {
484
- document.removeEventListener('keyup', this.closeKeyHandler);
485
- },
486
- closeKeyHandler(e) {
487
- if (e.keyCode === KEY.ESCAPE ) {
488
- this.close();
489
- }
490
- },
491
481
  // Keyboard support
492
482
  itemKeyHandler(e, opt) {
493
483
  if (e.keyCode === KEY.DOWN ) {
494
484
  e.preventDefault();
495
485
  e.stopPropagation();
496
486
  this.down();
497
- } else if (e.keyCode === KEY.UP ) {
487
+
488
+ return;
489
+ }
490
+
491
+ if (e.keyCode === KEY.UP) {
498
492
  e.preventDefault();
499
493
  e.stopPropagation();
500
494
  this.up();
501
- } else if (e.keyCode === KEY.SPACE || e.keyCode === KEY.CR) {
495
+
496
+ return;
497
+ }
498
+
499
+ if (e.keyCode === KEY.SPACE || e.keyCode === KEY.CR) {
502
500
  if (this.namespaceFilterMode && !opt.enabled) {
503
501
  return;
504
502
  }
@@ -515,10 +513,8 @@ export default {
515
513
  e.stopPropagation();
516
514
  this.down(true);
517
515
  break;
518
- case KEY.TAB:
519
- // Tab out of the input box
516
+ case KEY.ESCAPE:
520
517
  this.close();
521
- e.target.blur();
522
518
  break;
523
519
  case KEY.CR:
524
520
  if (this.filtered.length === 1) {
@@ -526,6 +522,10 @@ export default {
526
522
  this.filter = '';
527
523
  }
528
524
  break;
525
+ case KEY.TAB:
526
+ if (e.shiftKey) {
527
+ this.close();
528
+ }
529
529
  }
530
530
  },
531
531
  mouseOver(event) {
@@ -541,11 +541,11 @@ export default {
541
541
  el.focus();
542
542
  this.activeElement = null;
543
543
  },
544
- down(input) {
545
- const exising = this.activeElement || document.activeElement;
544
+ down(input, focusFirst = true) {
545
+ const existing = this.activeElement || document.activeElement;
546
546
 
547
547
  // Focus the first element in the list
548
- if (input || !exising) {
548
+ if (input || (!existing && !focusFirst)) {
549
549
  if (this.$refs.options) {
550
550
  const c = this.$refs.options.children;
551
551
 
@@ -554,15 +554,15 @@ export default {
554
554
  }
555
555
  }
556
556
  } else {
557
- let next = exising.nextSibling;
557
+ let next = existing.nextElementSibling;
558
558
 
559
- if (next?.children?.length) {
560
- const item = next.children[0];
559
+ if (!next) {
560
+ next = existing.parentNode.firstElementChild;
561
+ }
561
562
 
562
- // Skip over dividers (assumes we don't have two dividers next to each other)
563
- if (item.classList.contains('ns-divider')) {
564
- next = next.nextSibling;
565
- }
563
+ // Skip over dividers (assumes we don't have two dividers next to each other)
564
+ if (next?.classList.contains('ns-divider')) {
565
+ next = next.nextElementSibling;
566
566
  }
567
567
 
568
568
  if (next?.focus) {
@@ -571,15 +571,17 @@ export default {
571
571
  }
572
572
  },
573
573
  up() {
574
- if (document.activeElement) {
575
- let prev = document.activeElement.previousSibling;
574
+ const existing = this.activeElement || document.activeElement;
576
575
 
577
- if (prev?.children?.length) {
578
- const item = prev.children[0];
576
+ if (existing) {
577
+ let prev = document.activeElement.previousElementSibling;
579
578
 
580
- if (item.classList.contains('ns-divider')) {
581
- prev = prev.previousSibling;
582
- }
579
+ if (!prev) {
580
+ prev = existing.parentNode.lastElementChild;
581
+ }
582
+
583
+ if (prev.classList.contains('ns-divider')) {
584
+ prev = prev.previousElementSibling;
583
585
  }
584
586
 
585
587
  if (prev?.focus) {
@@ -599,17 +601,20 @@ export default {
599
601
  this.$nextTick(() => {
600
602
  this.focusFilter();
601
603
  });
602
- this.addCloseKeyHandler();
603
604
  this.layout();
604
605
  },
606
+ clearFilter() {
607
+ this.filter = '';
608
+ this.focusFilter();
609
+ },
605
610
  focusFilter() {
606
- this.$refs.filter.focus();
611
+ this.$refs.filterInput.focus();
607
612
  },
608
613
  close() {
609
614
  this.isOpen = false;
610
615
  this.activeElement = null;
611
- this.removeCloseKeyHandler();
612
616
  this.layout();
617
+ this.$refs.namespaceFilterInput.focus();
613
618
  },
614
619
  clear() {
615
620
  this.value = [];
@@ -689,11 +694,15 @@ export default {
689
694
  <template>
690
695
  <div
691
696
  v-if="!$fetchState.pending"
697
+ ref="namespaceFilterInput"
698
+ role="combobox"
699
+ :aria-expanded="isOpen"
700
+ :aria-activedescendant="containerId"
692
701
  class="ns-filter"
693
702
  data-testid="namespaces-filter"
694
703
  tabindex="0"
695
704
  @mousedown.prevent
696
- @focus="open()"
705
+ @keydown.self.down.enter.space.prevent="open"
697
706
  >
698
707
  <div
699
708
  v-if="isOpen"
@@ -703,6 +712,7 @@ export default {
703
712
 
704
713
  <!-- Select Dropdown control -->
705
714
  <div
715
+ :id="containerId"
706
716
  ref="dropdown"
707
717
  class="ns-dropdown"
708
718
  data-testid="namespaces-dropdown"
@@ -754,13 +764,18 @@ export default {
754
764
  >
755
765
  <div>{{ ns.label }}</div>
756
766
  <!-- block user from removing the last selection if ns forced filtering is on -->
757
- <i
767
+ <RcButton
758
768
  v-if="!namespaceFilterMode || value.length > 1"
759
- class="icon icon-close"
769
+ small
770
+ ghost
771
+ class="ns-chip-button"
760
772
  :data-testid="`namespaces-values-close-${j}`"
761
773
  @click="removeOption(ns, $event)"
774
+ @keydown.enter.space.stop="removeOption(ns, $event)"
762
775
  @mousedown="handleValueMouseDown(ns, $event)"
763
- />
776
+ >
777
+ <i class="icon icon-close" />
778
+ </RcButton>
764
779
  </div>
765
780
  </div>
766
781
 
@@ -795,20 +810,33 @@ export default {
795
810
  data-testid="namespaces-menu"
796
811
  >
797
812
  <div class="ns-controls">
798
- <div class="ns-input">
813
+ <div
814
+ class="ns-input"
815
+ role="status"
816
+ aria-live="polite"
817
+ >
799
818
  <input
800
- ref="filter"
819
+ ref="filterInput"
801
820
  v-model="filter"
802
821
  tabindex="0"
803
822
  class="ns-filter-input"
823
+ :aria-label="t('namespaceFilter.input')"
804
824
  @click="focusFilter"
805
825
  @keydown="inputKeyHandler($event)"
806
826
  >
807
- <i
827
+ <RcButton
808
828
  v-if="hasFilter"
809
- class="ns-filter-clear icon icon-close"
810
- @click="filter = ''"
811
- />
829
+ small
830
+ ghost
831
+ class="ns-filter-clear"
832
+ :aria-label="t('namespaceFilter.button.clearFilter')"
833
+ @click="clearFilter"
834
+ @keydown.enter.stop="clearFilter"
835
+ >
836
+ <i
837
+ class="icon icon-close"
838
+ />
839
+ </RcButton>
812
840
  </div>
813
841
  <div
814
842
  v-if="namespaceFilterMode"
@@ -819,57 +847,74 @@ export default {
819
847
  class="icon icon-info"
820
848
  />
821
849
  </div>
822
- <div
850
+ <RcButton
823
851
  v-else
852
+ small
853
+ ghost
824
854
  class="ns-clear"
855
+ :aria-label="t('namespaceFilter.button.clear')"
856
+ @click="clear"
857
+ @keydown.enter.stop="clear"
858
+ @keydown.tab.exact.prevent="down"
825
859
  >
826
860
  <i
827
861
  class="icon icon-close"
828
- @click="clear()"
829
862
  />
830
- </div>
863
+ </RcButton>
831
864
  </div>
832
865
  <div class="ns-divider mt-0" />
833
866
  <div
834
867
  ref="options"
835
868
  class="ns-options"
836
- role="list"
869
+ role="listbox"
870
+ tabindex="0"
871
+ aria-live="polite"
872
+ @keydown.down.enter.stop="down"
873
+ @keydown.escape="close"
874
+ @keydown.tab.exact.stop="close"
837
875
  >
838
- <div
876
+ <template
839
877
  v-for="(opt, i) in cachedFiltered"
840
- :id="opt.elementId"
841
878
  :key="opt.id"
842
- tabindex="0"
843
- class="ns-option"
844
- :disabled="opt.enabled ? null : true"
845
- :class="{
846
- 'ns-selected': opt.selected,
847
- 'ns-single-match': cachedFiltered.length === 1 && !opt.selected,
848
- }"
849
- :data-testid="`namespaces-option-${i}`"
850
- @click="opt.enabled && selectOption(opt)"
851
- @mouseover="opt.enabled && mouseOver($event)"
852
- @keydown="itemKeyHandler($event, opt)"
853
879
  >
854
- <div
880
+ <hr
855
881
  v-if="opt.kind === NAMESPACE_FILTER_KINDS.DIVIDER"
882
+ role="separator"
883
+ aria-orientation="horizontal"
856
884
  class="ns-divider"
857
- />
885
+ >
858
886
  <div
859
887
  v-else
860
- class="ns-item"
888
+ :id="opt.elementId"
889
+ tabindex="-1"
890
+ role="option"
891
+ class="ns-option"
892
+ :aria-selected="opt.selected"
893
+ :disabled="opt.enabled ? null : true"
894
+ :class="{
895
+ 'ns-selected': opt.selected,
896
+ 'ns-single-match': cachedFiltered.length === 1 && !opt.selected,
897
+ }"
898
+ :data-testid="`namespaces-option-${i}`"
899
+ @click="opt.enabled && selectOption(opt)"
900
+ @mouseover="opt.enabled && mouseOver($event)"
901
+ @keydown="itemKeyHandler($event, opt)"
861
902
  >
862
- <i
863
- v-if="opt.kind === NAMESPACE_FILTER_KINDS.NAMESPACE"
864
- class="icon icon-folder"
865
- />
866
- <div>{{ opt.label }}</div>
867
- <i
868
- v-if="opt.selected"
869
- class="icon icon-checkmark"
870
- />
903
+ <div
904
+ class="ns-item"
905
+ >
906
+ <i
907
+ v-if="opt.kind === NAMESPACE_FILTER_KINDS.NAMESPACE"
908
+ class="icon icon-folder"
909
+ />
910
+ <div>{{ opt.label }}</div>
911
+ <i
912
+ v-if="opt.selected"
913
+ class="icon icon-checkmark"
914
+ />
915
+ </div>
871
916
  </div>
872
- </div>
917
+ </template>
873
918
  <div
874
919
  v-if="cachedFiltered.length === 0"
875
920
  class="ns-none"
@@ -892,6 +937,7 @@ export default {
892
937
  .ns-filter {
893
938
  width: 280px;
894
939
  display: inline-block;
940
+ border-radius: var(--border-radius);
895
941
 
896
942
  .ns-glass {
897
943
  top: 0;
@@ -910,18 +956,15 @@ export default {
910
956
  }
911
957
 
912
958
  .ns-clear {
959
+ padding: 0 5px;
913
960
  &:hover {
914
961
  color: var(--primary);
915
- cursor: pointer;
916
962
  }
917
963
  }
918
964
 
919
965
  .ns-singleton-info, .ns-clear {
920
966
  align-items: center;
921
967
  display: flex;
922
- > i {
923
- padding-right: 5px;
924
- }
925
968
  }
926
969
 
927
970
  .ns-input {
@@ -938,10 +981,15 @@ export default {
938
981
  cursor: pointer;
939
982
  position: absolute;
940
983
  right: 10px;
941
- top: 5px;
984
+ top: 10px;
942
985
  line-height: 24px;
943
986
  text-align: center;
944
- width: 24px;
987
+ width: 14px;
988
+ min-height: 14px;
989
+ }
990
+
991
+ .ns-chip-button {
992
+ min-height: 14px;
945
993
  }
946
994
 
947
995
  .ns-dropdown-menu {
@@ -430,8 +430,7 @@ export default {
430
430
 
431
431
  return {
432
432
  content,
433
- placement: 'right',
434
- popperOptions: { modifiers: { preventOverflow: { enabled: false }, hide: { enabled: false } } },
433
+ placement: 'right',
435
434
  popperClass
436
435
  };
437
436
  },
@@ -699,7 +698,7 @@ export default {
699
698
  v-if="clustersFiltered.length > 0"
700
699
  class="category-title"
701
700
  >
702
- <hr>
701
+ <hr role="none">
703
702
  </div>
704
703
  </div>
705
704
 
@@ -813,7 +812,7 @@ export default {
813
812
  <div
814
813
  class="category-title"
815
814
  >
816
- <hr>
815
+ <hr role="none">
817
816
  <span>
818
817
  {{ t('nav.categories.multiCluster') }}
819
818
  </span>
@@ -846,7 +845,7 @@ export default {
846
845
  <div
847
846
  class="category-title"
848
847
  >
849
- <hr>
848
+ <hr role="none">
850
849
  <span>
851
850
  {{ t('nav.categories.configuration') }}
852
851
  </span>
@@ -10,8 +10,11 @@ import AsyncButton from '@shell/components/AsyncButton';
10
10
  import Select from '@shell/components/form/Select';
11
11
  import VirtualList from 'vue3-virtual-scroll-list';
12
12
  import LogItem from '@shell/components/LogItem';
13
+ import ContainerLogsActions from '@shell/components/nav/WindowManager/ContainerLogsActions.vue';
13
14
  import { shallowRef } from 'vue';
15
+ import { useStore } from 'vuex';
14
16
  import { debounce } from 'lodash';
17
+ import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
15
18
 
16
19
  import { escapeRegex } from '@shell/utils/string';
17
20
  import { HARVESTER_NAME as VIRTUAL } from '@shell/config/features';
@@ -91,6 +94,7 @@ export default {
91
94
  Checkbox,
92
95
  AsyncButton,
93
96
  VirtualList,
97
+ ContainerLogsActions,
94
98
  },
95
99
 
96
100
  props: {
@@ -130,6 +134,13 @@ export default {
130
134
  }
131
135
  },
132
136
 
137
+ setup() {
138
+ const store = useStore();
139
+ const { featureDropdownMenu } = useRuntimeFlag(store);
140
+
141
+ return { featureDropdownMenu };
142
+ },
143
+
133
144
  data() {
134
145
  return {
135
146
  container: this.initialContainer || this.pod?.defaultContainerName,
@@ -145,7 +156,8 @@ export default {
145
156
  lines: [],
146
157
  now: new Date(),
147
158
  logItem: shallowRef(LogItem),
148
- isContainerMenuOpen: false
159
+ isContainerMenuOpen: false,
160
+ range: '',
149
161
  };
150
162
  },
151
163
 
@@ -636,72 +648,85 @@ export default {
636
648
  </div>
637
649
 
638
650
  <div class="log-action log-action-group ml-5">
639
- <div
640
- role="menu"
641
- tabindex="0"
642
- :aria-label="t('wm.containerLogs.logActionMenu')"
643
- @click="openContainerMenu"
644
- @blur.capture="closeContainerMenu"
645
- @keyup.enter="openContainerMenu"
646
- @keyup.space="openContainerMenu"
647
- >
648
- <v-dropdown
649
- :triggers="[]"
650
- :shown="isContainerMenuOpen"
651
- placement="top"
652
- popperClass="containerLogsDropdown"
653
- :autoHide="false"
654
- :flip="false"
655
- :container="false"
656
- @focus.capture="openContainerMenu"
651
+ <template v-if="featureDropdownMenu">
652
+ <ContainerLogsActions
653
+ :range="range"
654
+ :range-options="rangeOptions"
655
+ :wrap="wrap"
656
+ :timestamps="timestamps"
657
+ @toggle-range="toggleRange"
658
+ @toggle-wrap="toggleWrap"
659
+ @toggle-timestamps="toggleTimestamps"
660
+ />
661
+ </template>
662
+ <template v-else>
663
+ <div
664
+ role="menu"
665
+ tabindex="0"
666
+ :aria-label="t('wm.containerLogs.logActionMenu')"
667
+ @click="openContainerMenu"
668
+ @blur.capture="closeContainerMenu"
669
+ @keyup.enter="openContainerMenu"
670
+ @keyup.space="openContainerMenu"
657
671
  >
658
- <button
659
- class="btn role-primary btn-cog"
660
- role="button"
661
- :aria-label="t('wm.containerLogs.options')"
672
+ <v-dropdown
673
+ :triggers="[]"
674
+ :shown="isContainerMenuOpen"
675
+ placement="top"
676
+ popperClass="containerLogsDropdown"
677
+ :autoHide="false"
678
+ :flip="false"
679
+ :container="false"
680
+ @focus.capture="openContainerMenu"
662
681
  >
663
- <i
664
- class="icon icon-gear"
665
- :alt="t('wm.containerLogs.options')"
666
- />
667
- <i
668
- class="icon icon-chevron-up"
669
- :alt="t('wm.containerLogs.expand')"
670
- />
671
- </button>
672
-
673
- <template #popper>
674
- <div class="filter-popup">
675
- <LabeledSelect
676
- v-model:value="range"
677
- class="range"
678
- :label="t('wm.containerLogs.range.label')"
679
- :options="rangeOptions"
680
- :clearable="false"
681
- placement="top"
682
- role="menuitem"
683
- @update:value="toggleRange($event)"
682
+ <button
683
+ class="btn role-primary btn-cog"
684
+ role="button"
685
+ :aria-label="t('wm.containerLogs.options')"
686
+ >
687
+ <i
688
+ class="icon icon-gear"
689
+ :alt="t('wm.containerLogs.options')"
684
690
  />
685
- <div>
686
- <Checkbox
687
- :label="t('wm.containerLogs.wrap')"
688
- :value="wrap"
689
- role="menuitem"
690
- @update:value="toggleWrap"
691
- />
692
- </div>
693
- <div>
694
- <Checkbox
695
- :label="t('wm.containerLogs.timestamps')"
696
- :value="timestamps"
691
+ <i
692
+ class="icon icon-chevron-up"
693
+ :alt="t('wm.containerLogs.expand')"
694
+ />
695
+ </button>
696
+
697
+ <template #popper>
698
+ <div class="filter-popup">
699
+ <LabeledSelect
700
+ v-model:value="range"
701
+ class="range"
702
+ :label="t('wm.containerLogs.range.label')"
703
+ :options="rangeOptions"
704
+ :clearable="false"
705
+ placement="top"
697
706
  role="menuitem"
698
- @update:value="toggleTimestamps"
707
+ @update:value="toggleRange($event)"
699
708
  />
709
+ <div>
710
+ <Checkbox
711
+ :label="t('wm.containerLogs.wrap')"
712
+ :value="wrap"
713
+ role="menuitem"
714
+ @update:value="toggleWrap"
715
+ />
716
+ </div>
717
+ <div>
718
+ <Checkbox
719
+ :label="t('wm.containerLogs.timestamps')"
720
+ :value="timestamps"
721
+ role="menuitem"
722
+ @update:value="toggleTimestamps"
723
+ />
724
+ </div>
700
725
  </div>
701
- </div>
702
- </template>
703
- </v-dropdown>
704
- </div>
726
+ </template>
727
+ </v-dropdown>
728
+ </div>
729
+ </template>
705
730
  </div>
706
731
 
707
732
  <div class="log-action log-action-group ml-5">
@@ -874,4 +899,5 @@ export default {
874
899
  }
875
900
  }
876
901
  }
902
+
877
903
  </style>