# HG changeset patch # User Lucas Thompson # Date 1484734775 0 # Node ID 2c3fe51ad1f0b57288ae94d6f4c309635b1f5ffe # Parent d3abd81e8ab6efbecb2c456399774f8b96022acc Wire up methods in the FeatureExtractionService for offloading to the worker and consume them from the feature extraction menu. diff -r d3abd81e8ab6 -r 2c3fe51ad1f0 src/app/feature-extraction-menu/feature-extraction-menu.component.ts --- 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; + private populateExtractors: (available: ListResponse) => void; extractors: Iterable; + private librariesUpdatedSubscription: Subscription; constructor(private piperService: FeatureExtractionService) { this.extractorsMap = new Map(); this.extractors = []; this.requestOutput = new EventEmitter(); 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(); + } } diff -r d3abd81e8ab6 -r 2c3fe51ad1f0 src/app/services/feature-extraction/feature-extraction.service.ts --- 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 { 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; featuresExtracted$: Observable; + private librariesUpdated: Subject; + librariesUpdated$: Observable; - constructor() { + constructor(private http: Http, @Inject('PiperRepoUri') private repositoryUri: RepoUri) { this.worker = new Worker('bootstrap-feature-extraction-worker.js'); this.featuresExtracted = new Subject(); this.featuresExtracted$ = this.featuresExtracted.asObservable(); + this.librariesUpdated = new Subject(); + 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 { @@ -58,6 +75,26 @@ }); } + updateAvailableLibraries(): Observable { + 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(request: RequestMessage, predicate: (ev: MessageEvent) => boolean) : Promise> {