Add Image Path
[src/xds/xds-agent.git] / webapp / src / app / @core-xds / services / sdk.service.ts
index d1daa86..0ad5d0f 100644 (file)
@@ -1,4 +1,22 @@
-import { Injectable, SecurityContext } from '@angular/core';
+/**
+* @license
+* Copyright (C) 2017-2018 "IoT.bzh"
+* Author Sebastien Douheret <sebastien@iot.bzh>
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { Injectable, SecurityContext, isDevMode } from '@angular/core';
 import { Observable } from 'rxjs/Observable';
 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
 
@@ -6,61 +24,190 @@ import { XDSAgentService } from '../services/xdsagent.service';
 
 import 'rxjs/add/observable/throw';
 
+/* FIXME: syntax only compatible with TS>2.4.0
+export enum StatusType {
+  DISABLE = 'Disable',
+  NOT_INSTALLED = 'Not Installed',
+  INSTALLING = 'Installing',
+  UNINSTALLING = 'Un-installing',
+  INSTALLED = 'Installed'
+}
+*/
+export type StatusTypeEnum = 'Disable' | 'Not Installed' | 'Installing' | 'Un-installing' | 'Installed';
+export const StatusType = {
+  DISABLE: 'Disable',
+  NOT_INSTALLED: 'Not Installed',
+  INSTALLING: 'Installing',
+  UNINSTALLING: 'Un-installing',
+  INSTALLED: 'Installed',
+};
+
 export interface ISdk {
-    id: string;
-    profile: string;
-    version: string;
-    arch: number;
-    path: string;
+  id: string;
+  name: string;
+  description: string;
+  profile: string;
+  version: string;
+  arch: string;
+  path: string;
+  url: string;
+  image_url: string;
+  status: string;
+  date: string;
+  size: string;
+  md5sum: string;
+  setupFile: string;
+  lastError: string;
+}
+
+export interface ISdkManagementMsg {
+  cmdID: string;
+  timestamp: string;
+  action: string;
+  sdk: ISdk;
+  stdout: string;
+  stderr: string;
+  progress: number;
+  exited: boolean;
+  code: number;
+  error: string;
 }
 
 @Injectable()
 export class SdkService {
-    public Sdks$: Observable<ISdk[]>;
-
-    private _sdksList = [];
-    private current: ISdk;
-    private sdksSubject = <BehaviorSubject<ISdk[]>>new BehaviorSubject(this._sdksList);
-
-    constructor(private xdsSvr: XDSAgentService) {
-        this.current = null;
-        this.Sdks$ = this.sdksSubject.asObservable();
-
-        this.xdsSvr.XdsConfig$.subscribe(cfg => {
-            if (!cfg || cfg.servers.length < 1) {
-                return;
-            }
-            // FIXME support multiple server
-            // cfg.servers.forEach(svr => {
-            this.xdsSvr.getSdks(cfg.servers[0].id).subscribe((s) => {
-                this._sdksList = s;
-                this.sdksSubject.next(s);
-            });
+  public Sdks$: Observable<ISdk[]>;
+  public curSdk$: Observable<ISdk>;
+
+  private _sdksList = [];
+  private sdksSubject = <BehaviorSubject<ISdk[]>>new BehaviorSubject(this._sdksList);
+  private current: ISdk;
+  private curSdkSubject = <BehaviorSubject<ISdk>>new BehaviorSubject(this.current);
+  private curServerID;
+
+  constructor(private xdsSvr: XDSAgentService) {
+    this.current = null;
+    this.Sdks$ = this.sdksSubject.asObservable();
+    this.curSdk$ = this.curSdkSubject.asObservable();
+
+    this.xdsSvr.XdsConfig$.subscribe(cfg => {
+      if (!cfg || cfg.servers.length < 1) {
+        return;
+      }
+      // FIXME support multiple server
+      // cfg.servers.forEach(svr => {
+      this.curServerID = cfg.servers[0].id;
+      this.xdsSvr.getSdks(this.curServerID).subscribe((sdks) => {
+        this._sdksList = [];
+        sdks.forEach(s => {
+          this._addUpdateSdk(s, true);
         });
-    }
 
-    public setCurrent(s: ISdk) {
-        this.current = s;
-    }
+        // TODO: get previous val from xds-config service / cookie
+        if (this._sdksList.length > 0) {
+          const installedSdks = this._sdksList.filter(sd => sd.status === StatusType.INSTALLED);
+          this.current = installedSdks.length > 0 ? installedSdks[0] : this._sdksList[0];
+          this.curSdkSubject.next(this.current);
+        }
+        this.sdksSubject.next(this._sdksList);
+      });
+    });
+
+    // Add listener on sdk creation, deletion and change events
+    this.xdsSvr.onSdkAdd().subscribe(sdk => this._addUpdateSdk(sdk));
+    this.xdsSvr.onSdkChange().subscribe(sdk => this._addUpdateSdk(sdk));
+
+    this.xdsSvr.onSdkRemove().subscribe(sdk => {
+      if (sdk.status !== StatusType.NOT_INSTALLED) {
+        /* tslint:disable:no-console */
+        console.log('Error: received event:sdk-remove with invalid status: sdk=', sdk);
+        return;
+      }
+      this._delSdk(sdk);
+    });
+  }
+
+  public setCurrent(s: ISdk) {
+    this.current = s;
+  }
 
-    public getCurrent(): ISdk {
-        return this.current;
+  public getCurrent(): ISdk {
+    return this.current;
+  }
+
+  public getCurrentId(): string {
+    if (this.current && this.current.id) {
+      return this.current.id;
     }
+    return '';
+  }
+
+  public install(sdk: ISdk): Observable<ISdk> {
+    return this.xdsSvr.installSdk(this.curServerID, sdk.id);
+  }
+
+  public onInstall(): Observable<ISdkManagementMsg> {
+    return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'installing');
+  }
+
+  public onRemove(): Observable<ISdkManagementMsg> {
+    return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'removing');
+  }
+
+  public abortInstall(sdk: ISdk): Observable<ISdk> {
+    return this.xdsSvr.abortInstall(this.curServerID, sdk.id);
+  }
+
+  public remove(sdk: ISdk): Observable<ISdk> {
+    return this.xdsSvr.removeSdk(this.curServerID, sdk.id);
+  }
+
+  /** Private **/
 
-    public getCurrentId(): string {
-        if (this.current && this.current.id) {
-            return this.current.id;
+  private _addUpdateSdk(sdk: ISdk, noNext?: boolean): ISdk {
+
+    // check if sdk already exists
+    const idx = this._sdksList.findIndex(s => s.id === sdk.id);
+    if (idx >= 0) {
+      // Just update existing one
+      this._sdksList[idx] = sdk;
+    } else {
+      // add new sdk
+      this._sdksList.push(sdk);
+
+      // sort sdk array
+      this._sdksList.sort((a, b) => {
+        if (a.name < b.name) {
+          return -1;
+        }
+        if (a.name > b.name) {
+          return 1;
         }
-        return '';
+        return 0;
+      });
     }
 
-    public add(sdk: ISdk): Observable<ISdk> {
-      // TODO SEB
-      return Observable.throw('Not implement yet');
+    if (!noNext) {
+      this.sdksSubject.next(this._sdksList);
     }
 
-    public delete(sdk: ISdk): Observable<ISdk> {
-      // TODO SEB
-      return Observable.throw('Not implement yet');
+    return sdk;
+  }
+
+  private _delSdk(sdk: ISdk) {
+    const idx = this._sdksList.findIndex(item => item.id === sdk.id);
+    if (idx === -1) {
+      if (isDevMode) {
+        /* tslint:disable:no-console */
+        console.log('Warning: Try to delete sdk unknown id: sdk=', sdk);
+      }
+      return;
+    }
+    const delId = this._sdksList[idx].id;
+    this._sdksList.splice(idx, 1);
+    if (delId === this.current.id) {
+      this.setCurrent(this._sdksList[0]);
     }
+    this.sdksSubject.next(this._sdksList);
+  }
+
 }