Skip to content

Commit

Permalink
fix closing menu when the user close it and then refresh the page again
Browse files Browse the repository at this point in the history
  • Loading branch information
bsatarnejad committed Nov 4, 2024
1 parent 953618b commit c36f13c
Showing 1 changed file with 53 additions and 45 deletions.
98 changes: 53 additions & 45 deletions frontend/src/app/core/main-menu/main-menu-toggle.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@
// See COPYRIGHT and LICENSE files for more details.
//++

import { Injectable, Injector } from '@angular/core';
import { Injectable, Injector, OnInit } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { I18nService } from 'core-app/core/i18n/i18n.service';
import { CurrentProjectService } from 'core-app/core/current-project/current-project.service';
import { DeviceService } from 'core-app/core/browser/device.service';
import { InjectField } from 'core-app/shared/helpers/angular/inject-field.decorator';

@Injectable({ providedIn: 'root' })
export class MainMenuToggleService {
export class MainMenuToggleService implements OnInit {
public toggleTitle:string;

private elementWidth:number;
Expand Down Expand Up @@ -67,6 +67,8 @@ export class MainMenuToggleService {

public changeData$ = this.changeData.asObservable();

private wasCollapsedByUser = false;

constructor(
protected I18n:I18nService,
public injector:Injector,
Expand All @@ -76,28 +78,29 @@ export class MainMenuToggleService {
window.addEventListener('resize', this.onWindowResize.bind(this));
}

public ngOnInit():void {

Check failure on line 81 in frontend/src/app/core/main-menu/main-menu-toggle.service.ts

View workflow job for this annotation

GitHub Actions / eslint

[eslint] frontend/src/app/core/main-menu/main-menu-toggle.service.ts#L81 <@angular-eslint/contextual-lifecycle>(https://github.com/angular-eslint/angular-eslint/blob/main/packages/eslint-plugin/docs/rules/contextual-lifecycle.md)

Angular will not invoke the `ngOnInit` lifecycle method within `@Injectable()` classes
Raw output
{"ruleId":"@angular-eslint/contextual-lifecycle","severity":2,"message":"Angular will not invoke the `ngOnInit` lifecycle method within `@Injectable()` classes","line":81,"column":10,"nodeType":"Identifier","messageId":"contextualLifecycle","endLine":81,"endColumn":18}
this.initializeMenu();
}

public initializeMenu():void {
if (!this.mainMenu) {
return;
}

this.elementWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string);
const menuCollapsed = window.OpenProject.guardedLocalStorage(this.localStorageStateKey) as string;
const menuCollapsed = window.OpenProject.guardedLocalStorage(this.localStorageStateKey) === 'true';

// Set the initial value of the collapse tracking flag
this.wasCollapsedByUser = menuCollapsed;

if (!this.elementWidth) {
this.saveWidth(this.mainMenu.offsetWidth);
} else if (menuCollapsed && JSON.parse(menuCollapsed)) {
} else if (menuCollapsed) {
this.closeMenu();
} else {
this.setWidth();
}

const currentProject:CurrentProjectService = this.injector.get(CurrentProjectService);
if (jQuery(document.body).hasClass('controller-my') && this.elementWidth === 0 || currentProject.id === null) {
this.saveWidth(this.defaultWidth);
}

// small desktop version default: hide menu on initialization
this.adjustMenuVisibility();
}

Expand All @@ -107,73 +110,77 @@ export class MainMenuToggleService {

private adjustMenuVisibility():void {
if (window.innerWidth >= 1012) {
this.setWidth(this.defaultWidth); // Open menu if the screen is wider than 1012px
// If wide screen, only open if it wasn't manually collapsed
if (!this.wasCollapsedByUser) {
this.setWidth(this.defaultWidth);
}
} else {
this.closeMenu(); // Close menu if the screen is narrower
// Narrow screen: always close the menu and reset the collapse flag
this.closeMenu();
this.wasCollapsedByUser = false;
}
}

// click on arrow or hamburger icon
public toggleNavigation(event?:JQuery.TriggeredEvent|Event):void {
if (event) {
event.stopPropagation();
event.preventDefault();
}

if (!this.showNavigation) { // sidebar is hidden -> show menu
if (this.deviceService.isSmallDesktop) { // small desktop version
this.setWidth(window.innerWidth);
} else { // desktop version
const savedWidth = parseInt(window.OpenProject.guardedLocalStorage(this.localStorageKey) as string);
const widthToSave = savedWidth >= this.elementMinWidth ? savedWidth : this.defaultWidth;
// Update the flag based on whether the menu is currently visible
this.wasCollapsedByUser = this.showNavigation;

this.saveWidth(widthToSave);
}
} else { // sidebar is expanded -> close menu
if (this.showNavigation) {
this.closeMenu();
} else {
this.openMenu();
}

// Set focus on first visible main menu item.
// This needs to be called after AngularJS has rendered the menu, which happens some when after(!) we leave this
// method here. So we need to set the focus after a timeout.
setTimeout(() => {
jQuery('#main-menu [class*="-menu-item"]:visible').first().focus();
}, 500);
// Save the collapsed state in localStorage
window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(!this.showNavigation));
}

public closeMenu():void {
this.setWidth(0);
this.wasCollapsedByUser = true;
window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'true');
jQuery('.searchable-menu--search-input').blur();
}

public saveWidth(width?:number):void {
this.setWidth(width);
window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth));
window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(this.elementWidth === 0));
public openMenu(): void {

Check failure on line 150 in frontend/src/app/core/main-menu/main-menu-toggle.service.ts

View workflow job for this annotation

GitHub Actions / eslint

[eslint] frontend/src/app/core/main-menu/main-menu-toggle.service.ts#L150 <@typescript-eslint/type-annotation-spacing>(https://typescript-eslint.io/rules/type-annotation-spacing)

Unexpected space after the ':'.
Raw output
{"ruleId":"@typescript-eslint/type-annotation-spacing","severity":2,"message":"Unexpected space after the ':'.","line":150,"column":20,"nodeType":"Punctuator","messageId":"unexpectedSpaceAfter","endLine":150,"endColumn":21,"fix":{"range":[4928,4929],"text":""}}
this.setWidth(this.defaultWidth);
this.wasCollapsedByUser = false;
window.OpenProject.guardedLocalStorage(this.localStorageStateKey, 'false');
}

public setWidth(width?:any):void {
public setWidth(width?:number):void {
if (width !== undefined) {
// Leave a minimum amount of space for space for the content
const maxMenuWidth = this.deviceService.isSmallDesktop ? window.innerWidth - 120 : window.innerWidth - 520;
this.elementWidth = Math.min(width as number, maxMenuWidth);
this.elementWidth = width;
}

this.snapBack();
this.setToggleTitle();
this.toggleClassHidden();
// Apply the width directly to the main menu
this.mainMenu.style.width = `${this.elementWidth}px`;

this.global.showNavigation = this.showNavigation;
// Apply to root CSS variable for any related layout adjustments
this.htmlNode.style.setProperty('--main-menu-width', `${this.elementWidth}px`);

// Send change event when size of menu is changing (menu toggled or resized)
const changeEvent = jQuery.Event('change');
this.changeData.next(changeEvent);
// Check if menu is open or closed and apply CSS class if needed
this.toggleClassHidden();

// Save the width if it's open
if (this.elementWidth > 0) {
window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth));
}
}

public saveWidth(width?:number):void {
this.setWidth(width);
window.OpenProject.guardedLocalStorage(this.localStorageKey, String(this.elementWidth));
window.OpenProject.guardedLocalStorage(this.localStorageStateKey, String(this.elementWidth === 0));
}

public get showNavigation():boolean {
return (this.elementWidth >= this.elementMinWidth);
return this.elementWidth >= this.elementMinWidth;
}

private snapBack():void {
Expand All @@ -192,6 +199,7 @@ export class MainMenuToggleService {
}

private toggleClassHidden():void {
this.hideElements.toggleClass('hidden-navigation', !this.showNavigation);
const isHidden = this.elementWidth < this.elementMinWidth;
this.hideElements.toggleClass('hidden-navigation', isHidden);
}
}

0 comments on commit c36f13c

Please sign in to comment.