From: Bill Erickson Date: Thu, 15 Jul 2021 16:04:27 +0000 (-0400) Subject: LP1936233 Grouped Menu component X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=f5b0b94793d3c8c2b3ad74c7266b6b6f76a7aa83;p=working%2FEvergreen.git LP1936233 Grouped Menu component Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu-entry.component.ts b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu-entry.component.ts new file mode 100644 index 0000000000..79436bd94c --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu-entry.component.ts @@ -0,0 +1,41 @@ +import {Component, Input, Output, EventEmitter, OnInit, Host} from '@angular/core'; +import {GroupedMenuComponent, GroupedMenuEntry} from './grouped-menu.component'; + +@Component({ + selector: 'eg-grouped-menu-entry', + template: '' +}) + +export class GroupedMenuEntryComponent implements OnInit { + + @Input() label: string; + @Input() group: string; + @Input() disabled: boolean; + @Input() isSeparator: boolean; + @Input() newTab: boolean; + @Input() routerLink: string; + @Input() href: string; + @Output() entryClicked: EventEmitter = + new EventEmitter(); + + menu: GroupedMenuComponent; + + constructor(@Host() menu: GroupedMenuComponent) { + this.menu = menu; + } + + ngOnInit() { + const entry = new GroupedMenuEntry(); + entry.label = this.label; + entry.group = this.group; + entry.disabled = this.disabled; + entry.newTab = this.newTab; + entry.routerLink = this.routerLink; + entry.href = this.href; + entry.isSeparator = this.isSeparator; + entry.entryClicked = this.entryClicked; + this.menu.menuEntries.push(entry); + } +} + + diff --git a/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.html b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.html new file mode 100644 index 0000000000..bbfdb980e0 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.html @@ -0,0 +1,21 @@ + +
+ +
+ +
+
diff --git a/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.ts b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.ts new file mode 100644 index 0000000000..9e04f9f696 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.component.ts @@ -0,0 +1,107 @@ +import {Component, Input, Output, EventEmitter, OnInit, AfterViewInit} from '@angular/core'; +import {Router} from '@angular/router'; +import {Location} from '@angular/common'; + +export class GroupedMenuEntry { + label: string; + group: string; + disabled: boolean; + isSeparator: boolean; + isGroup: boolean; + routerLink: string; + newTab: boolean; // routerLink or href open a new tab + href: string; + entryClicked: EventEmitter; +} + +@Component({ + selector: 'eg-grouped-menu', + templateUrl: './grouped-menu.component.html' +}) + +export class GroupedMenuComponent implements OnInit, AfterViewInit { + + static autoId = 0; + + // Label for dropdown button + @Input() label: string; + + @Input() domId = 'grouped-menu-' + GroupedMenuComponent.autoId++; + + menuEntries: GroupedMenuEntry[] = []; + + constructor( + private router: Router, + private ngLocation: Location + ) {} + + ngOnInit() { + } + + ngAfterViewInit() { + setTimeout(() => this.sortActions()); + } + + sortActions() { + const actions = this.menuEntries; + + const unGrouped = actions.filter(a => !a.group) + .sort((a, b) => { + return a.label < b.label ? -1 : 1; + }); + + const grouped = actions.filter(a => Boolean(a.group)) + .sort((a, b) => { + if (a.group === b.group) { + return a.label < b.label ? -1 : 1; + } else { + return a.group < b.group ? -1 : 1; + } + }); + + // Insert group markers for rendering + const seen: any = {}; + const grouped2: any[] = []; + grouped.forEach(action => { + if (!seen[action.group]) { + seen[action.group] = true; + const act = new GroupedMenuEntry(); + act.label = action.group; + act.isGroup = true; + grouped2.push(act); + } + grouped2.push(action); + }); + + this.menuEntries = unGrouped.concat(grouped2); + } + + performAction(entry: GroupedMenuEntry) { + if (entry.isGroup || entry.isSeparator) { return; } + + // Always emit, even if no one is listening. + entry.entryClicked.emit(entry); + + let url; + if (entry.href) { + url = entry.href; + } else if (entry.routerLink) { + if (entry.newTab) { + url = this.ngLocation.prepareExternalUrl(entry.routerLink); + } else { + this.router.navigate([entry.routerLink]); + return; + } + } + + if (url) { + if (entry.newTab) { + window.open(url); + } else { + location.href = url; + } + return; + } + } +} + diff --git a/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.module.ts b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.module.ts new file mode 100644 index 0000000000..a2dea638f8 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/grouped-menu/grouped-menu.module.ts @@ -0,0 +1,23 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; +import {GroupedMenuComponent} from './grouped-menu.component'; +import {GroupedMenuEntryComponent} from './grouped-menu-entry.component'; + +@NgModule({ + declarations: [ + GroupedMenuComponent, + GroupedMenuEntryComponent + ], + imports: [ + CommonModule, + NgbModule + ], + exports: [ + GroupedMenuComponent, + GroupedMenuEntryComponent + ] +}) + +export class GroupedMenuModule { } +