Prevent browser freeze on WS data flooding.
[src/xds/xds-agent.git] / webapp / src / app / pages / sdks / sdk-management / sdk-install.component.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 { Component, OnInit, Input, ViewChild, AfterViewChecked, ElementRef } from '@angular/core';
20 import { DomSanitizer } from '@angular/platform-browser';
21 import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
22
23 import { AlertService } from '../../../@core-xds/services/alert.service';
24 import { SdkService, ISdk } from '../../../@core-xds/services/sdk.service';
25
26 import 'rxjs/add/operator/bufferTime';
27
28 @Component({
29   selector: 'xds-sdk-install-modal',
30   template: `
31   <div tabindex="-1">
32     <div class="modal-header">
33       SDK installation
34     </div>
35
36     <div class="modal-body row">
37       <div class="col-12 text-center">
38         Installation of <b> {{ sdk?.name }} '</b> <span [innerHTML]="instStatus"></span>
39       </div>
40       <br>
41       <br>
42       <div class="col-12 text-center">
43         <textarea rows="20" class="textarea-scroll" #scrollOutput [innerHtml]="installOutput"></textarea>
44       </div>
45       <div class="col-12 text-center">
46         <button type="button" class="btn" tabindex="1"
47         [ngClass]="(btnName=='Cancel')?'btn-default':'btn-primary'"
48         (click)="onBtnClick()">{{ btnName }}</button>
49       </div>
50     </div>
51
52     <!-- <div *ngIf="footer!=''" class="modal-footer">
53       <div class="col-12 text-center">
54       </div>
55     </div> -->
56   </div>
57   `,
58   styles: [`
59     .btn {
60       margin-top: 2em;
61       min-width: 10em;
62     }
63     .textarea-scroll {
64       font-family: monospace;
65       width: 100%;
66       overflow-y: scroll;
67   `],
68 })
69
70 export class SdkInstallComponent implements OnInit {
71   @Input() sdk;
72   @ViewChild('scrollOutput') private scrollContainer: ElementRef;
73
74   constructor(
75     private modalRef: NgbActiveModal,
76     private sanitizer: DomSanitizer,
77     private alert: AlertService,
78     private sdkSvr: SdkService,
79   ) { }
80
81   onInstallSub: any;
82   installOutput = '';
83   btnName = 'Cancel';
84   instStatus = '';
85
86   ngOnInit() {
87     this.instStatus = 'in progress...';
88
89     this.onInstallSub = this.sdkSvr.onInstall()
90       .bufferTime(500)  // prevent browser freeze
91       .subscribe(evts => {
92         let out = '';
93         evts.forEach(ev => {
94           if (ev.exited) {
95             this.btnName = 'OK';
96             this.instStatus = '<font color="green"> Done. </font>';
97
98             if (ev.code === 0) {
99               this.alert.info('SDK ' + ev.sdk.name + ' successfully installed.');
100
101             } else {
102               if (ev.sdk.lastError !== '') {
103                 this.alert.error(ev.sdk.lastError);
104               } else {
105                 this.alert.error('SDK ' + ev.sdk.name + ' installation failed. ' + ev.error);
106               }
107             }
108
109           } else {
110             if (ev.stdout !== '') {
111               out += ev.stdout;
112             }
113             if (ev.stderr !== '') {
114               out += ev.stderr;
115             }
116           }
117         });
118         if (out !== '') {
119           this.installOutput += out;
120           this._scrollToBottom();
121         }
122       });
123   }
124
125   onBtnClick(): void {
126     this.onInstallSub.unsubscribe();
127     if (this.btnName === 'Cancel') {
128       this.btnName = 'OK';
129       this.instStatus = '<b><font color="red"> ABORTED </font></b>';
130       this.sdkSvr.abortInstall(this.sdk).subscribe(r => { }, err => this.alert.error(err));
131     } else {
132       this.modalRef.close();
133     }
134   }
135
136   private _scrollToBottom(): void {
137     try {
138       this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
139     } catch (err) { }
140   }
141 }