import {EgPermService} from '@eg/core/perm.service';
import {EgPcrudService} from '@eg/core/pcrud.service';
import {EgOrgService} from '@eg/core/org.service';
-import {EgAudioService} from '@eg/share/audio.service';
+import {EgAudioService} from '@eg/share/util/audio.service';
@NgModule({
declarations: [
import {EgAuthService} from './auth.service';
interface HasPermAtResult {
- [permName: string]: number[];
+ [permName: string]: any[]; // org IDs or org unit objects
}
interface HasPermHereResult {
// Downgraded components
//import {EgDialogComponent} from '@eg/share/dialog/dialog.component';
//import {EgConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
-import {EgHelloWorldComponent} from '@eg/share/hello-world.component';
declare var angular: any;
EgCommonModule.forRoot()
],
declarations: [
- EgHelloWorldComponent,
//EgDialogComponent,
//EgConfirmDialogComponent
],
entryComponents: [
- EgHelloWorldComponent,
//EgDialogComponent,
//EgConfirmDialogComponent
]
.factory('eg2Pcrud', downgradeInjectable(EgPcrudService))
.factory('eg2Org', downgradeInjectable(EgOrgService))
.factory('ng2Title', downgradeInjectable(Title))
- .directive('eg2HelloWorld',
- downgradeComponent({component: EgHelloWorldComponent}))
/*
.directive('eg2ConfirmDialog',
downgradeComponent({component: EgConfirmDialogComponent}))
-Common Angular services and associated types/classes.
-
-This collection of services MIGHT be used by practically all applications.
-They are NOT automatically imported/exported by the base module and should
-be loaded within the requesting application as needed.
+Shared Angular services, components, directives, and associated classes.
+These items are NOT automatically imported to the base module. Import
+as needed.
+++ /dev/null
-/**
- * Plays audio files (alerts, generally) by key name. Each sound uses a
- * dot-path to indicate the sound.
- *
- * For example:
- *
- * this.audio.play('warning.checkout.no_item');
- *
- * URLs are tested in the following order until an audio file is found
- * or no other paths are left to check.
- *
- * /audio/notifications/warning/checkout/not_found.wav
- * /audio/notifications/warning/checkout.wav
- * /audio/notifications/warning.wav
- *
- * Files are only played when sounds are configured to play via
- * workstation settings.
- */
-import {Injectable, EventEmitter} from '@angular/core';
-import {EgStoreService} from '@eg/core/store.service';
-const AUDIO_BASE_URL = '/audio/notifications/';
-
-@Injectable()
-export class EgAudioService {
-
- // map of requested audio path to resolved path
- private urlCache: {[path:string] : string} = {};
-
- constructor(private store: EgStoreService) {}
-
- play(path: string): void {
- if (path) {
- this.playUrl(path, path);
- }
- }
-
- playUrl(path: string, origPath: string): void {
- //console.debug(`audio: playUrl(${path}, ${origPath})`);
-
- this.store.getItem('eg.audio.disable').then(audioDisabled => {
- if (audioDisabled) return;
-
- let url = this.urlCache[path] ||
- AUDIO_BASE_URL + path.replace(/\./g, '/') + '.wav';
-
- let player = new Audio(url);
-
- player.onloadeddata = () => {
- this.urlCache[origPath] = url;
- player.play();
- console.debug(`audio: ${url}`);
- };
-
- if (this.urlCache[path]) {
- // when serving from the cache, avoid secondary URL lookups.
- return;
- }
-
- player.onerror = () => {
- // Unable to play path at the requested URL.
-
- if (!path.match(/\./)) {
- // all fall-through options have been exhausted.
- // No path to play.
- console.warn(
- "No suitable URL found for path '" + origPath + "'");
- return;
- }
-
- // Fall through to the next (more generic) option
- path = path.replace(/\.[^\.]+$/, '');
- this.playUrl(path, origPath);
- }
- });
- }
-}
-
-
import {Injectable} from '@angular/core';
import {EgOrgService} from '@eg/core/org.service';
-import {EgUnapiService} from '@eg/share/unapi.service';
+import {EgUnapiService} from '@eg/share/catalog/unapi.service';
import {EgIdlObject} from '@eg/core/idl.service';
import {EgNetService} from '@eg/core/net.service';
import {EgPcrudService} from '@eg/core/pcrud.service';
--- /dev/null
+import {Injectable, EventEmitter} from '@angular/core';
+import {EgOrgService} from '@eg/core/org.service';
+
+/*
+TODO: Add Display Fields to UNAPI
+https://library.biz/opac/extras/unapi?id=tag::U2@bre/1{bre.extern,holdings_xml,mra}/BR1/0&format=mods32
+*/
+
+const UNAPI_PATH = '/opac/extras/unapi?id=tag::U2@';
+
+interface EgUnapiParams {
+ target: string; // bre, ...
+ id: number | string; // 1 | 1,2,3,4,5
+ extras: string; // {holdings_xml,mra,...}
+ format: string; // mods32, marxml, ...
+ orgId?: number; // org unit ID
+ depth?: number; // org unit depth
+};
+
+@Injectable()
+export class EgUnapiService {
+
+ constructor(private org: EgOrgService) {}
+
+ createUrl(params: EgUnapiParams): string {
+ let depth = params.depth || 0;
+ let org = params.orgId ? this.org.get(params.orgId) : this.org.root();
+
+ return `${UNAPI_PATH}${params.target}/${params.id}${params.extras}/` +
+ `${org.shortname()}/${depth}&format=${params.format}`;
+ }
+
+ getAsXmlDocument(params: EgUnapiParams): Promise<XMLDocument> {
+ // XReq creates an XML document for us. Seems like the right
+ // tool for the job.
+ let url = this.createUrl(params);
+ return new Promise((resolve, reject) => {
+ var xhttp = new XMLHttpRequest();
+ xhttp.onreadystatechange = function() {
+ if (this.readyState == 4) {
+ if (this.status == 200) {
+ resolve(xhttp.responseXML);
+ } else {
+ reject(`UNAPI request failed for ${url}`);
+ }
+ }
+ }
+ xhttp.open("GET", url, true);
+ xhttp.send();
+ });
+ }
+}
+
+
// Allow the caller to pass in a free-form context blob to
// be addedto the caller's custom template context, along
// with our stock context.
- context?: [fields: string]: any
+ context?: {[fields: string]: any}
}
interface CustomFieldContext {
// Returns a context object to be inserted into a custom
// field template.
- customTemplateFieldContext(fieldDef: any): FmEditorCustomFieldContext {
+ customTemplateFieldContext(fieldDef: any): CustomFieldContext {
return Object.assign(
{ record : this.record,
field: fieldDef // from this.fields
+++ /dev/null
-import {Component, Input} from '@angular/core';
-
-@Component({
- selector: 'eg-hello-world',
- template: `
- <div>Hello, World {{message}}!</div>
- `
-})
-export class EgHelloWorldComponent {
- @Input() public message: string;
- constructor() {}
-}
-
-
+++ /dev/null
-
-<!-- todo disabled -->
-<ng-template #displayTemplate let-r="result">
-{{r.label}}
-</ng-template>
-
-<input type="text"
- class="form-control"
- [placeholder]="placeholder"
- [(ngModel)]="selected"
- [ngbTypeahead]="filter"
- [resultTemplate]="displayTemplate"
- [inputFormatter]="formatter"
- (click)="click$.next($event.target.value)"
- (selectItem)="orgChanged($event)"
- #instance="ngbTypeahead"
-/>
+++ /dev/null
-import {Component, OnInit, Input, Output, ViewChild, EventEmitter} from '@angular/core';
-import {Observable} from 'rxjs/Observable';
-import {map, debounceTime} from 'rxjs/operators';
-import {Subject} from 'rxjs/Subject';
-import {EgAuthService} from '@eg/core/auth.service';
-import {EgStoreService} from '@eg/core/store.service';
-import {EgOrgService} from '@eg/core/org.service';
-import {EgIdlObject} from '@eg/core/idl.service';
-import {NgbTypeahead, NgbTypeaheadSelectItemEvent}
- from '@ng-bootstrap/ng-bootstrap';
-
-// Use a unicode char for spacing instead of ASCII=32 so the browser
-// won't collapse the nested display entries down to a single space.
-const PAD_SPACE: string = ' '; // U+2007
-
-interface OrgDisplay {
- id: number;
- label: string;
- disabled: boolean;
-}
-
-@Component({
- selector: 'eg-org-select',
- templateUrl: './org-select.component.html'
-})
-export class EgOrgSelectComponent implements OnInit {
-
- selected: OrgDisplay;
- hidden: number[] = [];
- disabled: number[] = [];
- click$ = new Subject<string>();
- startOrg: EgIdlObject;
-
- @ViewChild('instance') instance: NgbTypeahead;
-
- // Placeholder text for selector input
- @Input() placeholder: string = '';
- @Input() stickySetting: string;
-
- // Org unit field displayed in the selector
- @Input() displayField: string = 'shortname';
-
- // Apply a default org unit value when none is set.
- // First tries workstation org unit, then user home org unit.
- // An onChange event WILL be generated when a default is applied.
- @Input() applyDefault: boolean = false;
-
- // List of org unit IDs to exclude from the selector
- @Input() set hideOrgs(ids: number[]) {
- if (ids) this.hidden = ids;
- }
-
- // List of org unit IDs to disable in the selector
- @Input() set disableOrgs(ids: number[]) {
- if (ids) this.disabled = ids;
- }
-
- // Apply an org unit value at load time.
- // This will NOT result in an onChange event.
- @Input() set initialOrg(org: EgIdlObject) {
- if (org) this.startOrg = org;
- }
-
- // Apply an org unit value by ID at load time.
- // This will NOT result in an onChange event.
- @Input() set initialOrgId(id: number) {
- if (id) this.startOrg = this.org.get(id);
- }
-
- // Modify the selected org unit via data binding.
- // This WILL result in an onChange event firing.
- @Input() set applyOrg(org: EgIdlObject) {
- if (org) this.selected = this.formatForDisplay(org);
- }
-
- // Modify the selected org unit by ID via data binding.
- // This WILL result in an onChange event firing.
- @Input() set applyOrgId(id: number) {
- if (id) this.selected = this.formatForDisplay(this.org.get(id));
- }
-
- // Emitted when the org unit value is changed via the selector.
- // Does not fire on initialOrg
- @Output() onChange = new EventEmitter<EgIdlObject>();
-
- constructor(
- private auth: EgAuthService,
- private store: EgStoreService,
- private org: EgOrgService
- ) {}
-
- ngOnInit() {
-
- // Apply a default org unit if desired and possible.
- if (!this.startOrg && this.applyDefault && this.auth.user()) {
- // note: ws_ou defaults to home_ou on the server
- // when when no workstation is used
- this.startOrg = this.org.get(this.auth.user().ws_ou());
- this.selected = this.formatForDisplay(
- this.org.get(this.auth.user().ws_ou())
- );
-
- // avoid notifying mid-digest
- setTimeout(() => this.onChange.emit(this.startOrg), 0);
- }
-
- if (this.startOrg) {
- this.selected = this.formatForDisplay(this.startOrg);
- }
- }
-
- // Format for display in the selector drop-down and input.
- formatForDisplay(org: EgIdlObject): OrgDisplay {
- return {
- id : org.id(),
- label : PAD_SPACE.repeat(org.ou_type().depth())
- + org[this.displayField](),
- disabled : false
- };
- }
-
- // Fired by the typeahead to inform us of a change.
- orgChanged(selEvent: NgbTypeaheadSelectItemEvent) {
- this.onChange.emit(this.org.get(selEvent.item.id));
- }
-
- // Remove the tree-padding spaces when matching.
- formatter = (result: OrgDisplay) => result.label.trim();
-
- filter = (text$: Observable<string>): Observable<OrgDisplay[]> => {
- return text$
- .debounceTime(200)
- .distinctUntilChanged()
- .merge(this.click$.filter(() => !this.instance.isPopupOpen()))
- .map(term => {
-
- return this.org.list().filter(org => {
-
- // Find orgs matching the search term
- return org[this.displayField]()
- .toLowerCase().indexOf(term.toLowerCase()) > -1
-
- }).filter(org => { // Exclude hidden orgs
- return this.hidden.filter(
- id => {return org.id() == id}).length == 0;
-
- }).map(org => {return this.formatForDisplay(org)})
- });
- }
-}
-
-
--- /dev/null
+
+<!-- todo disabled -->
+<ng-template #displayTemplate let-r="result">
+{{r.label}}
+</ng-template>
+
+<input type="text"
+ class="form-control"
+ [placeholder]="placeholder"
+ [(ngModel)]="selected"
+ [ngbTypeahead]="filter"
+ [resultTemplate]="displayTemplate"
+ [inputFormatter]="formatter"
+ (click)="click$.next($event.target.value)"
+ (selectItem)="orgChanged($event)"
+ #instance="ngbTypeahead"
+/>
--- /dev/null
+import {Component, OnInit, Input, Output, ViewChild, EventEmitter} from '@angular/core';
+import {Observable} from 'rxjs/Observable';
+import {map, debounceTime} from 'rxjs/operators';
+import {Subject} from 'rxjs/Subject';
+import {EgAuthService} from '@eg/core/auth.service';
+import {EgStoreService} from '@eg/core/store.service';
+import {EgOrgService} from '@eg/core/org.service';
+import {EgIdlObject} from '@eg/core/idl.service';
+import {NgbTypeahead, NgbTypeaheadSelectItemEvent}
+ from '@ng-bootstrap/ng-bootstrap';
+
+// Use a unicode char for spacing instead of ASCII=32 so the browser
+// won't collapse the nested display entries down to a single space.
+const PAD_SPACE: string = ' '; // U+2007
+
+interface OrgDisplay {
+ id: number;
+ label: string;
+ disabled: boolean;
+}
+
+@Component({
+ selector: 'eg-org-select',
+ templateUrl: './org-select.component.html'
+})
+export class EgOrgSelectComponent implements OnInit {
+
+ selected: OrgDisplay;
+ hidden: number[] = [];
+ disabled: number[] = [];
+ click$ = new Subject<string>();
+ startOrg: EgIdlObject;
+
+ @ViewChild('instance') instance: NgbTypeahead;
+
+ // Placeholder text for selector input
+ @Input() placeholder: string = '';
+ @Input() stickySetting: string;
+
+ // Org unit field displayed in the selector
+ @Input() displayField: string = 'shortname';
+
+ // Apply a default org unit value when none is set.
+ // First tries workstation org unit, then user home org unit.
+ // An onChange event WILL be generated when a default is applied.
+ @Input() applyDefault: boolean = false;
+
+ // List of org unit IDs to exclude from the selector
+ @Input() set hideOrgs(ids: number[]) {
+ if (ids) this.hidden = ids;
+ }
+
+ // List of org unit IDs to disable in the selector
+ @Input() set disableOrgs(ids: number[]) {
+ if (ids) this.disabled = ids;
+ }
+
+ // Apply an org unit value at load time.
+ // This will NOT result in an onChange event.
+ @Input() set initialOrg(org: EgIdlObject) {
+ if (org) this.startOrg = org;
+ }
+
+ // Apply an org unit value by ID at load time.
+ // This will NOT result in an onChange event.
+ @Input() set initialOrgId(id: number) {
+ if (id) this.startOrg = this.org.get(id);
+ }
+
+ // Modify the selected org unit via data binding.
+ // This WILL result in an onChange event firing.
+ @Input() set applyOrg(org: EgIdlObject) {
+ if (org) this.selected = this.formatForDisplay(org);
+ }
+
+ // Modify the selected org unit by ID via data binding.
+ // This WILL result in an onChange event firing.
+ @Input() set applyOrgId(id: number) {
+ if (id) this.selected = this.formatForDisplay(this.org.get(id));
+ }
+
+ // Emitted when the org unit value is changed via the selector.
+ // Does not fire on initialOrg
+ @Output() onChange = new EventEmitter<EgIdlObject>();
+
+ constructor(
+ private auth: EgAuthService,
+ private store: EgStoreService,
+ private org: EgOrgService
+ ) {}
+
+ ngOnInit() {
+
+ // Apply a default org unit if desired and possible.
+ if (!this.startOrg && this.applyDefault && this.auth.user()) {
+ // note: ws_ou defaults to home_ou on the server
+ // when when no workstation is used
+ this.startOrg = this.org.get(this.auth.user().ws_ou());
+ this.selected = this.formatForDisplay(
+ this.org.get(this.auth.user().ws_ou())
+ );
+
+ // avoid notifying mid-digest
+ setTimeout(() => this.onChange.emit(this.startOrg), 0);
+ }
+
+ if (this.startOrg) {
+ this.selected = this.formatForDisplay(this.startOrg);
+ }
+ }
+
+ // Format for display in the selector drop-down and input.
+ formatForDisplay(org: EgIdlObject): OrgDisplay {
+ return {
+ id : org.id(),
+ label : PAD_SPACE.repeat(org.ou_type().depth())
+ + org[this.displayField](),
+ disabled : false
+ };
+ }
+
+ // Fired by the typeahead to inform us of a change.
+ orgChanged(selEvent: NgbTypeaheadSelectItemEvent) {
+ this.onChange.emit(this.org.get(selEvent.item.id));
+ }
+
+ // Remove the tree-padding spaces when matching.
+ formatter = (result: OrgDisplay) => result.label.trim();
+
+ filter = (text$: Observable<string>): Observable<OrgDisplay[]> => {
+ return text$
+ .debounceTime(200)
+ .distinctUntilChanged()
+ .merge(this.click$.filter(() => !this.instance.isPopupOpen()))
+ .map(term => {
+
+ return this.org.list().filter(org => {
+
+ // Find orgs matching the search term
+ return org[this.displayField]()
+ .toLowerCase().indexOf(term.toLowerCase()) > -1
+
+ }).filter(org => { // Exclude hidden orgs
+ return this.hidden.filter(
+ id => {return org.id() == id}).length == 0;
+
+ }).map(org => {return this.formatForDisplay(org)})
+ });
+ }
+}
+
+
+++ /dev/null
-import {Injectable, EventEmitter} from '@angular/core';
-import {EgOrgService} from '@eg/core/org.service';
-
-/*
-TODO: Add Display Fields to UNAPI
-https://library.biz/opac/extras/unapi?id=tag::U2@bre/1{bre.extern,holdings_xml,mra}/BR1/0&format=mods32
-*/
-
-const UNAPI_PATH = '/opac/extras/unapi?id=tag::U2@';
-
-interface EgUnapiParams {
- target: string; // bre, ...
- id: number | string; // 1 | 1,2,3,4,5
- extras: string; // {holdings_xml,mra,...}
- format: string; // mods32, marxml, ...
- orgId?: number; // org unit ID
- depth?: number; // org unit depth
-};
-
-@Injectable()
-export class EgUnapiService {
-
- constructor(private org: EgOrgService) {}
-
- createUrl(params: EgUnapiParams): string {
- let depth = params.depth || 0;
- let org = params.orgId ? this.org.get(params.orgId) : this.org.root();
-
- return `${UNAPI_PATH}${params.target}/${params.id}${params.extras}/` +
- `${org.shortname()}/${depth}&format=${params.format}`;
- }
-
- getAsXmlDocument(params: EgUnapiParams): Promise<XMLDocument> {
- // XReq creates an XML document for us. Seems like the right
- // tool for the job.
- let url = this.createUrl(params);
- return new Promise((resolve, reject) => {
- var xhttp = new XMLHttpRequest();
- xhttp.onreadystatechange = function() {
- if (this.readyState == 4) {
- if (this.status == 200) {
- resolve(xhttp.responseXML);
- } else {
- reject(`UNAPI request failed for ${url}`);
- }
- }
- }
- xhttp.open("GET", url, true);
- xhttp.send();
- });
- }
-}
-
-
--- /dev/null
+/**
+ * Plays audio files (alerts, generally) by key name. Each sound uses a
+ * dot-path to indicate the sound.
+ *
+ * For example:
+ *
+ * this.audio.play('warning.checkout.no_item');
+ *
+ * URLs are tested in the following order until an audio file is found
+ * or no other paths are left to check.
+ *
+ * /audio/notifications/warning/checkout/not_found.wav
+ * /audio/notifications/warning/checkout.wav
+ * /audio/notifications/warning.wav
+ *
+ * Files are only played when sounds are configured to play via
+ * workstation settings.
+ */
+import {Injectable, EventEmitter} from '@angular/core';
+import {EgStoreService} from '@eg/core/store.service';
+const AUDIO_BASE_URL = '/audio/notifications/';
+
+@Injectable()
+export class EgAudioService {
+
+ // map of requested audio path to resolved path
+ private urlCache: {[path:string] : string} = {};
+
+ constructor(private store: EgStoreService) {}
+
+ play(path: string): void {
+ if (path) {
+ this.playUrl(path, path);
+ }
+ }
+
+ playUrl(path: string, origPath: string): void {
+ //console.debug(`audio: playUrl(${path}, ${origPath})`);
+
+ this.store.getItem('eg.audio.disable').then(audioDisabled => {
+ if (audioDisabled) return;
+
+ let url = this.urlCache[path] ||
+ AUDIO_BASE_URL + path.replace(/\./g, '/') + '.wav';
+
+ let player = new Audio(url);
+
+ player.onloadeddata = () => {
+ this.urlCache[origPath] = url;
+ player.play();
+ console.debug(`audio: ${url}`);
+ };
+
+ if (this.urlCache[path]) {
+ // when serving from the cache, avoid secondary URL lookups.
+ return;
+ }
+
+ player.onerror = () => {
+ // Unable to play path at the requested URL.
+
+ if (!path.match(/\./)) {
+ // all fall-through options have been exhausted.
+ // No path to play.
+ console.warn(
+ "No suitable URL found for path '" + origPath + "'");
+ return;
+ }
+
+ // Fall through to the next (more generic) option
+ path = path.replace(/\.[^\.]+$/, '');
+ this.playUrl(path, origPath);
+ }
+ });
+ }
+}
+
+
import {NgModule} from '@angular/core';
import {EgStaffCommonModule} from '@eg/staff/common.module';
-import {EgUnapiService} from '@eg/share/unapi.service';
+import {EgUnapiService} from '@eg/share/catalog/unapi.service';
import {EgCatalogRoutingModule} from './routing.module';
import {EgCatalogService} from '@eg/share/catalog/catalog.service';
import {EgCatalogUrlService} from '@eg/share/catalog/catalog-url.service';
import {NgModule, ModuleWithProviders} from '@angular/core';
import {EgCommonModule} from '@eg/common.module';
import {EgStaffBannerComponent} from './share/staff-banner.component';
-import {EgOrgSelectComponent} from '@eg/share/org-select.component';
+import {EgOrgSelectComponent} from '@eg/share/org-select/org-select.component';
import {EgDialogComponent} from '@eg/share/dialog/dialog.component';
import {EgConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
import {EgPromptDialogComponent} from '@eg/share/dialog/prompt.component';
import {EgStoreService} from '@eg/core/store.service';
import {EgNetService} from '@eg/core/net.service';
import {EgAuthService, EgAuthWsState} from '@eg/core/auth.service';
+import {EgPermService} from '@eg/core/perm.service';
const LOGIN_PATH = '/staff/login';
const WS_MANAGE_PATH = '/staff/admin/workstation/workstations/manage';
private ngLocation: Location,
private store: EgStoreService,
private net: EgNetService,
- private auth: EgAuthService
+ private auth: EgAuthService,
+ private perm: EgPermService,
) {}
resolve(
this.auth.testAuthToken().then(
tokenOk => {
console.debug('EgStaffResolver: authtoken verified');
- this.auth.verifyWorkstation().then(
- wsOk => {
- this.loadStartupData()
- .then(ok => this.observer.complete())
- },
- wsNotOk => this.handleInvalidWorkstation(path)
+ this.confirmStaffPerms().then(
+ hasPerms => {
+ this.auth.verifyWorkstation().then(
+ wsOk => {
+ this.loadStartupData()
+ .then(ok => this.observer.complete())
+ },
+ wsNotOk => this.handleInvalidWorkstation(path)
+ );
+ },
+ hasNotPerms => {
+ this.observer.error(
+ 'User does not have staff permissions');
+ }
);
},
tokenNotOk => this.handleInvalidToken(state)
return observable;
}
+
+ // Confirm the user has the STAFF_LOGIN permission anywhere before
+ // allowing the staff sub-tree to load. This will prevent users
+ // with valid, non-staff authtokens from attempting to connect and
+ // subsequently getting redirected to the workstation admin page
+ // (since they won't have a valid WS either).
+ confirmStaffPerms(): Promise<any> {
+ return new Promise((resolve, reject) => {
+ this.perm.hasWorkPermAt(['STAFF_LOGIN']).then(
+ permMap => {
+ if (permMap.STAFF_LOGIN.length) {
+ resolve('perm check OK');
+ } else {
+ reject('perm check faield');
+ }
+ }
+ );
+ });
+ }
+
+
// A page that's not the login page was requested without a
// valid auth token. Send the caller back to the login page.
handleInvalidToken(state: RouterStateSnapshot): void {
</div>
</div>
-<!--
-<eg2-confirm-dialog
- #testDialog
- dialogTitle="Test Dialog"
- dialogBody='Test Dialog Body'>
-</eg2-confirm-dialog>
--->
-
-<eg2-hello-world #testHello message="Look out, I'm testing here!"></eg2-hello-world>
-
<div class="row">
<div class="col-md-12">
<div ng-if="is_backdate()" class="alert-danger pad-all-min">