// Each facet is a JSON encoded blob of class, name, and value
context.facetFilters.forEach(facet => {
- params.facets.push(JSON.stringify(facet));
+ params.facets.push(JSON.stringify({
+ c : facet.facetClass,
+ n : facet.facetName,
+ v : facet.facetValue
+ }));
});
params.org = context.searchOrg.id();
});
params.getAll('facets').forEach(blob => {
- let facet: FacetFilter = JSON.parse(blob);
- context.addFacet(facet);
+ let facet = JSON.parse(blob);
+ context.addFacet(new FacetFilter(facet.c, facet.n, facet.v));
});
context.searchOrg =
import {Pager} from '@eg/share/util/pager';
import {Params} from '@angular/router';
+export enum CatalogSearchState {
+ PENDING,
+ SEARCHING,
+ COMPLETE
+}
-// Document and enforce facet filter entries.
export class FacetFilter {
facetClass: string;
facetName: string;
}
}
-export enum CatalogSearchState {
- PENDING,
- SEARCHING,
- COMPLETE
-}
-
// Not an angular service.
// It's conceviable there could be multiple contexts.
export class CatalogSearchContext {
+++ /dev/null
-import {CommonModule} from '@angular/common';
-import {NgModule} from '@angular/core';
-import {EgAdminRoutingModule} from './routing.module';
-
-@NgModule({
- declarations: [],
- imports: [EgAdminRoutingModule]
-})
-
-export class EgAdminModule {}
path: '',
children : [{
path: 'workstation',
- loadChildren: '@eg/staff/admin/workstation/app.module#EgAdminWsModule'
+ loadChildren: '@eg/staff/admin/workstation/routing.module#EgAdminWsRoutingModule'
}]
}];
+++ /dev/null
-import {NgModule} from '@angular/core';
-import {CommonModule} from '@angular/common';
-import {EgStaffModule} from '../../app.module';
-import {EgAdminWsRoutingModule} from './routing.module';
-import {EgWorkstationsComponent} from './workstations.component';
-
-@NgModule({
- declarations: [
- EgWorkstationsComponent
- ],
- imports: [
- EgStaffModule,
- EgAdminWsRoutingModule,
- CommonModule
- ]
-})
-
-export class EgAdminWsModule {}
-
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
-import {EgWorkstationsComponent} from './workstations.component';
-const routes: Routes = [
- // TODO: load each sub-app lazily
- { path: 'workstations',
- component: EgWorkstationsComponent
- }
-];
+const routes: Routes = [{
+ path: 'workstations',
+ loadChildren: '@eg/staff/admin/workstation/workstations/app.module#ManageWorkstationsModule'
+}];
@NgModule({
imports: [RouterModule.forChild(routes)],
+++ /dev/null
-<div class="row">
- <div class="col-8 offset-1">
- <div class="alert alert-warning" *ngIf="removingWs" i18n>
- Workstation {{removingWs}} is no longer valid. Removing registration.
- </div>
- <div class="alert alert-danger" *ngIf="workstations.length == 0">
- <span i18n>Please register a workstation.</span>
- </div>
-
- <div class="row">
- <div class="col" i18n>Register a New Workstation For This Browser</div>
- </div>
- <div class="row mt-2">
- <div class="col-2">
- <eg-org-select
- (onChange)="orgOnChange"
- [hideOrgs]="hideOrgs"
- [disableOrgs]="disableOrgs"
- [initialOrg]="initialOrg"
- [placeholder]="'Owner'" >
- </eg-org-select>
- </div>
- <div class="col-6">
- <div class="input-group">
- <input type='text'
- class='form-control'
- i18n-title
- title="Workstation Name"
- i18n-placeholder
- placeholder="Workstation Name"
- [(ngModel)]='newName'/>
- <div class="input-group-btn">
- <button class="btn btn-light" (click)="registerWorkstation()">
- <span i18n>Register</span>
- </button>
- </div>
- </div>
- </div>
- </div>
- <div class="row mt-3 pt-3 border border-left-0 border-right-0 border-bottom-0 border-light">
- <div class="col">
- <span i18n>Workstations Registered With This Browser</span>
- </div>
- </div>
- <div class="row">
- <div class="col-6">
- <select
- class="form-control"
- [(ngModel)]="selectedId">
- <option *ngFor="let ws of workstations" value="{{ws.id}}">
- {{ws.name}}
- </option>
- </select>
- </div>
- </div>
- <div class="row mt-2">
- <div class="col-md-6">
- <button i18n class="btn btn-success"
- (click)="useNow()" [disabled]="!selected">
- Use Now
- </button>
- <button i18n class="btn btn-light"
- (click)="setDefault()" [disabled]="!selected">
- Mark As Default
- </button>
- <button i18n class="btn btn-danger"
- (click)="removeSelected()"
- [disabled]="!selected || isRemoving || !canDeleteSelected()">
- Remove
- </button>
- </div>
- </div>
- </div>
-</div>
-
+++ /dev/null
-import {Component, OnInit} from '@angular/core';
-import {ActivatedRoute} from '@angular/router';
-import {EgStoreService} from '@eg/core/store';
-import {EgIdlObject} from '@eg/core/idl';
-import {EgNetService} from '@eg/core/net';
-import {EgAuthService} from '@eg/core/auth';
-import {EgOrgService} from '@eg/core/org';
-
-// Slim version of the WS that's stored in the cache.
-interface Workstation {
- id: number;
- name: string;
- owning_lib: number;
-}
-
-@Component({
- templateUrl: 'workstations.component.html'
-})
-export class EgWorkstationsComponent implements OnInit {
-
- selectedId: Number;
- workstations: Workstation[] = [];
- isRemoving: boolean = false;
- newOwner: EgIdlObject;
- newName: String;
-
-
- // Org selector options.
- hideOrgs: number[];
- disableOrgs: number[];
- orgOnChange = (org: EgIdlObject): void => {
- this.newOwner = org;
- }
-
- constructor(
- private route: ActivatedRoute,
- private net: EgNetService,
- private store: EgStoreService,
- private auth: EgAuthService,
- private org: EgOrgService
- ) {}
-
- ngOnInit() {
- this.store.getItem('eg.workstation.all')
- .then(res => this.workstations = res);
-
- // TODO: perm limits required here too
- this.disableOrgs = this.org.filterList({canHaveUsers : true}, true);
- }
-
- selected(): Workstation {
- return this.workstations.filter(
- ws => {return ws.id == this.selectedId})[0];
- }
-
- useNow(): void {
- console.debug('using ' + this.selected().name);
- }
-
- setDefault(): void {
- console.debug('defaulting ' + this.selected().name);
- }
-
- removeSelected(): void {
- console.debug('removing ' + this.selected().name);
- }
-
- canDeleteSelected(): boolean {
- return true;
- }
-
- registerWorkstation(): void {
- console.log(`Registering new workstation ` +
- `"${this.newName}" at ${this.newOwner.shortname()}`);
- }
-}
-
-
--- /dev/null
+<div class="row">
+ <div class="col-8 offset-1">
+ <div class="alert alert-warning" *ngIf="removingWs" i18n>
+ Workstation {{removingWs}} is no longer valid. Removing registration.
+ </div>
+ <div class="alert alert-danger" *ngIf="workstations.length == 0">
+ <span i18n>Please register a workstation.</span>
+ </div>
+
+ <div class="row">
+ <div class="col" i18n>Register a New Workstation For This Browser</div>
+ </div>
+ <div class="row mt-2">
+ <div class="col-2">
+ <eg-org-select
+ (onChange)="orgOnChange"
+ [hideOrgs]="hideOrgs"
+ [disableOrgs]="disableOrgs"
+ [initialOrg]="initialOrg"
+ [placeholder]="'Owner'" >
+ </eg-org-select>
+ </div>
+ <div class="col-6">
+ <div class="input-group">
+ <input type='text'
+ class='form-control'
+ i18n-title
+ title="Workstation Name"
+ i18n-placeholder
+ placeholder="Workstation Name"
+ [(ngModel)]='newName'/>
+ <div class="input-group-btn">
+ <button class="btn btn-light" (click)="registerWorkstation()">
+ <span i18n>Register</span>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="row mt-3 pt-3 border border-left-0 border-right-0 border-bottom-0 border-light">
+ <div class="col">
+ <span i18n>Workstations Registered With This Browser</span>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-6">
+ <select
+ class="form-control"
+ [(ngModel)]="selectedId">
+ <option *ngFor="let ws of workstations" value="{{ws.id}}">
+ {{ws.name}}
+ </option>
+ </select>
+ </div>
+ </div>
+ <div class="row mt-2">
+ <div class="col-md-6">
+ <button i18n class="btn btn-success"
+ (click)="useNow()" [disabled]="!selected">
+ Use Now
+ </button>
+ <button i18n class="btn btn-light"
+ (click)="setDefault()" [disabled]="!selected">
+ Mark As Default
+ </button>
+ <button i18n class="btn btn-danger"
+ (click)="removeSelected()"
+ [disabled]="!selected || isRemoving || !canDeleteSelected()">
+ Remove
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
--- /dev/null
+import {Component, OnInit} from '@angular/core';
+import {ActivatedRoute} from '@angular/router';
+import {EgStoreService} from '@eg/core/store';
+import {EgIdlObject} from '@eg/core/idl';
+import {EgNetService} from '@eg/core/net';
+import {EgAuthService} from '@eg/core/auth';
+import {EgOrgService} from '@eg/core/org';
+
+// Slim version of the WS that's stored in the cache.
+interface Workstation {
+ id: number;
+ name: string;
+ owning_lib: number;
+}
+
+@Component({
+ templateUrl: 'app.component.html'
+})
+export class WorkstationsComponent implements OnInit {
+
+ selectedId: Number;
+ workstations: Workstation[] = [];
+ removeWorkstation: string;
+ newOwner: EgIdlObject;
+ newName: String;
+
+ // Org selector options.
+ hideOrgs: number[];
+ disableOrgs: number[];
+ orgOnChange = (org: EgIdlObject): void => {
+ this.newOwner = org;
+ }
+
+ constructor(
+ private route: ActivatedRoute,
+ private net: EgNetService,
+ private store: EgStoreService,
+ private auth: EgAuthService,
+ private org: EgOrgService
+ ) {}
+
+ ngOnInit() {
+ this.store.getItem('eg.workstation.all')
+ .then(res => this.workstations = res);
+
+ // TODO: perm limits required here too
+ this.disableOrgs = this.org.filterList({canHaveUsers : true}, true);
+
+ this.removeWorkstation = this.route.snapshot.paramMap.get('remove');
+ if (this.removeWorkstation) {
+ console.log('Removing workstation ' + this.removeWorkstation);
+ // TODO remove
+ }
+ }
+
+ selected(): Workstation {
+ return this.workstations.filter(
+ ws => {return ws.id == this.selectedId})[0];
+ }
+
+ useNow(): void {
+ console.debug('using ' + this.selected().name);
+ }
+
+ setDefault(): void {
+ console.debug('defaulting ' + this.selected().name);
+ }
+
+ removeSelected(): void {
+ console.debug('removing ' + this.selected().name);
+ }
+
+ canDeleteSelected(): boolean {
+ return true;
+ }
+
+ registerWorkstation(): void {
+ console.log(`Registering new workstation ` +
+ `"${this.newName}" at ${this.newOwner.shortname()}`);
+ }
+}
+
+
--- /dev/null
+import {NgModule} from '@angular/core';
+import {CommonModule} from '@angular/common';
+import {EgStaffModule} from '@eg/staff/app.module';
+import {WorkstationsRoutingModule} from './routing.module';
+import {WorkstationsComponent} from './app.component';
+
+@NgModule({
+ declarations: [
+ WorkstationsComponent
+ ],
+ imports: [
+ CommonModule,
+ EgStaffModule,
+ WorkstationsRoutingModule
+ ]
+})
+
+export class ManageWorkstationsModule {
+ constructor() {console.log('Loading ManageWorkstationsModule')}
+}
+
--- /dev/null
+import {NgModule} from '@angular/core';
+import {RouterModule, Routes} from '@angular/router';
+import {WorkstationsComponent} from './app.component';
+
+// Note that we need a path value (e.g. 'manage') because without it
+// there is nothing for the router to match, unless we rely on the parent
+// module to handle all of our routing for us.
+const routes: Routes = [
+ {
+ path: 'manage',
+ component: WorkstationsComponent
+ }, {
+ path: 'remove/:remove',
+ component: WorkstationsComponent
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+
+export class WorkstationsRoutingModule {
+}
+
export class EgStaffComponent implements OnInit {
readonly loginPath = '/staff/login';
- readonly wsAdminPath = '/staff/admin/workstation/workstations';
+ readonly wsAdminPath = '/staff/admin/workstation/workstations/manage';
constructor(
private router: Router,
this.net.authExpired$.subscribe(uhOh => {
console.debug('Auth session has expired. Redirecting to login');
this.auth.redirectUrl = this.router.url;
- this.router.navigate(['/staff/login']);
+ this.router.navigate([this.loginPath]);
});
this.route.data.subscribe((data: {staffResolver : any}) => {
+++ /dev/null
-import { CommonModule } from '@angular/common';
-import { NgModule } from '@angular/core';
-import { EgCircRoutingModule } from './routing.module';
-
-@NgModule({
- declarations: [
- ],
- imports: [
- EgCircRoutingModule
- ],
- providers: []
-})
-
-export class EgCircModule {
-
-}
// post-login URL
let url: string = this.auth.redirectUrl || '/staff/splash';
+ let workstation: string = this.args.workstation;
this.auth.login(this.args).then(
ok => {
this.auth.redirectUrl = null;
if (this.auth.workstationState == EgAuthWsState.NOT_FOUND_SERVER) {
- // User is logged in without a workstation.
- // Redirect them to the WS admin page.
+ // User attempted to login with a workstation that is
+ // unknown to the server. Redirect to the WS admin page.
this.router.navigate(
- ['/staff/admin/workstation/workstations']);
+ ['/staff/admin/workstation/workstations/remove/${workstation}']);
} else {
// Force reload of the app after a successful login.
// This allows the route resolver to re-run with a
export class EgStaffResolver implements Resolve<Observable<any>> {
readonly loginPath = '/staff/login';
- readonly wsAdminPath = '/staff/admin/workstation/workstations';
+ readonly wsAdminPath = '/staff/admin/workstation/workstations/manage';
constructor(
private router: Router,
console.debug('EgStaffResolver:resolve()');
// Staff cookies stay in /$base/staff/
+ // NOTE: storing session data at '/' so it can be shared by
+ // Angularjs apps.
this.store.loginSessionBasePath = '/';
//this.ngLocation.prepareExternalUrl('/staff');
component: EgStaffSplashComponent
}, {
path: 'circ',
- loadChildren : '@eg/staff/circ/app.module#EgCircModule'
+ loadChildren : '@eg/staff/circ/routing.module#EgCircRoutingModule'
}, {
path: 'catalog',
loadChildren : '@eg/staff/catalog/app.module#EgCatalogModule'
}, {
path: 'admin',
- loadChildren : '@eg/staff/admin/app.module#EgAdminModule'
+ loadChildren : '@eg/staff/admin/routing.module#EgAdminRoutingModule'
}]
}];
-<b>Staff Splash Page</b>
-<br/>
+<div class="container">
-<a routerLink="/staff/admin/workstation/workstations">Workstation Admin</a>
-<br/>
+ <!-- header icon -->
+ <div class="row mb-3">
+ <div class="col-12 text-center">
+ <img src="/images/portal/logo.png"/>
+ </div>
+ </div>
+
+ <div class="row" id="splash-nav">
+ <div class="col-4">
+ <div class="card">
+ <div class="card-header bg-success">
+ <div class="panel-title text-center">Circulation and Patrons</div>
+ </div>
+ <div class="card-body">
+ <div class="list-group">
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/forward.png"/>
+ <a href="/eg/staff/circ/patron/bcsearch">Check Out Items</a>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/back.png"/>
+ <a href="/eg/staff/circ/checkin/index">Check In Items</a>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/retreivepatron.png"/>
+ <a href="/eg/staff/circ/patron/search">Search For Patron By Name</a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-4">
+ <div class="card">
+ <div class="card-header bg-success">
+ <div class="panel-title text-center">Item Search and Cataloging</div>
+ </div>
+ <div class="card-body">
+ <div class="list-group">
+ <div class="list-group-item border-0 p-2">
+ <div class="input-group">
+ <input type="text" class="form-control"
+ [(ngModel)]="catSearchQuery"
+ id='catalog-search-input'
+ (keyup)="checkEnter($event)"
+ i18n-placeholder placeholder="Search for...">
+ <span class="input-group-btn">
+ <button class="btn btn-outline-secondary"
+ (click)="searchCatalog()" type="button">
+ Search
+ </button>
+ </span>
+ <!--
+ <input focus-me="focus_search"
+ class="form-control" ng-model="cat_query" type="text"
+ ng-keypress="catalog_search($event)"
+ placeholder="Search catalog for..."/>
+ <button class='btn btn-light' ng-click="catalog_search()">
+ Search
+ </button>
+ -->
+ </div>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/bucket.png"/>
+ <a href="/eg/staff/cat/bucket/record/">Record Buckets</a>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/bucket.png"/>
+ <a href="/eg/staff/cat/bucket/copy/">Copy Buckets</a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-4">
+ <div class="card">
+ <div class="card-header bg-success">
+ <div class="panel-title text-center">Administration</div>
+ </div>
+ <div class="card-body">
+ <div class="list-group">
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/helpdesk.png"/>
+ <a target="_top" href="http://docs.evergreen-ils.org/">
+ Evergreen Documentation
+ </a>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/helpdesk.png"/>
+ <a target="_top" href="/eg/staff/admin/workstation/index">
+ Workstation Administration
+ </a>
+ </div>
+ <div class="list-group-item border-0 p-2">
+ <img src="/images/portal/reports.png"/>
+ <a target="_top" href="/eg/staff/reporter/legacy/main">
+ Reports
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
-import {Component, OnInit} from '@angular/core';
+import {Component, OnInit, Renderer} from '@angular/core';
+import {Router} from '@angular/router';
@Component({
templateUrl: 'splash.component.html'
export class EgStaffSplashComponent implements OnInit {
+ catSearchQuery: string;
+
+ constructor(
+ private renderer: Renderer,
+ private router: Router
+ ) {}
+
ngOnInit() {
+
+ // Focus catalog search form
+ this.renderer.selectRootElement('#catalog-search-input').focus();
+ }
+
+ checkEnter($event: any): void {
+ if ($event.keyCode == 13)
+ this.searchCatalog();
+ }
+
+ searchCatalog(): void {
+ if (!this.catSearchQuery) return;
+
+ this.router.navigate(
+ ['/staff/catalog/search'],
+ {queryParams: {query : this.catSearchQuery}}
+ );
}
}