f7e8c2f5e2e8fe300840adf9f96dde43cd35892a
[src/xds/xds-agent.git] / webapp / src / app / @core-xds / services / sdk.service.ts
1 /**
2 * @license
3 * Copyright (C) 2017-2018 "IoT.bzh"
4 * Author Sebastien Douheret <sebastien@iot.bzh>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 import { Injectable, SecurityContext, isDevMode } from '@angular/core';
20 import { Observable } from 'rxjs/Observable';
21 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
22
23 import { XDSAgentService } from '../services/xdsagent.service';
24
25 import 'rxjs/add/observable/throw';
26
27 /* FIXME: syntax only compatible with TS>2.4.0
28 export enum StatusType {
29   DISABLE = 'Disable',
30   NOT_INSTALLED = 'Not Installed',
31   INSTALLING = 'Installing',
32   UNINSTALLING = 'Un-installing',
33   INSTALLED = 'Installed'
34 }
35 */
36 export type StatusTypeEnum = 'Disable' | 'Not Installed' | 'Installing' | 'Un-installing' | 'Installed';
37 export const StatusType = {
38   DISABLE: 'Disable',
39   NOT_INSTALLED: 'Not Installed',
40   INSTALLING: 'Installing',
41   UNINSTALLING: 'Un-installing',
42   INSTALLED: 'Installed',
43 };
44
45 export interface ISdk {
46   id: string;
47   name: string;
48   description: string;
49   profile: string;
50   version: string;
51   arch: string;
52   path: string;
53   url: string;
54   status: string;
55   date: string;
56   size: string;
57   md5sum: string;
58   setupFile: string;
59   lastError: string;
60 }
61
62 export interface ISdkManagementMsg {
63   cmdID: string;
64   timestamp: string;
65   action: string;
66   sdk: ISdk;
67   stdout: string;
68   stderr: string;
69   progress: number;
70   exited: boolean;
71   code: number;
72   error: string;
73 }
74
75 @Injectable()
76 export class SdkService {
77   public Sdks$: Observable<ISdk[]>;
78   public curSdk$: Observable<ISdk>;
79
80   private _sdksList = [];
81   private sdksSubject = <BehaviorSubject<ISdk[]>>new BehaviorSubject(this._sdksList);
82   private current: ISdk;
83   private curSdkSubject = <BehaviorSubject<ISdk>>new BehaviorSubject(this.current);
84   private curServerID;
85
86   constructor(private xdsSvr: XDSAgentService) {
87     this.current = null;
88     this.Sdks$ = this.sdksSubject.asObservable();
89     this.curSdk$ = this.curSdkSubject.asObservable();
90
91     this.xdsSvr.XdsConfig$.subscribe(cfg => {
92       if (!cfg || cfg.servers.length < 1) {
93         return;
94       }
95       // FIXME support multiple server
96       // cfg.servers.forEach(svr => {
97       this.curServerID = cfg.servers[0].id;
98       this.xdsSvr.getSdks(this.curServerID).subscribe((sdks) => {
99         this._sdksList = [];
100         sdks.forEach(s => {
101           this._addUpdateSdk(s, true);
102         });
103
104         // TODO: get previous val from xds-config service / cookie
105         if (this._sdksList.length > 0) {
106           const installedSdks = this._sdksList.filter(sd => sd.status === StatusType.INSTALLED);
107           this.current = installedSdks.length > 0 ? installedSdks[0] : this._sdksList[0];
108           this.curSdkSubject.next(this.current);
109         }
110
111         this.sdksSubject.next(this._sdksList);
112       });
113     });
114
115     // Add listener on sdk creation, deletion and change events
116     this.xdsSvr.onSdkAdd().subscribe(sdk => this._addUpdateSdk(sdk));
117     this.xdsSvr.onSdkChange().subscribe(sdk => this._addUpdateSdk(sdk));
118
119     this.xdsSvr.onSdkRemove().subscribe(sdk => {
120       if (sdk.status !== StatusType.NOT_INSTALLED) {
121         /* tslint:disable:no-console */
122         console.log('Error: received event:sdk-remove with invalid status: sdk=', sdk);
123         return;
124       }
125       this._delSdk(sdk);
126     });
127   }
128
129   public setCurrent(s: ISdk) {
130     this.current = s;
131   }
132
133   public getCurrent(): ISdk {
134     return this.current;
135   }
136
137   public getCurrentId(): string {
138     if (this.current && this.current.id) {
139       return this.current.id;
140     }
141     return '';
142   }
143
144   public install(sdk: ISdk): Observable<ISdk> {
145     return this.xdsSvr.installSdk(this.curServerID, sdk.id);
146   }
147
148   public onInstall(): Observable<ISdkManagementMsg> {
149     return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'installing');
150   }
151
152   public onRemove(): Observable<ISdkManagementMsg> {
153     return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'removing');
154   }
155
156   public abortInstall(sdk: ISdk): Observable<ISdk> {
157     return this.xdsSvr.abortInstall(this.curServerID, sdk.id);
158   }
159
160   public remove(sdk: ISdk): Observable<ISdk> {
161     return this.xdsSvr.removeSdk(this.curServerID, sdk.id);
162   }
163
164   /** Private **/
165
166   private _addUpdateSdk(sdk: ISdk, noNext?: boolean): ISdk {
167
168     // check if sdk already exists
169     const idx = this._sdksList.findIndex(s => s.id === sdk.id);
170     if (idx >= 0) {
171       // Just update existing one
172       this._sdksList[idx] = sdk;
173     } else {
174       // add new sdk
175       this._sdksList.push(sdk);
176
177       // sort sdk array
178       this._sdksList.sort((a, b) => {
179         if (a.name < b.name) {
180           return -1;
181         }
182         if (a.name > b.name) {
183           return 1;
184         }
185         return 0;
186       });
187     }
188
189     if (!noNext) {
190       this.sdksSubject.next(this._sdksList);
191     }
192
193     return sdk;
194   }
195
196   private _delSdk(sdk: ISdk) {
197     const idx = this._sdksList.findIndex(item => item.id === sdk.id);
198     if (idx === -1) {
199       if (isDevMode) {
200         /* tslint:disable:no-console */
201         console.log('Warning: Try to delete sdk unknown id: sdk=', sdk);
202       }
203       return;
204     }
205     const delId = this._sdksList[idx].id;
206     this._sdksList.splice(idx, 1);
207     if (delId === this.current.id) {
208       this.setCurrent(this._sdksList[0]);
209     }
210     this.sdksSubject.next(this._sdksList);
211   }
212
213 }