LP#626157 Ang2 experiments
authorBill Erickson <berickxx@gmail.com>
Mon, 20 Nov 2017 22:05:33 +0000 (17:05 -0500)
committerBill Erickson <berickxx@gmail.com>
Mon, 11 Dec 2017 17:39:51 +0000 (12:39 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/webby-src/package.json
Open-ILS/webby-src/src/app/base.module.ts
Open-ILS/webby-src/src/app/core/eg-auth.service.ts [new file with mode: 0644]
Open-ILS/webby-src/src/app/core/eg-idl.service.ts
Open-ILS/webby-src/src/app/core/eg-net-request.ts [deleted file]
Open-ILS/webby-src/src/app/core/eg-net.service.ts
Open-ILS/webby-src/src/app/staff/circ/patron/bcsearch/bcsearch.component.ts
Open-ILS/webby-src/src/app/staff/nav.component.css [new file with mode: 0644]
Open-ILS/webby-src/src/app/staff/nav.component.html
Open-ILS/webby-src/src/app/staff/nav.component.ts

index 69892f8..88f8edc 100644 (file)
@@ -24,6 +24,7 @@
     "@ng-bootstrap/ng-bootstrap": "^1.0.0-beta.5",
     "core-js": "^2.4.1",
     "jquery": "^3.2.1",
+    "ngx-cookie": "^2.0.1",
     "rxjs": "^5.5.2",
     "zone.js": "^0.8.14"
   },
index 02a487b..7358b00 100644 (file)
@@ -12,6 +12,8 @@ import { EgBaseComponent }     from './base.component';
 import { EgBaseRoutingModule } from './base-routing.module';
 import { WelcomeComponent }    from './welcome.component';
 import { EgIdlService }        from '@eg/core/eg-idl.service';
+import { EgNetService }        from '@eg/core/eg-net.service';
+import { EgAuthService }       from '@eg/core/eg-auth.service';
 
 @NgModule({
   declarations: [
@@ -23,7 +25,11 @@ import { EgIdlService }        from '@eg/core/eg-idl.service';
     BrowserModule,
     NgbModule.forRoot()
   ],
-  providers: [EgIdlService],
+  providers: [
+    EgIdlService,
+    EgNetService,
+    EgAuthService
+  ],
   bootstrap: [EgBaseComponent]
 })
 
diff --git a/Open-ILS/webby-src/src/app/core/eg-auth.service.ts b/Open-ILS/webby-src/src/app/core/eg-auth.service.ts
new file mode 100644 (file)
index 0000000..f73720b
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * 
+ */
+import { Injectable, EventEmitter } from '@angular/core';
+import { Observable } from 'rxjs/Rx';
+import { EgNetService } from './eg-net.service';
+import { EgEvent } from './eg-event';
+import { EgIdlService, EgIdlObject } from './eg-idl.service';
+
+class EgAuthUser {
+    user : EgIdlObject;
+    workstation : String;
+    token : String;
+    authtime : Number;
+
+    constructor(token: String, authtime: Number, workstation: String) {
+        this.token = token;
+        this.workstation = workstation;
+        this.authtime = authtime;
+    }
+}
+
+interface EgAuthArgs {
+    username : String,
+    password : String,
+    workstation : String
+}
+
+@Injectable()
+export class EgAuthService {
+
+    private activeUser : EgAuthUser;
+    private opChangeUser : EgAuthUser;
+
+    user(): EgIdlObject { 
+        return this.activeUser.user 
+    };
+
+    // Workstation name.
+    workstation(): String { 
+        return this.activeUser.workstation 
+    };
+
+    token(): String { 
+        return this.activeUser.token 
+    };
+
+    authtime(): Number { 
+        return this.activeUser.authtime 
+    };
+
+    constructor(private egNet: EgNetService) { 
+    }
+
+    login(args: EgAuthArgs, ops?: Object): Promise<any> {
+
+        return new Promise<any>((resolve, reject) => {
+            this.egNet.request('open-ils.auth', 'open-ils.auth.login', args)
+            .subscribe(res => {
+                let evt = EgEvent.parse(res);
+                if (evt) {
+                    if (evt.textcode == 'SUCCESS') {
+                        this.handleLoginOk(args, evt);
+                        resolve();
+                    }
+                }
+            });
+        });
+    }
+
+    // Stash the login data
+    handleLoginOk(args: EgAuthArgs, evt: EgEvent): void {
+
+        this.activeUser = new EgAuthUser(
+            evt.payload.authtoken,
+            evt.payload.authtime,
+            args.workstation
+        )
+
+        // TODO: put stuff into login session cache;
+    }
+}
index 787d6a9..3fffd12 100644 (file)
@@ -3,6 +3,21 @@ import { Injectable } from '@angular/core';
 // Added globally by /IDL2js
 declare var _preload_fieldmapper_IDL: Object;
 
