fix in adding and editing markers
[u/erikhf/frm.git] / src / components / sidebar / sidebar.ts
1 import {Component, NgFor, NgIf, EventEmitter, NgModel, Control, ControlGroup, ControlArray, Validators, FormBuilder, CORE_DIRECTIVES,FORM_DIRECTIVES} from 'angular2/angular2';
2 import {Http, Headers} from 'angular2/http';
3
4 declare var zone:Zone;
5
6 @Component({
7     selector: 'mou-sidebar',
8     directives: [CORE_DIRECTIVES, FORM_DIRECTIVES, NgFor, NgModel, NgIf],
9     events: ['tempmarker', 'updateorg'],
10     templateUrl: './components/sidebar/sidebar.html'
11 })
12
13 export class Sidebar {
14     http:Http;
15     newObject:boolean;
16     editmode:boolean;
17     active:boolean;
18     coordinatePoint:boolean;
19
20     groupSets:Array<any> = [];
21     groupsDoubleArray:any[][] = [];
22
23     id:Control = new Control("");
24     name:Control = new Control("", Validators.required);
25     shortName:Control = new Control("", Validators.required);
26     description:Control = new Control("");
27     code:Control = new Control("");
28     openingDate:Control = new Control("", Validators.required);
29     closedDate:Control = new Control("");
30     url:Control = new Control("");
31     lat:Control = new Control("");
32     lng:Control = new Control("");
33     parent:Control = new Control("");
34     contactPerson:Control = new Control("");
35     address:Control = new Control("");
36     email:Control = new Control("");
37     phoneNumber:Control = new Control("");
38     exitButton:any;
39     featureType:Control = new Control("");
40     coordinates:Control = new Control("");
41     ctrlGroups:Array<Control> = [new Control('')];
42     groupsArray:ControlArray = new ControlArray(this.ctrlGroups);
43
44
45     form:ControlGroup = new ControlGroup({
46         organisationUnitGroups: this.groupsArray,
47         id: this.id,
48         name: this.name,
49         shortName: this.shortName,
50         description: this.description,
51         code: this.code,
52         openingDate: this.openingDate,
53         closedDate: this.closedDate,
54         url: this.url,
55         lat: this.lat,
56         lng: this.lng,
57         parent: this.parent,
58         contactPerson: this.contactPerson,
59         address: this.address,
60         email: this.email,
61         phoneNumber: this.phoneNumber,
62         featureType: this.featureType,
63         coordinates: this.coordinates
64     });
65
66     constructor(http:Http, fb:FormBuilder) {
67         this.http = http;
68         this.editmode = false;
69         this.active = false;
70         this.coordinatePoint = false;
71         this.tempmarker = new EventEmitter();
72         this.updateorg = new EventEmitter();
73         this.exitButton = document.getElementById("slideout")
74         let instance = this;
75
76         // listener for value change in coordinate input field
77         this.lat.valueChanges.observer({
78             next: (value) => {
79                 if (instance.lng.value && value) {
80                     let pos = {lat: value, lng: instance.lng.value};
81                     this.tempmarker.next(pos);
82                 }
83             }
84         });
85         this.lng.valueChanges.observer({
86             next: (value) => {
87                 if (instance.lat.value && value) {
88                     let pos = {lat: instance.lat.value, lng: value};
89                     this.tempmarker.next(pos);
90                 }
91             }
92         });
93
94         // find all orgUnitSets
95         this.findOrgUnitSets();
96     }
97
98     // this method is called when the sidebar should update its content with new org unit
99     update(orgunitId) {
100         this.active = true;
101         this.newObject = false;
102         this.http.get(dhisAPI + "/api/organisationUnits/" + orgunitId)
103             .map(res => res.json())
104             .subscribe(res => this.updateValues(res))
105     }
106
107     // update form values with new information from http get result
108     updateValues(res) {
109
110         // update the form controls with data from incoming json object
111         for (control in this.form.controls) {
112             if (this.form.controls[control] instanceof ControlArray) {
113                 console.log("nothing to do here");
114             }
115             else if (res[control] !== undefined) {
116                 this.form.controls[control].updateValue(res[control]);
117             }
118             else
119                 this.form.controls[control].updateValue("");
120
121         }
122
123         // Date fix:
124         if (res["openingDate"]) {
125             this.form.controls["openingDate"].updateValue((new Date(res["openingDate"].substring(0, 10))).toISOString().substring(0, 10));
126         }
127         if (res["closedDate"]) {
128             this.form.controls["closedDate"].updateValue((new Date(res["closedDate"].substring(0, 10))).toISOString().substring(0, 10));
129         }
130
131         // we're only interested in coordinates if it's a featureType point. Since we want to use two different input fields for lat and lang (and the api uses a single object for both)
132         // we need to have a separate data structure for coordinates, and update them manually
133         if (res.featureType === "POINT") {
134             this.coordinatePoint = true;
135             let coord = new Object();
136             coord = JSON.parse(res["coordinates"]);
137             this.form.controls.lat.updateValue(coord[1]);
138             this.form.controls.lng.updateValue(coord[0]);
139         }
140         else {
141             this.coordinatePoint = false;
142         }
143
144         // Update organisationUnitGroups with correct values from api
145         for (var i = 0; i < this.groupsDoubleArray.length; i++) {
146             for (var j = 0; j < this.groupsDoubleArray[i].length; j++) {
147                 for (group in res.organisationUnitGroups) {
148                     if (res.organisationUnitGroups[group].id == this.groupsDoubleArray[i][j].id) {
149                         this.form.controls.organisationUnitGroups.controls[i].updateValue(this.groupsDoubleArray[i][j].name);
150                     }
151                 }
152             }
153         }
154     }
155
156     // called on form submit
157     onSubmit() {
158         this.editmode = false;
159
160         let headers = new Headers();
161         headers.append('Accept', 'application/json');
162
163         headers.append('Content-Type', 'application/json');
164
165
166         let jsonObject = this.form.value;
167
168         // remove empty fields from the form object, no need to send empty values to the api
169         $.each(jsonObject, function (key, value) {
170             if (value === "" || value === null) {
171                 delete jsonObject[key];
172             }
173         });
174
175         // we were unable to find a way to associate a new (or existing) organisation unit with one or more organisationUnitGroups, so we're removing the data before posting to API
176         $.each(jsonObject.organisationUnitGroups, function (key, value) {
177 //            if( value === "" || value === null){
178             delete jsonObject.organisationUnitGroups[key];
179             //          } else {
180             //              jsonObject.organisationUnitGroups[key].id = value;
181             //         }
182         });
183
184         jsonObject.openingDate = (new Date(this.form.value.openingDate)).toISOString();
185
186         if (this.form.value.closedDate) {
187             jsonObject.closedDate = (new Date(this.form.value.closedDate)).toISOString();
188         }
189
190         if (this.coordinatePoint) {
191             jsonObject.featureType = "POINT";
192             jsonObject.coordinates = "[" + this.form.controls.lng.value + "," + this.form.controls.lat.value + "]";
193         }
194
195         // POST if the object is new, PUT if it's an update to an existing orgUnit
196         if (this.newObject) {
197             jsonObject.parent = {};
198             jsonObject.parent.id = this.form.controls.parent.value;
199
200             delete jsonObject["lat"];
201             delete jsonObject["lng"];
202             this.http.post(dhisAPI + "/api/organisationUnits/", JSON.stringify(jsonObject), {
203                     headers: headers
204                 })
205                 .map(res => res.json())
206                 .subscribe(res => this.emitNewUpdatedObject(res));
207         } else {
208             this.http.put(dhisAPI + "/api/organisationUnits/" + this.form.controls.id.value, JSON.stringify(jsonObject), {
209                     headers: headers
210                 })
211                 .map(res => res.json())
212                 .subscribe(res => this.emitNewUpdatedObject(res));
213         }
214     }
215
216     // emit an event that the current orgUnit has been updated (useful for map component)
217     emitNewUpdatedObject(obj) {
218         this.updateorg.next(obj.response.lastImported);
219     }
220
221     // cancel editing orgUnit
222     cancel() {
223         this.editmode = false;
224         this.tempmarker.next(null);
225     }
226
227     // Prepare sidebar for adding new object. Receiving location and parent for the new orgUnit
228     add(data) {
229         this.coordinatePoint = true;
230         this.newObject = true;
231         this.active = true;
232         this.editmode = true;
233
234         for (control in this.form.controls) {
235             if (!(this.form.controls[control] instanceof ControlArray))
236                 this.form.controls[control].updateValue("");
237         }
238
239         this.form.controls.lat.updateValue(data.location.lat);
240         this.form.controls.lng.updateValue(data.location.lng);
241         this.form.controls.featureType.updateValue("POINT");
242         this.form.controls.parent.updateValue(data.parent);
243
244     }
245
246     // dismiss sidebar
247     exit() {
248         this.active = false;
249     }
250
251     // dynamically find all orgUnitSets for populating input selects
252     findOrgUnitSets() {
253         let instance = this;
254         this.http.get(dhisAPI + "/api/organisationUnitGroupSets?paging=false")
255             .map(res => res.json())
256             .map(res => res.organisationUnitGroupSets)
257             .subscribe(res => this.addOrgUnitSets(instance, res))
258     }
259
260     // adding the orgUnitSets from the api
261     addOrgUnitSets(instance, res) {
262         //delete instance.ctrlGroups[0];
263         for (group in res) {
264             instance.groupsArray.push(new Control(''));
265             instance.groupSets.push(res[group]);
266
267             this.http.get(dhisAPI + "/api/organisationUnitGroupSets/" + res[group].id)
268                 .map(res => res.json())
269                 .map(res => res.organisationUnitGroups)
270                 .subscribe(res => this.addOrgUnitGroup(instance, res))
271
272         }
273     }
274
275     // add orgUnitGroup as option to input selects
276     addOrgUnitGroup(instance, res) {
277         let ar:Array<any> = [];
278         for (group in res) {
279             ar.push(res[group]);
280         }
281         instance.groupsDoubleArray.push(ar);
282     }
283 }
284