diff options
Diffstat (limited to 'app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue')
-rw-r--r-- | app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue | 84 |
1 files changed, 22 insertions, 62 deletions
diff --git a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue index 1cbd64b501d..cac8fecb6b1 100644 --- a/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue +++ b/app/assets/javascripts/nav/components/top_nav_dropdown_menu.vue @@ -1,17 +1,15 @@ <script> +import { cloneDeep } from 'lodash'; import { FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS } from '~/frequent_items/constants'; import KeepAliveSlots from '~/vue_shared/components/keep_alive_slots.vue'; import TopNavContainerView from './top_nav_container_view.vue'; -import TopNavMenuItem from './top_nav_menu_item.vue'; - -const ACTIVE_CLASS = 'gl-shadow-none! gl-font-weight-bold! active'; -const SECONDARY_GROUP_CLASS = 'gl-pt-3 gl-mt-3 gl-border-1 gl-border-t-solid gl-border-gray-100'; +import TopNavMenuSections from './top_nav_menu_sections.vue'; export default { components: { KeepAliveSlots, TopNavContainerView, - TopNavMenuItem, + TopNavMenuSections, }, props: { primary: { @@ -31,29 +29,25 @@ export default { }, }, data() { + // It's expected that primary & secondary never change, so these are treated as "init" props. + // We need to clone so that we can mutate the data without mutating the props + const menuSections = [ + { id: 'primary', menuItems: cloneDeep(this.primary) }, + { id: 'secondary', menuItems: cloneDeep(this.secondary) }, + ].filter((x) => x.menuItems?.length); + return { - activeId: '', + menuSections, }; }, computed: { - menuItemGroups() { - return [ - { key: 'primary', items: this.primary, classes: '' }, - { - key: 'secondary', - items: this.secondary, - classes: SECONDARY_GROUP_CLASS, - }, - ].filter((x) => x.items?.length); - }, allMenuItems() { - return this.menuItemGroups.flatMap((x) => x.items); - }, - activeMenuItem() { - return this.allMenuItems.find((x) => x.id === this.activeId); + return this.menuSections.flatMap((x) => x.menuItems); }, activeView() { - return this.activeMenuItem?.view; + const active = this.allMenuItems.find((x) => x.active); + + return active?.view; }, menuClass() { if (!this.activeView) { @@ -63,67 +57,33 @@ export default { return ''; }, }, - created() { - // Initialize activeId based on initialization prop - this.activeId = this.allMenuItems.find((x) => x.active)?.id; - }, methods: { - onClick({ id, href }) { - // If we're a link, let's just do the default behavior so the view won't change - if (href) { - return; - } - - this.activeId = id; - }, - menuItemClasses(menuItem) { - if (menuItem.id === this.activeId) { - return ACTIVE_CLASS; - } - - return ''; + onMenuItemClick({ id }) { + this.allMenuItems.forEach((menuItem) => { + this.$set(menuItem, 'active', id === menuItem.id); + }); }, }, FREQUENT_ITEMS_PROJECTS, FREQUENT_ITEMS_GROUPS, - // expose for unit tests - ACTIVE_CLASS, - SECONDARY_GROUP_CLASS, }; </script> <template> <div class="gl-display-flex gl-align-items-stretch"> <div - class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10" + class="gl-w-grid-size-30 gl-flex-shrink-0 gl-bg-gray-10 gl-py-3 gl-px-5" :class="menuClass" data-testid="menu-sidebar" > - <div - class="gl-py-3 gl-px-5 gl-h-full gl-display-flex gl-align-items-stretch gl-flex-direction-column" - > - <div - v-for="group in menuItemGroups" - :key="group.key" - :class="group.classes" - data-testid="menu-item-group" - > - <top-nav-menu-item - v-for="(menu, index) in group.items" - :key="menu.id" - data-testid="menu-item" - :class="[{ 'gl-mt-1': index !== 0 }, menuItemClasses(menu)]" - :menu-item="menu" - @click="onClick(menu)" - /> - </div> - </div> + <top-nav-menu-sections :sections="menuSections" @menu-item-click="onMenuItemClick" /> </div> <keep-alive-slots v-show="activeView" :slot-key="activeView" class="gl-w-grid-size-40 gl-overflow-hidden gl-py-3 gl-px-5" data-testid="menu-subview" + data-qa-selector="menu_subview_container" > <template #projects> <top-nav-container-view |