Fixed connection retry to local Syncthing.
[src/xds/xds-server.git] / webapp / src / app / build / build.component.ts
1 import { Component, AfterViewChecked, ElementRef, ViewChild, OnInit } from '@angular/core';
2 import { Observable } from 'rxjs';
3 import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms';
4
5 import 'rxjs/add/operator/scan';
6 import 'rxjs/add/operator/startWith';
7
8 import { XDSServerService, ICmdOutput } from "../common/xdsserver.service";
9 import { ConfigService, IConfig, IProject } from "../common/config.service";
10 import { AlertService, IAlert } from "../common/alert.service";
11
12 @Component({
13     selector: 'build',
14     moduleId: module.id,
15     templateUrl: './build.component.html',
16     styleUrls: ['./build.component.css']
17 })
18
19 export class BuildComponent implements OnInit, AfterViewChecked {
20     @ViewChild('scrollOutput') private scrollContainer: ElementRef;
21
22     config$: Observable<IConfig>;
23
24     buildForm: FormGroup;
25     subpathCtrl = new FormControl("", Validators.required);
26
27     public cmdOutput: string;
28     public confValid: boolean;
29     public curProject: IProject;
30     public cmdInfo: string;
31
32     private startTime: Map<string, number> = new Map<string, number>();
33
34     // I initialize the app component.
35     constructor(private configSvr: ConfigService, private sdkSvr: XDSServerService,
36         private fb: FormBuilder, private alertSvr: AlertService
37     ) {
38         this.cmdOutput = "";
39         this.confValid = false;
40         this.cmdInfo = "";      // TODO: to be remove (only for debug)
41         this.buildForm = fb.group({ subpath: this.subpathCtrl });
42     }
43
44     ngOnInit() {
45         this.config$ = this.configSvr.conf;
46         this.config$.subscribe((cfg) => {
47             if ("projects" in cfg) {
48                 this.curProject = cfg.projects[0];
49                 this.confValid = (cfg.projects.length && this.curProject.id != null);
50             } else {
51                 this.curProject = null;
52                 this.confValid = false;
53             }
54         });
55
56         // Command output data tunneling
57         this.sdkSvr.CmdOutput$.subscribe(data => {
58             this.cmdOutput += data.stdout + "\n";
59         });
60
61         // Command exit
62         this.sdkSvr.CmdExit$.subscribe(exit => {
63             if (this.startTime.has(exit.cmdID)) {
64                 this.cmdInfo = 'Last command duration: ' + this._computeTime(this.startTime.get(exit.cmdID));
65                 this.startTime.delete(exit.cmdID);
66             }
67
68             if (exit && exit.code !== 0) {
69                 this.cmdOutput += "--- Command exited with code " + exit.code + " ---\n\n";
70             }
71         });
72
73         this._scrollToBottom();
74     }
75
76     ngAfterViewChecked() {
77         this._scrollToBottom();
78     }
79
80     reset() {
81         this.cmdOutput = '';
82     }
83
84     make(args: string) {
85         if (!this.curProject) {
86             this.alertSvr.warning('No active project', true);
87         }
88
89         let prjID = this.curProject.id;
90
91         this.cmdOutput += this._outputHeader();
92
93         let t0 = performance.now();
94         this.cmdInfo = 'Start build of ' + prjID + ' at ' + t0;
95
96         this.sdkSvr.make(prjID, this.buildForm.value.subpath, args)
97             .subscribe(res => {
98                 this.startTime.set(String(res.cmdID), t0);
99             },
100             err => {
101                 this.cmdInfo = 'Last command duration: ' + this._computeTime(t0);
102                 this.alertSvr.error('ERROR: ' + err);
103             });
104     }
105
106     private _scrollToBottom(): void {
107         try {
108             this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;
109         } catch (err) { }
110     }
111
112     private _computeTime(t0: number, t1?: number): string {
113         let enlap = Math.round((t1 || performance.now()) - t0);
114         if (enlap < 1000.0) {
115             return enlap.toFixed(2) + ' ms';
116         } else {
117             return (enlap / 1000.0).toFixed(3) + ' seconds';
118         }
119     }
120
121     private _outputHeader(): string {
122         return "--- " + new Date().toString() + " ---\n";
123     }
124
125     private _outputFooter(): string {
126         return "\n";
127     }
128 }