<div [ngClass]="{'col-lg-9': showSummaryPane(), 'col-lg-12': !showSummaryPane()}">
<div class="sticky-top-with-nav bg-white">
- <ul ngbNav #patronNav="ngbNav" class="nav-tabs"
+ <ul ngbNav #patronNav="ngbNav" class="nav-tabs" [keyboard]="false"
[activeId]="patronTab" (navChange)="beforeTabChange($event)">
<ng-container *ngIf="patronTab !== 'search'">
</ng-container>
<li ngbNavItem="checkout" [disabled]="!context.summary">
- <a ngbNavLink i18n>Check Out</a>
+ <a ngbNavLink (click)="navItemClick('checkout', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/checkout" i18n>Check Out</a>
<ng-template ngbNavContent>
<div class="">
<eg-patron-checkout></eg-patron-checkout>
</li>
<li ngbNavItem="items_out" [disabled]="!context.summary">
- <a ngbNavLink i18n>
+ <a ngbNavLink (click)="navItemClick('items_out', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/items_out" i18n>
Items Out ({{counts('checkouts', 'total_out')}})
</a>
<ng-template ngbNavContent>
</li>
<li ngbNavItem="holds" [disabled]="!context.summary">
- <a ngbNavLink i18n>
+ <a ngbNavLink (click)="navItemClick('holds', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/holds" i18n>
Holds ({{counts('holds', 'ready')}} / {{counts('holds', 'total')}})
</a>
<ng-template ngbNavContent>
</li>
<li ngbNavItem="bills" [disabled]="!context.summary">
- <a ngbNavLink (click)="billsTabClicked()" i18n>
+ <a ngbNavLink (click)="navItemClick('bills', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/bills" i18n>
Bills
<span [ngClass]="{'text-danger': counts('fines', 'balance_owed') > 0}">
({{counts('fines', 'balance_owed') | currency}})
</li>
<li ngbNavItem="messages" [disabled]="!context.summary">
- <a ngbNavLink i18n>Messages</a>
+ <a ngbNavLink (click)="navItemClick('messages', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/messages" i18n>Messages</a>
<ng-template ngbNavContent>
<div class="">
<eg-patron-messages [patronId]="patronId"></eg-patron-messages>
</li>
<li ngbNavItem="edit" [disabled]="!context.summary">
- <a ngbNavLink i18n>Edit</a>
+ <a ngbNavLink (click)="navItemClick('edit', $event)"
+ routerLink="/staff/circ/patron/{{patronId}}/edit" i18n>Edit</a>
<ng-template ngbNavContent>
<eg-patron-edit #patronEditor [patronId]="patronId" [toolbar]="editorToolbar">
</eg-patron-edit>
import {Component, ViewChild, OnInit, AfterViewInit, HostListener} from '@angular/core';
import {Router, ActivatedRoute, ParamMap, RoutesRecognized} from '@angular/router';
+import {Location} from '@angular/common';
import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
import {Observable, throwError, empty} from 'rxjs';
import {filter, pairwise, concatMap, tap} from 'rxjs/operators';
constructor(
private router: Router,
private route: ActivatedRoute,
+ private ngLocation: Location,
private net: NetService,
private auth: AuthService,
private pcrud: PcrudService,
ngAfterViewInit() {
}
- beforeTabChange(evt: NgbNavChangeEvent) {
- // tab will change with route navigation.
+ // Navigate, opening new tabs when requested via control-click.
+ // NOTE: The nav items have routerLinks, but for some reason,
+ // control-click on the links does not open them in a new tab.
+ // Mouse middle-click does, though. *shrug*
+ navItemClick(tab: string, evt: PointerEvent) {
evt.preventDefault();
-
- // Protect against tab changes with dirty data.
this.canDeactivate().then(ok => {
if (ok) {
- this.patronTab = evt.nextId;
- this.routeToTab();
+ this.routeToTab(tab, evt.ctrlKey);
}
});
}
- // The bills tab has various sub-interfaces. If the user is already
- // on the Bills tab and clicks the tab, return them to the main bills
- // screen.
- // Avoid the navigate call when not on the bills tab because it
- // interferes with the pre-tab-change "changes pending" confirm dialog
- // used by the editor and possibily others.
- billsTabClicked() {
- if (this.patronTab === 'bills') {
- this.router.navigate(['/staff/circ/patron', this.patronId, 'bills']);
- }
+ beforeTabChange(evt: NgbNavChangeEvent) {
+ // Prevent the nav component from changing tabs so we can
+ // control the behaviour.
+ evt.preventDefault();
}
- routeToTab() {
+ routeToTab(tab?: string, newWindow?: boolean) {
let url = '/staff/circ/patron/';
- switch (this.patronTab) {
+ tab = tab || this.patronTab;
+
+ switch (tab) {
case 'search':
case 'bcsearch':
- url += this.patronTab;
+ url += tab;
break;
case 'other':
url += `${this.patronId}/${this.altTab}`;
break;
default:
- url += `${this.patronId}/${this.patronTab}`;
+ url += `${this.patronId}/${tab}`;
}
- this.router.navigate([url]);
+ if (newWindow) {
+ url = this.ngLocation.prepareExternalUrl(url);
+ window.open(url);
+ } else {
+ this.router.navigate([url]);
+ }
}
showSummaryPane(): boolean {
patronAlertsShown(): boolean {
if (!this.summary) { return false; }
- const shown = this.store.getSessionItem('eg.circ.last_alerted_patron');
+ this.store.addLoginSessionKey('eg.circ.last_alerted_patron');
+ const shown = this.store.getLoginSessionItem('eg.circ.last_alerted_patron');
if (shown === this.summary.patron.id()) { return true; }
- this.store.setSessionItem('eg.circ.last_alerted_patron', this.summary.patron.id());
+ this.store.setLoginSessionItem('eg.circ.last_alerted_patron', this.summary.patron.id());
return false;
}