aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastien Douheret <sebastien.douheret@iot.bzh>2017-08-16 14:24:49 +0200
committerSebastien Douheret <sebastien.douheret@iot.bzh>2017-08-16 14:27:40 +0200
commit4feef5296bf3aea331fdde4cd7b94ee2322a907e (patch)
tree764618c74a241a7ce53a07e0105b01a4fb07f9c6
parentdd6f08b10b1597f44e3dc25509ac9a45336b0914 (diff)
Moved project creation in a modal windows
Signed-off-by: Sebastien Douheret <sebastien.douheret@iot.bzh>
-rw-r--r--.vscode/settings.json1
-rw-r--r--lib/folder/folder-pathmap.go20
-rw-r--r--lib/model/folders.go2
-rw-r--r--webapp/src/app/app.module.ts8
-rw-r--r--webapp/src/app/config/config.component.css2
-rw-r--r--webapp/src/app/config/config.component.html78
-rw-r--r--webapp/src/app/config/config.component.ts69
-rw-r--r--webapp/src/app/projects/projectAddModal.component.css24
-rw-r--r--webapp/src/app/projects/projectAddModal.component.html54
-rw-r--r--webapp/src/app/projects/projectAddModal.component.ts142
-rw-r--r--webapp/src/app/projects/projectCard.component.ts12
-rw-r--r--webapp/src/app/sdks/sdkAddModal.component.html23
-rw-r--r--webapp/src/app/sdks/sdkAddModal.component.ts24
-rw-r--r--webapp/src/app/services/alert.service.ts6
-rw-r--r--webapp/src/app/services/config.service.ts85
-rw-r--r--webapp/src/systemjs.config.js3
16 files changed, 403 insertions, 150 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 60fab57..7ccd637 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -12,7 +12,6 @@
"webapp/dist": true,
"webapp/node_modules": true
},
-
// Specify paths/files to ignore. (Supports Globs)
"cSpell.ignorePaths": [
"**/node_modules/**",
diff --git a/lib/folder/folder-pathmap.go b/lib/folder/folder-pathmap.go
index 8711df2..2ad8a93 100644
--- a/lib/folder/folder-pathmap.go
+++ b/lib/folder/folder-pathmap.go
@@ -7,18 +7,22 @@ import (
"path/filepath"
common "github.com/iotbzh/xds-common/golib"
+ "github.com/iotbzh/xds-server/lib/xdsconfig"
)
// IFOLDER interface implementation for native/path mapping folders
// PathMap .
type PathMap struct {
- config FolderConfig
+ globalConfig *xdsconfig.Config
+ config FolderConfig
}
// NewFolderPathMap Create a new instance of PathMap
-func NewFolderPathMap() *PathMap {
- f := PathMap{}
+func NewFolderPathMap(gc *xdsconfig.Config) *PathMap {
+ f := PathMap{
+ globalConfig: gc,
+ }
return &f
}
@@ -28,8 +32,13 @@ func (f *PathMap) Add(cfg FolderConfig) (*FolderConfig, error) {
return nil, fmt.Errorf("ServerPath must be set")
}
- // Sanity check
+ // Use shareRootDir if ServerPath is a relative path
dir := cfg.DataPathMap.ServerPath
+ if !filepath.IsAbs(dir) {
+ dir = filepath.Join(f.globalConfig.FileConf.ShareRootDir, dir)
+ }
+
+ // Sanity check
if !common.Exists(dir) {
// try to create if not existing
if err := os.MkdirAll(dir, 0755); err != nil {
@@ -52,7 +61,8 @@ func (f *PathMap) Add(cfg FolderConfig) (*FolderConfig, error) {
}
f.config = cfg
- f.config.RootPath = cfg.DataPathMap.ServerPath
+ f.config.RootPath = dir
+ f.config.DataPathMap.ServerPath = dir
f.config.Status = StatusEnable
return &f.config, nil
diff --git a/lib/model/folders.go b/lib/model/folders.go
index 3c2457c..02c3254 100644
--- a/lib/model/folders.go
+++ b/lib/model/folders.go
@@ -208,7 +208,7 @@ func (f *Folders) createUpdate(newF folder.FolderConfig, create bool) (*folder.F
fld = f.SThg.NewFolderST(f.Conf)
// PATH MAP
case folder.TypePathMap:
- fld = folder.NewFolderPathMap()
+ fld = folder.NewFolderPathMap(f.Conf)
default:
return nil, fmt.Errorf("Unsupported folder type")
}
diff --git a/webapp/src/app/app.module.ts b/webapp/src/app/app.module.ts
index 4877f6e..10ff7a4 100644
--- a/webapp/src/app/app.module.ts
+++ b/webapp/src/app/app.module.ts
@@ -10,6 +10,7 @@ import { ModalModule } from 'ngx-bootstrap/modal';
import { AccordionModule } from 'ngx-bootstrap/accordion';
import { CarouselModule } from 'ngx-bootstrap/carousel';
import { PopoverModule } from 'ngx-bootstrap/popover';
+import { CollapseModule } from 'ngx-bootstrap/collapse';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
// Import the application components and services.
@@ -21,9 +22,11 @@ import { DlXdsAgentComponent, CapitalizePipe } from "./config/downloadXdsAgent.c
import { ProjectCardComponent } from "./projects/projectCard.component";
import { ProjectReadableTypePipe } from "./projects/projectCard.component";
import { ProjectsListAccordionComponent } from "./projects/projectsListAccordion.component";
+import { ProjectAddModalComponent} from "./projects/projectAddModal.component";
import { SdkCardComponent } from "./sdks/sdkCard.component";
import { SdksListAccordionComponent } from "./sdks/sdksListAccordion.component";
import { SdkSelectDropdownComponent } from "./sdks/sdkSelectDropdown.component";
+import { SdkAddModalComponent} from "./sdks/sdkAddModal.component";
import { HomeComponent } from "./home/home.component";
import { DevelComponent } from "./devel/devel.component";
@@ -52,6 +55,7 @@ import { SdkService } from "./services/sdk.service";
AccordionModule.forRoot(),
CarouselModule.forRoot(),
PopoverModule.forRoot(),
+ CollapseModule.forRoot(),
BsDropdownModule.forRoot(),
],
declarations: [
@@ -67,9 +71,11 @@ import { SdkService } from "./services/sdk.service";
ProjectCardComponent,
ProjectReadableTypePipe,
ProjectsListAccordionComponent,
+ ProjectAddModalComponent,
SdkCardComponent,
SdksListAccordionComponent,
SdkSelectDropdownComponent,
+ SdkAddModalComponent,
],
providers: [
AppRoutingProviders,
@@ -88,4 +94,4 @@ import { SdkService } from "./services/sdk.service";
bootstrap: [AppComponent]
})
export class AppModule {
-} \ No newline at end of file
+}
diff --git a/webapp/src/app/config/config.component.css b/webapp/src/app/config/config.component.css
index f480857..208ce6f 100644
--- a/webapp/src/app/config/config.component.css
+++ b/webapp/src/app/config/config.component.css
@@ -23,4 +23,4 @@ tr.info>th {
tr.info>td {
vertical-align: middle;
-} \ No newline at end of file
+}
diff --git a/webapp/src/app/config/config.component.html b/webapp/src/app/config/config.component.html
index 5211c2d..6af7f0d 100644
--- a/webapp/src/app/config/config.component.html
+++ b/webapp/src/app/config/config.component.html
@@ -1,11 +1,18 @@
<div class="panel panel-default">
- <div class="panel-heading clearfix">
- <h2 class="panel-title pull-left">Global Configuration</h2>
- <div class="pull-right">
- <span class="fa fa-fw fa-exchange fa-size-x2" [style.color]="((serverStatus$ | async)?.WS_connected)?'green':'red'"></span>
- </div>
+ <div class="panel-heading">
+ <h2 class="panel-title" (click)="gConfigIsCollapsed = !gConfigIsCollapsed">
+ Global Configuration
+ <div class="pull-right">
+ <span class="fa fa-fw fa-exchange fa-size-x2" [style.color]="((serverStatus$ | async)?.WS_connected)?'green':'red'"></span>
+
+ <button class="btn btn-link" (click)="gConfigIsCollapsed = !gConfigIsCollapsed; $event.stopPropagation()">
+ <span *ngIf="gConfigIsCollapsed" class="fa fa-angle-double-right fa-size-x2"></span>
+ <span *ngIf="!gConfigIsCollapsed" class="fa fa-angle-double-down fa-size-x2"></span>
+ </button>
+ </div>
+ </h2>
</div>
- <div class="panel-body">
+ <div class="panel-body" [collapse]="gConfigIsCollapsed">
<div class="row">
<div class="col-xs-12">
<table class="table table-condensed">
@@ -50,9 +57,19 @@
<div class="panel panel-default">
<div class="panel-heading">
- <h2 class="panel-title">Cross SDKs Configuration</h2>
+ <h2 class="panel-title" (click)="sdksIsCollapsed = !sdksIsCollapsed">
+ Cross SDKs
+ <div class="pull-right">
+ <button class="btn btn-link" (click)="childSdkModal.show(); $event.stopPropagation()"><span class="fa fa-plus fa-size-x2"></span></button>
+
+ <button class="btn btn-link" (click)="sdksIsCollapsed = !sdksIsCollapsed; $event.stopPropagation()">
+ <span *ngIf="sdksIsCollapsed" class="fa fa-angle-double-right fa-size-x2"></span>
+ <span *ngIf="!sdksIsCollapsed" class="fa fa-angle-double-down fa-size-x2"></span>
+ </button>
+ </div>
+ </h2>
</div>
- <div class="panel-body">
+ <div class="panel-body" [collapse]="sdksIsCollapsed">
<div class="row col-xs-12">
<sdks-list-accordion [sdks]="(sdks$ | async)"></sdks-list-accordion>
</div>
@@ -61,43 +78,30 @@
<div class="panel panel-default">
<div class="panel-heading">
- <h2 class="panel-title">Projects Configuration</h2>
- </div>
- <div class="panel-body">
- <form [formGroup]="addProjectForm" (ngSubmit)="onSubmit()">
- <div class="row ">
- <div class="col-xs-2">
- <button class="btn btn-primary" type="submit" [disabled]="!addProjectForm.valid"><i class="fa fa-plus"></i>&nbsp;Add Folder</button>
- </div>
+ <h2 class="panel-title" (click)="projectsIsCollapsed = !projectsIsCollapsed; $event.stopPropagation()">
+ Projects
+ <div class="pull-right">
+ <button class="btn btn-link" (click)="childProjectModal.show(); $event.stopPropagation()"><span class="fa fa-plus fa-size-x2"></span></button>
- <div class="col-xs-6">
- <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>
+ <button class="btn btn-link" (click)="projectsIsCollapsed = !projectsIsCollapsed; $event.stopPropagation()">
+ <span *ngIf="projectsIsCollapsed" class="fa fa-angle-double-right fa-size-x2"></span>
+ <span *ngIf="!projectsIsCollapsed" class="fa fa-angle-double-down fa-size-x2"></span>
+ </button>
</div>
- </form>
-
+ </h2>
+ </div>
+ <div class="panel-body" [collapse]="projectsIsCollapsed">
<div class="row col-xs-12">
<projects-list-accordion [projects]="(config$ | async).projects"></projects-list-accordion>
</div>
</div>
</div>
+<!-- Modals -->
+<project-add-modal #childProjectModal [title]="'Add a new project'">
+</project-add-modal>
+<sdk-add-modal #childSdkModal [title]="'Add a new SDK'">
+</sdk-add-modal>
<!-- only for debug -->
<div *ngIf="false" class="row">
diff --git a/webapp/src/app/config/config.component.ts b/webapp/src/app/config/config.component.ts
index 0df707b..b107e81 100644
--- a/webapp/src/app/config/config.component.ts
+++ b/webapp/src/app/config/config.component.ts
@@ -1,19 +1,16 @@
-import { Component, OnInit } from "@angular/core";
+import { Component, ViewChild, OnInit } from "@angular/core";
import { Observable } from 'rxjs/Observable';
import { FormControl, FormGroup, Validators, FormBuilder } from '@angular/forms';
+import { CollapseModule } from 'ngx-bootstrap/collapse';
-// Import RxJs required methods
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/filter';
-import 'rxjs/add/operator/debounceTime';
-
-import { ConfigService, IConfig, IProject, ProjectType, ProjectTypes,
- IxdsAgentPackage } from "../services/config.service";
+import { ConfigService, IConfig, 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";
import { AlertService } from "../services/alert.service";
import { ISdk, SdkService } from "../services/sdk.service";
+import { ProjectAddModalComponent } from "../projects/projectAddModal.component";
+import { SdkAddModalComponent } from "../sdks/sdkAddModal.component";
@Component({
templateUrl: './app/config/config.component.html',
@@ -24,6 +21,8 @@ import { ISdk, SdkService } from "../services/sdk.service";
// and from http://plnkr.co/edit/vCdjZM?p=preview
export class ConfigComponent implements OnInit {
+ @ViewChild('childProjectModal') childProjectModal: ProjectAddModalComponent;
+ @ViewChild('childSdkModal') childSdkModal: SdkAddModalComponent;
config$: Observable<IConfig>;
sdks$: Observable<ISdk[]>;
@@ -34,22 +33,21 @@ export class ConfigComponent implements OnInit {
curProj: number;
userEditedLabel: boolean = false;
xdsAgentPackages: IxdsAgentPackage[] = [];
- projectTypes = ProjectTypes;
+
+ gConfigIsCollapsed: boolean = true;
+ sdksIsCollapsed: boolean = true;
+ projectsIsCollapsed: boolean = false;
// TODO replace by reactive FormControl + add validation
syncToolUrl: string;
xdsAgentUrl: string;
xdsAgentRetry: string;
- projectsRootDir: string;
+ projectsRootDir: string; // FIXME: should be remove when projectAddModal will always return full path
showApplyBtn = { // Used to show/hide Apply buttons
"retry": false,
"rootDir": false,
};
- addProjectForm: FormGroup;
- pathCliCtrl = new FormControl("", Validators.required);
- pathSvrCtrl = new FormControl("", Validators.required);
-
constructor(
private configSvr: ConfigService,
private xdsServerSvr: XDSServerService,
@@ -57,19 +55,7 @@ export class ConfigComponent implements OnInit {
private stSvr: SyncthingService,
private sdkSvr: SdkService,
private alert: AlertService,
- private fb: FormBuilder
) {
- // 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({
- pathCli: this.pathCliCtrl,
- pathSvr: this.pathSvrCtrl,
- label: ["", Validators.nullValidator],
- type: [selectedType, Validators.pattern("[0-9]+")],
- });
}
ngOnInit() {
@@ -88,23 +74,6 @@ export class ConfigComponent implements OnInit {
this.xdsAgentPackages = cfg.xdsAgentPackages;
});
- // Auto create label name
- this.pathCliCtrl.valueChanges
- .debounceTime(100)
- .filter(n => n)
- .map(n => "Project_" + n.split('/')[0])
- .subscribe(value => {
- if (value && !this.userEditedLabel) {
- this.addProjectForm.patchValue({ label: value });
- }
- });
-
- // Select 1 first type by default
- // SEB this.typeCtrl.setValue({type: ProjectTypes[0].value});
- }
-
- onKeyLabel(event: any) {
- this.userEditedLabel = (this.addProjectForm.value.label !== "");
}
submitGlobConf(field: string) {
@@ -134,18 +103,4 @@ export class ConfigComponent implements OnInit {
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'],
- pathClient: formVal['pathCli'],
- pathServer: formVal['pathSvr'],
- type: numType,
- // FIXME: allow to set defaultSdkID from New Project config panel
- });
- }
-
}
diff --git a/webapp/src/app/projects/projectAddModal.component.css b/webapp/src/app/projects/projectAddModal.component.css
new file mode 100644
index 0000000..77f73a5
--- /dev/null
+++ b/webapp/src/app/projects/projectAddModal.component.css
@@ -0,0 +1,24 @@
+.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;
+}
+
+tr>th {
+ vertical-align: middle;
+}
+
+tr>td {
+ vertical-align: middle;
+}
+
+th label {
+ margin-bottom: 0;
+}
+
+td input {
+ width: 100%;
+}
diff --git a/webapp/src/app/projects/projectAddModal.component.html b/webapp/src/app/projects/projectAddModal.component.html
new file mode 100644
index 0000000..dc84985
--- /dev/null
+++ b/webapp/src/app/projects/projectAddModal.component.html
@@ -0,0 +1,54 @@
+<div bsModal #childProjectModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel"
+ [config]="{backdrop: 'static'}" aria-hidden="true">
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title pull-left">{{title}}</h4>
+ <button type="button" class="close pull-right" aria-label="Close" (click)="hide()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+
+ <form [formGroup]="addProjectForm" (ngSubmit)="onSubmit()">
+ <div class="modal-body">
+ <div class="row ">
+ <div class="col-xs-12">
+ <table class="table table-borderless">
+ <tbody>
+ <tr>
+ <th><label>Sharing Type </label></th>
+ <td><select class="form-control" formControlName="type">
+ <option *ngFor="let t of projectTypes" [value]="t.value">{{t.display}}
+ </option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <th><label for="select-local-path">Local Path </label></th>
+ <td><input type="text" id="select-local-path" formControlName="pathCli" placeholder="/tmp/myProject" (change)="onChangeLocalProject($event)"></td>
+ </tr>
+ <tr>
+ <th><label for="select-server-path">Server Path </label></th>
+ <td><input type="text" id="select-server-path" formControlName="pathSvr"></td>
+ </tr>
+ <tr>
+ <th><label for="select-label">Label </label></th>
+ <td><input type="text" formControlName="label" id="select-label" (keyup)="onKeyLabel($event)"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <div class="pull-left">
+ <button class="btn btn-default" (click)="cancelAction=true; hide()"> Cancel </button>
+ </div>
+ <div class="">
+ <button class="btn btn-primary" type="submit" [disabled]="!addProjectForm.valid">Add Folder</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
diff --git a/webapp/src/app/projects/projectAddModal.component.ts b/webapp/src/app/projects/projectAddModal.component.ts
new file mode 100644
index 0000000..47e9c89
--- /dev/null
+++ b/webapp/src/app/projects/projectAddModal.component.ts
@@ -0,0 +1,142 @@
+import { Component, Input, ViewChild, OnInit } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import { ModalDirective } from 'ngx-bootstrap/modal';
+import { FormControl, FormGroup, Validators, FormBuilder, ValidatorFn, AbstractControl } from '@angular/forms';
+
+// Import RxJs required methods
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/filter';
+import 'rxjs/add/operator/debounceTime';
+
+import { AlertService, IAlert } from "../services/alert.service";
+import {
+ ConfigService, IConfig, IProject, ProjectType, ProjectTypes,
+ IxdsAgentPackage
+} from "../services/config.service";
+
+
+@Component({
+ selector: 'project-add-modal',
+ templateUrl: './app/projects/projectAddModal.component.html',
+ styleUrls: ['./app/projects/projectAddModal.component.css']
+})
+export class ProjectAddModalComponent {
+ @ViewChild('childProjectModal') public childProjectModal: ModalDirective;
+ @Input() title?: string;
+
+ config$: Observable<IConfig>;
+
+ cancelAction: boolean = false;
+ userEditedLabel: boolean = false;
+ projectTypes = ProjectTypes;
+
+ addProjectForm: FormGroup;
+ typeCtrl: FormControl;
+ pathCliCtrl: FormControl;
+ pathSvrCtrl: FormControl;
+
+ constructor(
+ private alert: AlertService,
+ private configSvr: ConfigService,
+ private fb: FormBuilder
+ ) {
+ // Define types (first one is special/placeholder)
+ this.projectTypes.unshift({ value: -1, display: "--Select a type--" });
+
+ this.typeCtrl = new FormControl(this.projectTypes[0].value, Validators.pattern("[0-9]+"));
+ this.pathCliCtrl = new FormControl("", Validators.required);
+ this.pathSvrCtrl = new FormControl({ value: "", disabled: true }, [Validators.required, Validators.minLength(1)]);
+
+ this.addProjectForm = fb.group({
+ type: this.typeCtrl,
+ pathCli: this.pathCliCtrl,
+ pathSvr: this.pathSvrCtrl,
+ label: ["", Validators.nullValidator],
+ });
+ }
+
+ ngOnInit() {
+ this.config$ = this.configSvr.conf;
+
+ // Auto create label name
+ this.pathCliCtrl.valueChanges
+ .debounceTime(100)
+ .filter(n => n)
+ .map(n => "Project_" + n.split('/')[0])
+ .subscribe(value => {
+ if (value && !this.userEditedLabel) {
+ this.addProjectForm.patchValue({ label: value });
+ }
+ });
+
+ // Handle disabling of Server path
+ this.typeCtrl.valueChanges
+ .debounceTime(500)
+ .subscribe(valType => {
+ let dis = (valType === String(ProjectType.SYNCTHING));
+ this.pathSvrCtrl.reset({ value: "", disabled: dis });
+ });
+ }
+
+ show() {
+ this.cancelAction = false;
+ this.childProjectModal.show();
+ }
+
+ hide() {
+ this.childProjectModal.hide();
+ }
+
+ onKeyLabel(event: any) {
+ this.userEditedLabel = (this.addProjectForm.value.label !== "");
+ }
+
+ /* FIXME: change input to file type
+ <td><input type="file" id="select-local-path" webkitdirectory
+ formControlName="pathCli" placeholder="myProject" (change)="onChangeLocalProject($event)"></td>
+
+ onChangeLocalProject(e) {
+ if e.target.files.length < 1 {
+ console.log('SEB NO files');
+ }
+ let dir = e.target.files[0].webkitRelativePath;
+ console.log("SEB files: " + dir);
+ let u = URL.createObjectURL(e.target.files[0]);
+ }
+ */
+ onChangeLocalProject(e) {
+ }
+
+ onSubmit() {
+ if (this.cancelAction) {
+ return;
+ }
+
+ let formVal = this.addProjectForm.value;
+
+ let type = formVal['type'].value;
+ let numType = Number(formVal['type']);
+ this.configSvr.addProject({
+ label: formVal['label'],
+ pathClient: formVal['pathCli'],
+ pathServer: formVal['pathSvr'],
+ type: numType,
+ // FIXME: allow to set defaultSdkID from New Project config panel
+ })
+ .subscribe(prj => {
+ this.alert.info("Project " + prj.label + " successfully created.");
+ this.hide();
+
+ // Reset Value for the next creation
+ this.addProjectForm.reset();
+ let selectedType = this.projectTypes[0].value;
+ this.addProjectForm.patchValue({ type: selectedType });
+
+ },
+ err => {
+ this.alert.error("Configuration ERROR: " + err, 60);
+ this.hide();
+ });
+ }
+
+}
diff --git a/webapp/src/app/projects/projectCard.component.ts b/webapp/src/app/projects/projectCard.component.ts
index 23e10a6..1b89fe7 100644
--- a/webapp/src/app/projects/projectCard.component.ts
+++ b/webapp/src/app/projects/projectCard.component.ts
@@ -1,5 +1,6 @@
import { Component, Input, Pipe, PipeTransform } from '@angular/core';
import { ConfigService, IProject, ProjectType } from "../services/config.service";
+import { AlertService } from "../services/alert.service";
@Component({
selector: 'project-card',
@@ -46,12 +47,19 @@ export class ProjectCardComponent {
@Input() project: IProject;
- constructor(private configSvr: ConfigService) {
+ constructor(
+ private alert: AlertService,
+ private configSvr: ConfigService
+ ) {
}
delete(prj: IProject) {
- this.configSvr.deleteProject(prj);
+ this.configSvr.deleteProject(prj)
+ .subscribe(res => {
+ }, err => {
+ this.alert.error("Delete local ERROR: " + err);
+ });
}
}
diff --git a/webapp/src/app/sdks/sdkAddModal.component.html b/webapp/src/app/sdks/sdkAddModal.component.html
new file mode 100644
index 0000000..2c07fca
--- /dev/null
+++ b/webapp/src/app/sdks/sdkAddModal.component.html
@@ -0,0 +1,23 @@
+<div bsModal #sdkChildModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel"
+ aria-hidden="true">
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title pull-left">{{title}}</h4>
+ <button type="button" class="close pull-right" aria-label="Close" (click)="hideChildModal()">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <ng-content select=".modal-body"> </ng-content>
+ <i>Not available for now.</i>
+ </div>
+
+ <div class="modal-footer">
+ <div class="pull-left">
+ <button class="btn btn-default" (click)="hide()"> Cancel </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/webapp/src/app/sdks/sdkAddModal.component.ts b/webapp/src/app/sdks/sdkAddModal.component.ts
new file mode 100644
index 0000000..b6c8eb2
--- /dev/null
+++ b/webapp/src/app/sdks/sdkAddModal.component.ts
@@ -0,0 +1,24 @@
+import { Component, Input, ViewChild } from '@angular/core';
+import { ModalDirective } from 'ngx-bootstrap/modal';
+
+@Component({
+ selector: 'sdk-add-modal',
+ templateUrl: './app/sdks/sdkAddModal.component.html',
+})
+export class SdkAddModalComponent {
+ @ViewChild('sdkChildModal') public sdkChildModal: ModalDirective;
+
+ @Input() title?: string;
+
+ // TODO
+ constructor() {
+ }
+
+ show() {
+ this.sdkChildModal.show();
+ }
+
+ hide() {
+ this.sdkChildModal.hide();
+ }
+}
diff --git a/webapp/src/app/services/alert.service.ts b/webapp/src/app/services/alert.service.ts
index 9dab36a..c3cae7a 100644
--- a/webapp/src/app/services/alert.service.ts
+++ b/webapp/src/app/services/alert.service.ts
@@ -30,8 +30,10 @@ export class AlertService {
this.uid = 0;
}
- public error(msg: string) {
- this.add({ type: "danger", msg: msg, dismissible: true });
+ public error(msg: string, dismissTime?: number) {
+ this.add({
+ type: "danger", msg: msg, dismissible: true, dismissTimeout: dismissTime
+ });
}
public warning(msg: string, dismissible?: boolean) {
diff --git a/webapp/src/app/services/config.service.ts b/webapp/src/app/services/config.service.ts
index c65332f..3b51768 100644
--- a/webapp/src/app/services/config.service.ts
+++ b/webapp/src/app/services/config.service.ts
@@ -277,7 +277,7 @@ export class ConfigService {
return id.slice(0, 15);
}
- addProject(prj: IProject) {
+ addProject(prj: IProject): Observable<IProject> {
// Substitute tilde with to user home path
let pathCli = prj.pathClient.trim();
if (pathCli.charAt(0) === '~') {
@@ -304,57 +304,58 @@ export class ConfigService {
};
// Send config to XDS server
let newPrj = prj;
- this.xdsServerSvr.addProject(xdsPrj)
- .subscribe(resStRemotePrj => {
+ return this.xdsServerSvr.addProject(xdsPrj)
+ .flatMap(resStRemotePrj => {
newPrj.remotePrjDef = resStRemotePrj;
newPrj.id = resStRemotePrj.id;
+ newPrj.pathClient = resStRemotePrj.path;
- // 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: resStRemotePrj.id,
- label: xdsPrj.label,
- path: xdsPrj.path,
- serverSyncThingID: stData.builderSThgID
- };
-
- // Set local Syncthing config
- this.stSvr.addProject(stLocPrj)
- .subscribe(resStLocalPrj => {
- newPrj.localPrjDef = resStLocalPrj;
-
- // FIXME: maybe reduce subject to only .project
- //this.confSubject.next(Object.assign({}, this.confStore).project);
- this.confStore.projects.push(Object.assign({}, newPrj));
- this.confSubject.next(Object.assign({}, this.confStore));
- },
- err => {
- this.alert.error("Configuration local ERROR: " + err);
- });
- },
- err => {
- this.alert.error("Configuration remote ERROR: " + err);
+ if (newPrj.type === ProjectType.SYNCTHING) {
+ // 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: resStRemotePrj.id,
+ label: xdsPrj.label,
+ path: xdsPrj.path,
+ serverSyncThingID: stData.builderSThgID
+ };
+
+ // Set local Syncthing config
+ return this.stSvr.addProject(stLocPrj);
+
+ } else {
+ newPrj.pathServer = resStRemotePrj.dataPathMap.serverPath;
+ return Observable.of(null);
+ }
+ })
+ .map(resStLocalPrj => {
+ newPrj.localPrjDef = resStLocalPrj;
+
+ // FIXME: maybe reduce subject to only .project
+ //this.confSubject.next(Object.assign({}, this.confStore).project);
+ this.confStore.projects.push(Object.assign({}, newPrj));
+ this.confSubject.next(Object.assign({}, this.confStore));
+
+ return newPrj;
});
}
- deleteProject(prj: IProject) {
+ deleteProject(prj: IProject): Observable<IProject> {
let idx = this._getProjectIdx(prj.id);
+ let delPrj = prj;
if (idx === -1) {
throw new Error("Invalid project id (id=" + prj.id + ")");
}
- this.xdsServerSvr.deleteProject(prj.id)
- .subscribe(res => {
- this.stSvr.deleteProject(prj.id)
- .subscribe(res => {
- this.confStore.projects.splice(idx, 1);
- }, err => {
- this.alert.error("Delete local ERROR: " + err);
- });
- }, err => {
- this.alert.error("Delete remote ERROR: " + err);
+ return this.xdsServerSvr.deleteProject(prj.id)
+ .flatMap(res => {
+ return this.stSvr.deleteProject(prj.id);
+ })
+ .map(res => {
+ this.confStore.projects.splice(idx, 1);
+ return delPrj;
});
}
diff --git a/webapp/src/systemjs.config.js b/webapp/src/systemjs.config.js
index 19fe225..15c52ba 100644
--- a/webapp/src/systemjs.config.js
+++ b/webapp/src/systemjs.config.js
@@ -39,6 +39,7 @@
'ngx-bootstrap/carousel': 'npm:ngx-bootstrap/bundles/ngx-bootstrap.umd.min.js',
'ngx-bootstrap/popover': 'npm:ngx-bootstrap/bundles/ngx-bootstrap.umd.min.js',
'ngx-bootstrap/dropdown': 'npm:ngx-bootstrap/bundles/ngx-bootstrap.umd.min.js',
+ 'ngx-bootstrap/collapse': 'npm:ngx-bootstrap/bundles/ngx-bootstrap.umd.min.js',
// other libraries
'socket.io-client': 'npm:socket.io-client/dist/socket.io.min.js'
},
@@ -65,4 +66,4 @@
}
}
});
-})(this); \ No newline at end of file
+})(this);