diff options
author | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-08-10 12:19:34 +0200 |
---|---|---|
committer | Sebastien Douheret <sebastien.douheret@iot.bzh> | 2017-08-16 14:27:28 +0200 |
commit | dd6f08b10b1597f44e3dc25509ac9a45336b0914 (patch) | |
tree | 3dcb835306bc3adbae7c27d94fc8a51de8d6f09a /webapp | |
parent | 0262f5bef6ff67e77b844a04733c57740fba9f00 (diff) |
Add folder interface and support native pathmap folder type.
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
Diffstat (limited to 'webapp')
-rw-r--r-- | webapp/src/app/config/config.component.html | 17 | ||||
-rw-r--r-- | webapp/src/app/config/config.component.ts | 35 | ||||
-rw-r--r-- | webapp/src/app/devel/deploy/deploy.component.ts | 6 | ||||
-rw-r--r-- | webapp/src/app/projects/projectCard.component.ts | 33 | ||||
-rw-r--r-- | webapp/src/app/services/config.service.ts | 80 | ||||
-rw-r--r-- | webapp/src/app/services/syncthing.service.ts | 4 | ||||
-rw-r--r-- | webapp/src/app/services/xdsserver.service.ts | 44 |
7 files changed, 130 insertions, 89 deletions
diff --git a/webapp/src/app/config/config.component.html b/webapp/src/app/config/config.component.html index d9229d5..5211c2d 100644 --- a/webapp/src/app/config/config.component.html +++ b/webapp/src/app/config/config.component.html @@ -71,13 +71,24 @@ </div> <div class="col-xs-6"> - <label>Folder Path </label> - <input type="text" style="width:70%;" formControlName="path" placeholder="myProject"> + <label>Client/Local Path </label> + <input type="text" style="width:70%;" formControlName="pathCli" placeholder="myProject"> + </div> + <div class="col-xs-6"> + <label>Server Path </label> + <input type="text" style="width:70%;" formControlName="pathSvr" placeholder="myProject"> </div> <div class="col-xs-4"> <label>Label </label> <input type="text" formControlName="label" (keyup)="onKeyLabel($event)"> </div> + <div class="col-xs-4"> + <label>Type </label> + <select class="form-control" formControlName="type"> + <option *ngFor="let t of projectTypes" [value]="t.value">{{t.display}} + </option> + </select> + </div> </div> </form> @@ -91,4 +102,4 @@ <!-- only for debug --> <div *ngIf="false" class="row"> {{config$ | async | json}} -</div>
\ No newline at end of file +</div> diff --git a/webapp/src/app/config/config.component.ts b/webapp/src/app/config/config.component.ts index 7d9931e..0df707b 100644 --- a/webapp/src/app/config/config.component.ts +++ b/webapp/src/app/config/config.component.ts @@ -7,7 +7,8 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/debounceTime'; -import { ConfigService, IConfig, IProject, ProjectType, IxdsAgentPackage } from "../services/config.service"; +import { ConfigService, IConfig, IProject, ProjectType, ProjectTypes, + IxdsAgentPackage } 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"; @@ -33,6 +34,7 @@ export class ConfigComponent implements OnInit { curProj: number; userEditedLabel: boolean = false; xdsAgentPackages: IxdsAgentPackage[] = []; + projectTypes = ProjectTypes; // TODO replace by reactive FormControl + add validation syncToolUrl: string; @@ -45,8 +47,8 @@ export class ConfigComponent implements OnInit { }; addProjectForm: FormGroup; - pathCtrl = new FormControl("", Validators.required); - + pathCliCtrl = new FormControl("", Validators.required); + pathSvrCtrl = new FormControl("", Validators.required); constructor( private configSvr: ConfigService, @@ -57,11 +59,16 @@ export class ConfigComponent implements OnInit { private alert: AlertService, private fb: FormBuilder ) { - // FIXME implement multi project support + // Define types (first one is special/placeholder) + this.projectTypes.unshift({value: -1, display: "--Select a type--"}); + let selectedType = this.projectTypes[0].value; + this.curProj = 0; this.addProjectForm = fb.group({ - path: this.pathCtrl, + pathCli: this.pathCliCtrl, + pathSvr: this.pathSvrCtrl, label: ["", Validators.nullValidator], + type: [selectedType, Validators.pattern("[0-9]+")], }); } @@ -82,7 +89,7 @@ export class ConfigComponent implements OnInit { }); // Auto create label name - this.pathCtrl.valueChanges + this.pathCliCtrl.valueChanges .debounceTime(100) .filter(n => n) .map(n => "Project_" + n.split('/')[0]) @@ -91,6 +98,9 @@ export class ConfigComponent implements OnInit { this.addProjectForm.patchValue({ label: value }); } }); + + // Select 1 first type by default + // SEB this.typeCtrl.setValue({type: ProjectTypes[0].value}); } onKeyLabel(event: any) { @@ -118,21 +128,24 @@ export class ConfigComponent implements OnInit { } xdsAgentRestartConn() { - let aurl = this.xdsAgentUrl; + let aUrl = this.xdsAgentUrl; this.configSvr.syncToolURL = this.syncToolUrl; - this.configSvr.xdsAgentUrl = aurl; + this.configSvr.xdsAgentUrl = aUrl; this.configSvr.loadProjects(); } onSubmit() { let formVal = this.addProjectForm.value; + let type = formVal['type'].value; + let numType = Number(formVal['type']); this.configSvr.addProject({ label: formVal['label'], - path: formVal['path'], - type: ProjectType.SYNCTHING, + pathClient: formVal['pathCli'], + pathServer: formVal['pathSvr'], + type: numType, // FIXME: allow to set defaultSdkID from New Project config panel }); } -}
\ 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 index 4dba256..e51b7f2 100644 --- a/webapp/src/app/devel/deploy/deploy.component.ts +++ b/webapp/src/app/devel/deploy/deploy.component.ts @@ -37,8 +37,8 @@ export class DeployComponent implements OnInit { ngOnInit() { this.deploying = false; - if (this.curProject && this.curProject.path) { - this.deployForm.patchValue({ wgtFile: this.curProject.path }); + if (this.curProject && this.curProject.pathClient) { + this.deployForm.patchValue({ wgtFile: this.curProject.pathClient }); } } @@ -60,4 +60,4 @@ export class DeployComponent implements OnInit { this.alert.error(msg); }); } -}
\ 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 7a7fa21..23e10a6 100644 --- a/webapp/src/app/projects/projectCard.component.ts +++ b/webapp/src/app/projects/projectCard.component.ts @@ -19,14 +19,23 @@ import { ConfigService, IProject, ProjectType } from "../services/config.service <td>{{ project.id }}</td> </tr> <tr> - <th><span class="fa fa-fw fa-folder-open-o"></span> <span>Folder path</span></th> - <td>{{ project.path}}</td> + <th><span class="fa fa-fw fa-exchange"></span> <span>Sharing type</span></th> + <td>{{ project.type | readableType }}</td> </tr> <tr> - <th><span class="fa fa-fw fa-exchange"></span> <span>Synchronization type</span></th> - <td>{{ project.type | readableType }}</td> + <th><span class="fa fa-fw fa-folder-open-o"></span> <span>Local path</span></th> + <td>{{ project.pathClient }}</td> </tr> - + <tr *ngIf="project.pathServer != ''"> + <th><span class="fa fa-fw fa-folder-open-o"></span> <span>Server path</span></th> + <td>{{ project.pathServer }}</td> + </tr> + <!-- + <tr> + <th><span class="fa fa-fw fa-status"></span> <span>Status</span></th> + <td>{{ project.remotePrjDef.status }}</td> + </tr> + --> </tbody> </table > `, @@ -53,11 +62,11 @@ export class ProjectCardComponent { }) export class ProjectReadableTypePipe implements PipeTransform { - transform(type: ProjectType): string { - switch (+type) { - case ProjectType.NATIVE: return "Native"; - case ProjectType.SYNCTHING: return "Cloud (Syncthing)"; - default: return String(type); + transform(type: ProjectType): string { + switch (type) { + case ProjectType.NATIVE_PATHMAP: return "Native (path mapping)"; + case ProjectType.SYNCTHING: return "Cloud (Syncthing)"; + default: return String(type); + } } - } -}
\ No newline at end of file +} diff --git a/webapp/src/app/services/config.service.ts b/webapp/src/app/services/config.service.ts index 722c347..c65332f 100644 --- a/webapp/src/app/services/config.service.ts +++ b/webapp/src/app/services/config.service.ts @@ -13,17 +13,22 @@ import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/mergeMap'; -import { XDSServerService, IXDSConfigProject } from "../services/xdsserver.service"; +import { XDSServerService, IXDSFolderConfig } 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, + NATIVE_PATHMAP = 1, SYNCTHING = 2 } +export var ProjectTypes = [ + { value: ProjectType.NATIVE_PATHMAP, display: "Path mapping" }, + { value: ProjectType.SYNCTHING, display: "Cloud Sync" } +]; + export interface INativeProject { // TODO } @@ -31,7 +36,8 @@ export interface INativeProject { export interface IProject { id?: string; label: string; - path: string; + pathClient: string; + pathServer?: string; type: ProjectType; remotePrjDef?: INativeProject | ISyncThingProject; localPrjDef?: any; @@ -172,7 +178,7 @@ export class ConfigService { let zurl = this.confStore.xdsAgentPackages && this.confStore.xdsAgentPackages.filter(elem => elem.os === os); if (zurl && zurl.length) { msg += " Download XDS-Agent tarball for " + zurl[0].os + " host OS "; - msg += "<a class=\"fa fa-download\" href=\"" + zurl[0].url + "\" target=\"_blank\"></a>"; + msg += "<a class=\"fa fa-download\" href=\"" + zurl[0].url + "\" target=\"_blank\"></a>"; } msg += "</span>"; this.alert.error(msg); @@ -213,8 +219,9 @@ export class ConfigService { let pp: IProject = { id: rPrj.id, label: rPrj.label, - path: rPrj.path, - type: ProjectType.SYNCTHING, // FIXME support other types + pathClient: rPrj.path, + pathServer: rPrj.dataPathMap.serverPath, + type: rPrj.type, remotePrjDef: Object.assign({}, rPrj), localPrjDef: Object.assign({}, lPrj[0]), }; @@ -272,57 +279,46 @@ export class ConfigService { addProject(prj: IProject) { // Substitute tilde with to user home path - prj.path = prj.path.trim(); - if (prj.path.charAt(0) === '~') { - prj.path = this.confStore.localSThg.tilde + prj.path.substring(1); + let pathCli = prj.pathClient.trim(); + if (pathCli.charAt(0) === '~') { + pathCli = this.confStore.localSThg.tilde + pathCli.substring(1); // Must be a full path (on Linux or Windows) - } else if (!((prj.path.charAt(0) === '/') || - (prj.path.charAt(1) === ':' && (prj.path.charAt(2) === '\\' || prj.path.charAt(2) === '/')))) { - prj.path = this.confStore.projectsRootDir + '/' + prj.path; - } - - if (prj.id == null) { - // FIXME - must be done on server side - let prefix = this.getLabelRootName() || new Date().toISOString(); - let splath = prj.path.split('/'); - prj.id = prefix + "_" + splath[splath.length - 1]; + } else if (!((pathCli.charAt(0) === '/') || + (pathCli.charAt(1) === ':' && (pathCli.charAt(2) === '\\' || pathCli.charAt(2) === '/')))) { + pathCli = this.confStore.projectsRootDir + '/' + pathCli; } - if (this._getProjectIdx(prj.id) !== -1) { - this.alert.warning("Project already exist (id=" + prj.id + ")", true); - return; - } - - // TODO - support others project types - if (prj.type !== ProjectType.SYNCTHING) { - this.alert.error('Project type not supported yet (type: ' + prj.type + ')'); - return; - } - - let sdkPrj: IXDSConfigProject = { - id: prj.id, - label: prj.label, - path: prj.path, - hostSyncThingID: this.confStore.localSThg.ID, + let xdsPrj: IXDSFolderConfig = { + id: "", + label: prj.label || "", + path: pathCli, + type: prj.type, defaultSdkID: prj.defaultSdkID, + dataPathMap: { + serverPath: prj.pathServer, + }, + dataCloudSync: { + syncThingID: this.confStore.localSThg.ID, + } }; - // Send config to XDS server let newPrj = prj; - this.xdsServerSvr.addProject(sdkPrj) + this.xdsServerSvr.addProject(xdsPrj) .subscribe(resStRemotePrj => { newPrj.remotePrjDef = resStRemotePrj; + newPrj.id = resStRemotePrj.id; // FIXME REWORK local ST config // move logic to server side tunneling-back by WS + let stData = resStRemotePrj.dataCloudSync; // Now setup local config let stLocPrj: ISyncThingProject = { - id: sdkPrj.id, - label: sdkPrj.label, - path: sdkPrj.path, - remoteSyncThingID: resStRemotePrj.builderSThgID + id: resStRemotePrj.id, + label: xdsPrj.label, + path: xdsPrj.path, + serverSyncThingID: stData.builderSThgID }; // Set local Syncthing config @@ -366,4 +362,4 @@ export class ConfigService { return this.confStore.projects.findIndex((item) => item.id === id); } -}
\ No newline at end of file +} diff --git a/webapp/src/app/services/syncthing.service.ts b/webapp/src/app/services/syncthing.service.ts index 0e8c51c..aefb039 100644 --- a/webapp/src/app/services/syncthing.service.ts +++ b/webapp/src/app/services/syncthing.service.ts @@ -16,7 +16,7 @@ import 'rxjs/add/operator/retryWhen'; export interface ISyncThingProject { id: string; path: string; - remoteSyncThingID: string; + serverSyncThingID: string; label?: string; } @@ -180,7 +180,7 @@ export class SyncthingService { return this.getID() .flatMap(() => this._getConfig()) .flatMap((stCfg) => { - let newDevID = prj.remoteSyncThingID; + let newDevID = prj.serverSyncThingID; // Add new Device if needed let dev = stCfg.devices.filter(item => item.deviceID === newDevID); diff --git a/webapp/src/app/services/xdsserver.service.ts b/webapp/src/app/services/xdsserver.service.ts index 4d20fa4..b11fe9f 100644 --- a/webapp/src/app/services/xdsserver.service.ts +++ b/webapp/src/app/services/xdsserver.service.ts @@ -20,7 +20,8 @@ import 'rxjs/add/operator/mergeMap'; export interface IXDSConfigProject { id: string; path: string; - hostSyncThingID: string; + clientSyncThingID: string; + type: number; label?: string; defaultSdkID?: string; } @@ -31,15 +32,28 @@ interface IXDSBuilderConfig { syncThingID: string; } -interface IXDSFolderConfig { +export interface IXDSFolderConfig { id: string; label: string; path: string; type: number; - syncThingID: string; - builderSThgID?: string; status?: string; defaultSdkID: string; + + // FIXME better with union but tech pb with go code + //data?: IXDSPathMapConfig|IXDSCloudSyncConfig; + dataPathMap?:IXDSPathMapConfig; + dataCloudSync?:IXDSCloudSyncConfig; +} + +export interface IXDSPathMapConfig { + // TODO + serverPath: string; +} + +export interface IXDSCloudSyncConfig { + syncThingID: string; + builderSThgID?: string; } interface IXDSConfig { @@ -172,16 +186,8 @@ export class XDSServerService { return this._get('/folders'); } - addProject(cfg: IXDSConfigProject): Observable<IXDSFolderConfig> { - let folder: IXDSFolderConfig = { - id: cfg.id || null, - label: cfg.label || "", - path: cfg.path, - type: FOLDER_TYPE_CLOUDSYNC, - syncThingID: cfg.hostSyncThingID, - defaultSdkID: cfg.defaultSdkID || "", - }; - return this._post('/folder', folder); + addProject(cfg: IXDSFolderConfig): Observable<IXDSFolderConfig> { + return this._post('/folder', cfg); } deleteProject(id: string): Observable<IXDSFolderConfig> { @@ -244,7 +250,13 @@ export class XDSServerService { private _decodeError(err: any) { let e: string; - 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) { @@ -253,7 +265,7 @@ export class XDSServerService { e = JSON.stringify(err); } } else { - e = err.json().error || 'Server error'; + e = err.message ? err.message : err.toString(); } return Observable.throw(e); } |