3 * Copyright (C) 2017-2018 "IoT.bzh"
4 * Author Sebastien Douheret <sebastien@iot.bzh>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import { Injectable, SecurityContext, isDevMode } from '@angular/core';
20 import { Observable } from 'rxjs/Observable';
21 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
23 import { XDSAgentService, IXDSProjectConfig } from '../services/xdsagent.service';
25 /* FIXME: syntax only compatible with TS>2.4.0
26 export enum ProjectType {
28 NATIVE_PATHMAP = 'PathMap',
29 SYNCTHING = 'CloudSync'
32 export type ProjectTypeEnum = '' | 'PathMap' | 'CloudSync';
33 export const ProjectType = {
35 NATIVE_PATHMAP: 'PathMap',
36 SYNCTHING: 'CloudSync',
39 export const ProjectTypes = [
40 { value: ProjectType.NATIVE_PATHMAP, display: 'Path mapping' },
41 { value: ProjectType.SYNCTHING, display: 'Cloud Sync' },
44 export const ProjectStatus = {
45 ErrorConfig: 'ErrorConfig',
52 export interface IUISettings {
61 export interface IProject {
67 type: ProjectTypeEnum;
71 serverPrjDef?: IXDSProjectConfig;
74 defaultSdkID?: string;
75 uiSettings?: IUISettings;
78 const defaultUISettings: IUISettings = {
80 cmdClean: 'rm -rf build && echo Done',
81 cmdPrebuild: 'mkdir -p build && cd build && cmake ..',
82 cmdBuild: 'cd build && make',
83 cmdPopulate: 'cd build && make remote-target-populate',
89 export class ProjectService {
90 projects$: Observable<IProject[]>;
91 curProject$: Observable<IProject>;
93 private _prjsList: IProject[] = [];
94 private prjsSubject = <BehaviorSubject<IProject[]>>new BehaviorSubject(this._prjsList);
95 private _current: IProject;
96 private curPrjSubject = <BehaviorSubject<IProject>>new BehaviorSubject(this._current);
98 constructor(private xdsSvr: XDSAgentService) {
100 this.projects$ = this.prjsSubject.asObservable();
101 this.curProject$ = this.curPrjSubject.asObservable();
103 // Load initial projects list
104 this.xdsSvr.getProjects().subscribe((projects) => {
106 projects.forEach(p => {
107 this._addProject(p, true);
110 // TODO: get previous val from xds-config service / cookie
111 if (this._prjsList.length > 0) {
112 this._current = this._prjsList[0];
113 this.curPrjSubject.next(this._current);
116 this.prjsSubject.next(this._prjsList);
119 // Add listener on projects creation, deletion and change events
120 this.xdsSvr.onProjectAdd().subscribe(prj => this._addProject(prj));
121 this.xdsSvr.onProjectDelete().subscribe(prj => this._delProject(prj));
122 this.xdsSvr.onProjectChange().subscribe(prj => this._updateProject(prj));
125 setCurrent(p: IProject): IProject | undefined {
127 this._current = null;
130 return this.setCurrentById(p.id);
133 setCurrentById(id: string): IProject | undefined {
134 const p = this._prjsList.find(item => item.id === id);
137 this.curPrjSubject.next(this._current);
139 return this._current;
142 getCurrent(): IProject {
143 return this._current;
146 add(prj: IProject): Observable<IProject> {
147 // Send config to XDS server
148 return this.xdsSvr.addProject(this._convToIXdsProject(prj))
149 .map(xp => this._convToIProject(xp));
152 delete(prj: IProject): Observable<IProject> {
153 const idx = this._getProjectIdx(prj.id);
156 throw new Error('Invalid project id (id=' + prj.id + ')');
158 return this.xdsSvr.deleteProject(prj.id)
162 sync(prj: IProject): Observable<string> {
163 const idx = this._getProjectIdx(prj.id);
165 throw new Error('Invalid project id (id=' + prj.id + ')');
167 return this.xdsSvr.syncProject(prj.id);
170 setSettings(prj: IProject): Observable<IProject> {
171 return this.xdsSvr.updateProject(this._convToIXdsProject(prj))
172 .map(xp => this._convToIProject(xp));
175 getDefaultSettings(): IUISettings {
176 return defaultUISettings;
179 /*** Private functions ***/
181 private _isUsableProject(p) {
182 return p && p.isInSync &&
183 (p.status === ProjectStatus.Enable) &&
184 (p.status !== ProjectStatus.Syncing);
187 private _getProjectIdx(id: string): number {
188 return this._prjsList.findIndex((item) => item.id === id);
192 private _convToIXdsProject(prj: IProject): IXDSProjectConfig {
193 const xPrj: IXDSProjectConfig = {
195 serverId: prj.serverId,
196 label: prj.label || '',
197 clientPath: prj.pathClient.trim(),
198 serverPath: prj.pathServer,
200 defaultSdkID: prj.defaultSdkID,
201 clientData: JSON.stringify(prj.uiSettings || defaultUISettings),
206 private _convToIProject(rPrj: IXDSProjectConfig): IProject {
207 let settings = defaultUISettings;
208 if (rPrj.clientData && rPrj.clientData !== '') {
209 settings = JSON.parse(rPrj.clientData);
212 // Convert XDSFolderConfig to IProject
213 const pp: IProject = {
215 serverId: rPrj.serverId,
217 pathClient: rPrj.clientPath,
218 pathServer: rPrj.serverPath,
221 isInSync: rPrj.isInSync,
222 isUsable: this._isUsableProject(rPrj),
223 defaultSdkID: rPrj.defaultSdkID,
224 serverPrjDef: Object.assign({}, rPrj), // do a copy
225 uiSettings: settings,
230 private _addProject(prj: IXDSProjectConfig, noNext?: boolean): IProject {
232 // Convert XDSFolderConfig to IProject
233 const pp = this._convToIProject(prj);
236 this._prjsList.push(pp);
238 // sort project array
239 this._prjsList.sort((a, b) => {
240 if (a.label < b.label) {
243 if (a.label > b.label) {
250 this.prjsSubject.next(this._prjsList);
256 private _delProject(prj: IXDSProjectConfig) {
257 const idx = this._prjsList.findIndex(item => item.id === prj.id);
260 /* tslint:disable:no-console */
261 console.log('Warning: Try to delete project unknown id: prj=', prj);
265 const delId = this._prjsList[idx].id;
266 this._prjsList.splice(idx, 1);
267 if (delId === this._current.id) {
268 this.setCurrent(this._prjsList[0]);
270 this.prjsSubject.next(this._prjsList);
273 private _updateProject(prj: IXDSProjectConfig) {
274 const i = this._getProjectIdx(prj.id);
276 // XXX for now, only isInSync and status may change
277 this._prjsList[i].isInSync = prj.isInSync;
278 this._prjsList[i].status = prj.status;
279 this._prjsList[i].isUsable = this._isUsableProject(prj);
280 this.prjsSubject.next(this._prjsList);