3 * Copyright (C) 2017-2018 "IoT.bzh"
4 * Author Sebastien Douheret <sebastien@iot.bzh>
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 import { Component, ViewEncapsulation, AfterViewChecked, ElementRef, ViewChild, OnInit, Input } from '@angular/core';
20 import { Observable } from 'rxjs/Observable';
21 import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms';
22 import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
24 import 'rxjs/add/operator/scan';
25 import 'rxjs/add/operator/startWith';
27 import { BuildSettingsModalComponent } from './build-settings-modal/build-settings-modal.component';
29 import { XDSAgentService, ICmdOutput } from '../../@core-xds/services/xdsagent.service';
30 import { ProjectService, IProject } from '../../@core-xds/services/project.service';
31 import { AlertService, IAlert } from '../../@core-xds/services/alert.service';
32 import { SdkService } from '../../@core-xds/services/sdk.service';
35 selector: 'xds-panel-build',
36 templateUrl: './build.component.html',
37 styleUrls: ['./build.component.scss'],
38 encapsulation: ViewEncapsulation.None,
41 export class BuildComponent implements OnInit, AfterViewChecked {
42 @ViewChild('scrollOutput') private scrollContainer: ElementRef;
44 // FIXME workaround of https://github.com/angular/angular-cli/issues/2034
45 // should be removed with angular 5
46 // @Input() curProject: IProject;
47 @Input() curProject = <IProject>null;
49 public buildIsCollapsed = false;
50 public cmdOutput: string;
51 public cmdInfo: string;
52 public curPrj: IProject;
54 private startTime: Map<string, number> = new Map<string, number>();
57 private prjSvr: ProjectService,
58 private xdsSvr: XDSAgentService,
59 private alertSvr: AlertService,
60 private sdkSvr: SdkService,
61 private modalService: NgbModal,
64 this.cmdInfo = ''; // TODO: to be remove (only for debug)
68 // Retreive current project
69 this.prjSvr.curProject$.subscribe(p => this.curPrj = p);
71 // Command output data tunneling
72 this.xdsSvr.CmdOutput$.subscribe(data => {
73 this.cmdOutput += data.stdout;
74 this.cmdOutput += data.stderr;
78 this.xdsSvr.CmdExit$.subscribe(exit => {
79 if (this.startTime.has(exit.cmdID)) {
80 this.cmdInfo = 'Last command duration: ' + this._computeTime(this.startTime.get(exit.cmdID));
81 this.startTime.delete(exit.cmdID);
84 if (exit && exit.code !== 0) {
85 this.cmdOutput += '--- Command exited with code ' + exit.code + ' ---\n\n';
89 this._scrollToBottom();
92 ngAfterViewChecked() {
93 this._scrollToBottom();
100 isSetupValid(): boolean {
101 return (typeof this.curPrj !== 'undefined');
105 if (!this.isSetupValid()) {
106 return this.alertSvr.warning('Please select first a valid project.', true);
108 const modal = this.modalService.open(
109 BuildSettingsModalComponent,
110 { size: 'lg', container: 'nb-layout' },
114 execCmd(cmdName: string) {
115 if (!this.isSetupValid()) {
116 return this.alertSvr.warning('Please select first a valid project.', true);
119 if (!this.curPrj.uiSettings) {
120 return this.alertSvr.warning('Invalid setting structure', true);
126 cmd = this.curPrj.uiSettings.cmdClean;
129 cmd = this.curPrj.uiSettings.cmdPrebuild;
132 cmd = this.curPrj.uiSettings.cmdBuild;
135 cmd = this.curPrj.uiSettings.cmdPopulate;
138 if (this.curPrj.uiSettings.cmdArgs instanceof Array) {
139 cmd = this.curPrj.uiSettings.cmdArgs.join(' ');
141 cmd = this.curPrj.uiSettings.cmdArgs;
145 return this.alertSvr.warning('Unknown command name ' + cmdName);
148 const prjID = this.curPrj.id;
149 const dir = this.curPrj.uiSettings.subpath;
150 const args: string[] = [];
151 const sdkid = this.sdkSvr.getCurrentId();
154 if (this.curPrj.uiSettings.envVars instanceof Array) {
155 env = this.curPrj.uiSettings.envVars.join(' ');
157 env = this.curPrj.uiSettings.envVars;
160 this.cmdOutput += this._outputHeader();
162 // Detect key=value in env string to build array of string
164 env.split(';').forEach(v => envArr.push(v.trim()));
166 const t0 = performance.now();
167 this.cmdInfo = 'Start build of ' + prjID + ' at ' + t0;
169 this.xdsSvr.exec(prjID, dir, cmd, sdkid, args, envArr)
171 this.startTime.set(String(res.cmdID), t0);
174 this.cmdInfo = 'Last command duration: ' + this._computeTime(t0);
175 this.alertSvr.error('ERROR: ' + err);
179 private _scrollToBottom(): void {
181 this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
185 private _computeTime(t0: number, t1?: number): string {
186 const enlap = Math.round((t1 || performance.now()) - t0);
187 if (enlap < 1000.0) {
188 return enlap.toFixed(2) + ' ms';
190 return (enlap / 1000.0).toFixed(3) + ' seconds';
194 private _outputHeader(): string {
195 return '--- ' + new Date().toString() + ' ---\n';
198 private _outputFooter(): string {