changeset 74:2c3fe51ad1f0

Wire up methods in the FeatureExtractionService for offloading to the worker and consume them from the feature extraction menu.
author Lucas Thompson <dev@lucas.im>
date Wed, 18 Jan 2017 10:19:35 +0000
parents d3abd81e8ab6
children 8aa6830ea41d
files src/app/feature-extraction-menu/feature-extraction-menu.component.ts src/app/services/feature-extraction/feature-extraction.service.ts
diffstat 2 files changed, 64 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/app/feature-extraction-menu/feature-extraction-menu.component.ts	Wed Jan 18 10:18:35 2017 +0000
+++ b/src/app/feature-extraction-menu/feature-extraction-menu.component.ts	Wed Jan 18 10:19:35 2017 +0000
@@ -1,5 +1,10 @@
-import {Component, OnInit, Output, EventEmitter, Input} from '@angular/core';
+import {
+  Component, OnInit, Output, EventEmitter, Input,
+  OnDestroy
+} from '@angular/core';
 import {FeatureExtractionService} from "../services/feature-extraction/feature-extraction.service";
+import {ListResponse} from "piper";
+import {Subscription} from "rxjs";
 
 export interface ExtractorOutputInfo {
   extractorKey: string;
@@ -13,7 +18,7 @@
   templateUrl: './feature-extraction-menu.component.html',
   styleUrls: ['./feature-extraction-menu.component.css']
 })
-export class FeatureExtractionMenuComponent implements OnInit {
+export class FeatureExtractionMenuComponent implements OnInit, OnDestroy {
 
   @Input()
   set disabled(isDisabled: boolean) {
@@ -28,17 +33,16 @@
 
   private isDisabled: boolean;
   private extractorsMap: Map<string, ExtractorOutputInfo>;
+  private populateExtractors: (available: ListResponse) => void;
   extractors: Iterable<ExtractorOutputInfo>;
+  private librariesUpdatedSubscription: Subscription;
 
   constructor(private piperService: FeatureExtractionService) {
     this.extractorsMap = new Map();
     this.extractors = [];
     this.requestOutput = new EventEmitter<ExtractorOutputInfo>();
     this.isDisabled = true;
-  }
-
-  ngOnInit() {
-    this.piperService.list().then(available => {
+    this.populateExtractors = available => {
       const maxCharacterLimit = 50;
       available.available.forEach(staticData => {
         const isSingleOutputExtractor = staticData.basicOutputInfo.length === 1;
@@ -57,11 +61,25 @@
         });
       });
       this.extractors = [...this.extractorsMap.values()];
-    });
+    };
+  }
+
+  ngOnInit() {
+    this.piperService.list().then(this.populateExtractors);
+    this.librariesUpdatedSubscription = this.piperService.librariesUpdated$.subscribe(this.populateExtractors);
   }
 
   extract(combinedKey: string): void {
     this.requestOutput.emit(this.extractorsMap.get(combinedKey));
   }
 
+  load(): void {
+    this.piperService.updateAvailableLibraries().subscribe(res => {
+      Object.keys(res).forEach(key => this.piperService.load(key));
+    });
+  }
+
+  ngOnDestroy(): void {
+    this.librariesUpdatedSubscription.unsubscribe();
+  }
 }
--- a/src/app/services/feature-extraction/feature-extraction.service.ts	Wed Jan 18 10:18:35 2017 +0000
+++ b/src/app/services/feature-extraction/feature-extraction.service.ts	Wed Jan 18 10:19:35 2017 +0000
@@ -1,4 +1,4 @@
-import {Injectable} from '@angular/core';
+import {Injectable, Inject} from '@angular/core';
 import {
   ListResponse, ListRequest
 } from "piper";
@@ -7,6 +7,7 @@
 } from "piper/HigherLevelUtilities";
 import {Subject} from "rxjs/Subject";
 import {Observable} from "rxjs";
+import {Http, Response} from "@angular/http";
 
 interface RequestMessage<RequestType> {
   method: string;
@@ -18,17 +19,33 @@
   result: ResponseType;
 }
 
+type RepoUri = string;
+export interface AvailableLibraries {
+  [libraryKey: string]: RepoUri;
+}
+
 @Injectable()
 export class FeatureExtractionService {
 
   private worker: Worker;
   private featuresExtracted: Subject<SimpleResponse>;
   featuresExtracted$: Observable<SimpleResponse>;
+  private librariesUpdated: Subject<ListResponse>;
+  librariesUpdated$: Observable<ListResponse>;
 
-  constructor() {
+  constructor(private http: Http, @Inject('PiperRepoUri') private repositoryUri: RepoUri) {
     this.worker = new Worker('bootstrap-feature-extraction-worker.js');
     this.featuresExtracted = new Subject<SimpleResponse>();
     this.featuresExtracted$ = this.featuresExtracted.asObservable();
+    this.librariesUpdated = new Subject<ListResponse>();
+    this.librariesUpdated$ = this.librariesUpdated.asObservable();
+    this.worker.addEventListener('message', (ev: MessageEvent) => {
+      const isValidResponse = ev.data.method === 'import'
+        && ev.data.result.available !== undefined;
+      if (isValidResponse) {
+        this.librariesUpdated.next(ev.data.result);
+      }
+    });
   }
 
   list(): Promise<ListResponse> {
@@ -58,6 +75,26 @@
     });
   }
 
+  updateAvailableLibraries(): Observable<AvailableLibraries> {
+    return this.http.get(this.repositoryUri)
+      .map(res => {
+        const map = res.json();
+        this.worker.postMessage({
+          method: 'addRemoteLibraries',
+          params: map
+        });
+        return map;
+      })
+      .catch((error: Response | any) => {
+        console.error(error);
+        return Observable.throw(error);
+      });
+  }
+
+  load(libraryKey: string): void {
+    this.worker.postMessage({method: 'import', params: libraryKey});
+  }
+
   private request<Req, Res>(request: RequestMessage<Req>,
                             predicate: (ev: MessageEvent) => boolean)
   : Promise<ResponseMessage<Res>> {