aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--lib/apiv1/apiv1.go2
-rw-r--r--lib/apiv1/exec.go41
-rw-r--r--lib/apiv1/make.go31
-rw-r--r--lib/common/execPipeWs.go16
-rw-r--r--lib/crosssdk/sdk.go4
-rw-r--r--lib/crosssdk/sdks.go6
-rw-r--r--lib/webserver/server.go4
-rw-r--r--main.go2
-rw-r--r--webapp/src/app/alert/alert.component.ts2
-rw-r--r--webapp/src/app/app.component.html2
-rw-r--r--webapp/src/app/app.module.ts20
-rw-r--r--webapp/src/app/app.routing.ts4
-rw-r--r--webapp/src/app/build/build.component.html71
-rw-r--r--webapp/src/app/config/config.component.ts12
-rw-r--r--webapp/src/app/devel/build/build.component.css (renamed from webapp/src/app/build/build.component.css)12
-rw-r--r--webapp/src/app/devel/build/build.component.html74
-rw-r--r--webapp/src/app/devel/build/build.component.ts (renamed from webapp/src/app/build/build.component.ts)111
-rw-r--r--webapp/src/app/devel/deploy/deploy.component.css45
-rw-r--r--webapp/src/app/devel/deploy/deploy.component.html31
-rw-r--r--webapp/src/app/devel/deploy/deploy.component.ts63
-rw-r--r--webapp/src/app/devel/devel.component.css14
-rw-r--r--webapp/src/app/devel/devel.component.html36
-rw-r--r--webapp/src/app/devel/devel.component.ts32
-rw-r--r--webapp/src/app/projects/projectCard.component.ts2
-rw-r--r--webapp/src/app/projects/projectsListAccordion.component.ts2
-rw-r--r--webapp/src/app/sdks/sdkCard.component.ts2
-rw-r--r--webapp/src/app/sdks/sdkSelectDropdown.component.ts2
-rw-r--r--webapp/src/app/sdks/sdksListAccordion.component.ts2
-rw-r--r--webapp/src/app/services/alert.service.ts (renamed from webapp/src/app/common/alert.service.ts)0
-rw-r--r--webapp/src/app/services/config.service.ts (renamed from webapp/src/app/common/config.service.ts)38
-rw-r--r--webapp/src/app/services/sdk.service.ts (renamed from webapp/src/app/common/sdk.service.ts)2
-rw-r--r--webapp/src/app/services/syncthing.service.ts (renamed from webapp/src/app/common/syncthing.service.ts)0
-rw-r--r--webapp/src/app/services/utils.service.ts (renamed from webapp/src/app/common/utils.service.ts)0
-rw-r--r--webapp/src/app/services/xdsagent.service.ts (renamed from webapp/src/app/common/xdsagent.service.ts)39
-rw-r--r--webapp/src/app/services/xdsserver.service.ts (renamed from webapp/src/app/common/xdsserver.service.ts)27
36 files changed, 555 insertions, 198 deletions
diff --git a/README.md b/README.md
index b910e06..1697009 100644
--- a/README.md
+++ b/README.md
@@ -128,3 +128,5 @@ Visual Studio Code launcher settings can be found into `.vscode/launch.json`.
- replace makefile by build.go to make Windows build support easier
- add more tests
- add more documentation
+- add authentication / login (oauth) + HTTPS
+- enable syncthing user/password + HTTPS
diff --git a/lib/apiv1/apiv1.go b/lib/apiv1/apiv1.go
index 2df8ea7..7fa69e9 100644
--- a/lib/apiv1/apiv1.go
+++ b/lib/apiv1/apiv1.go
@@ -50,10 +50,8 @@ func New(r *gin.Engine, sess *session.Sessions, cfg *xdsconfig.Config, mfolder *
s.apiRouter.POST("/make", s.buildMake)
s.apiRouter.POST("/make/:id", s.buildMake)
- /* TODO: to be tested and then enabled
s.apiRouter.POST("/exec", s.execCmd)
s.apiRouter.POST("/exec/:id", s.execCmd)
- */
return s
}
diff --git a/lib/apiv1/exec.go b/lib/apiv1/exec.go
index 18fdc7e..895807d 100644
--- a/lib/apiv1/exec.go
+++ b/lib/apiv1/exec.go
@@ -12,10 +12,12 @@ import (
// ExecArgs JSON parameters of /exec command
type ExecArgs struct {
- ID string `json:"id"`
- RPath string `json:"rpath"` // relative path into project
+ ID string `json:"id" binding:"required"`
+ SdkID string `json:"sdkid"` // sdk ID to use for setting env
Cmd string `json:"cmd" binding:"required"`
Args []string `json:"args"`
+ Env []string `json:"env"`
+ RPath string `json:"rpath"` // relative path into project
CmdTimeout int `json:"timeout"` // command completion timeout in Second
}
@@ -51,7 +53,7 @@ func (s *APIService) execCmd(c *gin.Context) {
return
}
- // TODO: add permission
+ // TODO: add permission ?
// Retrieve session info
sess := s.sessions.Get(c)
@@ -89,14 +91,23 @@ func (s *APIService) execCmd(c *gin.Context) {
// Define callback for output
var oCB common.EmitOutputCB
- oCB = func(sid string, id int, stdout, stderr string) {
+ oCB = func(sid string, id int, stdout, stderr string, data *map[string]interface{}) {
// IO socket can be nil when disconnected
so := s.sessions.IOSocketGet(sid)
if so == nil {
s.log.Infof("%s not emitted: WS closed - sid: %s - msg id:%d", ExecOutEvent, sid, id)
return
}
- s.log.Debugf("%s emitted - WS sid %s - id:%d", ExecOutEvent, sid, id)
+
+ // Retrieve project ID and RootPath
+ prjID := (*data)["ID"].(string)
+ prjRootPath := (*data)["RootPath"].(string)
+
+ // Cleanup any references to internal rootpath in stdout & stderr
+ stdout = strings.Replace(stdout, prjRootPath, "", -1)
+ stderr = strings.Replace(stderr, prjRootPath, "", -1)
+
+ s.log.Debugf("%s emitted - WS sid %s - id:%d - prjID:%s", ExecOutEvent, sid, id, prjID)
// FIXME replace by .BroadcastTo a room
err := (*so).Emit(ExecOutEvent, ExecOutMsg{
@@ -135,14 +146,26 @@ func (s *APIService) execCmd(c *gin.Context) {
cmdID := execCommandID
execCommandID++
+ cmd := []string{}
- cmd := "cd " + prj.GetFullPath(args.RPath) + " && " + args.Cmd
+ // Setup env var regarding Sdk ID (used for example to setup cross toolchain)
+ if envCmd := s.sdks.GetEnvCmd(args.SdkID, prj.DefaultSdk); len(envCmd) > 0 {
+ cmd = append(cmd, envCmd...)
+ cmd = append(cmd, "&&")
+ }
+
+ cmd = append(cmd, "cd", prj.GetFullPath(args.RPath), "&&", args.Cmd)
if len(args.Args) > 0 {
- cmd += " " + strings.Join(args.Args, " ")
+ cmd = append(cmd, args.Args...)
}
- s.log.Debugf("Execute [Cmd ID %d]: %v %v", cmdID, cmd)
- err := common.ExecPipeWs(cmd, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB)
+ s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd)
+
+ data := make(map[string]interface{})
+ data["ID"] = prj.ID
+ data["RootPath"] = prj.RootPath
+
+ err := common.ExecPipeWs(cmd, args.Env, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB, &data)
if err != nil {
common.APIError(c, err.Error())
return
diff --git a/lib/apiv1/make.go b/lib/apiv1/make.go
index fb6435e..098e41c 100644
--- a/lib/apiv1/make.go
+++ b/lib/apiv1/make.go
@@ -13,11 +13,12 @@ import (
// MakeArgs is the parameters (json format) of /make command
type MakeArgs struct {
- ID string `json:"id"`
- RPath string `json:"rpath"` // relative path into project
- Args string `json:"args"` // args to pass to make command
- SdkID string `json:"sdkid"` // sdk ID to use for setting env
- CmdTimeout int `json:"timeout"` // command completion timeout in Second
+ ID string `json:"id"`
+ SdkID string `json:"sdkid"` // sdk ID to use for setting env
+ Args []string `json:"args"` // args to pass to make command
+ Env []string `json:"env"`
+ RPath string `json:"rpath"` // relative path into project
+ CmdTimeout int `json:"timeout"` // command completion timeout in Second
}
// MakeOutMsg Message send on each output (stdout+stderr) of make command
@@ -85,14 +86,9 @@ func (s *APIService) buildMake(c *gin.Context) {
execTmo = 24 * 60 * 60 // 1 day
}
- cmd := "cd " + prj.GetFullPath(args.RPath) + " && make"
- if args.Args != "" {
- cmd += " " + args.Args
- }
-
// Define callback for output
var oCB common.EmitOutputCB
- oCB = func(sid string, id int, stdout, stderr string) {
+ oCB = func(sid string, id int, stdout, stderr string, data *map[string]interface{}) {
// IO socket can be nil when disconnected
so := s.sessions.IOSocketGet(sid)
if so == nil {
@@ -138,14 +134,21 @@ func (s *APIService) buildMake(c *gin.Context) {
cmdID := makeCommandID
makeCommandID++
+ cmd := []string{}
// Retrieve env command regarding Sdk ID
- if envCmd := s.sdks.GetEnvCmd(args.SdkID, prj.DefaultSdk); envCmd != "" {
- cmd = envCmd + " && " + cmd
+ if envCmd := s.sdks.GetEnvCmd(args.SdkID, prj.DefaultSdk); len(envCmd) > 0 {
+ cmd = append(cmd, envCmd...)
+ cmd = append(cmd, "&&")
+ }
+
+ cmd = append(cmd, "cd", prj.GetFullPath(args.RPath), "&&", "make")
+ if len(args.Args) > 0 {
+ cmd = append(cmd, args.Args...)
}
s.log.Debugf("Execute [Cmd ID %d]: %v", cmdID, cmd)
- err := common.ExecPipeWs(cmd, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB)
+ err := common.ExecPipeWs(cmd, args.Env, sop, sess.ID, cmdID, execTmo, s.log, oCB, eCB, nil)
if err != nil {
common.APIError(c, err.Error())
return
diff --git a/lib/common/execPipeWs.go b/lib/common/execPipeWs.go
index 3b63cdc..4994d9d 100644
--- a/lib/common/execPipeWs.go
+++ b/lib/common/execPipeWs.go
@@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
+ "strings"
"time"
"syscall"
@@ -14,7 +15,7 @@ import (
)
// EmitOutputCB is the function callback used to emit data
-type EmitOutputCB func(sid string, cmdID int, stdout, stderr string)
+type EmitOutputCB func(sid string, cmdID int, stdout, stderr string, data *map[string]interface{})
// EmitExitCB is the function callback used to emit exit proc code
type EmitExitCB func(sid string, cmdID int, code int, err error)
@@ -23,8 +24,8 @@ type EmitExitCB func(sid string, cmdID int, code int, err error)
// https://github.com/gorilla/websocket/blob/master/examples/command/main.go
// ExecPipeWs executes a command and redirect stdout/stderr into a WebSocket
-func ExecPipeWs(cmd string, so *socketio.Socket, sid string, cmdID int,
- cmdExecTimeout int, log *logrus.Logger, eoCB EmitOutputCB, eeCB EmitExitCB) error {
+func ExecPipeWs(cmd []string, env []string, so *socketio.Socket, sid string, cmdID int,
+ cmdExecTimeout int, log *logrus.Logger, eoCB EmitOutputCB, eeCB EmitExitCB, data *map[string]interface{}) error {
outr, outw, err := os.Pipe()
if err != nil {
@@ -39,9 +40,10 @@ func ExecPipeWs(cmd string, so *socketio.Socket, sid string, cmdID int,
return fmt.Errorf("Pipe stdin error: " + err.Error())
}
- bashArgs := []string{"/bin/bash", "-c", cmd}
+ bashArgs := []string{"/bin/bash", "-c", strings.Join(cmd, " ")}
proc, err := os.StartProcess("/bin/bash", bashArgs, &os.ProcAttr{
Files: []*os.File{inr, outw, outw},
+ Env: append(os.Environ(), env...),
})
if err != nil {
outr.Close()
@@ -58,7 +60,7 @@ func ExecPipeWs(cmd string, so *socketio.Socket, sid string, cmdID int,
defer inw.Close()
stdoutDone := make(chan struct{})
- go cmdPumpStdout(so, outr, stdoutDone, sid, cmdID, log, eoCB)
+ go cmdPumpStdout(so, outr, stdoutDone, sid, cmdID, log, eoCB, data)
// Blocking function that poll input or wait for end of process
cmdPumpStdin(so, inw, proc, sid, cmdID, cmdExecTimeout, log, eeCB)
@@ -133,13 +135,13 @@ func cmdPumpStdin(so *socketio.Socket, w io.Writer, proc *os.Process,
}
func cmdPumpStdout(so *socketio.Socket, r io.Reader, done chan struct{},
- sid string, cmdID int, log *logrus.Logger, emitFuncCB EmitOutputCB) {
+ sid string, cmdID int, log *logrus.Logger, emitFuncCB EmitOutputCB, data *map[string]interface{}) {
defer func() {
}()
sc := bufio.NewScanner(r)
for sc.Scan() {
- emitFuncCB(sid, cmdID, string(sc.Bytes()), "")
+ emitFuncCB(sid, cmdID, string(sc.Bytes()), "", data)
}
if sc.Err() != nil {
log.Errorln("scan:", sc.Err())
diff --git a/lib/crosssdk/sdk.go b/lib/crosssdk/sdk.go
index 9aeec90..5a5770d 100644
--- a/lib/crosssdk/sdk.go
+++ b/lib/crosssdk/sdk.go
@@ -48,6 +48,6 @@ func NewCrossSDK(path string) (*SDK, error) {
}
// GetEnvCmd returns the command used to initialized the environment
-func (s *SDK) GetEnvCmd() string {
- return ". " + s.EnvFile
+func (s *SDK) GetEnvCmd() []string {
+ return []string{"source", s.EnvFile}
}
diff --git a/lib/crosssdk/sdks.go b/lib/crosssdk/sdks.go
index abfef82..d08afc5 100644
--- a/lib/crosssdk/sdks.go
+++ b/lib/crosssdk/sdks.go
@@ -71,15 +71,15 @@ func (s *SDKs) Get(id int) SDK {
}
// GetEnvCmd returns the command used to initialized the environment for an SDK
-func (s *SDKs) GetEnvCmd(id string, defaultID string) string {
+func (s *SDKs) GetEnvCmd(id string, defaultID string) []string {
if id == "" && defaultID == "" {
// no env cmd
- return ""
+ return []string{}
}
s.mutex.Lock()
defer s.mutex.Unlock()
- defaultEnv := ""
+ defaultEnv := []string{}
for _, sdk := range s.Sdks {
if sdk.ID == id {
return sdk.GetEnvCmd()
diff --git a/lib/webserver/server.go b/lib/webserver/server.go
index 774195c..4268b40 100644
--- a/lib/webserver/server.go
+++ b/lib/webserver/server.go
@@ -154,12 +154,10 @@ func (s *Server) middlewareXDSDetails() gin.HandlerFunc {
// CORS middleware
func (s *Server) middlewareCORS() gin.HandlerFunc {
return func(c *gin.Context) {
-
if c.Request.Method == "OPTIONS" {
c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Headers", "Content-Type")
- c.Header("Access-Control-Allow-Methods", "POST, DELETE, GET, PUT")
- c.Header("Content-Type", "application/json")
+ c.Header("Access-Control-Allow-Methods", "GET, POST, DELETE")
c.Header("Access-Control-Max-Age", cookieMaxAge)
c.AbortWithStatus(204)
return
diff --git a/main.go b/main.go
index 69f6676..49f36a5 100644
--- a/main.go
+++ b/main.go
@@ -183,7 +183,7 @@ func xdsApp(cliCtx *cli.Context) error {
relativePath = stFld.RawPath
}
- newFld := xdsconfig.NewFolderConfig(stFld.ID, stFld.Label, ctx.Config.ShareRootDir, strings.Trim(relativePath, "/"), defaultSdk)
+ newFld := xdsconfig.NewFolderConfig(stFld.ID, stFld.Label, ctx.Config.ShareRootDir, strings.TrimRight(relativePath, "/"), defaultSdk)
ctx.Config.Folders = ctx.Config.Folders.Update(xdsconfig.FoldersConfig{newFld})
}
diff --git a/webapp/src/app/alert/alert.component.ts b/webapp/src/app/alert/alert.component.ts
index 449506f..672d7bf 100644
--- a/webapp/src/app/alert/alert.component.ts
+++ b/webapp/src/app/alert/alert.component.ts
@@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
-import {AlertService, IAlert} from '../common/alert.service';
+import {AlertService, IAlert} from '../services/alert.service';
@Component({
selector: 'app-alert',
diff --git a/webapp/src/app/app.component.html b/webapp/src/app/app.component.html
index ab792be..3dc77ef 100644
--- a/webapp/src/app/app.component.html
+++ b/webapp/src/app/app.component.html
@@ -6,7 +6,7 @@
<div class="navbar-collapse collapse menu2">
<ul class="nav navbar-nav navbar-right">
- <li><a routerLink="/build"><i class="fa fa-2x fa-play-circle" title="Open build page"></i></a></li>
+ <li><a routerLink="/devel"><i class="fa fa-2x fa-play-circle" title="Open build page"></i></a></li>
<li><a routerLink="/config"><i class="fa fa-2x fa-cog" title="Open configuration page"></i></a></li>
<li><a routerLink="/home"><i class="fa fa-2x fa-home" title="Back to home page"></i></a></li>
</ul>
diff --git a/webapp/src/app/app.module.ts b/webapp/src/app/app.module.ts
index 1abcf0c..d02cdf2 100644
--- a/webapp/src/app/app.module.ts
+++ b/webapp/src/app/app.module.ts
@@ -24,14 +24,16 @@ import { SdksListAccordionComponent } from "./sdks/sdksListAccordion.component";
import { SdkSelectDropdownComponent } from "./sdks/sdkSelectDropdown.component";
import { HomeComponent } from "./home/home.component";
-import { BuildComponent } from "./build/build.component";
-import { XDSServerService } from "./common/xdsserver.service";
-import { XDSAgentService } from "./common/xdsagent.service";
-import { SyncthingService } from "./common/syncthing.service";
-import { ConfigService } from "./common/config.service";
-import { AlertService } from './common/alert.service';
-import { UtilsService } from './common/utils.service';
-import { SdkService } from "./common/sdk.service";
+import { DevelComponent } from "./devel/devel.component";
+import { BuildComponent } from "./devel/build/build.component";
+import { DeployComponent } from "./devel/deploy/deploy.component";
+import { XDSServerService } from "./services/xdsserver.service";
+import { XDSAgentService } from "./services/xdsagent.service";
+import { SyncthingService } from "./services/syncthing.service";
+import { ConfigService } from "./services/config.service";
+import { AlertService } from './services/alert.service';
+import { UtilsService } from './services/utils.service';
+import { SdkService } from "./services/sdk.service";
@@ -54,6 +56,8 @@ import { SdkService } from "./common/sdk.service";
AlertComponent,
HomeComponent,
BuildComponent,
+ DevelComponent,
+ DeployComponent,
ConfigComponent,
ProjectCardComponent,
ProjectReadableTypePipe,
diff --git a/webapp/src/app/app.routing.ts b/webapp/src/app/app.routing.ts
index 747727c..f0d808f 100644
--- a/webapp/src/app/app.routing.ts
+++ b/webapp/src/app/app.routing.ts
@@ -2,7 +2,7 @@ import {Routes, RouterModule} from "@angular/router";
import {ModuleWithProviders} from "@angular/core";
import {ConfigComponent} from "./config/config.component";
import {HomeComponent} from "./home/home.component";
-import {BuildComponent} from "./build/build.component";
+import {DevelComponent} from "./devel/devel.component";
const appRoutes: Routes = [
@@ -10,7 +10,7 @@ const appRoutes: Routes = [
{path: 'config', component: ConfigComponent, data: {title: 'Config'}},
{path: 'home', component: HomeComponent, data: {title: 'Home'}},
- {path: 'build', component: BuildComponent, data: {title: 'Build'}}
+ {path: 'devel', component: DevelComponent, data: {title: 'Build & Deploy'}}
];
export const AppRoutingProviders: any[] = [];
diff --git a/webapp/src/app/build/build.component.html b/webapp/src/app/build/build.component.html
deleted file mode 100644
index 3d866f3..0000000
--- a/webapp/src/app/build/build.component.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<form [formGroup]="buildForm">
- <div class="col-xs-12">
- <table class="table table-borderless">
- <tbody>
- <tr>
- <th style="border: none;">Project</th>
- <td>
- <div class="btn-group" dropdown *ngIf="curProject">
- <button dropdownToggle type="button" class="btn btn-primary dropdown-toggle" style="width: 20em;">
- {{curProject.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)="curProject=prj">
- {{prj.label}}</a>
- </li>
- </ul>
- </div>
- </td>
- </tr>
- <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>Sub-directory</th>
- <td> <input type="text" style="width:99%;" formControlName="subpath"> </td>
- </tr>
- <tr>
- <th>Make arguments</th>
- <td> <input type="text" style="width:99%;" formControlName="makeArgs"> </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)="make() " [disabled]="!confValid ">Build</button>
- <button class="btn btn-primary btn-large" (click)="make('clean') " [disabled]="!confValid ">Clean</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>
diff --git a/webapp/src/app/config/config.component.ts b/webapp/src/app/config/config.component.ts
index 1e1e9c2..c6b2573 100644
--- a/webapp/src/app/config/config.component.ts
+++ b/webapp/src/app/config/config.component.ts
@@ -7,12 +7,12 @@ import 'rxjs/add/operator/map';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/debounceTime';
-import { ConfigService, IConfig, IProject, ProjectType } from "../common/config.service";
-import { XDSServerService, IServerStatus, IXDSAgentInfo } from "../common/xdsserver.service";
-import { XDSAgentService, IAgentStatus } from "../common/xdsagent.service";
-import { SyncthingService, ISyncThingStatus } from "../common/syncthing.service";
-import { AlertService } from "../common/alert.service";
-import { ISdk, SdkService } from "../common/sdk.service";
+import { ConfigService, IConfig, IProject, ProjectType } from "../services/config.service";
+import { XDSServerService, IServerStatus, IXDSAgentInfo } from "../services/xdsserver.service";
+import { XDSAgentService, IAgentStatus } from "../services/xdsagent.service";
+import { SyncthingService, ISyncThingStatus } from "../services/syncthing.service";
+import { AlertService } from "../services/alert.service";
+import { ISdk, SdkService } from "../services/sdk.service";
@Component({
templateUrl: './app/config/config.component.html',
diff --git a/webapp/src/app/build/build.component.css b/webapp/src/app/devel/build/build.component.css
index 11784db..6784a9f 100644
--- a/webapp/src/app/build/build.component.css
+++ b/webapp/src/app/devel/build/build.component.css
@@ -10,6 +10,12 @@
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,
@@ -30,4 +36,10 @@
.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/build/build.component.ts b/webapp/src/app/devel/build/build.component.ts
index 17e545f..b7003b1 100644
--- a/webapp/src/app/build/build.component.ts
+++ b/webapp/src/app/devel/build/build.component.ts
@@ -1,17 +1,18 @@
-import { Component, AfterViewChecked, ElementRef, ViewChild, OnInit } from '@angular/core';
+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 "../common/xdsserver.service";
-import { ConfigService, IConfig, IProject } from "../common/config.service";
-import { AlertService, IAlert } from "../common/alert.service";
-import { SdkService } from "../common/sdk.service";
+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: 'build',
+ selector: 'panel-build',
moduleId: module.id,
templateUrl: './build.component.html',
styleUrls: ['./build.component.css']
@@ -20,46 +21,34 @@ import { SdkService } from "../common/sdk.service";
export class BuildComponent implements OnInit, AfterViewChecked {
@ViewChild('scrollOutput') private scrollContainer: ElementRef;
- config$: Observable<IConfig>;
+ @Input() curProject: IProject;
buildForm: FormGroup;
subpathCtrl = new FormControl("", Validators.required);
+ debugEnable: boolean = false;
public cmdOutput: string;
- public confValid: boolean;
- public curProject: IProject;
public cmdInfo: string;
private startTime: Map<string, number> = new Map<string, number>();
- // I initialize the app component.
constructor(private configSvr: ConfigService,
private xdsSvr: XDSServerService,
private fb: FormBuilder,
private alertSvr: AlertService,
- private sdkSvr: SdkService
+ private sdkSvr: SdkService,
+ private cookie: CookieService,
) {
this.cmdOutput = "";
- this.confValid = false;
this.cmdInfo = ""; // TODO: to be remove (only for debug)
this.buildForm = fb.group({
subpath: this.subpathCtrl,
- makeArgs: ["", Validators.nullValidator],
+ cmdArgs: ["", Validators.nullValidator],
+ envVars: ["", Validators.nullValidator],
});
}
ngOnInit() {
- this.config$ = this.configSvr.conf;
- this.config$.subscribe((cfg) => {
- if ("projects" in cfg) {
- this.curProject = cfg.projects[0];
- this.confValid = (cfg.projects.length && this.curProject.id != null);
- } else {
- this.curProject = null;
- this.confValid = false;
- }
- });
-
// Command output data tunneling
this.xdsSvr.CmdOutput$.subscribe(data => {
this.cmdOutput += data.stdout + "\n";
@@ -78,6 +67,9 @@ export class BuildComponent implements OnInit, AfterViewChecked {
});
this._scrollToBottom();
+
+ // only use for debug
+ this.debugEnable = (this.cookie.get("debug_build") !== "");
}
ngAfterViewChecked() {
@@ -88,6 +80,69 @@ export class BuildComponent implements OnInit, AfterViewChecked {
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);
@@ -99,12 +154,16 @@ export class BuildComponent implements OnInit, AfterViewChecked {
let sdkid = this.sdkSvr.getCurrentId();
- let cmdArgs = args ? args : this.buildForm.value.makeArgs;
+ 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, cmdArgs, sdkid)
+ this.xdsSvr.make(prjID, this.buildForm.value.subpath, sdkid, argsArr, envArr)
.subscribe(res => {
this.startTime.set(String(res.cmdID), t0);
},
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
diff --git a/webapp/src/app/projects/projectCard.component.ts b/webapp/src/app/projects/projectCard.component.ts
index 010b476..7a7fa21 100644
--- a/webapp/src/app/projects/projectCard.component.ts
+++ b/webapp/src/app/projects/projectCard.component.ts
@@ -1,5 +1,5 @@
import { Component, Input, Pipe, PipeTransform } from '@angular/core';
-import { ConfigService, IProject, ProjectType } from "../common/config.service";
+import { ConfigService, IProject, ProjectType } from "../services/config.service";
@Component({
selector: 'project-card',
diff --git a/webapp/src/app/projects/projectsListAccordion.component.ts b/webapp/src/app/projects/projectsListAccordion.component.ts
index bea3f0f..1b43cea 100644
--- a/webapp/src/app/projects/projectsListAccordion.component.ts
+++ b/webapp/src/app/projects/projectsListAccordion.component.ts
@@ -1,6 +1,6 @@
import { Component, Input } from "@angular/core";
-import { IProject } from "../common/config.service";
+import { IProject } from "../services/config.service";
@Component({
selector: 'projects-list-accordion',
diff --git a/webapp/src/app/sdks/sdkCard.component.ts b/webapp/src/app/sdks/sdkCard.component.ts
index f5d2a54..579d224 100644
--- a/webapp/src/app/sdks/sdkCard.component.ts
+++ b/webapp/src/app/sdks/sdkCard.component.ts
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
-import { ISdk } from "../common/sdk.service";
+import { ISdk } from "../services/sdk.service";
@Component({
selector: 'sdk-card',
diff --git a/webapp/src/app/sdks/sdkSelectDropdown.component.ts b/webapp/src/app/sdks/sdkSelectDropdown.component.ts
index f213db0..a2fe37a 100644
--- a/webapp/src/app/sdks/sdkSelectDropdown.component.ts
+++ b/webapp/src/app/sdks/sdkSelectDropdown.component.ts
@@ -1,6 +1,6 @@
import { Component, Input } from "@angular/core";
-import { ISdk, SdkService } from "../common/sdk.service";
+import { ISdk, SdkService } from "../services/sdk.service";
@Component({
selector: 'sdk-select-dropdown',
diff --git a/webapp/src/app/sdks/sdksListAccordion.component.ts b/webapp/src/app/sdks/sdksListAccordion.component.ts
index 9094f27..9d5f7e9 100644
--- a/webapp/src/app/sdks/sdksListAccordion.component.ts
+++ b/webapp/src/app/sdks/sdksListAccordion.component.ts
@@ -1,6 +1,6 @@
import { Component, Input } from "@angular/core";
-import { ISdk } from "../common/sdk.service";
+import { ISdk } from "../services/sdk.service";
@Component({
selector: 'sdks-list-accordion',
diff --git a/webapp/src/app/common/alert.service.ts b/webapp/src/app/services/alert.service.ts
index 9dab36a..9dab36a 100644
--- a/webapp/src/app/common/alert.service.ts
+++ b/webapp/src/app/services/alert.service.ts
diff --git a/webapp/src/app/common/config.service.ts b/webapp/src/app/services/config.service.ts
index 091ee06..390340a 100644
--- a/webapp/src/app/common/config.service.ts
+++ b/webapp/src/app/services/config.service.ts
@@ -13,11 +13,11 @@ import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/mergeMap';
-import { XDSServerService, IXDSConfigProject } from "../common/xdsserver.service";
-import { XDSAgentService } from "../common/xdsagent.service";
-import { SyncthingService, ISyncThingProject, ISyncThingStatus } from "../common/syncthing.service";
-import { AlertService, IAlert } from "../common/alert.service";
-import { UtilsService } from "../common/utils.service";
+import { XDSServerService, IXDSConfigProject } from "../services/xdsserver.service";
+import { XDSAgentService } from "../services/xdsagent.service";
+import { SyncthingService, ISyncThingProject, ISyncThingStatus } from "../services/syncthing.service";
+import { AlertService, IAlert } from "../services/alert.service";
+import { UtilsService } from "../services/utils.service";
export enum ProjectType {
NATIVE = 1,
@@ -150,9 +150,27 @@ export class ConfigService {
this.AgentConnectObs = this.xdsAgentSvr.connect(cfg.retry, cfg.URL)
.subscribe((sts) => {
//console.log("Agent sts", sts);
- }, error => this.alert.error(error)
- );
+ // FIXME: load projects from local XDS Agent and
+ // not directly from local syncthing
+ this._loadProjectFromLocalST();
+
+ }, error => {
+ if (error.indexOf("XDS local Agent not responding") !== -1) {
+ let msg = "<span><strong>" + error + "<br></strong>";
+ msg += "You may need to download and execute XDS-Agent.<br>";
+ if (this.confStore.xdsAgentZipUrl !== "") {
+ msg += "<a class=\"fa fa-download\" href=\"" + this.confStore.xdsAgentZipUrl + "\" target=\"_blank\"></a>";
+ msg += " Download XDS-Agent tarball.";
+ }
+ msg += "</span>";
+ this.alert.error(msg);
+ } else {
+ this.alert.error(error);
+ }
+ });
+ }
+ private _loadProjectFromLocalST() {
// Remove previous subscriber if existing
if (this.stConnectObs) {
try {
@@ -198,11 +216,7 @@ export class ConfigService {
}, error => {
if (error.indexOf("Syncthing local daemon not responding") !== -1) {
let msg = "<span><strong>" + error + "<br></strong>";
- msg += "You may need to download and execute XDS-Agent.<br>";
- if (this.confStore.xdsAgentZipUrl !== "") {
- msg += "<a class=\"fa fa-download\" href=\"" + this.confStore.xdsAgentZipUrl + "\" target=\"_blank\"></a>";
- msg += " Download XDS-Agent tarball.";
- }
+ msg += "Please check that local XDS-Agent is running.<br>";
msg += "</span>";
this.alert.error(msg);
} else {
diff --git a/webapp/src/app/common/sdk.service.ts b/webapp/src/app/services/sdk.service.ts
index 19c49d9..fa4cd55 100644
--- a/webapp/src/app/common/sdk.service.ts
+++ b/webapp/src/app/services/sdk.service.ts
@@ -2,7 +2,7 @@ import { Injectable, SecurityContext } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
-import { XDSServerService } from "../common/xdsserver.service";
+import { XDSServerService } from "../services/xdsserver.service";
export interface ISdk {
id: string;
diff --git a/webapp/src/app/common/syncthing.service.ts b/webapp/src/app/services/syncthing.service.ts
index 0e8c51c..0e8c51c 100644
--- a/webapp/src/app/common/syncthing.service.ts
+++ b/webapp/src/app/services/syncthing.service.ts
diff --git a/webapp/src/app/common/utils.service.ts b/webapp/src/app/services/utils.service.ts
index 291ffd3..291ffd3 100644
--- a/webapp/src/app/common/utils.service.ts
+++ b/webapp/src/app/services/utils.service.ts
diff --git a/webapp/src/app/common/xdsagent.service.ts b/webapp/src/app/services/xdsagent.service.ts
index 86f0336..c6c52c8 100644
--- a/webapp/src/app/common/xdsagent.service.ts
+++ b/webapp/src/app/services/xdsagent.service.ts
@@ -21,6 +21,11 @@ export interface IXDSVersion {
}
+export interface IXDSDeploy {
+ boardIP: string;
+ file: string;
+}
+
export interface IAgentStatus {
baseURL: string;
connected: boolean;
@@ -66,9 +71,7 @@ export class XDSAgentService {
if (url) {
this._initURLs(url);
}
- //FIXME [XDS-Agent]: not implemented yet, set always as connected
- //this._status.connected = false;
- this._status.connected = true;
+ this._status.connected = false;
this._status.connectionRetry = 0;
this.connectionMaxRetry = retry || 3600; // 1 hour
@@ -85,14 +88,11 @@ export class XDSAgentService {
}
public getVersion(): Observable<IXDSVersion> {
- /*FIXME [XDS-Agent]: Not implemented for now
return this._get('/version');
- */
- return Observable.of({
- version: "NOT_IMPLEMENTED",
- apiVersion: "NOT_IMPLEMENTED",
- gitTag: "NOT_IMPLEMENTED"
- });
+ }
+
+ public deploy(dpy: IXDSDeploy) {
+ return this._post('/deploy', dpy);
}
private _initURLs(url: string) {
@@ -139,7 +139,6 @@ export class XDSAgentService {
options = options || {};
let headers = options.headers || new Headers();
// headers.append('Authorization', 'Basic ' + btoa('username:password'));
- headers.append('Access-Control-Allow-Origin', '*');
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
if (this.apikey !== "") {
@@ -156,7 +155,7 @@ export class XDSAgentService {
return Observable.of(true);
}
- return this.http.get(this._status.baseURL, this._attachAuthHeaders())
+ return this.http.get(this.baseRestUrl + "/version", this._attachAuthHeaders())
.map((r) => this._status.connected = true)
.retryWhen((attempts) => {
this._status.connectionRetry = 0;
@@ -181,9 +180,7 @@ export class XDSAgentService {
return this._checkAlive()
.flatMap(() => this.http.post(this.baseRestUrl + url, JSON.stringify(body), this._attachAuthHeaders()))
.map((res: Response) => res.json())
- .catch((error) => {
- return this._decodeError(error);
- });
+ .catch(this._decodeError);
}
private _delete(url: string): Observable<any> {
return this._checkAlive()
@@ -197,7 +194,13 @@ export class XDSAgentService {
if (this._status) {
this._status.connected = false;
}
- if (typeof err === "object") {
+ if (err instanceof Response) {
+ const body = err.json() || 'Server error';
+ e = body.error || JSON.stringify(body);
+ if (!e || e === "") {
+ e = `${err.status} - ${err.statusText || 'Unknown error'}`;
+ }
+ } else if (typeof err === "object") {
if (err.statusText) {
e = err.statusText;
} else if (err.error) {
@@ -205,10 +208,6 @@ export class XDSAgentService {
} else {
e = JSON.stringify(err);
}
- } else if (err instanceof Response) {
- const body = err.json() || 'Server error';
- const error = body.error || JSON.stringify(body);
- e = `${err.status} - ${err.statusText || ''} ${error}`;
} else {
e = err.message ? err.message : err.toString();
}
diff --git a/webapp/src/app/common/xdsserver.service.ts b/webapp/src/app/services/xdsserver.service.ts
index 49c2d37..22e4ac9 100644
--- a/webapp/src/app/common/xdsserver.service.ts
+++ b/webapp/src/app/services/xdsserver.service.ts
@@ -147,6 +147,14 @@ export class XDSServerService {
this.CmdExit$.next(Object.assign({}, <ICmdExit>data));
});
+ this.socket.on('exec:output', data => {
+ this.CmdOutput$.next(Object.assign({}, <ICmdOutput>data));
+ });
+
+ this.socket.on('exec:exit', data => {
+ this.CmdExit$.next(Object.assign({}, <ICmdExit>data));
+ });
+
}
getSdks(): Observable<ISdk[]> {
@@ -177,16 +185,27 @@ export class XDSServerService {
return this._delete('/folder/' + id);
}
- exec(cmd: string, args?: string[], options?: any): Observable<any> {
+ exec(prjID: string, dir: string, cmd: string, sdkid?: string, args?: string[], env?: string[]): Observable<any> {
return this._post('/exec',
{
+ id: prjID,
+ rpath: dir,
cmd: cmd,
- args: args || []
+ sdkid: sdkid || "",
+ args: args || [],
+ env: env || [],
});
}
- make(prjID: string, dir: string, args: string, sdkid?: string): Observable<any> {
- return this._post('/make', { id: prjID, rpath: dir, args: args, sdkid: sdkid });
+ make(prjID: string, dir: string, sdkid?: string, args?: string[], env?: string[]): Observable<any> {
+ return this._post('/make',
+ {
+ id: prjID,
+ rpath: dir,
+ sdkid: sdkid,
+ args: args || [],
+ env: env || [],
+ });
}