From: Bill Erickson Date: Sun, 17 Dec 2017 22:31:10 +0000 (-0500) Subject: LP#626157 Ang2 experiments X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=c473b05fea352b77e98ba230dd37de14ec063fc3;p=working%2FEvergreen.git LP#626157 Ang2 experiments Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/eg2-src/src/app/core/store.ts b/Open-ILS/eg2-src/src/app/core/store.ts index e1a879b390..fcb83c6675 100644 --- a/Open-ILS/eg2-src/src/app/core/store.ts +++ b/Open-ILS/eg2-src/src/app/core/store.ts @@ -39,7 +39,7 @@ export class EgStoreService { this.loginSessionKeys.push(key); } - setItem(key: string, val: any, isJson?: Boolean): Promise { + setItem(key: string, val: any, isJson?: Boolean): Promise { // TODO: route keys appropriately this.setLocalItem(key, val, false); return Promise.resolve(); @@ -50,7 +50,7 @@ export class EgStoreService { window.localStorage.setItem(key, val); } - setServerItem(key: string, val: any): Promise { + setServerItem(key: string, val: any): Promise { return Promise.resolve(); } @@ -94,7 +94,7 @@ export class EgStoreService { window.localStorage.removeItem(key); } - removeServerItem(key: string): Promise { + removeServerItem(key: string): Promise { return Promise.resolve(); } diff --git a/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.html b/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.html index 1bc1cf084a..859c70c461 100644 --- a/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.html +++ b/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.html @@ -8,9 +8,9 @@
-
-
- Workstation {{removingWs}} is no longer valid. Removing registration. +
+
+ Workstation {{removeWorkstation}} is no longer valid. Removing registration.
Please register a workstation. @@ -22,7 +22,7 @@
-
@@ -52,12 +54,15 @@
-
- +
@@ -68,7 +73,7 @@ (click)="useNow()" [disabled]="!selected"> Use Now - diff --git a/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.ts b/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.ts index 43ca664da4..96d0784d53 100644 --- a/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.ts +++ b/Open-ILS/eg2-src/src/app/staff/admin/workstation/workstations/app.component.ts @@ -1,10 +1,11 @@ import {Component, OnInit, ViewChild} from '@angular/core'; -import {ActivatedRoute} from '@angular/router'; +import {Router, 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'; +import {EgEventService} from '@eg/core/event'; import {EgConfirmDialogComponent} from '@eg/share/confirm-dialog.component'; // Slim version of the WS that's stored in the cache. @@ -19,11 +20,12 @@ interface Workstation { }) export class WorkstationsComponent implements OnInit { - selectedId: Number; + selectedName: string; workstations: Workstation[] = []; removeWorkstation: string; newOwner: EgIdlObject; - newName: string = 'NewTestName'; + newName: string; + defaultName: string; @ViewChild('workstationExistsDialog') private wsExistsDialog: EgConfirmDialogComponent; @@ -36,7 +38,9 @@ export class WorkstationsComponent implements OnInit { } constructor( + private router: Router, private route: ActivatedRoute, + private evt: EgEventService, private net: EgNetService, private store: EgStoreService, private auth: EgAuthService, @@ -45,38 +49,48 @@ export class WorkstationsComponent implements OnInit { ngOnInit() { this.store.getItem('eg.workstation.all') - .then(res => this.workstations = res); + .then(list => this.workstations = list || []) + .then(noop => this.store.getItem('eg.workstation.default')) + .then(defWs => { + this.defaultName = defWs; + this.selectedName = this.auth.workstation() || defWs + }) + .then(noop => { + let rm = this.route.snapshot.paramMap.get('remove'); + if (rm) this.removeSelected(this.removeWorkstation = rm) + }) // 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]; + ws => {return ws.name == this.selectedName})[0]; } useNow(): void { - //console.debug('using ' + this.selected().name); - - this.wsExistsDialog.open().then( - confirmed => console.log('dialog confirmed'), - dismissed => console.log('dialog dismissed') - ); + if (!this.selected()) return; + this.router.navigate(['/staff/login'], + {queryParams: {workstation: this.selected().name}}); } setDefault(): void { - console.debug('defaulting ' + this.selected().name); + if (!this.selected()) return; + this.defaultName = this.selected().name; + this.store.setItem('eg.workstation.default', this.defaultName); } - removeSelected(): void { - console.debug('removing ' + this.selected().name); + removeSelected(name?: string): void { + if (!name) name = this.selected().name; + + this.workstations = this.workstations.filter(w => w.name != name); + this.store.setItem('eg.workstation.all', this.workstations); + + if (this.defaultName == name) { + this.defaultName = null; + this.store.removeItem('eg.workstation.default'); + } } canDeleteSelected(): boolean { @@ -86,6 +100,67 @@ export class WorkstationsComponent implements OnInit { registerWorkstation(): void { console.log(`Registering new workstation ` + `"${this.newName}" at ${this.newOwner.shortname()}`); + + this.newName = this.newOwner.shortname() + '-' + this.newName; + + this.registerWorkstationApi().then( + wsId => this.registerWorkstationLocal(wsId)); + + } + + private handleCollision(): Promise { + return new Promise((resolve, reject) => { + this.wsExistsDialog.open() + .then( + confirmed => { + this.registerWorkstationApi(true).then( + wsId => resolve(wsId), + notOk => reject() + ) + }, + dismissed => reject() + ) + }); + } + + + private registerWorkstationApi(override?: boolean): Promise { + let method = 'open-ils.actor.workstation.register'; + if (override) method += '.override'; + + return new Promise((resolve, reject) => { + this.net.request( + 'open-ils.actor', method, + this.auth.token(), this.newName, this.newOwner.id() + ).subscribe(wsId => { + let evt = this.evt.parse(wsId); + if (evt) { + if (evt.textcode == 'WORKSTATION_NAME_EXISTS') { + this.handleCollision().then( + id => resolve(id), + notOk => reject(notOk) + ) + } else { + console.error(`Registration failed ${evt}`); + reject(); + } + } else { + resolve(wsId); + } + }); + }); + } + + private registerWorkstationLocal(wsId: number) { + let ws: Workstation = { + id: wsId, + name: this.newName, + owning_lib: this.newOwner.id() + }; + + this.workstations.push(ws); + this.store.setItem('eg.workstation.all', this.workstations) + .then(ok => this.newName = ''); } } diff --git a/Open-ILS/eg2-src/src/app/staff/app.component.ts b/Open-ILS/eg2-src/src/app/staff/app.component.ts index 3c90ab0a91..6f1dbdab55 100644 --- a/Open-ILS/eg2-src/src/app/staff/app.component.ts +++ b/Open-ILS/eg2-src/src/app/staff/app.component.ts @@ -11,7 +11,7 @@ import { EgNetService } from '@eg/core/net'; export class EgStaffComponent implements OnInit { readonly loginPath = '/staff/login'; - readonly wsAdminPath = '/staff/admin/workstation/workstations/manage'; + readonly wsAdminBasePath = '/staff/admin/workstation/workstations/'; constructor( private router: Router, @@ -46,12 +46,13 @@ export class EgStaffComponent implements OnInit { } /** - * Verifying auth token on every route is overkill, since an expired - * token will make itself known with the first API call, but we do + * Verifying the auth token on every route is overkill, since + * an expired token will make itself known with the first API + * call or when the auth session poll discovers it, but we do * want to prevent navigation from the login or workstation admin * page, since these can be accessed without a valid authtoken or - * workstation, respectively, once the initial route resolvers - * have done their jobs. + * workstation, respectively, once the initial route resolvers have + * done their jobs. */ basicAuthChecks(routeEvent: NavigationEnd): void { @@ -63,10 +64,10 @@ export class EgStaffComponent implements OnInit { // Access to workstation admin page is granted regardless // of workstation validity. - if (routeEvent.url == this.wsAdminPath) return; + if (routeEvent.url.indexOf(this.wsAdminBasePath) >= 0) return; if (this.auth.workstationState != EgAuthWsState.VALID) - this.router.navigate([this.wsAdminPath]); + this.router.navigate([this.wsAdminBasePath]); } } diff --git a/Open-ILS/eg2-src/src/app/staff/app.module.ts b/Open-ILS/eg2-src/src/app/staff/app.module.ts index 3b9418fc3c..6cefff5698 100644 --- a/Open-ILS/eg2-src/src/app/staff/app.module.ts +++ b/Open-ILS/eg2-src/src/app/staff/app.module.ts @@ -23,6 +23,7 @@ import {EgConfirmDialogComponent} from '@eg/share/confirm-dialog.component'; EgConfirmDialogComponent ], imports: [ + CommonModule, EgStaffRoutingModule, FormsModule, NgbModule diff --git a/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.css b/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.css index f67d8fa0c7..6201dff923 100644 --- a/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.css +++ b/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.css @@ -4,6 +4,13 @@ margin-bottom: .1rem; } +/* BS default height is 2.25rem + 2px which is quite chunky. + * This better matches the text input heights */ +select.form-control:not([size]):not([multiple]) { + padding: .355rem .55rem; + height: 2.2rem; +} + #staffcat-search-form { border-bottom: 2px dashed rgba(0,0,0,.225); } diff --git a/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.html b/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.html index 3ee4d2110b..e02c3e6581 100644 --- a/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.html +++ b/Open-ILS/eg2-src/src/app/staff/catalog/search-form.component.html @@ -4,7 +4,7 @@ TODO focus search input
-
+
+
+ +
+
+ +
@@ -91,7 +99,7 @@ TODO focus search input
-
+
-
- Sign In -
-
+
+
+
+ Sign In +
+ -
- - -
+
+ + +
-
- - -
+
+ + +
- - -
+
+ + +
+ +
+
+ +
+
+ +
+
diff --git a/Open-ILS/eg2-src/src/app/staff/login.component.ts b/Open-ILS/eg2-src/src/app/staff/login.component.ts index 64ae6c5361..fadcfc25e4 100644 --- a/Open-ILS/eg2-src/src/app/staff/login.component.ts +++ b/Open-ILS/eg2-src/src/app/staff/login.component.ts @@ -1,8 +1,8 @@ -import { Component, OnInit, Renderer } from '@angular/core'; -import { Location } from '@angular/common'; -import { Router } from '@angular/router'; -import { EgAuthService, EgAuthWsState } from '@eg/core/auth'; -import { EgStoreService } from '@eg/core/store'; // TODO: testing +import {Component, OnInit, Renderer} from '@angular/core'; +import {Location} from '@angular/common'; +import {Router, ActivatedRoute} from '@angular/router'; +import {EgAuthService, EgAuthWsState} from '@eg/core/auth'; +import {EgStoreService} from '@eg/core/store'; @Component({ templateUrl : './login.component.html' @@ -10,18 +10,18 @@ import { EgStoreService } from '@eg/core/store'; // TODO: testing export class EgStaffLoginComponent implements OnInit { + workstations: any[]; + args = { username : '', password : '', - type : 'staff', - //workstation : '' - workstation : 'BR1-skiddoo' // testing + workstation : '', + type : 'staff' }; - workstations = []; - constructor( private router: Router, + private route: ActivatedRoute, private ngLocation: Location, private renderer: Renderer, private auth: EgAuthService, @@ -36,13 +36,23 @@ export class EgStaffLoginComponent implements OnInit { // Focus username this.renderer.selectRootElement('#username').focus(); - // load browser-local workstation data + this.store.getItem('eg.workstation.all') + .then(list => this.workstations = list || []) + .then(list => this.store.getItem('eg.workstation.default')) + .then(defWs => this.args.workstation = defWs) + .then(noOp => this.applyWorkstation()) + } + + applyWorkstation() { + let wanted = this.route.snapshot.queryParamMap.get('workstation'); + if (!wanted) return; // use the default - // TODO: insert for testing. - this.store.setItem( - 'eg.workstation.all', - [{name:'BR1-skiddoo',id:1,owning_lib:4}] - ); + let exists = this.workstations.filter(w => w.name == wanted)[0]; + if (exists) { + this.args.workstation = wanted; + } else { + console.error(`Unknown workstation requested: ${wanted}`); + } } handleSubmit() { @@ -59,7 +69,7 @@ export class EgStaffLoginComponent implements OnInit { // 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/remove/${workstation}']); + [`/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 diff --git a/Open-ILS/eg2-src/src/app/staff/nav.component.html b/Open-ILS/eg2-src/src/app/staff/nav.component.html index 859ec7f865..f325a7410a 100644 --- a/Open-ILS/eg2-src/src/app/staff/nav.component.html +++ b/Open-ILS/eg2-src/src/app/staff/nav.component.html @@ -169,9 +169,9 @@
@@ -188,13 +188,17 @@ i18n-title title="Log out and more..." class="nav-link dropdown-toggle no-caret with-material-icon"> - list + more_vert
diff --git a/Open-ILS/eg2-src/src/app/staff/resolver.service.ts b/Open-ILS/eg2-src/src/app/staff/resolver.service.ts index 8c23030377..28e228fd50 100644 --- a/Open-ILS/eg2-src/src/app/staff/resolver.service.ts +++ b/Open-ILS/eg2-src/src/app/staff/resolver.service.ts @@ -2,6 +2,7 @@ import {Injectable} from '@angular/core'; import {Location} from '@angular/common'; import {Observable, Observer} from 'rxjs/Rx'; import {Router, Resolve, RouterStateSnapshot, + ActivatedRoute, ActivatedRouteSnapshot} from '@angular/router'; import {EgStoreService} from '@eg/core/store'; import {EgNetService} from '@eg/core/net'; @@ -16,10 +17,11 @@ import {EgAuthService} from '@eg/core/auth'; export class EgStaffResolver implements Resolve> { readonly loginPath = '/staff/login'; - readonly wsAdminPath = '/staff/admin/workstation/workstations/manage'; + readonly wsRemPath = '/staff/admin/workstation/workstations/remove/'; constructor( private router: Router, + private route: ActivatedRoute, private ngLocation: Location, private store: EgStoreService, private net: EgNetService, @@ -38,8 +40,9 @@ export class EgStaffResolver implements Resolve> { this.store.loginSessionBasePath = '/'; //this.ngLocation.prepareExternalUrl('/staff'); - // Login resets everything. No need to load data. - if (state.url == '/staff/login') return Observable.of(true); + // Not sure how to get the path without params... using this for now. + let path = state.url.split('?')[0] + if (path == '/staff/login') return Observable.of(true); return Observable.create(observer => { this.auth.testAuthToken().then( @@ -52,8 +55,10 @@ export class EgStaffResolver implements Resolve> { ); }, wsNotOk => { - if (state.url != this.wsAdminPath) { - this.router.navigate([this.wsAdminPath]); + if (path.indexOf(this.wsRemPath) < 0) { + this.router.navigate([ + this.wsRemPath + this.auth.workstation() + ]); } observer.complete(); } diff --git a/Open-ILS/eg2-src/src/styles.css b/Open-ILS/eg2-src/src/styles.css index c580fb05cb..9f7b83a8b2 100644 --- a/Open-ILS/eg2-src/src/styles.css +++ b/Open-ILS/eg2-src/src/styles.css @@ -30,7 +30,9 @@ h5 {font-size: .95rem} } -/** BS has flex utility classes, but none for specifying flex widths */ +/** BS has flex utility classes, but none for specifying flex widths. + * BS class="col" is roughly equivelent to flex-1, but col-2 is not + * equivalent to flex-2, since col-2 really means 2/12 width. */ .flex-1 {flex: 1} .flex-2 {flex: 2} .flex-3 {flex: 3}