diff options
Diffstat (limited to 'webapp/src/app/devel')
-rw-r--r-- | webapp/src/app/devel/build/build.component.css | 45 | ||||
-rw-r--r-- | webapp/src/app/devel/build/build.component.html | 74 | ||||
-rw-r--r-- | webapp/src/app/devel/build/build.component.ts | 198 | ||||
-rw-r--r-- | webapp/src/app/devel/deploy/deploy.component.css | 45 | ||||
-rw-r--r-- | webapp/src/app/devel/deploy/deploy.component.html | 31 | ||||
-rw-r--r-- | webapp/src/app/devel/deploy/deploy.component.ts | 63 | ||||
-rw-r--r-- | webapp/src/app/devel/devel.component.css | 14 | ||||
-rw-r--r-- | webapp/src/app/devel/devel.component.html | 36 | ||||
-rw-r--r-- | webapp/src/app/devel/devel.component.ts | 32 |
9 files changed, 538 insertions, 0 deletions
diff --git a/webapp/src/app/devel/build/build.component.css b/webapp/src/app/devel/build/build.component.css new file mode 100644 index 0000000..6784a9f --- /dev/null +++ b/webapp/src/app/devel/build/build.component.css @@ -0,0 +1,45 @@ +.vcenter { + display: inline-block; + vertical-align: middle; +} + +.blocks .btn-primary { + margin-left: 5px; + margin-right: 5px; + margin-top: 5px; + border-radius: 4px !important; +} + +.table-center { + width: 80%; + margin-left: auto; + margin-right: auto; +} + +.table-borderless>tbody>tr>td, +.table-borderless>tbody>tr>th, +.table-borderless>tfoot>tr>td, +.table-borderless>tfoot>tr>th, +.table-borderless>thead>tr>td, +.table-borderless>thead>tr>th { + border: none; +} + +.btn-large { + width: 10em; +} + +.fa-size-x2 { + font-size: 18px; +} + +.textarea-scroll { + width: 100%; + overflow-y: scroll; +} + +h2 { + font-family: sans-serif; + font-variant: small-caps; + font-size: x-large; +}
\ No newline at end of file diff --git a/webapp/src/app/devel/build/build.component.html b/webapp/src/app/devel/build/build.component.html new file mode 100644 index 0000000..f4be204 --- /dev/null +++ b/webapp/src/app/devel/build/build.component.html @@ -0,0 +1,74 @@ +<div class="panel panel-default"> + <div class="panel-heading"> + <h2 class="panel-title">Build</h2> + </div> + <div class="panel-body"> + <form [formGroup]="buildForm"> + <div class="col-xs-12"> + <table class="table table-borderless table-center"> + <tbody> + <tr> + <th>Cross SDK</th> + <td> + <!-- FIXME why not working ? + <sdk-select-dropdown [sdks]="(sdks$ | async)"></sdk-select-dropdown> + --> + <sdk-select-dropdown></sdk-select-dropdown> + </td> + </tr> + <tr> + <th>Project root path</th> + <td> <input type="text" disabled style="width:99%;" [value]="curProject && curProject.path"></td> + </tr> + <tr> + <th>Sub-path</th> + <td> <input type="text" style="width:99%;" formControlName="subpath"> </td> + </tr> + <tr> + <th>Command arguments</th> + <td> <input type="text" style="width:99%;" formControlName="cmdArgs"> </td> + </tr> + <tr> + <th>Env variables</th> + <td> <input type="text" style="width:99%;" formControlName="envVars"> </td> + </tr> + </tbody> + </table> + </div> + <div class="row"> + <div class="col-xs-12 text-center"> + <div class="btn-group blocks"> + <button class="btn btn-primary btn-large" (click)="preBuild()" [disabled]="!curProject">Pre-Build</button> + <button class="btn btn-primary btn-large" (click)="build()" [disabled]="!curProject">Build</button> + <button class="btn btn-primary btn-large" (click)="populate()" [disabled]="!curProject ">Populate</button> + <button *ngIf="debugEnable" class="btn btn-primary btn-large" (click)="execCmd()" [disabled]="!curProject ">Execute command</button> + <button *ngIf="debugEnable" class="btn btn-primary btn-large" (click)="make()" [disabled]="!curProject ">Make</button> + </div> + </div> + </div> + </form> + + <div style="margin-left: 2em; margin-right: 2em; "> + <div class="row "> + <div class="col-xs-10"> + <div class="row "> + <div class="col-xs-4"> + <label>Command Output</label> + </div> + <div class="col-xs-8" style="font-size:x-small; margin-top:5px;"> + {{ cmdInfo }} + </div> + </div> + </div> + <div class="col-xs-2"> + <button class="btn btn-link pull-right " (click)="reset() "><span class="fa fa-eraser fa-size-x2"></span></button> + </div> + </div> + <div class="row "> + <div class="col-xs-12 text-center "> + <textarea rows="20" class="textarea-scroll" #scrollOutput>{{ cmdOutput }}</textarea> + </div> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/webapp/src/app/devel/build/build.component.ts b/webapp/src/app/devel/build/build.component.ts new file mode 100644 index 0000000..b7003b1 --- /dev/null +++ b/webapp/src/app/devel/build/build.component.ts @@ -0,0 +1,198 @@ +import { Component, AfterViewChecked, ElementRef, ViewChild, OnInit, Input } from '@angular/core'; +import { Observable } from 'rxjs'; +import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms'; +import { CookieService } from 'ngx-cookie'; + +import 'rxjs/add/operator/scan'; +import 'rxjs/add/operator/startWith'; + +import { XDSServerService, ICmdOutput } from "../../services/xdsserver.service"; +import { ConfigService, IConfig, IProject } from "../../services/config.service"; +import { AlertService, IAlert } from "../../services/alert.service"; +import { SdkService } from "../../services/sdk.service"; + +@Component({ + selector: 'panel-build', + moduleId: module.id, + templateUrl: './build.component.html', + styleUrls: ['./build.component.css'] +}) + +export class BuildComponent implements OnInit, AfterViewChecked { + @ViewChild('scrollOutput') private scrollContainer: ElementRef; + + @Input() curProject: IProject; + + buildForm: FormGroup; + subpathCtrl = new FormControl("", Validators.required); + debugEnable: boolean = false; + + public cmdOutput: string; + public cmdInfo: string; + + private startTime: Map<string, number> = new Map<string, number>(); + + constructor(private configSvr: ConfigService, + private xdsSvr: XDSServerService, + private fb: FormBuilder, + private alertSvr: AlertService, + private sdkSvr: SdkService, + private cookie: CookieService, + ) { + this.cmdOutput = ""; + this.cmdInfo = ""; // TODO: to be remove (only for debug) + this.buildForm = fb.group({ + subpath: this.subpathCtrl, + cmdArgs: ["", Validators.nullValidator], + envVars: ["", Validators.nullValidator], + }); + } + + ngOnInit() { + // Command output data tunneling + this.xdsSvr.CmdOutput$.subscribe(data => { + this.cmdOutput += data.stdout + "\n"; + }); + + // Command exit + this.xdsSvr.CmdExit$.subscribe(exit => { + if (this.startTime.has(exit.cmdID)) { + this.cmdInfo = 'Last command duration: ' + this._computeTime(this.startTime.get(exit.cmdID)); + this.startTime.delete(exit.cmdID); + } + + if (exit && exit.code !== 0) { + this.cmdOutput += "--- Command exited with code " + exit.code + " ---\n\n"; + } + }); + + this._scrollToBottom(); + + // only use for debug + this.debugEnable = (this.cookie.get("debug_build") !== ""); + } + + ngAfterViewChecked() { + this._scrollToBottom(); + } + + reset() { + this.cmdOutput = ''; + } + + preBuild() { + this._exec( + "mkdir -p build && cd build && cmake ..", + this.buildForm.value.subpath, + [], + this.buildForm.value.envVars); + } + + build() { + this._exec( + "cd build && make", + this.buildForm.value.subpath, + this.buildForm.value.cmdArgs, + this.buildForm.value.envVars + ); + } + + populate() { + this._exec( + "SEB_TODO_script_populate", + this.buildForm.value.subpath, + [], // args + this.buildForm.value.envVars + ); + } + + execCmd() { + this._exec( + this.buildForm.value.cmdArgs, + this.buildForm.value.subpath, + [], + this.buildForm.value.envVars + ); + } + + private _exec(cmd: string, dir: string, args: string[], env: string) { + if (!this.curProject) { + this.alertSvr.warning('No active project', true); + } + + let prjID = this.curProject.id; + + this.cmdOutput += this._outputHeader(); + + let sdkid = this.sdkSvr.getCurrentId(); + + // Detect key=value in env string to build array of string + let envArr = []; + env.split(';').forEach(v => envArr.push(v.trim())); + + let t0 = performance.now(); + this.cmdInfo = 'Start build of ' + prjID + ' at ' + t0; + + this.xdsSvr.exec(prjID, dir, cmd, sdkid, args, envArr) + .subscribe(res => { + this.startTime.set(String(res.cmdID), t0); + }, + err => { + this.cmdInfo = 'Last command duration: ' + this._computeTime(t0); + this.alertSvr.error('ERROR: ' + err); + }); + } + + make(args: string) { + if (!this.curProject) { + this.alertSvr.warning('No active project', true); + } + + let prjID = this.curProject.id; + + this.cmdOutput += this._outputHeader(); + + let sdkid = this.sdkSvr.getCurrentId(); + + let argsArr = args ? args.split(' ') : this.buildForm.value.cmdArgs.split(' '); + + // Detect key=value in env string to build array of string + let envArr = []; + this.buildForm.value.envVars.split(';').forEach(v => envArr.push(v.trim())); + + let t0 = performance.now(); + this.cmdInfo = 'Start build of ' + prjID + ' at ' + t0; + + this.xdsSvr.make(prjID, this.buildForm.value.subpath, sdkid, argsArr, envArr) + .subscribe(res => { + this.startTime.set(String(res.cmdID), t0); + }, + err => { + this.cmdInfo = 'Last command duration: ' + this._computeTime(t0); + this.alertSvr.error('ERROR: ' + err); + }); + } + + private _scrollToBottom(): void { + try { + this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight; + } catch (err) { } + } + + private _computeTime(t0: number, t1?: number): string { + let enlap = Math.round((t1 || performance.now()) - t0); + if (enlap < 1000.0) { + return enlap.toFixed(2) + ' ms'; + } else { + return (enlap / 1000.0).toFixed(3) + ' seconds'; + } + } + + private _outputHeader(): string { + return "--- " + new Date().toString() + " ---\n"; + } + + private _outputFooter(): string { + return "\n"; + } +}
\ No newline at end of file diff --git a/webapp/src/app/devel/deploy/deploy.component.css b/webapp/src/app/devel/deploy/deploy.component.css new file mode 100644 index 0000000..c1b39d8 --- /dev/null +++ b/webapp/src/app/devel/deploy/deploy.component.css @@ -0,0 +1,45 @@ +.vcenter { + display: inline-block; + vertical-align: middle; +} + +.blocks .btn-primary { + margin-left: 5px; + margin-right: 5px; + margin-top: 5px; + border-radius: 4px !important; +} + +.table-center { + width: 99%; + margin-left: auto; + margin-right: auto; +} + +.table-borderless>tbody>tr>td, +.table-borderless>tbody>tr>th, +.table-borderless>tfoot>tr>td, +.table-borderless>tfoot>tr>th, +.table-borderless>thead>tr>td, +.table-borderless>thead>tr>th { + border: none; +} + +.btn-large { + width: 10em; +} + +.fa-size-x2 { + font-size: 18px; +} + +.textarea-scroll { + width: 100%; + overflow-y: scroll; +} + +h2 { + font-family: sans-serif; + font-variant: small-caps; + font-size: x-large; +}
\ No newline at end of file diff --git a/webapp/src/app/devel/deploy/deploy.component.html b/webapp/src/app/devel/deploy/deploy.component.html new file mode 100644 index 0000000..7a15fa6 --- /dev/null +++ b/webapp/src/app/devel/deploy/deploy.component.html @@ -0,0 +1,31 @@ +<div class="panel panel-default"> + <div class="panel-heading"> + <h2 class="panel-title">Deployment</h2> + </div> + <div class="panel-body"> + <form [formGroup]="deployForm"> + <div class="col-xs-12"> + <table class="table table-borderless table-center"> + <tbody> + <tr> + <th>Board IP</th> + <td> <input type="text" style="width:99%;" formControlName="boardIP" placeholder="1.2.3.4"> </td> + </tr> + <tr> + <th>File to deploy</th> + <td> <input type="text" style="width:99%;" formControlName="wgtFile"> </td> + </tr> + </tbody> + </table> + </div> + <div class="row"> + <div class="col-xs-12 text-center"> + <div class="btn-group blocks"> + <button class="btn btn-primary btn-large" (click)="deploy()" [disabled]="!curProject ">Deploy</button> + </div> + </div> + </div> + </form> + + </div> +</div>
\ No newline at end of file diff --git a/webapp/src/app/devel/deploy/deploy.component.ts b/webapp/src/app/devel/deploy/deploy.component.ts new file mode 100644 index 0000000..4dba256 --- /dev/null +++ b/webapp/src/app/devel/deploy/deploy.component.ts @@ -0,0 +1,63 @@ +import { Component, OnInit, Input } from "@angular/core"; +import { Observable } from 'rxjs'; +import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms'; + +import 'rxjs/add/operator/scan'; +import 'rxjs/add/operator/startWith'; + +import { XDSAgentService, IXDSDeploy } from "../../services/xdsagent.service"; +import { ConfigService, IConfig, IProject } from "../../services/config.service"; +import { AlertService, IAlert } from "../../services/alert.service"; +import { SdkService } from "../../services/sdk.service"; + +@Component({ + selector: 'panel-deploy', + moduleId: module.id, + templateUrl: './deploy.component.html', + styleUrls: ['./deploy.component.css'] +}) + +export class DeployComponent implements OnInit { + + @Input() curProject: IProject; + + deploying: boolean; + deployForm: FormGroup; + + constructor(private configSvr: ConfigService, + private xdsAgent: XDSAgentService, + private fb: FormBuilder, + private alert: AlertService, + ) { + this.deployForm = fb.group({ + boardIP: ["", Validators.nullValidator], + wgtFile: ["", Validators.nullValidator], + }); + } + + ngOnInit() { + this.deploying = false; + if (this.curProject && this.curProject.path) { + this.deployForm.patchValue({ wgtFile: this.curProject.path }); + } + } + + deploy() { + this.deploying = true; + + this.xdsAgent.deploy( + { + boardIP: this.deployForm.value.boardIP, + file: this.deployForm.value.wgtFile + } + ).subscribe(res => { + this.deploying = false; + }, err => { + this.deploying = false; + let msg = '<span>ERROR while deploying "' + this.deployForm.value.wgtFile + '"<br>'; + msg += err; + msg += '</span>'; + this.alert.error(msg); + }); + } +}
\ No newline at end of file diff --git a/webapp/src/app/devel/devel.component.css b/webapp/src/app/devel/devel.component.css new file mode 100644 index 0000000..40d6fec --- /dev/null +++ b/webapp/src/app/devel/devel.component.css @@ -0,0 +1,14 @@ +.table-center { + width: 60%; + margin-left: auto; + margin-right: auto; +} + +.table-borderless>tbody>tr>td, +.table-borderless>tbody>tr>th, +.table-borderless>tfoot>tr>td, +.table-borderless>tfoot>tr>th, +.table-borderless>thead>tr>td, +.table-borderless>thead>tr>th { + border: none; +} diff --git a/webapp/src/app/devel/devel.component.html b/webapp/src/app/devel/devel.component.html new file mode 100644 index 0000000..5950f51 --- /dev/null +++ b/webapp/src/app/devel/devel.component.html @@ -0,0 +1,36 @@ +<div class="row"> + <div class="col-md-8"> + <table class="table table-borderless table-center"> + <tbody> + <tr> + <th style="border: none;">Project</th> + <td> + <div class="btn-group" dropdown *ngIf="curPrj"> + <button dropdownToggle type="button" class="btn btn-primary dropdown-toggle" style="width: 20em;"> + {{curPrj.label}} <span class="caret" style="float: right; margin-top: 8px;"></span> + </button> + <ul *dropdownMenu class="dropdown-menu" role="menu"> + <li role="menuitem"><a class="dropdown-item" *ngFor="let prj of (config$ | async)?.projects" (click)="curPrj=prj">{{prj.label}}</a> + </li> + </ul> + </div> + <span *ngIf="!curPrj" style="color:red; font-style: italic;"> + No project detected, please create first a project using the configuration page. + </span> + </td> + </tr> + </tbody> + </table> + </div> +</div> + +<div class="row"> + <div class="col-md-8"> + <panel-build [curProject]=curPrj></panel-build> + </div> + <!-- TODO: disable for now + <div class="col-md-4"> + <panel-deploy [curProject]=curPrj></panel-deploy> + </div> + --> +</div>
\ No newline at end of file diff --git a/webapp/src/app/devel/devel.component.ts b/webapp/src/app/devel/devel.component.ts new file mode 100644 index 0000000..ff12127 --- /dev/null +++ b/webapp/src/app/devel/devel.component.ts @@ -0,0 +1,32 @@ +import { Component } from '@angular/core'; + +import { Observable } from 'rxjs'; + +import { ConfigService, IConfig, IProject } from "../services/config.service"; + +@Component({ + selector: 'devel', + moduleId: module.id, + templateUrl: './devel.component.html', + styleUrls: ['./devel.component.css'], +}) + +export class DevelComponent { + + curPrj: IProject; + config$: Observable<IConfig>; + + constructor(private configSvr: ConfigService) { + } + + ngOnInit() { + this.config$ = this.configSvr.conf; + this.config$.subscribe((cfg) => { + if ("projects" in cfg) { + this.curPrj = cfg.projects[0]; + } else { + this.curPrj = null; + } + }); + } +}
\ No newline at end of file |