fix in adding and editing markers
[u/erikhf/frm.git] / src / components / map / map.ts
CommitLineData
7ee898bc 1import {Component, EventEmitter,CORE_DIRECTIVES,} from 'angular2/angular2';
a2d7d6b4 2import {Headers, Http} from 'angular2/http';
cb2c4ba8
JHR
3
4@Component({
28765058 5 selector: 'mou-map',
cb2c4ba8 6 directives: [CORE_DIRECTIVES],
0fc3af96 7 events: ['newactive', 'neworg'],
28765058 8 templateUrl: './components/map/map.html'
cb2c4ba8
JHR
9})
10
11
28765058 12export class Map {
6ced1bc7 13
0fc3af96 14 hideModal:any;
dd095993 15 map:Object;
65c7cdf5
JHR
16 http:Http;
17 LEVEL:number;
57a79ad4 18 allLevels:Object;
65c7cdf5 19 runned:boolean;
65c7cdf5 20 uprunned:boolean;
57a79ad4 21 parent:Object;
59ffa1e6 22 activeId:string;
57a79ad4 23 currentPos:Object;
59ffa1e6 24 currentMarker:Object;
e58627b7 25 isSearched:boolean;
d7f50e3a
JHR
26 popupON:boolean;
27 popup:Object;
2e861c75 28 COLORS:Object;
17574902 29 colornum:number;
19468546 30
17574902
JHR
31 /**
32 * initializes all the global variabels
33 * @param http - for http requests
34 */
dd095993 35 constructor(http:Http) {
59ffa1e6
JHR
36
37 this.activeId = null;
7ee898bc 38 this.newactive = new EventEmitter();
ebaf2f58 39 this.neworg = new EventEmitter();
f800869b
EHF
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 },
57a79ad4 46 zoomControlOptions: {
f800869b
EHF
47 position: google.maps.ControlPosition.LEFT_BOTTOM
48 },
49 streetViewControl: false
50 });
6ced1bc7
JHR
51 this.init();
52 this.http = http;
57a79ad4 53 this.LEVEL = 2;//
0d91e9f9 54 this.runned = false;
57a79ad4 55 this.getLevels(this);
65c7cdf5 56 this.parent = null;
a8451d12 57 this.currentPos = null;
951b1c9f 58 this.uprunned = false;
59ffa1e6 59 this.currentMarker = null;
e58627b7 60 this.isSearched = false;
2e861c75 61 this.colornum = 0;
17574902 62 this.COLORS = ['#ede1bb', '#1d407e', '#ff512e', '#662d47', '#3b3a35', '#419175', '#983e41', '#f3002d', '#b0a875', '#00bfb5', '#926851', '#47a0a4', '#333f50', '#6f007b'];
d7f50e3a 63 this.popupON = false;
58627f9c 64 this.popup = null;
784566de 65 }
9d471cab 66
ac22d373 67
17574902
JHR
68 /**
69 * Sets the global variabel
fb027b00 70 * @param id - id of the active marker
17574902 71 */
57a79ad4
JHR
72 setActiveId(id) {
73 this.activeId = id;
74 }
9992f01a 75
17574902
JHR
76 /**
77 * returns the global map
78 * @returns {Object}
79 */
57a79ad4
JHR
80 getMap() {
81 return this.map;
82 }
330dd6d3 83
17574902
JHR
84 /**
85 * returns global http
86 * @returns {Http}
87 */
57a79ad4
JHR
88 getHttp() {
89 return this.http;
90 }
b41d2490 91
17574902
JHR
92 /**
93 * Sets the avctive markers position
94 * @param latlng - position of the active marker
95 */
57a79ad4
JHR
96 setcurrentPos(latlng) {
97 this.currentPos = latlng;
98 }
b41d2490 99
17574902
JHR
100 /**
101 * returns the active markers position
102 * @returns {Object}
103 */
57a79ad4
JHR
104 getcurrentPos() {
105 return this.currentPos;
106 }
9d471cab 107
17574902
JHR
108 /**
109 * sets the parent of the avtive marker
110 * @param id - of the parent
111 */
57a79ad4
JHR
112 setParent(id) {
113 this.parent = id;
114 }
59ffa1e6 115
17574902
JHR
116 /**
117 * returns the actice markers parent
118 * @returns {Object}
119 */
57a79ad4
JHR
120 getParent() {
121 return this.parent;
122 }
9992f01a 123
17574902
JHR
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 */
57a79ad4
JHR
128 setRunned(value) {
129 this.runned = value;
130 }
36f8898a 131
17574902
JHR
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 */
57a79ad4
JHR
136 setupRunned(value) {
137 this.uprunned = value;
138 }
65c7cdf5 139
17574902
JHR
140 /**
141 * sets the current level in the org.unit hierarchy
142 * @param value - for the level variabel
143 */
57a79ad4
JHR
144 setLevel(value) {
145 this.LEVEL = value;
146 }
9992f01a 147
17574902
JHR
148 /**
149 * add level when drilling down (little hack for synconisity)
150 */
57a79ad4
JHR
151 addLevel() {
152 this.LEVEL++;
153 }
65c7cdf5 154
17574902
JHR
155 /**
156 * goes up level when drilling up (little hack for synconisity)
157 */
57a79ad4
JHR
158 upLevel() {
159 this.LEVEL--;
160 }
b470b939 161
19468546
JHR
162 /**
163 * initiates the map with position and zoom
164 */
6ced1bc7 165 init() {
a2d7d6b4 166
6ced1bc7 167 let map = this.map;
b27f57f1 168 let pos = {lat: 9.1, lng: -11.6};
b27f57f1
JHR
169 map.setCenter(pos, 0);
170 map.setZoom(7);
171
a2d7d6b4
JHR
172 }
173
19468546
JHR
174 /**
175 * prints out error messages in the console
17574902 176 * @param error - the error massage
19468546 177 */
a2d7d6b4
JHR
178 logError(error) {
179 console.error(error);
180
cb2c4ba8 181 }
28765058 182
19468546
JHR
183 /**
184 * gets data from DHIS API
185 * @param query - for what kind of data to retrieve
186 * @param instance - this instance to use
17574902 187 * @param isParent - little hack to see if you want to levels up (the parent of a parent)
19468546 188 */
65c7cdf5
JHR
189 getData(query, instance, isParent) {
190 instance.http.get(dhisAPI + '/api/organisationUnits' + query)
6ced1bc7
JHR
191 .map(res => res.json())
192 .subscribe(
65c7cdf5 193 res => instance.parseResult(res, instance, isParent),
c7e8b786 194 error => instance.logError(error)
6ced1bc7 195 );
6ced1bc7
JHR
196 }
197
19468546 198 /**
17574902 199 * Gets the number of levels in the org.unit hierarchy from DHIS
19468546 200 */
57a79ad4
JHR
201 getLevels() {
202 this.http.get(dhisAPI + '/api/organisationUnitLevels')
203 .map(res => res.json())
204 .subscribe(
e58627b7 205 res => this.saveLevelTotalandGetdata(res, this),
57a79ad4
JHR
206 err => this.logError(err)
207 );
208 }
209
17574902
JHR
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 */
e58627b7 215 saveLevelTotalandGetdata(res, instance) {
57a79ad4 216 instance.allLevels = res.pager.total;
e58627b7 217 instance.getData('?paging=false&level=2', instance, false);
57a79ad4
JHR
218 }
219
17574902
JHR
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 */
65c7cdf5 226 parseResult(res, instance, isParent) {
65c7cdf5 227 if (isParent) {
03c7df04 228 instance.setParent(res.parent.id);
65c7cdf5 229 instance.getData('/' + res.parent.id + '/children', instance, false);
03c7df04 230 }
65c7cdf5 231 else {
951b1c9f
JHR
232 if (res.organisationUnits) {
233 for (let item in res.organisationUnits) {
234 this.getData('/' + res.organisationUnits[item].id, this);
235
b470b939 236 }
951b1c9f 237 instance.setupRunned(false);
03c7df04 238 instance.setRunned(false);
951b1c9f
JHR
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);
b470b939 247 }
951b1c9f
JHR
248 else {
249 this.drawPolygon(res, instance);
250 }
03c7df04 251 }
6ced1bc7 252 }
57a79ad4 253
17574902
JHR
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 */
65c7cdf5 259 drawPolygon(item, instance) {
1f8c27ee 260 let feature;
65c7cdf5 261 let incoming:string;
1f8c27ee 262 incoming = item.featureType.toLowerCase();
65c7cdf5 263 switch (incoming) {
1f8c27ee
JHR
264 case "point":
265 feature = 'Point';
266 break;
267 case "multi_polygon":
268 feature = 'MultiPolygon';
269 break;
65c7cdf5
JHR
270 case "polygon":
271 feature = 'MultiPolygon';
1f8c27ee
JHR
272 break;
273 default:
274 }
2cab9a95 275
65c7cdf5 276 if (feature !== undefined) {
1f8c27ee
JHR
277 let unit = {
278 "type": "Feature",
279 "geometry": {
280 "type": feature,
281 "coordinates": JSON.parse(item.coordinates)
282 },
283 "properties": {
e58627b7 284 "title": item.name,
1f8c27ee 285 "name": item.name,
98cc809b 286 "id": item.id,
17574902 287 "color": instance.COLORS[instance.colornum],
15b422d5 288 "icon": null
65c7cdf5 289 }
1f8c27ee 290 };
17574902 291 if (instance.COLORS.length == instance.colornum) {
2e861c75 292 instance.colornum = 0;
17574902
JHR
293 } else {
294 instance.colornum++;
295 }
2e861c75 296
65c7cdf5 297 if (unit.geometry.type == 'Point') {
15b422d5
JHR
298 unit.properties.icon = {
299 path: google.maps.SymbolPath.CIRCLE,
b3b5cc9c 300 strokeColor: 'black',
ac22d373 301 scale: 4
15b422d5 302 };
17574902 303 instance.map.setCenter({lat: unit.geometry.coordinates[1], lng: unit.geometry.coordinates[0]});
f3e550a1 304 }
65c7cdf5 305
1f8c27ee 306 this.map.data.addGeoJson(unit);
0fc3af96 307 this.map.data.setStyle(function (feature) {
15b422d5
JHR
308 let color = 'gray';
309 let icon;
0fc3af96
EHF
310 if (feature.getProperty('icon') !== null) {
311 icon = feature.getProperty('icon');
15b422d5
JHR
312 }
313 color = feature.getProperty('color');
314 return /** @type {google.maps.Data.StyleOptions} */({
315 fillColor: color,
ac22d373
JHR
316 fillOpacity: 0.91,
317 strokeColor: 'white',
318 strokeWeight: 2,
15b422d5
JHR
319 icon: icon
320 });
321 });
17574902 322 if (instance.isSearched) {
e58627b7
JHR
323 instance.seeDetails();
324 }
65c7cdf5 325 this.map.data.addListener('click', function (event) {
cad70644 326 $('#myModal').modal('show');
59ffa1e6
JHR
327 instance.setActiveId(event.feature.O.id);
328 instance.setcurrentPos(event.latLng);
951b1c9f 329
59ffa1e6 330 if (instance.uprunned == false && instance.LEVEL == 2) {
cad70644
EHF
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";
59ffa1e6 334 }
57a79ad4 335 else if (instance.runned == false && instance.LEVEL < instance.allLevels) {
cad70644
EHF
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";
57a79ad4 339 } else if (instance.runned == false && instance.LEVEL <= instance.allLevels) {
cad70644
EHF
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";
951b1c9f 343
65c7cdf5 344 instance.setcurrentPos(event.latLng);
59ffa1e6 345 }
59ffa1e6 346 });
d7f50e3a 347
19468546 348//slette ?? §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
17574902
JHR
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 });*/
d7f50e3a 365
59ffa1e6 366 }
bf25c5cf 367 }
03c7df04 368
17574902
JHR
369 /**
370 * removes the polygon on current level and calles getData on one level down in the org.unit hierarchy
371 */
372 drillDown() {
59ffa1e6
JHR
373 this.closeModal();
374 let map = this.getMap();
375 let id = this.activeId;
376 let level = this.LEVEL;
59ffa1e6
JHR
377 this.setRunned(true);
378 this.setParent(id);
784566de 379
59ffa1e6
JHR
380 map.data.forEach(function (feature) {
381 if (!(feature.O.id == id && level == 3)) {
382 map.data.remove(feature);
03c7df04 383
59ffa1e6
JHR
384 }
385 });
03c7df04 386
59ffa1e6
JHR
387 this.addLevel();
388 this.getData('/' + id + '/children', this);
03c7df04 389
59ffa1e6 390 }
bbee9db0 391
17574902
JHR
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() {
57a79ad4
JHR
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 });
e58627b7 404 if (this.currentMarker !== null) {
57a79ad4 405 this.currentMarker.setMap(null);
15b422d5 406 }
57a79ad4
JHR
407 let parent = instance.getParent();
408 instance.getData('/' + parent, instance, true);
409
59ffa1e6
JHR
410 this.closeModal();
411 }
412
17574902
JHR
413 /**
414 * focuses map and colors to the clicked marker/polygon and fires an event to sidebar with the id of the marker
415 */
59ffa1e6 416 seeDetails() {
f09cdf19
JHR
417
418 console.log("inne i seeDetails");
59ffa1e6
JHR
419 let map = this.getMap();
420 let id = this.activeId;
f09cdf19 421 let instance = this;
59ffa1e6
JHR
422 this.closeModal();
423 map.data.forEach(function (feature) {
424 if (feature.getProperty('id') == id) {
425 feature.setProperty('color', 'red');
b3b5cc9c
JHR
426 if (feature.getProperty('icon') !== null) {
427 feature.O.icon.strokeColor = 'red';
428 }
17574902 429 this.isSearched = false;
f09cdf19 430 console.log(this.isSearched);
b3b5cc9c
JHR
431 }
432 else {
433 feature.setProperty('color', 'gray');
434 if (feature.getProperty('icon') !== null) {
435 feature.O.icon.strokeColor = 'black';
436 }
59ffa1e6
JHR
437 }
438 });
439 this.newactive.next(this.activeId);
6ced1bc7
JHR
440 }
441
17574902
JHR
442 /**
443 * gets the position of the clicked position on the map, saves the parent and sends it in an event.
444 */
65c7cdf5 445 addUnit() {
59ffa1e6 446 this.closeModal();
9992f01a 447 let pos = this.getcurrentPos();
951b1c9f 448 let lat = pos.lat();
59ffa1e6 449 let lng = pos.lng();
59ffa1e6
JHR
450 let parent = this.getParent();
451
65c7cdf5
JHR
452 let location = {lat: lat, lng: lng};
453 let event = {location, parent};
ebaf2f58 454 this.neworg.next(event);
0fc3af96 455 this.closeModal();
bc2f4c9e 456 this.setRunned(false);
a8451d12 457 }
dd095993 458
17574902
JHR
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 */
65c7cdf5 464 update(event) {
f09cdf19
JHR
465 if(event !== null) {
466 if (this.currentMarker) {
467 this.currentMarker.setMap(null);
468 }
36f8898a 469
f09cdf19
JHR
470 this.newactive.next(event);
471 let map = this.getMap();
472 let http = this.getHttp();
e58627b7 473
f09cdf19
JHR
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 }
7ee898bc 483 }
d647078e 484
17574902
JHR
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 */
65c7cdf5 491 mapUpdate(res, instance) {
d647078e 492 this.setLevel(res.level);
e58627b7
JHR
493 this.setActiveId(res.id);
494 this.isSearched = true;
d647078e 495 this.setParent(res.parent.id);
f09cdf19 496 // this.setcurrentPos({lat: JSON.parse(res.coordinates)[1],lng: JSON.parse(res.coordinates)[0]});
e58627b7
JHR
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 }
d647078e
JHR
506
507 }
508
17574902
JHR
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 */
fa052229 513 tempMarker(pos) {
f09cdf19
JHR
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;
fb027b00 520
f09cdf19
JHR
521 let position = {};
522 position.lat = Math.round(pos.lat * 10000) / 10000;
523 position.lng = Math.round(pos.lng * 10000) / 10000;
b9b9539b 524
f09cdf19 525 if ((current.lat != position.lat) || (current.lng != position.lng)) {
b9b9539b 526
f09cdf19 527 let map = this.map;
b9b9539b 528
b9b9539b 529
f09cdf19
JHR
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 }
b9b9539b 543 }
fa052229 544
fa052229 545 }
b3b5cc9c 546
258519d6 547
17574902
JHR
548 /**
549 * closes the modal box over the map.
550 */
258519d6 551 closeModal() {
cad70644 552 $("#myModal").modal("hide");
258519d6
JHR
553 this.setRunned(false);
554 }
555
6ced1bc7 556}
dd095993 557
dd095993
JHR
558
559
560
561