From: Bill Erickson Date: Sun, 19 Nov 2017 15:42:42 +0000 (-0500) Subject: LP#626157 Ang2 experiments / service X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=c0e7dd0a2b6298b34f4f9b15655560efba5a6add;p=working%2FEvergreen.git LP#626157 Ang2 experiments / service Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/webby-src/README.adoc b/Open-ILS/webby-src/README.adoc new file mode 100644 index 0000000000..fd58af9902 --- /dev/null +++ b/Open-ILS/webby-src/README.adoc @@ -0,0 +1,17 @@ += EG Angular2 App = + +=== Apache Configuration === + +[source,conf] +--------------------------------------------------------------------- + + FallbackResource /webby/index.html + +--------------------------------------------------------------------- + +=== Transpile + Deploy in --watch mode for Dev === + +[source,sh] +--------------------------------------------------------------------- +ng build --deploy-url /webby/ --base-href /webby/ --output-path ../web/webby/ --watch +--------------------------------------------------------------------- diff --git a/Open-ILS/webby-src/src/app/core/README b/Open-ILS/webby-src/src/app/core/README index 3195b3cec4..217411dc7b 100644 --- a/Open-ILS/webby-src/src/app/core/README +++ b/Open-ILS/webby-src/src/app/core/README @@ -1 +1,5 @@ Core types (classes) and Angular services used by all modules. + +Class files are named $classname.ts + +Service files are named $servicename.service.ts diff --git a/Open-ILS/webby-src/src/app/core/eg-event.ts b/Open-ILS/webby-src/src/app/core/eg-event.ts new file mode 100644 index 0000000000..1561fedbb1 --- /dev/null +++ b/Open-ILS/webby-src/src/app/core/eg-event.ts @@ -0,0 +1,47 @@ + +export class EgEvent { + code : Number; + textcode : String; + payload : any; + desc : String; + debug : String; + note : String; + servertime : String; + ilsperm : String; + ilspermloc : Number; + success : Boolean = false; + + toString(): String { + let s = `Event: ${this.code}:${this.textcode} -> ${this.desc}`; + if (this.ilsperm) + s += ` ${this.ilsperm}@${this.ilspermloc}`; + if (this.note) + s += `\n${this.note}`; + return s; + } + + /** + * Returns an EgEvent if 'thing' is an event, null otherwise. + */ + public static parse(thing: any): EgEvent { + + // All events have a textcode + if (thing && typeof thing == 'object' && 'textcode' in thing) { + + let evt = new EgEvent(); + + ['textcode','payload','desc','note','servertime','ilsperm'] + .forEach(field => { evt[field] = thing[field]; }); + + evt.debug = thing.stacktrace; + evt.code = new Number(thing.code); + evt.ilspermloc = new Number(thing.ilspermloc); + evt.success = thing.textcode == 'SUCCESS'; + + return evt; + } + + return null; + } +} + 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 new file mode 100644 index 0000000000..428d59a1b1 --- /dev/null +++ b/Open-ILS/webby-src/src/app/core/eg-net-request.ts @@ -0,0 +1,20 @@ +import { EgEvent } from './eg-event'; + +public class EgNetRequest { + service : String; + method : String; + params : any[]; + observer : Observer; + 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; + } +} diff --git a/Open-ILS/webby-src/src/app/core/eg-net.service.ts b/Open-ILS/webby-src/src/app/core/eg-net.service.ts new file mode 100644 index 0000000000..c272c673eb --- /dev/null +++ b/Open-ILS/webby-src/src/app/core/eg-net.service.ts @@ -0,0 +1,117 @@ +/** + * + * constructor(private egNet : EgNetService) { + * ... + * egNet.request(service, method, param1 [, param2, ...]) + * .subscribe( + * (res) => console.log('received one resopnse: ' + res), + * (err) => console.error('recived request error: ' + err), + * () => console.log('request complete') + * ) + * ); + * ... + * } + * + * Each response is relayed via Observable onNext(). The interface is + * the same for streaming and atomic requests. + */ +import { Injectable } from '@angular/core'; +import { Observable, Observer, EventEmitter } 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; + +@Injectable() +export class EgNetService { + + public permFailed$: EventEmitter; + public authExpired$: EventEmitter; + + // If true, permission failures are emitted via permFailed$ + // and the active request is marked as superseded. + public permFailedHasHandler: Boolean = false; + + constructor() { + this.permFailed$ = new EventEmitter(); + this.authExpired$ = new EventEmitter(); + } + + // Variadic params version + request(service: String, method: String, ...params: any[]): Observable { + return this.request(service, method, params); + } + + // Array params version + request(service: String, method: String, params: any[]): Observable { + var request = new EgNetRequest(service, method, params); + + return Observable.create( + observer => { + request.observer = observer; + this.sendRequest(request); + } + ); + } + + private sendRequest(request: EgNetRequest): void { + OpenSRF.Session.transport = OSRF_TRANSPORT_TYPE_WS; + + new OpenSRF.ClientSession(request.service).request({ + async : true, + method : request.method, + params : request.params, + oncomplete : function() { + // A superseded request will be complete()'ed by the + // superseder at a later time. + if (!request.superseded) + request.observer.complete(); + }, + onresponse : function(r) { + this.dispatchResponse(request, r.recv().content()); + }, + onerror : function(msg) { + let msg = `${request.method} failed! See server logs.`; + console.error(msg); + request.observer.error(msg); + }, + onmethoderror : function(req, statCode, statMsg) { + let msg = + `${request.method} failed! stat=${statCode} msg=${statMsg}`; + console.error(msg); + request.observer.error(msg); + } + + }).send(); + } + + // Relay response object to the caller for typical/successful responses. + // Applies special handling to response events that require global attention. + private dispatchResponse = function(request, response) { + request.evt = EgEvent.parse(response); + + if (request.evt) { + switch(request.evt.textcode) { + + case 'NO_SESSION': + console.debug(`EgNet emitting event: ${request.evt}`); + request.observer.error(request.evt.toString()); + this.authExpired$.emit(request); + return; + + case 'PERM_FAILURE': + if (permFailedHasHandler) { + console.debug(`EgNet emitting event: ${request.evt}`); + request.superseded = true; + this.permFailed$.emit(request); + return; + } + } + } + + // Pass the response to the caller. + request.observer.next(response); + }; +} diff --git a/Open-ILS/webby-src/src/app/core/types/eg-event.ts b/Open-ILS/webby-src/src/app/core/types/eg-event.ts deleted file mode 100644 index 1561fedbb1..0000000000 --- a/Open-ILS/webby-src/src/app/core/types/eg-event.ts +++ /dev/null @@ -1,47 +0,0 @@ - -export class EgEvent { - code : Number; - textcode : String; - payload : any; - desc : String; - debug : String; - note : String; - servertime : String; - ilsperm : String; - ilspermloc : Number; - success : Boolean = false; - - toString(): String { - let s = `Event: ${this.code}:${this.textcode} -> ${this.desc}`; - if (this.ilsperm) - s += ` ${this.ilsperm}@${this.ilspermloc}`; - if (this.note) - s += `\n${this.note}`; - return s; - } - - /** - * Returns an EgEvent if 'thing' is an event, null otherwise. - */ - public static parse(thing: any): EgEvent { - - // All events have a textcode - if (thing && typeof thing == 'object' && 'textcode' in thing) { - - let evt = new EgEvent(); - - ['textcode','payload','desc','note','servertime','ilsperm'] - .forEach(field => { evt[field] = thing[field]; }); - - evt.debug = thing.stacktrace; - evt.code = new Number(thing.code); - evt.ilspermloc = new Number(thing.ilspermloc); - evt.success = thing.textcode == 'SUCCESS'; - - return evt; - } - - return null; - } -} -