f854744525846e90efa92f05928a70b12f32ddce
[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           this.current = this._sdksList[0];
107           this.curSdkSubject.next(this.current);
108         }
109
110         this.sdksSubject.next(this._sdksList);
111       });
112     });
113
114     // Add listener on sdk creation, deletion and change events
115     this.xdsSvr.onSdkAdd().subscribe(sdk => this._addUpdateSdk(sdk));
116     this.xdsSvr.onSdkChange().subscribe(sdk => this._addUpdateSdk(sdk));
117
118     this.xdsSvr.onSdkRemove().subscribe(sdk => {
119       if (sdk.status !== StatusType.NOT_INSTALLED) {
120         /* tslint:disable:no-console */
121         console.log('Error: received event:sdk-remove with invalid status: sdk=', sdk);
122         return;
123       }
124       this._delSdk(sdk);
125     });
126   }
127
128   public setCurrent(s: ISdk) {
129     this.current = s;
130   }
131
132   public getCurrent(): ISdk {
133     return this.current;
134   }
135
136   public getCurrentId(): string {
137     if (this.current && this.current.id) {
138       return this.current.id;
139     }
140     return '';
141   }
142
143   public install(sdk: ISdk): Observable<ISdk> {
144     return this.xdsSvr.installSdk(this.curServerID, sdk.id);
145   }
146
147   public onInstall(): Observable<ISdkManagementMsg> {
148     return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'installing');
149   }
150
151   public onRemove(): Observable<ISdkManagementMsg> {
152     return this.xdsSvr.onSdkManagement().filter(ev => ev.action === 'removing');
153   }
154
155   public abortInstall(sdk: ISdk): Observable<ISdk> {
156     return this.xdsSvr.abortInstall(this.curServerID, sdk.id);
157   }
158
159   public remove(sdk: ISdk): Observable<ISdk> {
160     return this.xdsSvr.removeSdk(this.curServerID, sdk.id);
161   }
162
163   /** Private **/
164
165   private _addUpdateSdk(sdk: ISdk, noNext?: boolean): ISdk {
166
167     // check if sdk already exists
168     const idx = this._sdksList.findIndex(s => s.id === sdk.id);
169     if (idx >= 0) {
170       // Just update existing one
171       this._sdksList[idx] = sdk;
172     } else {
173       // add new sdk
174       this._sdksList.push(sdk);
175
176       // sort sdk array
177       this._sdksList.sort((a, b) => {
178         if (a.name < b.name) {
179           return -1;
180         }
181         if (a.name > b.name) {
182           return 1;
183         }
184         return 0;
185       });
186     }
187
188     if (!noNext) {
189       this.sdksSubject.next(this._sdksList);
190     }
191
192     return sdk;
193   }
194
195   private _delSdk(sdk: ISdk) {
196     const idx = this._sdksList.findIndex(item => item.id === sdk.id);
197     if (idx === -1) {
198       if (isDevMode) {
199         /* tslint:disable:no-console */
200         console.log('Warning: Try to delete sdk unknown id: sdk=', sdk);
201       }
202       return;
203     }
204     const delId = this._sdksList[idx].id;
205     this._sdksList.splice(idx, 1);
206     if (delId === this.current.id) {
207       this.setCurrent(this._sdksList[0]);
208     }
209     this.sdksSubject.next(this._sdksList);
210   }
211
212 }