Fix navbar rendering

- Fix: items still being displayed when navigation cache is cleared
- Fix: duplicate entries were added to the more dropdown

- Move the ready checks to the navbar abstract
- Move the display type decision logic to the navbar abstract
- Add ready method to be easier to check if dependencies are loaded
- Cleanup
-- add js doc
-- format code
This commit is contained in:
Clemente Raposo 2020-04-13 12:42:13 +01:00 committed by Dillon-Brown
parent 77c7057328
commit 7195848d86
4 changed files with 187 additions and 69 deletions

View file

@ -2,9 +2,10 @@ import {ActionLinkModel} from './action-link-model';
import {CurrentUserModel} from './current-user-model';
import {AllMenuModel} from './all-menu-model';
import {LogoModel} from '../logo/logo-model';
import {NavbarModuleMap, GroupedTab} from '@base/facades/navigation/navigation.facade';
import {GroupedTab, NavbarModuleMap} from '@base/facades/navigation/navigation.facade';
import {LanguageListStringMap, LanguageStringMap} from '@base/facades/language/language.facade';
import {MenuItem} from '@components/navbar/navbar.abstract';
import {UserPreferenceMap} from '@base/facades/user-preference/user-preference.facade';
export interface NavbarModel {
authenticated: boolean;
@ -17,6 +18,17 @@ export interface NavbarModel {
resetMenu(): void;
build(
tabs: string[],
modules: NavbarModuleMap,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
menuItemThreshold: number,
groupedTabs: GroupedTab[],
userPreferences: UserPreferenceMap
): void;
buildGroupTabMenu(
items: string[],
modules: NavbarModuleMap,
@ -25,7 +37,7 @@ export interface NavbarModel {
appListStrings: LanguageListStringMap,
menuItemThreshold: number,
groupedTabs: GroupedTab[]
): void;
): void;
buildTabMenu(
items: string[],
@ -33,5 +45,5 @@ export interface NavbarModel {
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
menuItemThreshold: number): void;
menuItemThreshold: number): void;
}

View file

@ -1,10 +1,12 @@
import {NavbarModel} from './navbar-model';
import {LogoAbstract} from '../logo/logo-abstract';
import {NavbarModule, NavbarModuleMap, GroupedTab} from "@base/facades/navigation/navigation.facade";
import {GroupedTab, NavbarModuleMap} from '@base/facades/navigation/navigation.facade';
import {LanguageListStringMap, LanguageStringMap} from '@base/facades/language/language.facade';
import {CurrentUserModel} from './current-user-model';
import {ActionLinkModel} from './action-link-model';
import {ready} from '@base/utils/object-utils';
import {UserPreferenceMap} from '@base/facades/user-preference/user-preference.facade';
export interface RecentRecordsMenuItem {
summary: string;
@ -16,7 +18,7 @@ export interface MenuItem {
label: string;
url: string;
route?: string;
params?: { [key: string]: string; }
params?: { [key: string]: string };
};
icon: string;
submenu: MenuItem[];
@ -65,28 +67,96 @@ export class NavbarAbstract implements NavbarModel {
};
menu: MenuItem[] = [];
public resetMenu() {
/**
* Reset menus
*/
public resetMenu(): void {
this.menu = [];
this.all.modules = [];
this.all.extra = [];
}
public buildGroupTabMenu(items: string[], modules: NavbarModuleMap, appStrings: LanguageStringMap,
modStrings: LanguageListStringMap, appListStrings: LanguageListStringMap, threshold: number, groupedTabs: GroupedTab[]): void
{
/**
* Build navbar
* @param tabs
* @param modules
* @param appStrings
* @param modStrings
* @param appListStrings
* @param menuItemThreshold
* @param groupedTabs
* @param userPreferences
*/
public build(
tabs: string[],
modules: NavbarModuleMap,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
menuItemThreshold: number,
groupedTabs: GroupedTab[],
userPreferences: UserPreferenceMap
): void {
this.resetMenu();
if (!ready([tabs, modules, appStrings, modStrings, appListStrings, userPreferences])) {
return;
}
const navigationParadigm = userPreferences.navigation_paradigm;
if (navigationParadigm.toString() === 'm') {
this.buildTabMenu(tabs, modules, appStrings, modStrings, appListStrings, menuItemThreshold);
return;
}
if (navigationParadigm.toString() === 'gm') {
this.buildGroupTabMenu(tabs, modules, appStrings, modStrings, appListStrings, menuItemThreshold, groupedTabs);
return;
}
}
/**
* Build Group tab menu
* @param items
* @param modules
* @param appStrings
* @param modStrings
* @param appListStrings
* @param threshold
* @param groupedTabs
*/
public buildGroupTabMenu(
items: string[],
modules: NavbarModuleMap,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
threshold: number,
groupedTabs: GroupedTab[]): void {
const navItems = [];
const moreItems = [];
if (!items || items.length === 0) {
this.menu = navItems;
this.all.extra = moreItems;
this.all.modules = moreItems;
return;
}
let count = 0;
groupedTabs.forEach((groupedTab: any) => {
if (count <= threshold) {
navItems.push(this.buildTabGroupedMenuItem(groupedTab.labelKey, groupedTab.modules, modules, appStrings, modStrings, appListStrings));
navItems.push(this.buildTabGroupedMenuItem(
groupedTab.labelKey,
groupedTab.modules,
modules,
appStrings,
modStrings,
appListStrings
));
}
count++;
@ -94,23 +164,31 @@ export class NavbarAbstract implements NavbarModel {
this.menu = navItems;
this.all.modules = moreItems;
this.all.extra = moreItems;
}
/**
* Build tab / module menu
* @param items
* @param modules
* @param appStrings
* @param modStrings
* @param appListStrings
* @param threshold
*/
public buildTabMenu(items: string[],
modules: NavbarModuleMap,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
threshold: number
): void {
modules: NavbarModuleMap,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap,
threshold: number
): void {
const navItems = [];
const moreItems = [];
if (!items || items.length === 0) {
this.menu = navItems;
this.all.extra = moreItems;
this.all.modules = moreItems;
return;
}
@ -132,9 +210,17 @@ export class NavbarAbstract implements NavbarModel {
this.menu = navItems;
this.all.modules = moreItems;
this.all.extra = moreItems;
}
/**
* Build Grouped Tab menu item
* @param moduleLabel to display
* @param groupedModules list
* @param modules list
* @param appStrings list
* @param modStrings list
* @param appListStrings list
*/
public buildTabGroupedMenuItem(
moduleLabel: string,
groupedModules: any[],
@ -166,6 +252,14 @@ export class NavbarAbstract implements NavbarModel {
return menuItem;
}
/**
* Build Grouped menu
* @param groupedModules
* @param modules
* @param appStrings
* @param modStrings
* @param appListStrings
*/
public buildGroupedMenu(
groupedModules: any[],
modules: NavbarModuleMap,
@ -178,25 +272,33 @@ export class NavbarAbstract implements NavbarModel {
groupedModules.forEach((groupedModule) => {
let module = modules[groupedModule];
const module = modules[groupedModule];
if (module === undefined) {
if (!module) {
return;
}
groupedItems.push(this.buildTabMenuItem(groupedModule, module, appStrings, modStrings, appListStrings));
});
return groupedItems;
}
/**
* Build module menu items
* @param module
* @param moduleInfo
* @param appStrings
* @param modStrings
* @param appListStrings
*/
public buildTabMenuItem(
module: string,
moduleInfo: any,
appStrings: LanguageStringMap,
modStrings: LanguageListStringMap,
appListStrings: LanguageListStringMap
): MenuItem {
): MenuItem {
let moduleUrl = (moduleInfo && moduleInfo.defaultRoute) || moduleInfo.defaultRoute;
let moduleRoute = null;

View file

@ -1,16 +1,15 @@
import {Component, OnInit, HostListener} from '@angular/core';
import {Component, HostListener, OnInit} from '@angular/core';
import {ApiService} from '../../services/api/api.service';
import {NavbarModel} from './navbar-model';
import {NavbarAbstract} from './navbar.abstract';
import {combineLatest, Observable} from 'rxjs';
import {NavbarModuleMap, NavigationFacade, GroupedTab} from '@base/facades/navigation/navigation.facade';
import {NavbarModuleMap, NavigationFacade} from '@base/facades/navigation/navigation.facade';
import {LanguageFacade, LanguageListStringMap, LanguageStringMap} from '@base/facades/language/language.facade';
import {UserPreferenceMap, UserPreferenceFacade} from '@base/facades/user-preference/user-preference.facade';
import {UserPreferenceFacade, UserPreferenceMap} from '@base/facades/user-preference/user-preference.facade';
import {map} from 'rxjs/operators';
import { exists } from 'fs';
@Component({
selector: 'scrm-navbar-ui',
@ -44,55 +43,29 @@ export class NavbarUiComponent implements OnInit {
groupedTabs$: Observable<any> = this.navigationFacade.groupedTabs$;
vm$ = combineLatest([
this.tabs$,
this.modules$,
this.appStrings$,
this.appListStrings$,
this.modStrings$,
this.tabs$,
this.modules$,
this.appStrings$,
this.appListStrings$,
this.modStrings$,
this.userPreferences$,
this.groupedTabs$
]).pipe(
map((
[
map(([tabs, modules, appStrings, appListStrings, modStrings, userPreferences, groupedTabs]) => {
this.navbar.build(
tabs,
modules,
appStrings,
appListStrings,
modStrings,
userPreferences,
groupedTabs
]) => {
if (tabs && tabs.length > 0 &&
modules && Object.keys(modules).length > 0 &&
appStrings && Object.keys(appStrings).length > 0 &&
modStrings && Object.keys(modStrings).length > 0 &&
appListStrings && Object.keys(appListStrings).length > 0 &&
userPreferences['navigation_paradigm'] && userPreferences['navigation_paradigm'].toString() == "m"
) {
this.navbar.resetMenu();
this.navbar.buildTabMenu(tabs, modules, appStrings, modStrings, appListStrings, this.menuItemThreshold);
}
if (tabs && tabs.length > 0 &&
modules && Object.keys(modules).length > 0 &&
appStrings && Object.keys(appStrings).length > 0 &&
modStrings && Object.keys(modStrings).length > 0 &&
appListStrings && Object.keys(appListStrings).length > 0 &&
userPreferences['navigation_paradigm'] && userPreferences['navigation_paradigm'].toString() == "gm"
) {
this.navbar.resetMenu();
this.navbar.buildGroupTabMenu(tabs, modules, appStrings, modStrings, appListStrings, this.menuItemThreshold, groupedTabs);
}
appListStrings,
this.menuItemThreshold,
groupedTabs,
userPreferences
)
return {
tabs,
modules,
appStrings,
appListStrings,
modStrings,
userPreferences,
groupedTabs
tabs, modules, appStrings, appListStrings, modStrings, userPreferences, groupedTabs
};
})
);

View file

@ -5,3 +5,34 @@
* @returns any
*/
export const deepClone = (obj: any): any => JSON.parse(JSON.stringify(obj));
/**
* Check if all entries have been loaded and are ready to use
*
* @param entries
* @returns boolean
*/
export const ready = (entries: (Array<any> | Record<string, any>)[]): boolean => {
let areReady = true;
entries.every(entry => {
if (!entry) {
areReady = false;
return false;
}
if (Array.isArray(entry) && entry.length <= 0) {
areReady = false;
return false;
}
if (typeof entry === 'object' && Object.keys(entry).length <= 0) {
areReady = false;
return false;
}
return true;
});
return areReady;
};