53adc8032dcda7cae55a6062a9e58cf3512b7663
[src/xds/xds-agent.git] / webapp / src / app / services / project.service.ts
1 import { Injectable, SecurityContext } from '@angular/core';
2 import { Observable } from 'rxjs/Observable';
3 import { BehaviorSubject } from 'rxjs/BehaviorSubject';
4
5 import { XDSAgentService, IXDSProjectConfig } from "../services/xdsagent.service";
6
7 export enum ProjectType {
8     UNSET = "",
9     NATIVE_PATHMAP = "PathMap",
10     SYNCTHING = "CloudSync"
11 }
12
13 export var ProjectTypes = [
14     { value: ProjectType.NATIVE_PATHMAP, display: "Path mapping" },
15     { value: ProjectType.SYNCTHING, display: "Cloud Sync" }
16 ];
17
18 export var ProjectStatus = {
19     ErrorConfig: "ErrorConfig",
20     Disable: "Disable",
21     Enable: "Enable",
22     Pause: "Pause",
23     Syncing: "Syncing"
24 };
25
26 export interface IProject {
27     id?: string;
28     serverId: string;
29     label: string;
30     pathClient: string;
31     pathServer?: string;
32     type: ProjectType;
33     status?: string;
34     isInSync?: boolean;
35     isUsable?: boolean;
36     serverPrjDef?: IXDSProjectConfig;
37     isExpanded?: boolean;
38     visible?: boolean;
39     defaultSdkID?: string;
40 }
41
42 @Injectable()
43 export class ProjectService {
44     public Projects$: Observable<IProject[]>;
45
46     private _prjsList: IProject[] = [];
47     private current: IProject;
48     private prjsSubject = <BehaviorSubject<IProject[]>>new BehaviorSubject(this._prjsList);
49
50     constructor(private xdsSvr: XDSAgentService) {
51         this.current = null;
52         this.Projects$ = this.prjsSubject.asObservable();
53
54         this.xdsSvr.getProjects().subscribe((projects) => {
55             this._prjsList = [];
56             projects.forEach(p => {
57                 this._addProject(p, true);
58             });
59             this.prjsSubject.next(Object.assign([], this._prjsList));
60         });
61
62         // Update Project data
63         this.xdsSvr.ProjectState$.subscribe(prj => {
64             let i = this._getProjectIdx(prj.id);
65             if (i >= 0) {
66                 // XXX for now, only isInSync and status may change
67                 this._prjsList[i].isInSync = prj.isInSync;
68                 this._prjsList[i].status = prj.status;
69                 this._prjsList[i].isUsable = this._isUsableProject(prj);
70                 this.prjsSubject.next(Object.assign([], this._prjsList));
71             }
72         });
73
74         // Add listener on create and delete project events
75         this.xdsSvr.addEventListener('event:project-add', (ev) => {
76             if (ev && ev.data && ev.data.id) {
77                 this._addProject(ev.data);
78             } else {
79                 console.log("Warning: received events with unknown data: ev=", ev);
80             }
81         });
82         this.xdsSvr.addEventListener('event:project-delete', (ev) => {
83             if (ev && ev.data && ev.data.id) {
84                 let idx = this._prjsList.findIndex(item => item.id === ev.data.id);
85                 if (idx === -1) {
86                     console.log("Warning: received events on unknown project id: ev=", ev);
87                     return;
88                 }
89                 this._prjsList.splice(idx, 1);
90                 this.prjsSubject.next(Object.assign([], this._prjsList));
91             } else {
92                 console.log("Warning: received events with unknown data: ev=", ev);
93             }
94         });
95
96     }
97
98     public setCurrent(s: IProject) {
99         this.current = s;
100     }
101
102     public getCurrent(): IProject {
103         return this.current;
104     }
105
106     public getCurrentId(): string {
107         if (this.current && this.current.id) {
108             return this.current.id;
109         }
110         return "";
111     }
112
113     Add(prj: IProject): Observable<IProject> {
114         let xdsPrj: IXDSProjectConfig = {
115             id: "",
116             serverId: prj.serverId,
117             label: prj.label || "",
118             clientPath: prj.pathClient.trim(),
119             serverPath: prj.pathServer,
120             type: prj.type,
121             defaultSdkID: prj.defaultSdkID,
122         };
123         // Send config to XDS server
124         return this.xdsSvr.addProject(xdsPrj)
125             .map(xdsPrj => this._convToIProject(xdsPrj));
126     }
127
128     Delete(prj: IProject): Observable<IProject> {
129         let idx = this._getProjectIdx(prj.id);
130         let delPrj = prj;
131         if (idx === -1) {
132             throw new Error("Invalid project id (id=" + prj.id + ")");
133         }
134         return this.xdsSvr.deleteProject(prj.id)
135             .map(res => { return delPrj; });
136     }
137
138     Sync(prj: IProject): Observable<string> {
139         let idx = this._getProjectIdx(prj.id);
140         if (idx === -1) {
141             throw new Error("Invalid project id (id=" + prj.id + ")");
142         }
143         return this.xdsSvr.syncProject(prj.id);
144     }
145
146     private _isUsableProject(p) {
147         return p && p.isInSync &&
148             (p.status === ProjectStatus.Enable) &&
149             (p.status !== ProjectStatus.Syncing);
150     }
151
152     private _getProjectIdx(id: string): number {
153         return this._prjsList.findIndex((item) => item.id === id);
154     }
155
156     private _convToIProject(rPrj: IXDSProjectConfig): IProject {
157         // Convert XDSFolderConfig to IProject
158         let pp: IProject = {
159             id: rPrj.id,
160             serverId: rPrj.serverId,
161             label: rPrj.label,
162             pathClient: rPrj.clientPath,
163             pathServer: rPrj.serverPath,
164             type: rPrj.type,
165             status: rPrj.status,
166             isInSync: rPrj.isInSync,
167             isUsable: this._isUsableProject(rPrj),
168             defaultSdkID: rPrj.defaultSdkID,
169             serverPrjDef: Object.assign({}, rPrj),  // do a copy
170         };
171         return pp;
172     }
173
174     private _addProject(rPrj: IXDSProjectConfig, noNext?: boolean): IProject {
175
176         // Convert XDSFolderConfig to IProject
177         let pp = this._convToIProject(rPrj);
178
179         // add new project
180         this._prjsList.push(pp);
181
182         // sort project array
183         this._prjsList.sort((a, b) => {
184             if (a.label < b.label) {
185                 return -1;
186             }
187             if (a.label > b.label) {
188                 return 1;
189             }
190             return 0;
191         });
192
193         if (!noNext) {
194             this.prjsSubject.next(Object.assign([], this._prjsList));
195         }
196
197         return pp;
198     }
199 }