From bce3e42113f59cc9af67108c2b5366a927f190b5 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Tue, 28 Nov 2017 15:17:43 -0500 Subject: [PATCH] LP#626157 Ang2 experiments Signed-off-by: Bill Erickson --- Open-ILS/webby-src/src/app/base.module.ts | 2 + Open-ILS/webby-src/src/app/core/idl.service.ts | 21 +++- Open-ILS/webby-src/src/app/core/org.service.ts | 87 ++++++++++++++++ .../app/staff/admin/workstation/admin-ws.module.ts | 7 +- .../admin/workstation/workstations.component.html | 112 ++++++++++++--------- .../admin/workstation/workstations.component.ts | 49 +++++++-- .../circ/patron/bcsearch/bcsearch.component.ts | 2 - .../webby-src/src/app/staff/login.component.html | 56 +---------- Open-ILS/webby-src/src/app/staff/nav.component.css | 53 +++++++--- .../webby-src/src/app/staff/nav.component.html | 64 +++++++----- .../src/app/staff/share/org-select.component.html | 9 ++ .../src/app/staff/share/org-select.component.ts | 48 +++++++++ .../webby-src/src/app/staff/splash.component.html | 3 - .../webby-src/src/app/staff/staff.component.html | 5 +- Open-ILS/webby-src/src/app/staff/staff.module.ts | 11 +- 15 files changed, 360 insertions(+), 169 deletions(-) create mode 100644 Open-ILS/webby-src/src/app/core/org.service.ts create mode 100644 Open-ILS/webby-src/src/app/staff/share/org-select.component.html create mode 100644 Open-ILS/webby-src/src/app/staff/share/org-select.component.ts diff --git a/Open-ILS/webby-src/src/app/base.module.ts b/Open-ILS/webby-src/src/app/base.module.ts index a464f61bc0..0a5ff2beb1 100644 --- a/Open-ILS/webby-src/src/app/base.module.ts +++ b/Open-ILS/webby-src/src/app/base.module.ts @@ -38,6 +38,8 @@ import {EgStoreService} from '@eg/core/store.service'; EgAuthService, EgStoreService ], + exports: [ + ], bootstrap: [EgBaseComponent] }) diff --git a/Open-ILS/webby-src/src/app/core/idl.service.ts b/Open-ILS/webby-src/src/app/core/idl.service.ts index 49a4317672..e503ba74a4 100644 --- a/Open-ILS/webby-src/src/app/core/idl.service.ts +++ b/Open-ILS/webby-src/src/app/core/idl.service.ts @@ -23,7 +23,17 @@ export interface EgIdlObject { @Injectable() export class EgIdlService { - classes: Object; + classes = {}; // IDL class metadata + constructors = {}; // IDL instance generators + + /** + * Create a new IDL object instance. + */ + create(cls: string, seed?:any[]): EgIdlObject { + if (this.constructors[cls]) + return new this.constructors[cls](seed); + throw new Error(`No such IDL class ${cls}`); + } parseIdl(): void { let this_ = this; @@ -55,13 +65,14 @@ export class EgIdlService { }); return x; - }) + }); - this_[cls] = generator(); + this_.constructors[cls] = generator(); // global class constructors required for JSON_v1.js - // TODO: Move away from requiring we add classes to window. - window[cls] = this_[cls]; + // TODO: polluting the window namespace w/ every IDL class + // is less than ideal. + window[cls] = this_.constructors[cls]; } for (var cls in this_.classes) diff --git a/Open-ILS/webby-src/src/app/core/org.service.ts b/Open-ILS/webby-src/src/app/core/org.service.ts new file mode 100644 index 0000000000..44eea6a01f --- /dev/null +++ b/Open-ILS/webby-src/src/app/core/org.service.ts @@ -0,0 +1,87 @@ +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs/Rx'; +import {EgIdlObject, EgIdlService} from './idl.service'; + +type EgOrgNodeOrId = number | EgIdlObject; + +@Injectable() +export class EgOrgService { + + private orgMap = {}; + private orgList: EgIdlObject[] = []; + private orgTree: EgIdlObject; // root node + children + + get(nodeOrId: EgOrgNodeOrId): EgIdlObject { + if (typeof nodeOrId == 'object') + return nodeOrId; + return this.orgMap[nodeOrId]; + }; + + list(): EgIdlObject[] { + return this.orgList; + }; + + tree(): EgIdlObject { + return this.orgTree; + } + + // get the root OU + root(): EgIdlObject { + return this.orgList[0]; + } + + // list of org_unit objects or IDs for ancestors + me + ancestors(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] { + let node = this.get(nodeOrId); + if (!node) return []; + let nodes = [node]; + while( (node = this.get(node.parent_ou()))) + nodes.push(node); + if (asId) + return nodes.map(function(n){return n.id()}); + return nodes; + }; + + // tests that a node can have users + canHaveUsers(nodeOrId): Boolean { + return this + .get(nodeOrId) + .ou_type() + .can_have_users() == 't'; + } + + // tests that a node can have volumes + canHaveVolumes(nodeOrId): Boolean { + return this + .get(nodeOrId) + .ou_type() + .can_have_vols() == 't'; + } + + // list of org_unit objects or IDs for me + descendants + descendants(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] { + let node = this.get(nodeOrId); + if (!node) return []; + let nodes = []; + function descend(n) { + nodes.push(n); + n.children().forEach(descend); + } + descend(node); + if (asId) + return nodes.map(function(n){return n.id()}); + return nodes; + } + + // list of org_unit objects or IDs for ancestors + me + descendants + fullPath(nodeOrId: EgOrgNodeOrId, asId: Boolean): EgIdlObject[] { + let list = this.ancestors(nodeOrId, false).concat( + this.descendants(nodeOrId, false).slice(1)); + if (asId) + return list.map(function(n){return n.id()}); + return list; + } + + // NOTE: see ./org-settings.service for settings + // TODO: ^-- +} diff --git a/Open-ILS/webby-src/src/app/staff/admin/workstation/admin-ws.module.ts b/Open-ILS/webby-src/src/app/staff/admin/workstation/admin-ws.module.ts index 743ef8595f..d6c5b0ee09 100644 --- a/Open-ILS/webby-src/src/app/staff/admin/workstation/admin-ws.module.ts +++ b/Open-ILS/webby-src/src/app/staff/admin/workstation/admin-ws.module.ts @@ -1,18 +1,17 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {FormsModule} from '@angular/forms'; +import {EgStaffModule} from '../../staff.module'; import {EgAdminWsRoutingModule} from './routing.module'; import {EgWorkstationsComponent} from './workstations.component'; - @NgModule({ declarations: [ EgWorkstationsComponent ], imports: [ + EgStaffModule, EgAdminWsRoutingModule, - CommonModule, - FormsModule, + CommonModule ] }) diff --git a/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.html b/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.html index ebb2b8f307..d3b6bb456b 100644 --- a/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.html +++ b/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.html @@ -1,59 +1,71 @@ -
-
- Workstation {{removingWs}} is no longer valid. Removing registration. -
-
- Please register a workstation. -
-
-
- Register a New Workstation For This Browser +
+
+
+ Workstation {{removingWs}} is no longer valid. Removing registration. +
+
+ Please register a workstation.
-
- - -
-
- Workstations Registered With This Browser +
+
+ Workstations Registered With This Browser +
-
-
-
- +
+
+ +
+
+
+
+ + + +
diff --git a/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.ts b/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.ts index bf7717da95..4e212cf090 100644 --- a/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.ts +++ b/Open-ILS/webby-src/src/app/staff/admin/workstation/workstations.component.ts @@ -1,17 +1,29 @@ import {Component, OnInit} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; -import {EgNetService} from '@eg/core/net.service'; import {EgStoreService} from '@eg/core/store.service'; +import {EgIdlObject} from '@eg/core/idl.service'; +import {EgNetService} from '@eg/core/net.service'; import {EgAuthService} from '@eg/core/auth.service'; +import {EgOrgService} from '@eg/core/org.service'; + +// 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 { - workstations: Object[] = []; - removingWs: boolean = false; + selectedId: Number; + workstations: Workstation[] = []; + isRemoving: boolean = false; + + newOwner: EgIdlObject; + newName: String; constructor( private route: ActivatedRoute, @@ -21,12 +33,33 @@ export class EgWorkstationsComponent implements OnInit { ) {} ngOnInit() { + this.egStore.getItem('eg.workstation.all') + .then(res => this.workstations = res); + } - console.log('EgWorkstationsComponent:ngOnInit()'); + 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; + } - this.egStore.getItem('eg.workstation.all').then( - res => this.workstations = res - ); + registerWorkstation(): void { + console.log('registering ' + this.newName); } } diff --git a/Open-ILS/webby-src/src/app/staff/circ/patron/bcsearch/bcsearch.component.ts b/Open-ILS/webby-src/src/app/staff/circ/patron/bcsearch/bcsearch.component.ts index 91561706d7..21bb111e67 100644 --- a/Open-ILS/webby-src/src/app/staff/circ/patron/bcsearch/bcsearch.component.ts +++ b/Open-ILS/webby-src/src/app/staff/circ/patron/bcsearch/bcsearch.component.ts @@ -3,8 +3,6 @@ import { ActivatedRoute } from '@angular/router'; import { EgNetService } from '@eg/core/net.service'; import { EgAuthService } from '@eg/core/auth.service'; -declare var js2JSON; - @Component({ templateUrl: 'bcsearch.component.html' }) diff --git a/Open-ILS/webby-src/src/app/staff/login.component.html b/Open-ILS/webby-src/src/app/staff/login.component.html index ae74776af8..869fe879cf 100644 --- a/Open-ILS/webby-src/src/app/staff/login.component.html +++ b/Open-ILS/webby-src/src/app/staff/login.component.html @@ -1,58 +1,4 @@ - - -
+
Sign In
diff --git a/Open-ILS/webby-src/src/app/staff/nav.component.css b/Open-ILS/webby-src/src/app/staff/nav.component.css index 96946d5c91..eb037e874b 100644 --- a/Open-ILS/webby-src/src/app/staff/nav.component.css +++ b/Open-ILS/webby-src/src/app/staff/nav.component.css @@ -1,24 +1,50 @@ +/* remove dropdown carret for icon-based entries */ +#staff-navbar .no-caret::after { + display:none; +} + +/* move the caret closer to the dropdown text */ +#staff-navbar .dropdown-toggle::after { + margin-left:0px; +} + #staff-navbar { background: -webkit-linear-gradient(#00593d, #007a54); background-color: #007a54; color: #fff; font-size: 14px; } -#staff-navbar .navbar-expander { - margin-right: auto; + +/* align top of dropdown w/ bottom of nav */ +#staff-navbar .dropdown-menu { + margin-top: 7px; } -#staff-navbar .navbar-nav>li>a { - color: #fff; - padding-top: 5px; - padding-bottom: 1px; +#staff-navbar .material-icons { + padding-right:3px; } -#staff-navbar .nav-item { - margin-right: 10px; +#staff-navbar .dropdown-item { + font-size: 14px; + font-weight: 400; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + padding-left: 0.5rem; + padding-right: 0.5rem; } -#staff-navbar .navbar-nav>li>a:hover { + +#staff-navbar .nav-link { + color: #fff; + padding-top:1px; + padding-bottom:1px; +} +#staff-navbar .nav-link:hover { color: #ddd; cursor: pointer; } +#staff-navbar .nav-item { + /* + margin-right: 8px; + */ +} + #staff-navbar .navbar-nav > .open > a, #staff-navbar .navbar-nav > .open > a:focus, #staff-navbar .navbar-nav > .open > a:hover { @@ -32,8 +58,11 @@ border-top-color: #ddd; border-bottom-color: #ddd; } -/* remove dropdown carret for icon-based entries */ -#staff-navbar .no-caret::after { - display:none; + +/* Align material-icons with sibling text; otherwise they float up */ +#staff-navbar .with-material-icon, #staff-navbar .dropdown-item { + display: inline-flex; + vertical-align: middle; + align-items: center; } diff --git a/Open-ILS/webby-src/src/app/staff/nav.component.html b/Open-ILS/webby-src/src/app/staff/nav.component.html index e5f32cdace..4206cd448f 100644 --- a/Open-ILS/webby-src/src/app/staff/nav.component.html +++ b/Open-ILS/webby-src/src/app/staff/nav.component.html @@ -1,40 +1,50 @@ - - -
- +
diff --git a/Open-ILS/webby-src/src/app/staff/share/org-select.component.html b/Open-ILS/webby-src/src/app/staff/share/org-select.component.html new file mode 100644 index 0000000000..b8fb2d574e --- /dev/null +++ b/Open-ILS/webby-src/src/app/staff/share/org-select.component.html @@ -0,0 +1,9 @@ + +
+ +
diff --git a/Open-ILS/webby-src/src/app/staff/share/org-select.component.ts b/Open-ILS/webby-src/src/app/staff/share/org-select.component.ts new file mode 100644 index 0000000000..f11169314d --- /dev/null +++ b/Open-ILS/webby-src/src/app/staff/share/org-select.component.ts @@ -0,0 +1,48 @@ +import {Component, OnInit, Input} from '@angular/core'; +import {Observable} from 'rxjs/Observable'; +import {map, tap, debounceTime, distinctUntilChanged} from 'rxjs/operators'; +import {EgAuthService} from '@eg/core/auth.service'; +import {EgStoreService} from '@eg/core/store.service'; +import {EgIdlObject} from '@eg/core/idl.service'; + +@Component({ + selector: 'eg-org-select', + templateUrl: './org-select.component.html' +}) + + +export class EgOrgSelectComponent implements OnInit { + + @Input() placeholder: String; + @Input() selectedOrg: EgIdlObject; + @Input() displayField: String = 'shortname'; + @Input() stickySetting: String; + @Input() onChange: (org:EgIdlObject) => void; + @Input() shouldDisable: (org:EgIdlObject) => Boolean; + @Input() shouldHide: (org:EgIdlObject) => Boolean; + @Input() allDisabled: Boolean = false; + + testString: String = ''; + + constructor( + private egAuth: EgAuthService, + private egStore: EgStoreService + ) {} + + ngOnInit() { + } + + states = ['Alabama', 'Alaska', 'American Samoa', 'Arizona']; + + orgFilter = (text$: Observable): Observable => { + return text$ + .debounceTime(100) + .distinctUntilChanged() + .map(term => this.states.filter( + v => v.toLowerCase().indexOf(term.toLowerCase()) > -1) + ); + } +} + + + diff --git a/Open-ILS/webby-src/src/app/staff/splash.component.html b/Open-ILS/webby-src/src/app/staff/splash.component.html index 0bb2f6cb81..85b2d35f2e 100644 --- a/Open-ILS/webby-src/src/app/staff/splash.component.html +++ b/Open-ILS/webby-src/src/app/staff/splash.component.html @@ -1,6 +1,3 @@ -
-
-
Staff Splash Page
diff --git a/Open-ILS/webby-src/src/app/staff/staff.component.html b/Open-ILS/webby-src/src/app/staff/staff.component.html index 0c4993de49..544e97f2ae 100644 --- a/Open-ILS/webby-src/src/app/staff/staff.component.html +++ b/Open-ILS/webby-src/src/app/staff/staff.component.html @@ -1,9 +1,10 @@ - -
+
+ +
diff --git a/Open-ILS/webby-src/src/app/staff/staff.module.ts b/Open-ILS/webby-src/src/app/staff/staff.module.ts index 456c58210d..692e6f687c 100644 --- a/Open-ILS/webby-src/src/app/staff/staff.module.ts +++ b/Open-ILS/webby-src/src/app/staff/staff.module.ts @@ -2,24 +2,33 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {NgbModule} from '@ng-bootstrap/ng-bootstrap'; +import {EgBaseModule} from '@eg/base.module'; import {EgStaffComponent} from './staff.component'; import {EgStaffRoutingModule} from './routing.module'; import {EgStaffNavComponent} from './nav.component'; import {EgStaffLoginComponent} from './login.component'; import {EgStaffSplashComponent} from './splash.component'; +import {EgOrgSelectComponent} from './share/org-select.component'; @NgModule({ declarations: [ EgStaffComponent, EgStaffNavComponent, EgStaffSplashComponent, - EgStaffLoginComponent + EgStaffLoginComponent, + EgOrgSelectComponent ], imports: [ EgStaffRoutingModule, FormsModule, NgbModule + ], + exports: [ + // Components available to all staff modules + EgOrgSelectComponent, + FormsModule, + NgbModule ] }) -- 2.11.0