-import {Component, OnInit, ViewEncapsulation} from '@angular/core';
+import {Component, OnInit, AfterViewInit, ViewChild, ViewEncapsulation} from '@angular/core';
import {Router, ActivatedRoute, NavigationEnd} from '@angular/router';
import {AuthService} from '@eg/core/auth.service';
+import {NetService} from '@eg/core/net.service';
import {SckoService} from './scko.service';
import {ServerStoreService} from '@eg/core/server-store.service';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
@Component({
templateUrl: 'scko.component.html',
encapsulation: ViewEncapsulation.None
})
-export class SckoComponent implements OnInit {
+export class SckoComponent implements OnInit, AfterViewInit {
+
+ @ViewChild('logoutDialog') logoutDialog: ConfirmDialogComponent;
constructor(
private router: Router,
private route: ActivatedRoute,
+ private net: NetService,
+ private auth: AuthService,
public scko: SckoService
) {}
ngOnInit() {
+ this.net.authExpired$.subscribe(how => {
+ console.debug("SCKO auth expired with info", how);
+ this.scko.resetPatron();
+ this.auth.logout();
+ this.router.navigate(['/scko']);
+ });
+
this.scko.load();
}
+
+ ngAfterViewInit() {
+ this.scko.logoutDialog = this.logoutDialog;
+ }
}
import {IdlService, IdlObject} from '@eg/core/idl.service';
import {StoreService} from '@eg/core/store.service';
import {PatronService, PatronSummary, PatronStats} from '@eg/staff/share/patron/patron.service';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
@Injectable({providedIn: 'root'})
export class SckoService {
patronSummary: PatronSummary;
barcodeRegex: RegExp;
patronPasswordRequired = false;
+ patronIdleTimeout: number;
+ patronTimeoutId: number;
+ logoutWarningTimeout = 20;
+ logoutWarningTimerId: number;
sessionCheckouts: any[] = [];
+ // We get this from the main scko component.
+ logoutDialog: ConfirmDialogComponent;
+
constructor(
+ private router: Router,
private route: ActivatedRoute,
private org: OrgService,
private net: NetService,
this.patronPasswordRequired =
sets['circ.selfcheck.patron_password_required'];
+ this.patronIdleTimeout =
+ Number(sets['circ.selfcheck.patron_login_timeout'] || 160);
+
+ // Compensate for the warning dialog
+ this.patronIdleTimeout -= this.logoutWarningTimeout;
+
// Load a patron by barcode via URL params.
// Useful for development.
const username = this.route.snapshot.queryParamMap.get('patron');
})
.then(patron => this.patronSummary = new PatronSummary(patron))
.then(_ => this.patrons.getVitalStats(this.patronSummary.patron))
- .then(stats => this.patronSummary.stats = stats);
+ .then(stats => this.patronSummary.stats = stats)
+ .then(_ => this.startPatronTimer());
+ }
+
+ resetPatronTimeout() {
+ if (this.patronTimeoutId) {
+ clearTimeout(this.patronTimeoutId);
+ }
+ this.startPatronTimer();
+ }
+
+ startPatronTimer() {
+ console.debug('Starting patron timeout counter', this.patronIdleTimeout);
+
+ this.patronTimeoutId = setTimeout(
+ () => this.showPatronLogoutWarning(),
+ this.patronIdleTimeout * 1000
+ );
+ }
+
+ showPatronLogoutWarning() {
+ console.debug('Session timing out. Show warning dialog');
+
+ this.logoutDialog.open().subscribe(remain => {
+ if (remain) {
+ clearTimeout(this.logoutWarningTimerId);
+ this.logoutWarningTimerId = null;
+ this.resetPatronTimeout();
+ } else {
+ this.resetPatron();
+ this.router.navigate(['/scko']);
+ }
+ });
+
+ // Force the session to end if no action is taken on the
+ // logout warning dialog.
+ this.logoutWarningTimerId = setTimeout(
+ () => {
+ console.debug('Clearing patron on warning dialog timeout');
+ this.resetPatron();
+ this.router.navigate(['/scko']);
+ },
+ this.logoutWarningTimeout * 1000
+ );
}
sessionTotalCheckouts(): number {
</ng-container>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-success"
- (click)="close(true)" i18n>Confirm</button>
- <button type="button" class="btn btn-warning"
- (click)="close(false)" i18n>Cancel</button>
+ <button type="button" class="btn btn-success" (click)="close(true)">
+ <ng-container *ngIf="confirmButtonText">{{confirmButtonText}}</ng-container>
+ <ng-container *ngIf="!confirmButtonText" i18n>Confirm</ng-container>
+ </button>
+ <button type="button" class="btn btn-warning" (click)="close(false)">
+ <ng-container *ngIf="cancelButtonText">{{cancelButtonText}}</ng-container>
+ <ng-container *ngIf="!cancelButtonText" i18n>Cancel</ng-container>
+ </button>
</div>
</ng-template>