diff options
Diffstat (limited to 'webapp/src/app/@core-xds/services')
8 files changed, 297 insertions, 98 deletions
diff --git a/webapp/src/app/@core-xds/services/alert.service.spec.ts b/webapp/src/app/@core-xds/services/alert.service.spec.ts index b3d364c..2de2ac3 100644 --- a/webapp/src/app/@core-xds/services/alert.service.spec.ts +++ b/webapp/src/app/@core-xds/services/alert.service.spec.ts @@ -3,13 +3,13 @@ import { TestBed, inject } from '@angular/core/testing'; import { AlertService } from './alert.service'; describe('AlertService', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [AlertService] - }); + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [AlertService], }); + }); - it('should be created', inject([AlertService], (service: AlertService) => { - expect(service).toBeTruthy(); - })); + it('should be created', inject([AlertService], (service: AlertService) => { + expect(service).toBeTruthy(); + })); }); diff --git a/webapp/src/app/@core-xds/services/alert.service.ts b/webapp/src/app/@core-xds/services/alert.service.ts index c15e176..23a5e5d 100644 --- a/webapp/src/app/@core-xds/services/alert.service.ts +++ b/webapp/src/app/@core-xds/services/alert.service.ts @@ -31,7 +31,7 @@ export class AlertService { public error(msg: string, dismissTime?: number) { this.add({ - type: 'error', msg: msg, dismissible: true, dismissTimeout: dismissTime + type: 'error', msg: msg, dismissible: true, dismissTimeout: dismissTime, }); } diff --git a/webapp/src/app/@core-xds/services/build-settings.service.ts b/webapp/src/app/@core-xds/services/build-settings.service.ts new file mode 100644 index 0000000..cb52ce3 --- /dev/null +++ b/webapp/src/app/@core-xds/services/build-settings.service.ts @@ -0,0 +1,78 @@ +import { Injectable } from '@angular/core'; +import { CookieService } from 'ngx-cookie'; +import { Observable } from 'rxjs/Observable'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; + +export interface IBuildSettings { + subpath: string; + cmdClean: string; + cmdPrebuild: string; + cmdBuild: string; + cmdPopulate: string; + cmdArgs: string[]; + envVars: string[]; +} + +@Injectable() +export class BuildSettingsService { + public settings$: Observable<IBuildSettings>; + + private settingsSubject: BehaviorSubject<IBuildSettings>; + private settingsStore: IBuildSettings; + + constructor( + private cookie: CookieService, + ) { + this._load(); + } + + // Load build settings from cookie + private _load() { + // Try to retrieve previous config from cookie + const cookConf = this.cookie.getObject('xds-build-settings'); + if (cookConf != null) { + this.settingsStore = <IBuildSettings>cookConf; + } else { + // Set default config + this.settingsStore = { + subpath: '', + cmdClean: 'rm -rf build && echo Done', + cmdPrebuild: 'mkdir -p build && cd build && cmake ..', + cmdBuild: 'cd build && make', + cmdPopulate: 'cd build && make remote-target-populate', + cmdArgs: [], + envVars: [], + }; + } + } + + // Save config into cookie + private _save() { + // Notify subscribers + this.settingsSubject.next(Object.assign({}, this.settingsStore)); + + const cfg = Object.assign({}, this.settingsStore); + this.cookie.putObject('xds-build-settings', cfg); + } + + // Get whole config values + get(): IBuildSettings { + return this.settingsStore; + } + + // Get whole config values + set(bs: IBuildSettings) { + this.settingsStore = bs; + this._save(); + } + + get subpath(): string { + return this.settingsStore.subpath; + } + + set subpath(p: string) { + this.settingsStore.subpath = p; + this._save(); + } + +} diff --git a/webapp/src/app/@core-xds/services/config.service.spec.ts b/webapp/src/app/@core-xds/services/config.service.spec.ts index a20d4ba..f39b9d9 100644 --- a/webapp/src/app/@core-xds/services/config.service.spec.ts +++ b/webapp/src/app/@core-xds/services/config.service.spec.ts @@ -5,7 +5,7 @@ import { ConfigService } from './config.service'; describe('ConfigService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [ConfigService] + providers: [ConfigService], }); }); diff --git a/webapp/src/app/@core-xds/services/project.service.spec.ts b/webapp/src/app/@core-xds/services/project.service.spec.ts index b8edfc7..0924a73 100644 --- a/webapp/src/app/@core-xds/services/project.service.spec.ts +++ b/webapp/src/app/@core-xds/services/project.service.spec.ts @@ -5,7 +5,7 @@ import { ProjectService } from './project.service'; describe('ProjectService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [ProjectService] + providers: [ProjectService], }); }); diff --git a/webapp/src/app/@core-xds/services/project.service.ts b/webapp/src/app/@core-xds/services/project.service.ts index 8aeed80..94469fe 100644 --- a/webapp/src/app/@core-xds/services/project.service.ts +++ b/webapp/src/app/@core-xds/services/project.service.ts @@ -1,4 +1,4 @@ -import { Injectable, SecurityContext } from '@angular/core'; +import { Injectable, SecurityContext, isDevMode } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; @@ -15,12 +15,12 @@ export type ProjectTypeEnum = '' | 'PathMap' | 'CloudSync'; export const ProjectType = { UNSET: '', NATIVE_PATHMAP: 'PathMap', - SYNCTHING: 'CloudSync' + SYNCTHING: 'CloudSync', }; export const ProjectTypes = [ { value: ProjectType.NATIVE_PATHMAP, display: 'Path mapping' }, - { value: ProjectType.SYNCTHING, display: 'Cloud Sync' } + { value: ProjectType.SYNCTHING, display: 'Cloud Sync' }, ]; export const ProjectStatus = { @@ -28,9 +28,18 @@ export const ProjectStatus = { Disable: 'Disable', Enable: 'Enable', Pause: 'Pause', - Syncing: 'Syncing' + Syncing: 'Syncing', }; +export interface IUISettings { + subpath: string; + cmdClean: string; + cmdPrebuild: string; + cmdBuild: string; + cmdPopulate: string; + cmdArgs: string[]; + envVars: string[]; +} export interface IProject { id?: string; serverId: string; @@ -45,95 +54,84 @@ export interface IProject { isExpanded?: boolean; visible?: boolean; defaultSdkID?: string; + uiSettings?: IUISettings; } +const defaultUISettings: IUISettings = { + subpath: '', + cmdClean: 'rm -rf build && echo Done', + cmdPrebuild: 'mkdir -p build && cd build && cmake ..', + cmdBuild: 'cd build && make', + cmdPopulate: 'cd build && make remote-target-populate', + cmdArgs: [], + envVars: [], +}; + @Injectable() export class ProjectService { - public Projects$: Observable<IProject[]>; + projects$: Observable<IProject[]>; + curProject$: Observable<IProject>; private _prjsList: IProject[] = []; - private current: IProject; private prjsSubject = <BehaviorSubject<IProject[]>>new BehaviorSubject(this._prjsList); + private _current: IProject; + private curPrjSubject = <BehaviorSubject<IProject>>new BehaviorSubject(this._current); constructor(private xdsSvr: XDSAgentService) { - this.current = null; - this.Projects$ = this.prjsSubject.asObservable(); + this._current = null; + this.projects$ = this.prjsSubject.asObservable(); + this.curProject$ = this.curPrjSubject.asObservable(); + // Load initial projects list this.xdsSvr.getProjects().subscribe((projects) => { this._prjsList = []; projects.forEach(p => { this._addProject(p, true); }); - this.prjsSubject.next(Object.assign([], this._prjsList)); - }); - // Update Project data - this.xdsSvr.ProjectState$.subscribe(prj => { - const i = this._getProjectIdx(prj.id); - if (i >= 0) { - // XXX for now, only isInSync and status may change - this._prjsList[i].isInSync = prj.isInSync; - this._prjsList[i].status = prj.status; - this._prjsList[i].isUsable = this._isUsableProject(prj); - this.prjsSubject.next(Object.assign([], this._prjsList)); + // TODO: get previous val from xds-config service / cookie + if (this._prjsList.length > 0) { + this._current = this._prjsList[0]; + this.curPrjSubject.next(this._current); } - }); - // Add listener on create and delete project events - this.xdsSvr.addEventListener('event:project-add', (ev) => { - if (ev && ev.data && ev.data.id) { - this._addProject(ev.data); - } else { - console.log('Warning: received events with unknown data: ev=', ev); - } - }); - this.xdsSvr.addEventListener('event:project-delete', (ev) => { - if (ev && ev.data && ev.data.id) { - const idx = this._prjsList.findIndex(item => item.id === ev.data.id); - if (idx === -1) { - console.log('Warning: received events on unknown project id: ev=', ev); - return; - } - this._prjsList.splice(idx, 1); - this.prjsSubject.next(Object.assign([], this._prjsList)); - } else { - console.log('Warning: received events with unknown data: ev=', ev); - } + this.prjsSubject.next(this._prjsList); }); + // Add listener on projects creation, deletion and change events + this.xdsSvr.onProjectAdd().subscribe(prj => this._addProject(prj)); + this.xdsSvr.onProjectDelete().subscribe(prj => this._delProject(prj)); + this.xdsSvr.onProjectChange().subscribe(prj => this._updateProject(prj)); } - public setCurrent(s: IProject) { - this.current = s; + setCurrent(p: IProject): IProject | undefined { + if (!p) { + this._current = null; + return undefined; + } + return this.setCurrentById(p.id); } - public getCurrent(): IProject { - return this.current; + setCurrentById(id: string): IProject | undefined { + const p = this._prjsList.find(item => item.id === id); + if (p) { + this._current = p; + this.curPrjSubject.next(this._current); + } + return this._current; } - public getCurrentId(): string { - if (this.current && this.current.id) { - return this.current.id; - } - return ''; + getCurrent(): IProject { + return this._current; } - Add(prj: IProject): Observable<IProject> { - const xdsPrj: IXDSProjectConfig = { - id: '', - serverId: prj.serverId, - label: prj.label || '', - clientPath: prj.pathClient.trim(), - serverPath: prj.pathServer, - type: prj.type, - defaultSdkID: prj.defaultSdkID, - }; + add(prj: IProject): Observable<IProject> { // Send config to XDS server - return this.xdsSvr.addProject(xdsPrj) + return this.xdsSvr.addProject(this._convToIXdsProject(prj)) .map(xp => this._convToIProject(xp)); } - Delete(prj: IProject): Observable<IProject> { + delete(prj: IProject): Observable<IProject> { const idx = this._getProjectIdx(prj.id); const delPrj = prj; if (idx === -1) { @@ -143,7 +141,7 @@ export class ProjectService { .map(res => delPrj); } - Sync(prj: IProject): Observable<string> { + sync(prj: IProject): Observable<string> { const idx = this._getProjectIdx(prj.id); if (idx === -1) { throw new Error('Invalid project id (id=' + prj.id + ')'); @@ -151,6 +149,17 @@ export class ProjectService { return this.xdsSvr.syncProject(prj.id); } + setSettings(prj: IProject): Observable<IProject> { + return this.xdsSvr.updateProject(this._convToIXdsProject(prj)) + .map(xp => this._convToIProject(xp)); + } + + getDefaultSettings(): IUISettings { + return defaultUISettings; + } + + /*** Private functions ***/ + private _isUsableProject(p) { return p && p.isInSync && (p.status === ProjectStatus.Enable) && @@ -161,7 +170,27 @@ export class ProjectService { return this._prjsList.findIndex((item) => item.id === id); } + + private _convToIXdsProject(prj: IProject): IXDSProjectConfig { + const xPrj: IXDSProjectConfig = { + id: prj.id || '', + serverId: prj.serverId, + label: prj.label || '', + clientPath: prj.pathClient.trim(), + serverPath: prj.pathServer, + type: prj.type, + defaultSdkID: prj.defaultSdkID, + clientData: JSON.stringify(prj.uiSettings || defaultUISettings), + }; + return xPrj; + } + private _convToIProject(rPrj: IXDSProjectConfig): IProject { + let settings = defaultUISettings; + if (rPrj.clientData && rPrj.clientData !== '') { + settings = JSON.parse(rPrj.clientData); + } + // Convert XDSFolderConfig to IProject const pp: IProject = { id: rPrj.id, @@ -175,14 +204,15 @@ export class ProjectService { isUsable: this._isUsableProject(rPrj), defaultSdkID: rPrj.defaultSdkID, serverPrjDef: Object.assign({}, rPrj), // do a copy + uiSettings: settings, }; return pp; } - private _addProject(rPrj: IXDSProjectConfig, noNext?: boolean): IProject { + private _addProject(prj: IXDSProjectConfig, noNext?: boolean): IProject { // Convert XDSFolderConfig to IProject - const pp = this._convToIProject(rPrj); + const pp = this._convToIProject(prj); // add new project this._prjsList.push(pp); @@ -199,9 +229,38 @@ export class ProjectService { }); if (!noNext) { - this.prjsSubject.next(Object.assign([], this._prjsList)); + this.prjsSubject.next(this._prjsList); } return pp; } + + private _delProject(prj: IXDSProjectConfig) { + const idx = this._prjsList.findIndex(item => item.id === prj.id); + if (idx === -1) { + if (isDevMode) { + /* tslint:disable:no-console */ + console.log('Warning: Try to delete project unknown id: prj=', prj); + } + return; + } + const delId = this._prjsList[idx].id; + this._prjsList.splice(idx, 1); + if (this._prjsList[idx].id === this._current.id) { + this.setCurrent(this._prjsList[0]); + } + this.prjsSubject.next(this._prjsList); + } + + private _updateProject(prj: IXDSProjectConfig) { + const i = this._getProjectIdx(prj.id); + if (i >= 0) { + // XXX for now, only isInSync and status may change + this._prjsList[i].isInSync = prj.isInSync; + this._prjsList[i].status = prj.status; + this._prjsList[i].isUsable = this._isUsableProject(prj); + this.prjsSubject.next(this._prjsList); + } + } + } diff --git a/webapp/src/app/@core-xds/services/xds-config.service.ts b/webapp/src/app/@core-xds/services/xds-config.service.ts index 7559673..2f751a7 100644 --- a/webapp/src/app/@core-xds/services/xds-config.service.ts +++ b/webapp/src/app/@core-xds/services/xds-config.service.ts @@ -47,7 +47,7 @@ export class XDSConfigService { } getCurServer(): IXDServerCfg { - return Object.assign({}, this._curServer); + return this._curServer; } setCurServer(svr: IXDServerCfg): Observable<IXDServerCfg> { @@ -58,7 +58,7 @@ export class XDSConfigService { .map(cfg => this._updateCurServer()) .catch(err => { this._curServer.connected = false; - this.curServer$.next(Object.assign({}, this._curServer)); + this.curServer$.next(this._curServer); return Observable.throw(err); }); } else { @@ -66,7 +66,7 @@ export class XDSConfigService { return this.xdsAgentSvr.setServerRetry(curSvr.id, svr.connRetry) .map(cfg => this._updateCurServer()) .catch(err => { - this.curServer$.next(Object.assign({}, this._curServer)); + this.curServer$.next(this._curServer); return Observable.throw(err); }); } @@ -76,7 +76,7 @@ export class XDSConfigService { private _updateCurServer() { this._curServer = this._getCurServer(); - this.curServer$.next(Object.assign({}, this._curServer)); + this.curServer$.next(this._curServer); } private _getCurServer(url?: string): IXDServerCfg { diff --git a/webapp/src/app/@core-xds/services/xdsagent.service.ts b/webapp/src/app/@core-xds/services/xdsagent.service.ts index 56e493f..06ca557 100644 --- a/webapp/src/app/@core-xds/services/xdsagent.service.ts +++ b/webapp/src/app/@core-xds/services/xdsagent.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Inject } from '@angular/core'; +import { Injectable, Inject, isDevMode } from '@angular/core'; import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http'; import { DOCUMENT } from '@angular/common'; import { Observable } from 'rxjs/Observable'; @@ -44,6 +44,7 @@ export interface IXDSProjectConfig { status?: string; isInSync?: boolean; defaultSdkID: string; + clientData?: string; } export interface IXDSVer { @@ -107,12 +108,16 @@ export class XDSAgentService { public XdsConfig$: Observable<IXDSConfig>; public Status$: Observable<IAgentStatus>; - public ProjectState$ = <Subject<IXDSProjectConfig>>new Subject(); public CmdOutput$ = <Subject<ICmdOutput>>new Subject(); public CmdExit$ = <Subject<ICmdExit>>new Subject(); + protected projectAdd$ = new Subject<IXDSProjectConfig>(); + protected projectDel$ = new Subject<IXDSProjectConfig>(); + protected projectChange$ = new Subject<IXDSProjectConfig>(); + private baseUrl: string; private wsUrl: string; + private httpSessionID: string; private _config = <IXDSConfig>{ servers: [] }; private _status = { connected: false, servers: [] }; @@ -130,14 +135,25 @@ export class XDSAgentService { const originUrl = this.document.location.origin; this.baseUrl = originUrl + '/api/v1'; - const re = originUrl.match(/http[s]?:\/\/([^\/]*)[\/]?/); - if (re === null || re.length < 2) { - console.error('ERROR: cannot determine Websocket url'); - } else { - this.wsUrl = 'ws://' + re[1]; - this._handleIoSocket(); - this._RegisterEvents(); - } + // Retrieve Session ID / token + this.http.get(this.baseUrl + '/version', { observe: 'response' }) + .subscribe( + resp => { + this.httpSessionID = resp.headers.get('xds-agent-sid'); + + const re = originUrl.match(/http[s]?:\/\/([^\/]*)[\/]?/); + if (re === null || re.length < 2) { + console.error('ERROR: cannot determine Websocket url'); + } else { + this.wsUrl = 'ws://' + re[1]; + this._handleIoSocket(); + this._RegisterEvents(); + } + }, + err => { + /* tslint:disable:no-console */ + console.error('ERROR while retrieving session id:', err); + }); } private _NotifyXdsAgentState(sts: boolean) { @@ -182,6 +198,8 @@ export class XDSAgentService { console.error('WS error:', err); }); + // XDS Events decoding + this.socket.on('make:output', data => { this.CmdOutput$.next(Object.assign({}, <ICmdOutput>data)); }); @@ -198,8 +216,6 @@ export class XDSAgentService { this.CmdExit$.next(Object.assign({}, <ICmdExit>data)); }); - // Events - // (project-add and project-delete events are managed by project.service) this.socket.on('event:server-config', ev => { if (ev && ev.data) { const cfg: IXDServerCfg = ev.data; @@ -212,19 +228,52 @@ export class XDSAgentService { } }); + this.socket.on('event:project-add', (ev) => { + if (ev && ev.data && ev.data.id) { + this.projectAdd$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Project "' + ev.data.label + '" has been added by another tool.'); + } + } else if (isDevMode) { + /* tslint:disable:no-console */ + console.log('Warning: received event:project-add with unknown data: ev=', ev); + } + }); + + this.socket.on('event:project-delete', (ev) => { + if (ev && ev.data && ev.data.id) { + this.projectDel$.next(Object.assign({}, ev.data)); + if (ev.sessionID !== this.httpSessionID && ev.data.label) { + this.alert.info('Project "' + ev.data.label + '" has been deleted by another tool.'); + } + } else if (isDevMode) { + console.log('Warning: received event:project-delete with unknown data: ev=', ev); + } + }); + this.socket.on('event:project-state-change', ev => { if (ev && ev.data) { - this.ProjectState$.next(Object.assign({}, ev.data)); + this.projectChange$.next(Object.assign({}, ev.data)); + } else if (isDevMode) { + console.log('Warning: received event:project-state-change with unknown data: ev=', ev); } }); } /** - ** Events + ** Events registration ***/ - addEventListener(ev: string, fn: Function): SocketIOClient.Emitter { - return this.socket.addEventListener(ev, fn); + onProjectAdd(): Observable<IXDSProjectConfig> { + return this.projectAdd$.asObservable(); + } + + onProjectDelete(): Observable<IXDSProjectConfig> { + return this.projectDel$.asObservable(); + } + + onProjectChange(): Observable<IXDSProjectConfig> { + return this.projectChange$.asObservable(); } /** @@ -307,6 +356,10 @@ export class XDSAgentService { return this._delete('/projects/' + id); } + updateProject(cfg: IXDSProjectConfig): Observable<IXDSProjectConfig> { + return this._put('/projects/' + cfg.id, cfg); + } + syncProject(id: string): Observable<string> { return this._post('/projects/sync/' + id, {}); } @@ -337,8 +390,8 @@ export class XDSAgentService { res => { }, error => { this.alert.error('ERROR while registering to all events: ' + error); - } - ); + }, + ); } private _getServer(ID: string): IXDServerCfg { @@ -371,6 +424,12 @@ export class XDSAgentService { return this._decodeError(error); }); } + private _put(url: string, body: any): Observable<any> { + return this.http.put(this.baseUrl + url, JSON.stringify(body), this._attachAuthHeaders()) + .catch((error) => { + return this._decodeError(error); + }); + } private _delete(url: string): Observable<any> { return this.http.delete(this.baseUrl + url, this._attachAuthHeaders()) .catch(this._decodeError); @@ -391,7 +450,10 @@ export class XDSAgentService { } else { e = err.message ? err.message : err.toString(); } - console.log('xdsagent.service - ERROR: ', e); + /* tslint:disable:no-console */ + if (isDevMode) { + console.log('xdsagent.service - ERROR: ', e); + } return Observable.throw(e); } } |