fix in adding and editing markers
[u/erikhf/frm.git] / src / components / map / map.ts
... / ...
CommitLineData
1import {Component, EventEmitter,CORE_DIRECTIVES,} from 'angular2/angular2';
2import {Headers, Http} from 'angular2/http';
3
4@Component({
5 selector: 'mou-map',
6 directives: [CORE_DIRECTIVES],
7 events: ['newactive', 'neworg'],
8 templateUrl: './components/map/map.html'
9})
10
11
12export class Map {
13
14 hideModal:any;
15 map:Object;
16 http:Http;
17 LEVEL:number;
18 allLevels:Object;
19 runned:boolean;
20 uprunned:boolean;
21 parent:Object;
22 activeId:string;
23 currentPos:Object;
24 currentMarker:Object;
25 isSearched:boolean;
26 popupON:boolean;
27 popup:Object;
28 COLORS:Object;
29 colornum:number;
30
31 /**
32 * initializes all the global variabels
33 * @param http - for http requests
34 */
35 constructor(http:Http) {
36
37 this.activeId = null;
38 this.newactive = new EventEmitter();
39 this.neworg = new EventEmitter();
40 this.map = new google.maps.Map(document.getElementById("map"), {
41 center: {lat: 0, lng: 0},
42 zoom: 12,
43 mapTypeControlOptions: {
44 position: google.maps.ControlPosition.BOTTOM_CENTER
45 },
46 zoomControlOptions: {
47 position: google.maps.ControlPosition.LEFT_BOTTOM
48 },
49 streetViewControl: false
50 });
51 this.init();
52 this.http = http;
53 this.LEVEL = 2;//
54 this.runned = false;
55 this.getLevels(this);
56 this.parent = null;
57 this.currentPos = null;
58 this.uprunned = false;
59 this.currentMarker = null;
60 this.isSearched = false;
61 this.colornum = 0;
62 this.COLORS = ['#ede1bb', '#1d407e', '#ff512e', '#662d47', '#3b3a35', '#419175', '#983e41', '#f3002d', '#b0a875', '#00bfb5', '#926851', '#47a0a4', '#333f50', '#6f007b'];
63 this.popupON = false;
64 this.popup = null;
65 }
66
67
68 /**
69 * Sets the global variabel
70 * @param id - id of the active marker
71 */
72 setActiveId(id) {
73 this.activeId = id;
74 }
75
76 /**
77 * returns the global map
78 * @returns {Object}
79 */
80 getMap() {
81 return this.map;
82 }
83
84 /**
85 * returns global http
86 * @returns {Http}
87 */
88 getHttp() {
89 return this.http;
90 }
91
92 /**
93 * Sets the avctive markers position
94 * @param latlng - position of the active marker
95 */
96 setcurrentPos(latlng) {
97 this.currentPos = latlng;
98 }
99
100 /**
101 * returns the active markers position
102 * @returns {Object}
103 */
104 getcurrentPos() {
105 return this.currentPos;
106 }
107
108 /**
109 * sets the parent of the avtive marker
110 * @param id - of the parent
111 */
112 setParent(id) {
113 this.parent = id;
114 }
115
116 /**
117 * returns the actice markers parent
118 * @returns {Object}
119 */
120 getParent() {
121 return this.parent;
122 }
123
124 /**
125 * sets a bool value for if the addListner for drilling down has runned (little hack)
126 * @param value - for the runned variabel
127 */
128 setRunned(value) {
129 this.runned = value;
130 }
131
132 /**
133 * sets a bool value for if the addListner for drilling up has runned (little hack)
134 * @param value - for the upRunned variabel
135 */
136 setupRunned(value) {
137 this.uprunned = value;
138 }
139
140 /**
141 * sets the current level in the org.unit hierarchy
142 * @param value - for the level variabel
143 */
144 setLevel(value) {
145 this.LEVEL = value;
146 }
147
148 /**
149 * add level when drilling down (little hack for synconisity)
150 */
151 addLevel() {
152 this.LEVEL++;
153 }
154
155 /**
156 * goes up level when drilling up (little hack for synconisity)
157 */
158 upLevel() {
159 this.LEVEL--;
160 }
161
162 /**
163 * initiates the map with position and zoom
164 */
165 init() {
166
167 let map = this.map;
168 let pos = {lat: 9.1, lng: -11.6};
169 map.setCenter(pos, 0);
170 map.setZoom(7);
171
172 }
173
174 /**
175 * prints out error messages in the console
176 * @param error - the error massage
177 */
178 logError(error) {
179 console.error(error);
180
181 }
182
183 /**
184 * gets data from DHIS API
185 * @param query - for what kind of data to retrieve
186 * @param instance - this instance to use
187 * @param isParent - little hack to see if you want to levels up (the parent of a parent)
188 */
189 getData(query, instance, isParent) {
190 instance.http.get(dhisAPI + '/api/organisationUnits' + query)
191 .map(res => res.json())
192 .subscribe(
193 res => instance.parseResult(res, instance, isParent),
194 error => instance.logError(error)
195 );
196 }
197
198 /**
199 * Gets the number of levels in the org.unit hierarchy from DHIS
200 */
201 getLevels() {
202 this.http.get(dhisAPI + '/api/organisationUnitLevels')
203 .map(res => res.json())
204 .subscribe(
205 res => this.saveLevelTotalandGetdata(res, this),
206 err => this.logError(err)
207 );
208 }
209
210 /**
211 * Saves the data from getLevels() in a global variabel and gets all the data from the second level.
212 * @param res - result from getLevels()
213 * @param instance - witch scope we are in
214 */
215 saveLevelTotalandGetdata(res, instance) {
216 instance.allLevels = res.pager.total;
217 instance.getData('?paging=false&level=2', instance, false);
218 }
219
220 /**
221 * parses all the data from getData() and calles methods based on the incomming data.
222 * @param res - result from getData()
223 * @param instance - witch scope we are in
224 * @param isParent - if it is a parent we have asked for
225 */
226 parseResult(res, instance, isParent) {
227 if (isParent) {
228 instance.setParent(res.parent.id);
229 instance.getData('/' + res.parent.id + '/children', instance, false);
230 }
231 else {
232 if (res.organisationUnits) {
233 for (let item in res.organisationUnits) {
234 this.getData('/' + res.organisationUnits[item].id, this);
235
236 }
237 instance.setupRunned(false);
238 instance.setRunned(false);
239 } else if (!res.displayName && res.children) {
240 for (let item in res.children) {
241 if (res.children[item].level == instance.LEVEL) {
242 this.getData('/' + res.children[item].id, this);
243 }
244 }
245 instance.setRunned(false);
246 instance.setupRunned(false);
247 }
248 else {
249 this.drawPolygon(res, instance);
250 }
251 }
252 }
253
254 /**
255 * creates and draws up the geojson polygons and adds listeners to them.
256 * @param item - an org.unit object
257 * @param instance - witch scope we are in
258 */
259 drawPolygon(item, instance) {
260 let feature;
261 let incoming:string;
262 incoming = item.featureType.toLowerCase();
263 switch (incoming) {
264 case "point":
265 feature = 'Point';
266 break;
267 case "multi_polygon":
268 feature = 'MultiPolygon';
269 break;
270 case "polygon":
271 feature = 'MultiPolygon';
272 break;
273 default:
274 }
275
276 if (feature !== undefined) {
277 let unit = {
278 "type": "Feature",
279 "geometry": {
280 "type": feature,
281 "coordinates": JSON.parse(item.coordinates)
282 },
283 "properties": {
284 "title": item.name,
285 "name": item.name,
286 "id": item.id,
287 "color": instance.COLORS[instance.colornum],
288 "icon": null
289 }
290 };
291 if (instance.COLORS.length == instance.colornum) {
292 instance.colornum = 0;
293 } else {
294 instance.colornum++;
295 }
296
297 if (unit.geometry.type == 'Point') {
298 unit.properties.icon = {
299 path: google.maps.SymbolPath.CIRCLE,
300 strokeColor: 'black',
301 scale: 4
302 };
303 instance.map.setCenter({lat: unit.geometry.coordinates[1], lng: unit.geometry.coordinates[0]});
304 }
305
306 this.map.data.addGeoJson(unit);
307 this.map.data.setStyle(function (feature) {
308 let color = 'gray';
309 let icon;
310 if (feature.getProperty('icon') !== null) {
311 icon = feature.getProperty('icon');
312 }
313 color = feature.getProperty('color');
314 return /** @type {google.maps.Data.StyleOptions} */({
315 fillColor: color,
316 fillOpacity: 0.91,
317 strokeColor: 'white',
318 strokeWeight: 2,
319 icon: icon
320 });
321 });
322 if (instance.isSearched) {
323 instance.seeDetails();
324 }
325 this.map.data.addListener('click', function (event) {
326 $('#myModal').modal('show');
327 instance.setActiveId(event.feature.O.id);
328 instance.setcurrentPos(event.latLng);
329
330 if (instance.uprunned == false && instance.LEVEL == 2) {
331 this.hideModal = document.getElementById("topLevel").style.display = "block";
332 this.hideModal = document.getElementById("middleLevel").style.display = "none";
333 this.hideModal = document.getElementById("bottomLevel").style.display = "none";
334 }
335 else if (instance.runned == false && instance.LEVEL < instance.allLevels) {
336 this.hideModal = document.getElementById("topLevel").style.display = "none";
337 this.hideModal = document.getElementById("middleLevel").style.display = "block";
338 this.hideModal = document.getElementById("bottomLevel").style.display = "none";
339 } else if (instance.runned == false && instance.LEVEL <= instance.allLevels) {
340 this.hideModal = document.getElementById("topLevel").style.display = "none";
341 this.hideModal = document.getElementById("middleLevel").style.display = "none";
342 this.hideModal = document.getElementById("bottomLevel").style.display = "block";
343
344 instance.setcurrentPos(event.latLng);
345 }
346 });
347
348//slette ?? §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
349 /* this.map.data.addListener('mouseover', function (e) {


350 if(!instance.popupON) {
351 instance.popupON = true;
352
353 instance.popup = new google.maps.InfoWindow({
354 content: e.feature.getProperty('name'),
355 position: e.latLng
356 });
357 instance.popup.open(instance.map);
358
359 }
360 });

361 this.map.data.addListener('mouseout', function (event) {


362 instance.popupON = false;
363 instance.popup.open(null);

364 });*/
365
366 }
367 }
368
369 /**
370 * removes the polygon on current level and calles getData on one level down in the org.unit hierarchy
371 */
372 drillDown() {
373 this.closeModal();
374 let map = this.getMap();
375 let id = this.activeId;
376 let level = this.LEVEL;
377 this.setRunned(true);
378 this.setParent(id);
379
380 map.data.forEach(function (feature) {
381 if (!(feature.O.id == id && level == 3)) {
382 map.data.remove(feature);
383
384 }
385 });
386
387 this.addLevel();
388 this.getData('/' + id + '/children', this);
389
390 }
391
392 /**
393 *removes the plogons on the current level and calles the get data with tha parents id and set parent true. this to say that we want this parent's parent
394 */
395 drillUp() {
396 this.setupRunned(true);
397 this.upLevel();
398 let instance = this;
399 this.closeModal();
400 this.map.data.forEach(function (feature) {
401 instance.map.data.remove(feature);
402
403 });
404 if (this.currentMarker !== null) {
405 this.currentMarker.setMap(null);
406 }
407 let parent = instance.getParent();
408 instance.getData('/' + parent, instance, true);
409
410 this.closeModal();
411 }
412
413 /**
414 * focuses map and colors to the clicked marker/polygon and fires an event to sidebar with the id of the marker
415 */
416 seeDetails() {
417
418 console.log("inne i seeDetails");
419 let map = this.getMap();
420 let id = this.activeId;
421 let instance = this;
422 this.closeModal();
423 map.data.forEach(function (feature) {
424 if (feature.getProperty('id') == id) {
425 feature.setProperty('color', 'red');
426 if (feature.getProperty('icon') !== null) {
427 feature.O.icon.strokeColor = 'red';
428 }
429 this.isSearched = false;
430 console.log(this.isSearched);
431 }
432 else {
433 feature.setProperty('color', 'gray');
434 if (feature.getProperty('icon') !== null) {
435 feature.O.icon.strokeColor = 'black';
436 }
437 }
438 });
439 this.newactive.next(this.activeId);
440 }
441
442 /**
443 * gets the position of the clicked position on the map, saves the parent and sends it in an event.
444 */
445 addUnit() {
446 this.closeModal();
447 let pos = this.getcurrentPos();
448 let lat = pos.lat();
449 let lng = pos.lng();
450 let parent = this.getParent();
451
452 let location = {lat: lat, lng: lng};
453 let event = {location, parent};
454 this.neworg.next(event);
455 this.closeModal();
456 this.setRunned(false);
457 }
458
459 /**
460 * triggered from an event in search and gets the search object from the DHIS API
461 * then calles mapupdate()
462 * @param event - event from an emitter
463 */
464 update(event) {
465 if(event !== null) {
466 if (this.currentMarker) {
467 this.currentMarker.setMap(null);
468 }
469
470 this.newactive.next(event);
471 let map = this.getMap();
472 let http = this.getHttp();
473
474 map.data.forEach(function (feature) {
475 map.data.remove(feature);
476 });
477 http.get(dhisAPI + '/api/organisationUnits/' + event)
478 .map(res => res.json())
479 .subscribe(
480 res => this.mapUpdate(res, this)
481 );
482 }
483 }
484
485 /**
486 * updates varabels activeId, level and parent to matche the incomming object and gets all the children on the same level.
487 * Then it calles drawPolygon()
488 * @param res - org.unit object
489 * @param instance
490 */
491 mapUpdate(res, instance) {
492 this.setLevel(res.level);
493 this.setActiveId(res.id);
494 this.isSearched = true;
495 this.setParent(res.parent.id);
496 // this.setcurrentPos({lat: JSON.parse(res.coordinates)[1],lng: JSON.parse(res.coordinates)[0]});
497
498 instance.getData('/' + res.parent.id + '/children', instance);
499 if (res.coordinates == null || instance.LEVEL == instance.allLevels) {
500 instance.http.get(dhisAPI + '/api/organisationUnits/' + res.parent.id)
501 .map(res => res.json())
502 .subscribe(
503 res => instance.drawPolygon(res, instance)
504 );
505 }
506
507 }
508
509 /**
510 * adds a temperary marker so the user can see an update of the latitude and longitude of a marker
511 * @param pos - position for the temp marker
512 */
513 tempMarker(pos) {
514 if (this.currentMarker)
515 this.currentMarker.setMap(null);
516 if(pos != null) {
517 let current = {};
518 current.lat = Math.round(this.getcurrentPos().lat() * 10000) / 10000;
519 current.lng = Math.round(this.getcurrentPos().lng() * 10000) / 10000;
520
521 let position = {};
522 position.lat = Math.round(pos.lat * 10000) / 10000;
523 position.lng = Math.round(pos.lng * 10000) / 10000;
524
525 if ((current.lat != position.lat) || (current.lng != position.lng)) {
526
527 let map = this.map;
528
529
530 this.currentMarker = new google.maps.Marker({
531 position: pos,
532 map: map,
533 title: 'neworg',
534 icon: {
535 path: google.maps.SymbolPath.CIRCLE,
536 strokeColor: "#871F78",
537 scale: 4
538 }
539 });
540 this.currentMarker.setMap(map);
541 map.panTo(this.currentMarker.getPosition());
542 }
543 }
544
545 }
546
547
548 /**
549 * closes the modal box over the map.
550 */
551 closeModal() {
552 $("#myModal").modal("hide");
553 this.setRunned(false);
554 }
555
556}
557
558
559
560
561