+/**
+ * NOTE: To achieve full type strictness and avoid compile warnings,
+ * we would likely have to pre-compile the IDL down to a .ts file with all 
+ * of the IDL class and field definitions.
+ */
+
+/**
+ * Every IDL object class implements this interface.
+ */
+export interface EgIdlObject {
+    a: any[];
+    classname: String;
+    _isfieldmapper: Boolean;
+}
+
 @Injectable()
 export class EgIdlService {
 
@@ -10,38 +25,46 @@ export class EgIdlService {
 
     parseIdl(): void {
         let this_ = this;
-
-        // retain a copy of the full IDL within the this
-        this.classes = _preload_fieldmapper_IDL;
+        this_.classes = _preload_fieldmapper_IDL;
 
         /**
          * Creates the class constructor and getter/setter
          * methods for each IDL class.
          */
         
-        let mkclass = function(cls, fields) {
+        let mkclass = (cls, fields) => {
             this_.classes[cls].classname = cls;
 
-            this_[cls] = function(seed) {
-                this.a = seed || [];
-                this.classname = cls;
-                this._isfieldmapper = true;
-            }
+            // This dance lets us encode each IDL object with the
+            // EgIdlObject interface.  Useful for adding type restrictions
+            // where desired for functions, etc.
+            let generator:any = ((): EgIdlObject => {
+
+                var x:any = function(seed) {
+                    this.a = seed || [];
+                    this.classname = cls;
+                    this._isfieldmapper = true;
+                };
 
-            /** creates the getter/setter methods for each field */
-            fields.forEach(function(field, idx) {
-                this_[cls].prototype[fields[idx].name] = function(n) {
-                    if (arguments.length==1) this.a[idx] = n;
-                    return this.a[idx];
-                }
-            });
+                fields.forEach(function(field, idx) {
+                    x.prototype[field.name] = function(n) {
+                        if (arguments.length==1) this.a[idx] = n;
+                        return this.a[idx];
+                    }
+                });
+
+                return x;
+            })
+
+            this_[cls] = generator();
 
             // global class constructors required for JSON_v1.js
+            // TODO: Move away from requiring we add classes to window.
             window[cls] = this_[cls]; 
         }
 
         for (var cls in this_.classes) 
             mkclass(cls, this_.classes[cls].fields);
     };
-
 }
+
diff --git a/Open-ILS/webby-src/src/app/core/eg-net-request.ts b/Open-ILS/webby-src/src/app/core/eg-net-request.ts
deleted file mode 100644 (file)
index e2c9179..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-import { EgEvent } from './eg-event';
-import { Observer } from 'rxjs/Rx';
-
-export class EgNetRequest {
-    service    : String;
-    method     : String;
-    params     : any[];
-    observer   : Observer<any>;
-    superseded : Boolean = false;
-
-    // Last EgEvent encountered by this request.
-    // Most callers will not need to import EgEvent since the parsed
-    // event will be available here.
-    evt: EgEvent;
-
-    constructor(service: String, method: String, params: any[]) {
-        this.service = service;
-        this.method = method;
-        this.params = params;
-    }
-}
index 8cc6b17..c279cca 100644 (file)
  */
 import { Injectable, EventEmitter } from '@angular/core';
 import { Observable, Observer } from 'rxjs/Rx';
-import { EgNetRequest } from './eg-net-request';
 import { EgEvent } from './eg-event';
 
 // Global vars from opensrf.js
 // These are availavble at runtime, but are not exported.
 declare var OpenSRF, OSRF_TRANSPORT_TYPE_WS;
 
+export class EgNetRequest {
+    service    : String;
+    method     : String;
+    params     : any[];
+    observer   : Observer<any>;
+    superseded : Boolean = false;
+
+    // Last EgEvent encountered by this request.
+    // Most callers will not need to import EgEvent since the parsed
+    // event will be available here.
+    evt: EgEvent;
+
+    constructor(service: String, method: String, params: any[]) {
+        this.service = service;
+        this.method = method;
+        this.params = params;
+    }
+}
+
 @Injectable()
 export class EgNetService {
 
index adb2e21..e93db6e 100644 (file)
@@ -1,7 +1,10 @@
 import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { EgNetService } from '@eg/core/eg-net.service';
-import { EgIdlService } from '@eg/core/eg-idl.service';
+import { EgIdlService, EgIdlObject } from '@eg/core/eg-idl.service';
+import { EgAuthService } from '@eg/core/eg-auth.service';
+
+declare var js2JSON;
 
 @Component({
   templateUrl: 'bcsearch.component.html'
@@ -15,7 +18,8 @@ export class EgBcSearchComponent implements OnInit {
     constructor(
         private route: ActivatedRoute,
         private egNet: EgNetService,
-        private egIdl : EgIdlService
+        private egIdl: EgIdlService,
+        private egAuth: EgAuthService
     ) {}
 
     ngOnInit() {
@@ -47,8 +51,24 @@ export class EgBcSearchComponent implements OnInit {
         );
 
         this.egIdl.parseIdl();
-        console.log(this.egIdl.aou);
+        
+        let org = new this.egIdl['aou']();
+        org.name('HELLO');
+        console.log(org.name() + ' : ' + js2JSON(org));
+
+        function foo(obj: EgIdlObject) {
+            console.log('org is an instance!');
+        }
 
+        foo(org);
+
+        this.egAuth.login({
+            username: 'admin', 
+            password: 'demo123', 
+            workstation : 'BR1-skiddoo'
+        }).then(res => {
+            console.log('login OK with auth ' + this.egAuth.token());
+        });
     }
 
     findUser(): void {
diff --git a/Open-ILS/webby-src/src/app/staff/nav.component.css b/Open-ILS/webby-src/src/app/staff/nav.component.css
new file mode 100644 (file)
index 0000000..11ae852
--- /dev/null
@@ -0,0 +1,24 @@
+#staff-navbar.navbar-default {
+    background: -webkit-linear-gradient(#00593d, #007a54);
+    background-color: #007a54;
+    color: #fff;
+}
+#staff-navbar.navbar-default .navbar-nav>li>a {
+    color: #fff;
+}
+#staff-navbar.navbar-default .navbar-nav>li>a:hover {
+    color: #ddd;
+}
+#staff-navbar.navbar-default .navbar-nav > .open > a,
+#staff-navbar.navbar-default .navbar-nav > .open > a:focus,
+#staff-navbar.navbar-default .navbar-nav > .open > a:hover {
+    background-color: #7a7a7a;
+}
+#staff-navbar.navbar-default .navbar-nav>.dropdown>a .caret {
+    border-top-color: #fff;
+    border-bottom-color: #fff;
+}
+#staff-navbar.navbar-default .navbar-nav>.dropdown>a:hover .caret {
+    border-top-color: #ddd;
+    border-bottom-color: #ddd;
+}
index 299c96a..cdb95bf 100644 (file)
@@ -4,7 +4,7 @@ href="./stuff"
 direct routing
 routerLink="/suff"
 -->
-<nav class="navbar navbar-expand-lg navbar-light bg-light">
+<nav id="staff-navbar" class="navbar navbar-expand-lg navbar-default">
   <div class="collapse navbar-collapse">
     <ul class="navbar-nav">
       <li class="nav-item active">
@@ -19,10 +19,7 @@ routerLink="/suff"
           <a i18n class="dropdown-item" routerLink="/staff">Another action</a>
 
           <a i18n class="dropdown-item" 
-            href="./staff/circ/patron/bcsearch">
-            <!--
             routerLink="/staff/circ/patron/bcsearch/">
-            -->
             Checkout
           </a>
         </div>
index 0b2dbd3..bbffd29 100644 (file)
@@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
 
 @Component({
     selector: 'eg-staff-nav-bar',
+    styleUrls: ['nav.component.css'],
     templateUrl: 'nav.component.html'
 })