· 6 years ago · Mar 30, 2020, 08:38 PM
1/* console shim*/
2(function () {
3 var f = function () { };
4 if (false || !window.console) {
5 window.console = {
6 log: f, info: f, warn: f, debug: f, error: f
7 };
8 }
9}());
10
11//TODO: find a better way to do this
12//$('#map-canvas').height(screen.availHeight - 250);
13////$('.treeView').height(screen.availHeight - 415);
14//$('.treeView').height(screen.availHeight - 415 + 60 + 38);
15
16//var isMobile = true;
17//if(isMobile){
18// $('.page-header').hide();
19// $('.page-header-fixed .page-container').css('margin-top', '0');
20//}
21
22if(Defaults.Locale == 'ar')
23 moment.locale('ar-ly');
24
25$('#map-canvas').height(screen.availHeight + window.innerHeight - window.outerHeight - 115);// - 140);
26$('.treeView').height(screen.availHeight + window.innerHeight - window.outerHeight - 185);//- 180);
27
28$('.dropdown .dropdown-toggle').dropdown();
29
30$("#vehiclesPortlet").css("height", (window.innerHeight - 235) + 'px');
31$("#map-canvas").css("height", (window.innerHeight - 173) + 'px');
32streamRecordTimer = null;
33var $window = $(window);
34$window.resize(function () {
35 $("#vehiclesPortlet").css("height", (window.innerHeight - 235) + 'px');
36 $("#map-canvas").css("height", (window.innerHeight - 173) + 'px');
37});
38
39$('.nav-tabs a').on('shown.bs.tab', function (event) {
40 //console.log('tab clicked', event.target, event.relatedTarget);
41 var href = $(event.target).attr('href');
42 if (href.indexOf('map') >= 0) {
43 if ($(document).width() >= 992) {
44 $('.page-container').css('overflow', 'hidden');
45 }
46 $('.filter-toolbar').show();
47 } else {
48 if ($(document).width() >= 992) {
49 $('.page-container').css('overflow', 'auto');
50 }
51 $('.filter-toolbar').hide();
52 }
53});
54
55var settingMapStyles = {
56 'Day': 'LynxMapDay',
57 'Night': 'LynxMapNight',
58 'Satellite': google.maps.MapTypeId.HYBRID
59};
60
61var settingMapRefreshes = {
62 'FiveSecond': { time: 5 * 1000, desc: '5 ' + resx.sec },
63 'ThirtySecond': { time: 30 * 1000, desc: '30 ' + resx.sec },
64 'OneMinute': { time: 60 * 1000, desc: '1 ' + resx.min },
65 'TwoMinute': { time: 2 * 60 * 1000, desc: '2 ' + resx.min },
66 'FiveMinute': { time: 5 * 60 * 1000, desc: '5 ' + resx.min }
67
68};
69
70var settingMapDistances = {
71 'Km': { m: 1, desc: 'Km' },
72 'Miles': { m: 0.621371, desc: 'mi' }
73};
74
75var settingMapSpeeds = {
76 'KmHr': { m: 1, desc: 'Km/h' },
77 'mph': { m: 0.621371, desc: 'mph' }
78};
79
80var settingMapDateFormats = {
81 'DayMonthYear': { moment: 'DD/MM/YYYY', calendar: '' },
82 'MonthDayYear': { moment: 'MM/DD/YYYY', calendar: '' }
83};
84
85window.momentFormats = ['YYYY-MM-DD', settingMapDateFormats[Defaults.DateFormat].moment];
86
87var settingMapTimeFormats = {
88 'TwentyFourHour': { hm: 'HH:mm', hms: 'HH:mm:ss' },
89 'TwelveHour': { hm: 'hh:mm A', hms: 'hh:mm:ss A' }
90};
91
92if (Defaults.UnitOfSpeed == 'mph') {
93 resx.kmHour = 'mph';
94}
95
96if (Defaults.UnitOfDistance == 'Miles') {
97 resx.km = 'mi';
98}
99
100
101var mapDayStyles = Defaults.MapDayStyle;
102var mapStyles = Defaults.MapDayStyle;
103var mapNightStyles = Defaults.MapNightStyle;
104
105var modalMap = new google.maps.Map(document.getElementById('modal-map'), {
106 center: { lat: 24.46648350413146, lng: 54.59715667919934 },
107 styles: mapStyles,
108 zoom: 10,
109 mapTypeId: settingMapStyles[Defaults.MapStyle] || google.maps.MapTypeId.HYBRID,
110 mapTypeControlOptions: {
111 mapTypeIds: ['satellite', 'hybrid', 'LynxMapDay', 'LynxMapNight']
112 }
113});
114
115console.log('Google Maps API version: ' + google.maps.version);
116
117/*
118var styledModalMapOptions = {
119 name: 'Map'
120};
121
122var lynxModalMapType = new google.maps.StyledMapType(
123 mapStyles, styledModalMapOptions);
124*/
125
126var modal_styledMapDayOptions = {
127 name: resx.styledMapDayOptions
128};
129
130var modal_lynxMapDayType = new google.maps.StyledMapType(
131 mapDayStyles, modal_styledMapDayOptions);
132
133var modal_styledMapNightOptions = {
134 name: resx.styledMapNightOptions
135};
136
137var modal_lynxMapNightType = new google.maps.StyledMapType(
138 mapNightStyles, modal_styledMapNightOptions);
139
140
141modalMap.mapTypes.set('LynxMapDay', modal_lynxMapDayType);
142modalMap.mapTypes.set('LynxMapNight', modal_lynxMapNightType);
143
144//modalMap.mapTypes.set('LynxMap', lynxModalMapType);
145
146var map_live = modalMap;
147
148$('#overlay-modal').on('shown', function () {
149 var currCenter = modalMap.getCenter();
150 google.maps.event.trigger(modalMap, 'resize');
151 modalMap.setCenter(currCenter);
152 //map is zoomed out to max when first open
153 if (app.bounds) {
154 modalMap.fitBounds(app.bounds);
155 }
156});
157
158
159
160var app = (function () {
161 var self = this;
162 var _app = {
163 };
164
165 _app.groupBy = function (dataToGroupOn, fieldNameToGroupOn, fieldNameForGroupName, fieldNameForChildren) {
166 var result = _.chain(dataToGroupOn)
167 .groupBy(fieldNameToGroupOn)
168 .toPairs()
169 .map(function (currentItem) {
170 return _.zipObject([fieldNameForGroupName, fieldNameForChildren], currentItem);
171 })
172 .value();
173 return result;
174 };
175
176 _app.download = function (url, key, data) {
177 var form = $('<form></form>').attr('action', url).attr('method', 'post');
178 form.append($("<input></input>").attr('type', 'hidden').attr('name', key).attr('value', data));
179 form.appendTo('body').submit().remove();
180 };
181
182 //_app.mapModel = new mapAppViewModel();
183 //ko.applyBindings($('#')[0])
184 _app.enableDirectionMap = false;
185 _app.directionIconPath = "M15.375,7L10,2.54C9.695,2.287,9.461,2,9,2C8.375,2,8,2.516,8,3v3H1C0.45,6,0,6.45,0,7v2c0,0.55,0.45,1,1,1h7v3 c0,0.484,0.375,1,1,1c0.461,0,0.695-0.287,1-0.54L15.375,9C15.758,8.688,16,8.445,16,8S15.758,7.313,15.375,7z";
186 return _app;
187})();
188
189
190var markers = [];
191var markersForVehicle = [];
192app.markers = markers;
193app.markersForVehicle = markersForVehicle;
194app.selectedVehicleMarker = null;
195
196var drawMapCheckBox = function (map) {
197 //#region marker Heading
198
199 // Create the DIV to hold the control and call the CenterControl()
200 // constructor passing in this DIV.
201 var centerControlDiv = document.createElement('div');
202
203 // Set CSS for the control border.
204 var controlUI = document.createElement('div');
205 controlUI.style.backgroundColor = '#25282d';
206 controlUI.style.border = '2px solid #25282d';
207 controlUI.style.borderRadius = '3px';
208 controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
209 controlUI.style.cursor = 'pointer';
210 controlUI.style.marginBottom = '22px';
211 controlUI.style.textAlign = 'center';
212 controlUI.style.color = '#fff';
213 controlUI.title = 'Click to toggle heading appearance';
214 centerControlDiv.appendChild(controlUI);
215
216 // Set CSS for the control interior.
217 var controlText = document.createElement('div');
218 //controlText.style.color = 'rgb(25,25,25)';
219 //controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
220 //controlText.style.fontSize = '16px';
221 //controlText.style.lineHeight = '38px';
222 //controlText.style.paddingLeft = '5px';
223 //controlText.style.paddingRight = '5px';
224 controlText.innerHTML = resx.showVehicleHeading;
225 controlUI.appendChild(controlText);
226
227
228 var newCheckBox = document.createElement('input');
229 newCheckBox.type = 'checkbox';
230 newCheckBox.id = 'checkboxHeading';
231 //newCheckBox.value = ('show Heading <br/>');
232
233 // initalize value from config
234
235 controlUI.appendChild(newCheckBox);
236
237 newCheckBox.addEventListener('change', function () {
238 app.enableDirectionMap = this.checked;
239 if (app.model) {
240 app.model.loadDataForMap();
241 }
242 });
243
244 //// Setup the click event listeners: simply set the map to Chicago.
245 //controlUI.addEventListener('click', function () {
246 // // map.setCenter(chicago);
247 // alert('hi')
248 //});
249
250
251 centerControlDiv.index = 1;
252 map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(centerControlDiv);
253
254 //#endregion
255
256}
257
258var map = waypointMap.init('map-canvas', {
259 center: { lat: Defaults.Lat, lng: Defaults.Lng },
260 styles: mapStyles,
261 mapTypeId: settingMapStyles[Defaults.MapStyle] || google.maps.MapTypeId.HYBRID,
262 mapTypeControlOptions: {
263 mapTypeIds: ['satellite', 'hybrid', 'LynxMapDay', 'LynxMapNight']
264 }
265});
266if (Defaults.EnableDirectionMap == 'True') {
267 drawMapCheckBox(map);
268}
269
270
271var styledMapDayOptions = {
272 name: resx.styledMapDayOptions
273};
274
275var lynxMapDayType = new google.maps.StyledMapType(
276 mapDayStyles, styledMapDayOptions);
277if (Defaults.freezeMapDeclustering) {
278 lynxMapDayType.maxZoom = 14;
279}
280var styledMapNightOptions = {
281 name: resx.styledMapNightOptions
282};
283
284var lynxMapNightType = new google.maps.StyledMapType(
285 mapNightStyles, styledMapNightOptions);
286
287if (Defaults.freezeMapDeclustering) {
288 lynxMapNightType.maxZoom = 14;
289 map.setOptions({ maxZoom: 14 });
290}
291
292
293map.mapTypes.set('LynxMapDay', lynxMapDayType);
294map.mapTypes.set('LynxMapNight', lynxMapNightType);
295//map.setMapTypeId('LynxMap');
296
297waypointMap.layers.init();
298//waypointMap.directions.init();
299waypointMap.panTo(Defaults.Lat, Defaults.Lng, 12);
300
301
302// This event listener calls addMarker() when the map is clicked.
303google.maps.event.addListener(map, 'click', function (e) {
304 //var marker = placeMarker(e.latLng, map);
305 //markers.push(marker);
306});
307
308//$('.portlet-body').slimScroll({ height: '80%' })
309//$('.portlet-body').slimScroll({ height: '320px' });
310
311var VehicleStatusModel = function (vehicleId, dateFrom, dateTo) {
312 var self = this;
313 self.Vehicles = ko.observableArray(Defaults.Vehicles);
314 self.VehicleId = ko.observable(vehicleId || 0);
315 self.DeviceType = ko.observable(0);
316 self.StreamingDeviceType = ko.observable(0);
317 self.VehicleName = ko.observable('');
318 self.ChassisNo = ko.observable('');
319 self.Rfids = ko.observableArray([]);
320 self.isRfidVisibile = ko.observableArray(false);
321 self.CrumbId = ko.observable('');
322 self.TimeStamp = ko.observable('');
323 self.Lat = ko.observable('');
324 self.Lng = ko.observable('');
325 self.Angle = ko.observable('');
326 self.Speed = ko.observable('');
327 self.IsEngineOn = ko.observable('');
328 self.EventId = ko.observable('');
329 self.CommunicationId = ko.observable('');
330 self.CommandDate = ko.observable('');
331 self.CommandId = ko.observable('');
332 self.IsConfirmed = ko.observable('');
333 self.IsError = ko.observable('');
334 self.Error = ko.observable('');
335 self.SentOn = ko.observable('');
336 self.ConfirmedOn = ko.observable('');
337 self.ReceivedConfirmOn = ko.observable('');
338 self.CommandName = ko.observable('');
339 self.CommandValue = ko.observable('0');
340 self.Location = ko.observable('');
341 self.Temperature = ko.observable(0);
342 self.IsTemperatureVisible = ko.observable(Defaults.IsTemperatureVisible);
343
344 self.LastVirtualOdometer = ko.observable(0);
345 self.BaseOdometer = ko.observable(0);
346 self.BaseCrumbId = ko.observable(0);
347 self.BaseVirtualOdometer = ko.observable(0);
348
349 self.SentMessageStatus = ko.observable(0);
350 self.SentMessageType = ko.observable(0);
351
352 self.lastCrumbId = 0;
353 self.ChannelCount = 0;
354 self.track_data = [];
355
356 self.toggleRfidVisibility = function (item, event) {
357 self.isRfidVisibile(!self.isRfidVisibile());
358 }
359
360 self.formatDateTime = function (date) {
361 return 'fffffffff';
362 };
363
364 self.CommandValueFormatted = ko.computed(function () {
365 var value = self.CommandValue();
366 var result = '';
367 switch (value) {
368 case 0: result = resx.resultCase0; break;
369 case 1: result = resx.resultCase1; break;
370 case 2: result = resx.resultCase2; break;
371 }
372 return result;
373 });
374
375 self.LastCommandIsDisable = ko.computed(function () {
376 var lastCommandValue = self.CommandValue();
377 var isConfirmed = self.IsConfirmed();
378 var isError = self.IsError();
379
380 var result = lastCommandValue == 0 && !isError;
381 return result;
382 });
383
384 self.LastCommandInSchedule = ko.computed(function () {
385 var sentMessageType = self.SentMessageType();
386 var sentMessageStatus = self.SentMessageStatus();
387 var lastCommandValue = self.CommandValue();
388 var isConfirmed = self.IsConfirmed();
389 var isError = self.IsError();
390
391 var scheduledStatus = 9;
392 var disableType = 6;
393
394 var result = lastCommandValue == 0 && !isError && sentMessageStatus == scheduledStatus && sentMessageType == disableType;
395 return result;
396 });
397
398 self.IsEngineOnFormatted = ko.computed(function () {
399 var value = self.IsEngineOn();
400 var result = value ? resx.On : resx.Off;
401 return result;
402 });
403
404 self.SpeedUnit = settingMapSpeeds[Defaults.UnitOfSpeed].desc;
405 self.DistanceUnit = settingMapDistances[Defaults.UnitOfDistance].desc;
406
407 var formatDate = function (value, format) {
408 if (!value) {
409 return '';
410 }
411 var m = moment(value);
412 if (m.year() < 2000) {
413 return '';
414 }
415 var result = m.format(format);
416 return result;
417 };
418
419 self.LatLngFormatted = ko.computed(function () {
420 var lat = self.Lat();
421 var lat_n = _.toNumber(lat);
422 var lat_t = _.isNaN(lat_n) ? lat : lat_n.toFixed(4);
423
424 var lng = self.Lng();
425 var lng_n = _.toNumber(lng);
426 var lng_t = _.isNaN(lng_n) ? lng : lng_n.toFixed(4);
427
428 var result = '(' + lat_t + ', ' + lng_t + ')';
429 return result;
430 });
431
432 self.LatFormatted = ko.computed(function () {
433 var value = self.Lat();
434 var n = _.toNumber(value);
435 var result = _.isNaN(n) ? value : n.toFixed(2);
436 return result;
437 });
438
439 self.LngFormatted = ko.computed(function () {
440 var value = self.Lng();
441 var n = _.toNumber(value);
442 var result = _.isNaN(n) ? value : n.toFixed(2);
443 return result;
444 });
445
446 self.Odometer = ko.computed(function () {
447 var lastVirtualOdometer = self.LastVirtualOdometer();
448 var baseOdometer = self.BaseOdometer();
449 var baseCrumbId = self.BaseCrumbId();
450 var baseVirtualOdometer = self.BaseVirtualOdometer();
451
452 var odometer = 0;
453 if (baseOdometer) {
454 odometer += baseOdometer;
455 }
456
457 if (lastVirtualOdometer && baseVirtualOdometer) {
458 var diff = (lastVirtualOdometer - baseVirtualOdometer) / 1000;
459 if (diff > 0) {
460 odometer += diff;
461 }
462 }
463
464 var result = '';
465 if (odometer) {
466 result = app.convertDistance(odometer).toFixed(2) + resx.km;
467 }
468 return result;
469 });
470
471 var angleDirections = [
472 { name: resx.N, min: 0, max: 23 },
473 { name: resx.NE, min: 23, max: 80 },
474 {
475 name: resx.E, min: 80, max: 113
476 },
477 { name: resx.SE, min: 113, max: 170 },
478 { name: resx.S, min: 170, max: 203 },
479 { name: resx.SW, min: 203, max: 260 },
480 { name: resx.W, min: 260, max: 293 },
481 { name: resx.NW, min: 293, max: 350 },
482 { name: resx.N, min: 350, max: 360 }
483 ];
484
485 var mapAngle = function (angle) {
486 for (var i = 0; i < angleDirections.length; i++) {
487 var ad = angleDirections[i];
488 if (angle >= ad.min && angle < ad.max) {
489 return ad.name;
490 }
491 }
492 return angle + '';
493 }
494
495 self.AngleFormatted = ko.computed(function () {
496 var value = self.Angle();
497 var n = _.toNumber(value);
498 var result = mapAngle(n);
499 return result;
500 });
501
502 self.TemperatureFormatted = ko.computed(function () {
503 var value = self.Temperature();
504 if (_.isNil(value)) {
505 self.IsTemperatureVisible(false);
506 return resx.Nan;
507 }
508 var n = _.toNumber(value);
509 self.IsTemperatureVisible(true);
510 var result = ((n / 10).toFixed(1)) + resx.celsius;
511 return result;
512 });
513
514
515 self.getLocation = function (count) {
516 var name = self.VehicleName();
517 var chassisno = self.ChassisNo();
518 var lat = self.Lat();
519 var lng = self.Lng();
520
521 if (!name) {
522 self.Location('');
523 }
524
525 geocoder.geocode(lat, lng, function (data, status) {
526 if (!count) {
527 count = 1;
528 }
529 if (status === 200) {
530 if (data.status == 'OVER_QUERY_LIMIT' && count < 10) {
531 setTimeout(function () {
532 count++;
533 self.getLocation(count);
534 }, 500);
535 } else {
536 self.Location(data.results[0] ? '<span class="x-label x-label-sm x-label-primary" style="white-space: pre-wrap; color: #73baf7; background: #4D4D4D;">' + data.results[0].formatted_address + '</span>' : '');
537 }
538 }
539 else {
540 self.Location('<span class="label label-sm label-danger">' + resx.Nan + '</span>');
541 }
542 });
543 };
544
545 self.TimeStampFormatted = ko.computed(function () {
546 var timeStamp = self.TimeStamp();
547 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
548 var result = formatDate(timeStamp, format);
549 return result || resx.Nan;
550 });
551
552 self.ConfirmedOnFormatted = ko.computed(function () {
553 var confirmedOn = self.ConfirmedOn();
554 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
555 var result = formatDate(confirmedOn, format);
556 return result || resx.Nan;
557 });
558
559 self.SentOnFormatted = ko.computed(function () {
560 var sentOn = self.SentOn();
561 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
562 var result = formatDate(sentOn, format);
563 return result || resx.Nan;
564 });
565
566 self.IsConfirmedFormatted = ko.computed(function () {
567 var isConfirmed = self.IsConfirmed();
568 var isError = self.IsError();
569 var error = self.Error();
570 var sentMessageStatus = self.SentMessageStatus();
571
572 //command cancelled
573 if (sentMessageStatus == 8) {
574 return (error || '');
575 }
576 if (isError) {
577 return resx.Faild + (error ? ': ' : '') + (error || '');
578 } else {
579 switch (sentMessageStatus) {
580 case 0: return resx.Pending; break;
581 case 1: return resx.Queued; break;
582 case 2: return resx.Sending; break;
583 case 3: return resx.Sent; break;
584 case 4: return resx.Failed; break;
585 case 5: return resx.Received; break;
586
587 case 6: return resx.Delivered; break;
588 case 7: return resx.Expired; break;
589 case 8: return resx.UserCanceled; break;
590 case 9: return resx.Scheduled; break;
591 case 10: return resx.Deleted; break;
592
593 case 11: return resx.Undeliverd; break;
594 case 12: return resx.Rejected; break;
595 case 13: return resx.Accepted; break;
596 case 14: return resx.Unknown; break;
597 case 15: return resx.Other; break;
598 }
599 }
600
601 if (isConfirmed) {
602 return resx.Confirm;
603 } else if (!isConfirmed) {
604 return resx.Pending;
605 }
606 return resx.Nan;
607 });
608
609 self.EventNames = {
610 '0': resx.None,
611 '1': resx.IgnitionOn,
612 '2': resx.IgnitionOff,
613 '3': resx.HarshBrake,
614 '4': resx.CourseChange,
615 '5': resx.GPRSConnected,
616 '6': resx.GPRSDisconnected,
617 '7': resx.GSMSignalOk,
618 '8': resx.GSMNoSignal,
619 '9': resx.RFID
620 };
621
622 self.EventIdFormatted = ko.computed(function () {
623 var value = self.EventId();
624 var result = self.EventNames[value] || resx.Nan;
625 return result;
626 });
627
628 self.stream = function (commandId, model, e, options, elementId, callback) {
629 //alert('STREAM!');
630
631 $("#StreamTitleDiv").append("<label class='tree-folder'>" + app.model.selectedVehicle.VehicleName + "</label>");
632 $.ajax({
633 url: '../Waypoint/GetDeviceTypeByVehicleId',
634 type: 'Get',
635 data: { VehicleId: app.model.selectedVehicle.VehicleId },
636 contentType: 'application/json',
637
638 success: function (data) {
639 console.log(data);
640 var channelsCount = data.ChannelsCount;
641 // channelsCount = 8;
642
643 if (channelsCount == 8) {
644 $('#4Channel').css("display", "none");
645 $('#8Channel').css("display", "block");
646
647
648 }
649 else {
650 $('#4Channel').css("display", "block");
651 $('#8Channel').css("display", "none");
652 }
653 var viewModel = new streamViewModel(app.model.selectedVehicle.VehicleId, channelsCount);
654
655 var id = 'streamModalContainer';
656 var el = document.getElementById(id);
657 ko.cleanNode(el);
658 ko.applyBindings(viewModel, el);
659
660 var canvasWidth = $('#video-canvas').width();
661
662 if (canvasWidth == 840) {
663 $('#stream-modal').modal({
664 width: 1100
665 });
666 }
667 else {
668 $('#stream-modal').modal();
669 }
670
671
672
673
674 },
675 fail: function (data) {
676 console.log('fail', data);
677 },
678 error: function (data) {
679 console.log('error', data);
680 }
681 });
682 return;
683 };
684
685
686
687 self.load = function (commandId, model, e, options, elementId, callback) {
688 if (commandId == 'live') {
689 app.disableRefreshingMap = true;
690 //$('#overlay-modal').unbind();
691 $('#overlay-modal').modal();
692
693 var lastRefresh = function () {
694 if (app.model.live_lastRefresh_time) {
695 var m = moment(moment().diff(app.model.live_lastRefresh_time));
696 var text = resx.LastRefresh;
697 if (m.minutes() > 0) {
698 text += m.format(resx.mFormat);
699 }
700 text += m.format(resx.sFormat);
701 app.model.live_lastRefresh(text);
702 //app.model.live_lastRefresh('Last Refresh: ' +app.model.live_lastRefresh_time.fromNow());
703 }
704 };
705
706
707 var liveTracking = function () {
708 Metronic.blockUI({ target: '#overlay-modal', animate: true });
709
710 app.model.live_vehicleName(app.model.selectedVehicle.VehicleName);
711 app.model.live_chassisNo(app.model.selectedVehicle.ChassisNo);
712 app.model.live_vehicle.VehicleId(self.VehicleId());
713 var lastCrumbId = app.model.live_vehicle.lastCrumbId;
714
715 app.model.live_vehicle.load(null, null, null, { LiveTracking: true, LastCrumbId: app.model.live_vehicle.lastCrumbId }, '#overlay-modal', function (data) {
716 app.model.live_speed(app.model.live_vehicle.Speed() + ' ' + resx.kmHour);
717 app.model.live_angle(app.model.live_vehicle.Angle());
718 app.model.live_lastRefresh_time = moment();
719
720 if (data.Track && data.Track.length) {
721 var track = _.first(data.Track);
722 if (!app.model.live_vehicle.track_data) {
723 app.model.live_vehicle.track_data = [];
724 }
725 _.forEach(track.TrackingItems, function (x) {
726 app.model.live_vehicle.track_data.push(x);
727 if (x.EventId == 3) {
728 var braking = app.model.live_events_harshBraking() || 0;
729 app.model.live_events_harshBraking(braking + 1);
730 }
731 var alert_count = 0;
732 var idling_count = 0;
733 _.forEach(x.TrackingAlerts, function (a) {
734 var alertName = (a.Name || '').toLowerCase();
735 if (alertName.indexOf('stationary') >= 0 || alertName.indexOf('idling') >= 0) {
736 idling_count++;
737 } else {
738 alert_count++;
739 }
740 });
741 var alerts = app.model.live_events_alerts() || 0;
742 app.model.live_events_alerts(alerts + alert_count);
743
744 var idling = app.model.live_events_idling() || 0;
745 app.model.live_events_idling(idling + idling_count);
746 });
747
748 var lastCrumb = _.last(track.TrackingItems);
749 if (lastCrumb) {
750 app.model.live_vehicle.lastCrumbId = lastCrumb.CrumbId;
751
752 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
753 app.model.live_lastUpdate(resx.LastUpdate + moment(lastCrumb.TimeStamp).format(format));
754 }
755
756 //live_live_map
757
758 if (app.markerInfoWindow_live) {
759 app.markerInfoWindow_live.close();
760 app.markerInfoWindow_live = null;
761 }
762 if (app.pathLines_live) {
763 _.forEach(app.pathLines_live, function (p) {
764 p.setMap(null);
765 p = null;
766 });
767 app.pathLines_live = [];
768 }
769 app.pathPositions_live = [];
770 if (app.markersForVehicle_live) {
771 _.forEach(app.markersForVehicle_live, function (p) {
772 if (p.marker) {
773 p.marker.setMap(null);
774 }
775 p = null;
776 });
777 }
778 app.markersForVehicle_live = [];
779
780 var prevLocation = null;
781 var trackingData = _.first(app.model.live_vehicle.track_data);
782 _.forEach(app.model.live_vehicle.track_data, function (c, i) {
783 var drawResult = app.model.drawTrackingMarkers(app.model.live_vehicle.track_data, i, prevLocation, app.zooms, { trip: true, live: true });
784 if (drawResult) {
785 prevLocation = drawResult;
786 }
787 });
788 app.model.drawTrackingPath(true, true, true);
789 modalMap.fitBounds(app.bounds)
790
791 //end_live_live_map
792
793
794 }
795 Metronic.unblockUI('#overlay-modal');
796 });
797 }
798
799 liveTracking();
800 var timer = setInterval(liveTracking, 1000 * 30);
801 var timer_refresh = setInterval(lastRefresh, 1000 * 5);
802
803 $('#overlay-modal').on('hidden.bs.modal', function () {
804 app.disableRefreshingMap = false;
805 //app.model.loadDataForMap();
806 app.model.live_vehicle.track_data = [];
807 app.model.live_lastRefresh_time = null;
808 app.model.live_vehicle.lastCrumbId = 0;
809 app.model.live_vehicle.VehicleId(0);
810 app.model.live_speed('');
811 app.model.live_angle('');
812 app.model.live_vehicleName('');
813 app.model.live_chassisNo('');
814 app.model.live_events_harshBraking(0);
815 app.model.live_events_alerts(0);
816 app.model.live_events_idling(0);
817 clearInterval(timer);
818 clearInterval(timer_refresh);
819 });
820
821 return;
822 }
823
824 var elementId = elementId || ('#map_infoWnd_' + self.VehicleId());
825 var name = self.VehicleName();
826 self.VehicleName('');
827
828 var chassisno = self.ChassisNo();
829 self.ChassisNo('');
830 var data = $.extend(options, {
831 vehicleId: self.VehicleId(),
832 commandId: commandId,
833 fromDate: dateFrom,
834 toDate: dateTo
835 });
836
837 if (commandId) {
838 var message = '';
839 if (commandId == '1') {
840 message = resx.Disableselectedvehicle;
841 } else if (commandId == '0') {
842 message = resx.Enableselectedvehicle;
843 } else {
844 message = resx.Cancellastcommand;
845 }
846
847 if (!confirm(message)) {
848 self.VehicleName(name);
849 self.ChassisNo(chassisno);
850 return;
851 }
852 }
853
854 var url = commandId ? 'Tracking/SendCommand' : 'Tracking/VehicleStatus';
855
856 var json = ko.toJSON(data);
857 Metronic.blockUI({ target: elementId, animate: true });
858
859 $.ajax({
860 url: url,
861 type: 'POST',
862 data: json,
863 contentType: 'application/json',
864 crossDomain: true,
865 cache: false,
866 success: function (data) {
867 if (data.IsException) {
868 alert(data.Message);
869 Metronic.unblockUI(elementId);
870 } else {
871 if (commandId == '1' && data.SentMessageStatus == 9) {
872 alert(resx.Vehiclespeediscurrentlyunsafe);
873 }
874
875 ko.mapping.fromJS(data, {}, self);
876
877 var deviceType = data.StreamingDeviceType || data.DeviceType;
878
879 if (self.ChannelCount == 8) {
880 $('#4Channel').css("display", "none");
881 $('#8Channel').css("display", "block");
882
883 }
884 else {
885 $('#4Channel').css("display", "block");
886 $('#8Channel').css("display", "none");
887 }
888 var StreamModal = $('#stream-modal');
889 var channelSelect = $('#StreamChannelId');
890 channelSelect.empty();
891 if (deviceType == 4) {
892 channelSelect.append('<option selected="selected" value="1">Channel 1</option>');
893 channelSelect.append('<option value="2">Channel 2</option>');
894 channelSelect.append('<option value="4">Channel 3</option>');
895 channelSelect.append('<option value="8">Channel 4</option>');
896 } else if (deviceType == 5) {
897 channelSelect.append('<option selected="selected" value="1">Channel 1</option>');
898 channelSelect.append('<option value="2">Channel 2</option>');
899 channelSelect.append('<option value="3">Channel 3</option>');
900 channelSelect.append('<option value="4">Channel 4</option>');
901 channelSelect.append('<option value="5">Channel 5</option>');
902 channelSelect.append('<option value="6">Channel 6</option>');
903 channelSelect.append('<option value="7">Channel 7</option>');
904 channelSelect.append('<option value="8">Channel 8</option>');
905 }
906
907 self.getLocation();
908 Metronic.unblockUI(elementId);
909 }
910 if (callback) { callback(data); };
911 },
912 fail: function (data) {
913 alert(resx.loaddatafailed);
914 console.log('fail', data);
915 Metronic.unblockUI(elementId);
916 },
917 error: function (data) {
918 var json = JSON.parse(data.responseText);
919 alert(resx.loaddataerror + (json.Message || ''));
920 console.log('error', data);
921 Metronic.unblockUI(elementId);
922 }
923 });
924 }
925};
926
927var AlertModel = function (alert, vehicleName) {
928 var self = this;
929 self.showAlertWndLoader = ko.observable(true);
930 self.showPlayTrackBtn = ko.observable(false);
931 self.Videos = [];
932 var json = ko.toJSON({ from: alert.FirstTime, to: alert.LastTime, vehicleName: vehicleName });
933 $.ajax({
934 url: '../Rental/Tracking/GetAlertVideos',
935 type: 'POST',
936 data: json,
937 contentType: 'application/json',
938 crossDomain: true,
939 cache: false,
940 success: function (data) {
941 self.showAlertWndLoader(false);
942 if (Array.isArray(data) && data && data.length > 0) {
943 self.showPlayTrackBtn(true);
944 self.Videos = data;
945 }
946 },
947 error: function (data) {
948 self.showAlertWndLoader(false);
949 }
950 });
951
952 self.load = function (commandId) {
953 if (commandId == 'PlayBack') {
954 if (alert.data != "undefined") {
955 // ...
956 $("#PlaybackTitleDiv").append("<center><label class='tree-folder'>" + app.model.selectedVehicle.VehicleName + " (" + self.Name() + " " + self.FirstTimeFormatted() + ")</label></center>");
957 for (var i = 0; i < self.Videos.length; i++) {
958 $("#PlaybackVideoDiv").append("<video controls='controls' width='50%' style='padding: 1px;'>" + "<source src=" + self.Videos[i].VideoUrl + " type='video/mp4'></video>");
959 }
960 $('#PlayBack-modal').modal();
961 return;
962 }
963 }
964 }
965
966
967 alert.data = alert.data || {};
968
969 self.alert = alert;
970 self.Name = ko.observable(alert.Name || 0);
971 self.TimeStamp = ko.observable(alert.data.TimeStamp || '');
972 self.FirstTime = ko.observable(alert.FirstTime || '');
973 self.LastTime = ko.observable(alert.LastTime || '');
974 self.Location = ko.observable('');
975 self.EventId = ko.observable('');
976 self.Resolution = ko.observable(alert.Resolution);
977 self.ResolvedBy = ko.observable(alert.ResolvedBy || '');
978 self.ResolvedDate = ko.observable(alert.ResolvedDate || '');
979
980 var speed = (settingMapSpeeds[Defaults.UnitOfSpeed].m * (alert.data.Speed || 0)).toFixed(1);
981 var speedLimit = (settingMapSpeeds[Defaults.UnitOfSpeed].m * (alert.data.SpeedLimit || 0)).toFixed(1);
982 self.Speed = ko.observable();
983 if (speed) {
984 self.Speed(speed + ' ' + Defaults.UnitOfSpeed);
985 }
986 self.SpeedLimit = ko.observable();
987 if (speed) {
988 self.SpeedLimit(speedLimit + ' ' + Defaults.UnitOfSpeed);
989 }
990 self.SpeedUnit = Defaults.UnitOfSpeed;
991
992 var formatDate = function (value, format) {
993 if (!value) {
994 return '';
995 }
996 var m = moment(value);
997 if (m.year() < 2000) {
998 return '';
999 }
1000 var result = m.format(format);
1001 return result;
1002 };
1003
1004 var resolutions = {
1005 ["1"]: "SMS",
1006 ["2"]: "Driver Call",
1007 ["3"]: "Start Investigation",
1008 ["4"]: "False Flag",
1009 ["5"]: "Fine"
1010 };
1011
1012 self.ResolutionFormatted = ko.computed(function () {
1013 var resolution = self.Resolution();
1014 var result = resolutions['' + resolution] || '';
1015 return result;
1016 });
1017
1018 self.getLocation = function () {
1019 var lat = alert.data.Lat;
1020 var lng = alert.data.Lng;
1021
1022 if (!lat || !lng) {
1023 self.Location('');
1024 }
1025
1026 geocoder.geocode(lat, lng, function (data, status, address) {
1027 if (status === 200) {
1028 self.Location(address ? '<span class="x-label x-label-sm x-label-primary" style="white-space: pre-wrap; color: #73baf7; background: #4D4D4D;">' + address + '</span>' : resx.Nan);
1029 }
1030 else {
1031 self.Location('<span class="label label-sm label-danger">' + resx.Nan + '</span>');
1032 }
1033 });
1034 };
1035
1036 self.ResolvedDateFormatted = ko.computed(function () {
1037 var resolvedDate = self.ResolvedDate();
1038 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
1039 var result = formatDate(resolvedDate, format);
1040 return result || resx.Nan;
1041 });
1042
1043 self.TimeStampFormatted = ko.computed(function () {
1044 var timeStamp = self.TimeStamp();
1045 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
1046 var result = formatDate(timeStamp, format);
1047 return result || resx.Nan;
1048 });
1049
1050 self.FirstTimeFormatted = ko.computed(function () {
1051 var dt = self.FirstTime();
1052 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
1053 var result = formatDate(dt, format);
1054 return result || resx.Nan;
1055 });
1056
1057 self.LastTimeFormatted = ko.computed(function () {
1058 var dt = self.LastTime();
1059 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
1060 var result = formatDate(dt, format);
1061 return result || resx.Nan;
1062 });
1063
1064 self.EventIdFormatted = ko.computed(function () {
1065 var value = self.EventId();
1066 var result = value;
1067 return result;
1068 });
1069
1070 self.IsVideoEnabled = Defaults.IsVideoEnabled;
1071
1072
1073};
1074
1075
1076
1077var NodeModel = function (data, nodeClickedHandler) {
1078
1079 var self = this;
1080
1081 self.isExpanded = ko.observable(true);
1082 self.description = ko.observable();
1083 self.name = ko.observable();
1084 self.nodes = ko.observableArray([]);
1085 self.type = ko.observable('');
1086 self.alert = ko.observable('');
1087 self.details = ko.observable('');
1088 self.error = ko.observable(false);
1089 self.isSelected = ko.observable(false);
1090
1091 self.nodeClickedHandler = nodeClickedHandler;
1092
1093 self.getSelectedColor = ko.computed(function () {
1094 var isSelected = self.isSelected();
1095 return isSelected ? '#5698FF' : '#eee';
1096 });
1097
1098 self.css_tree = ko.computed(function () {
1099 var x = 'tree pointer-icon';
1100 if (self.type()) {
1101 x += ' type-' + self.type();
1102 }
1103 if (self.alert()) {
1104 x += ' status-alert';
1105 }
1106 return x;
1107 });
1108
1109 self.css_folder = ko.computed(function () {
1110 var x = 'tree-folder';
1111 if (self.type()) {
1112 x += ' type-' + self.type();
1113 }
1114 if (self.alert()) {
1115 x += ' status-alert';
1116 }
1117 return x;
1118 });
1119
1120 self.css_node = ko.computed(function () {
1121 var x = 'tree-node pointer-icon';
1122 if (self.type()) {
1123 x += ' type-' + self.type();
1124 }
1125 if (self.alert()) {
1126 x += ' status-alert';
1127 }
1128 return x;
1129 });
1130
1131 self.css_node_name = ko.computed(function () {
1132 var x = 'tree-node-name';
1133 if (self.isExpanded() && self.nodes().length > 0) {
1134 x += ' glyphicon-chevron-down';
1135 }
1136 if (!self.isExpanded() && self.nodes().length > 0) {
1137 x += ' glyphicon-chevron-right';
1138 }
1139 if (self.type()) {
1140 x += ' type-' + self.type();
1141 }
1142 return x;
1143 });
1144
1145 self.toggleVisibility = function (data, e) {
1146 self.isExpanded(!self.isExpanded());
1147
1148 //if (nodeClickedHandler) {
1149 // nodeClickedHandler(data, e);
1150 //}
1151 };
1152
1153 self.dblClickHandler = function (data, e) {
1154 if (nodeClickedHandler) {
1155 self.toggleVisibility();
1156 nodeClickedHandler(data, e);
1157 }
1158 };
1159
1160 self.dblClickHandler = function (data, e) {
1161 if (nodeClickedHandler) {
1162 self.toggleVisibility();
1163 nodeClickedHandler(data, e);
1164 }
1165 };
1166
1167 self.dblClickHandler2 = function (data, e) {
1168 return false;
1169 if (nodeClickedHandler) {
1170 self.toggleVisibility();
1171 nodeClickedHandler(data, e);
1172 }
1173 };
1174
1175 ko.mapping.fromJS(data, self.mapOptions, self);
1176 if (data) {
1177 self.data = data.data;
1178 }
1179 //self.isExpanded(self.type() !== 'vehicle');
1180 self.isExpanded(self.type() === 'vehicle');
1181};
1182
1183NodeModel.prototype.mapOptions = {
1184 nodes: {
1185 create: function (args) {
1186 return new NodeModel(args.data, args.parent.nodeClickedHandler);
1187 }
1188 },
1189 'copy': ['positions', 'trip', 'parent']
1190};
1191var expandedItem = null;
1192var expandedEvent = null;
1193var PeriodOfRecording = $("#StreamTitleDiv").attr("RecoredingPeriod");
1194
1195var streamViewModel = function (vehicleId, channelsCount) {
1196
1197 var self = this;
1198
1199 self.streamBlockPeriod = 3000;
1200 self.streamPlayer = null;
1201 self.streamSerial = 0;
1202 self.streamChannel = 0;
1203 self.streamName = ko.observable('');
1204 self.streamClientSessionId = ko.observable('');
1205 self.streamRequesting = ko.observable(false);
1206 self.streamMessage = ko.observable(resx.LiveStream);
1207 self.streamRecord = { VehicleId: vehicleId };
1208 self.channelsCount = ko.observable(channelsCount);
1209 self.canvas1StreamMessage = ko.observable("");
1210 self.canvas2StreamMessage = ko.observable("");
1211 self.canvas3StreamMessage = ko.observable("");
1212 self.canvas4StreamMessage = ko.observable("");
1213 self.canvas5StreamMessage = ko.observable("");
1214 self.canvas6StreamMessage = ko.observable("");
1215 self.canvas7StreamMessage = ko.observable("");
1216 self.canvas8StreamMessage = ko.observable("");
1217 self.Quality = ko.observable(1);//low
1218 self.isMultiStreamingEnabled = ko.observable(Defaults.isMultiStreamingEnabled == 'True');
1219 self.generateSessionId = function () {
1220 return (new Date()).getTime().toString() + "_" + Math.floor(Math.random() * 999999).toString();
1221 }
1222 var SessionId = self.generateSessionId();
1223
1224 streamRecordTimer = setTimeout(function () {
1225 if (self.IsStreaming() && self.isSingleView()) {
1226 toggleRecording();
1227 }
1228
1229 }, PeriodOfRecording * 60000);
1230
1231 var streamChannels = { '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8' };
1232
1233 self.multiStreamChannels = ko.observableArray([]);
1234 self.activeMultiStreamChannels = ko.observableArray([]);
1235
1236 self.closeStreamPlayer = function (channel) {
1237 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1238 return a.channel == channel;
1239 })[0];
1240 if (!activeStream) {
1241 return;
1242 }
1243 if (activeStream.streamPlayer) {
1244 activeStream.streamPlayer.destroy();
1245 activeStream.streamPlayer = null;
1246 }
1247 };
1248 var isExpanded = $("#isExpandedField").text();
1249 self.isExpanded = ko.observable(false);
1250 if (isExpanded == 'true') {
1251 self.isExpanded = ko.observable(true);
1252 }
1253
1254 self.expand = function (item, event) {
1255 expandedItem = item;
1256 expandedEvent = event;
1257 if (self.isExpanded()) {
1258 return;
1259 }
1260 self.Quality(2);//high
1261 var value = 200;
1262 var modal = $(event.target).closest("#stream-modal");
1263 var modalBody = $(event.target).closest(".modal-body");
1264 var modalBodyHeight = modalBody.height();
1265 modalBody.height(modalBody.height() + value + "px");
1266 modal.width(modal.width() + value + "px");
1267 modal.addClass("model-expand");
1268 if (self.isSingleView()) {
1269
1270 var canvas = modalBody.find("#video-canvas");
1271 canvas.addClass("model-canvas-expand");
1272 canvas.height(canvas.height() + value + "px");
1273 canvas.width(canvas.width() + value + "px");
1274 var activeStream = self.activeMultiStreamChannels()[0];
1275 if (activeStream) {
1276 self.openStream2(activeStream.channel, false);//to close the channel
1277 self.openStream2(activeStream.channel, false);//to open the channel
1278 }
1279 }
1280 else {
1281 var parentDiv = $(event.target).closest(".col-md-6");
1282 parentDiv.siblings(".col-md-6").css("display", "none");
1283 parentDiv.removeClass("col-md-6");
1284 parentDiv.addClass("col-md-12");
1285 var canvas = parentDiv.find("canvas");
1286 canvas.height(360 + value + "px");
1287 parentDiv.parent().siblings(".row").css("display", "none");
1288 canvas.addClass("model-canvas-expand");
1289 if (self.channelsCount() == 8) {
1290 modalBody.height(modalBodyHeight + 59 + "px");
1291 }
1292 if (canvas[0] && canvas[0].id) {
1293 var canvasId = canvas[0].id;
1294 var canvasChannel = parseInt(canvasId.substr(canvasId.length - 1));
1295 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1296 return a.channel == canvasChannel;
1297 })[0];
1298 if (activeStream) {
1299 self.addChannel(canvasChannel);//to close the channel
1300 self.addChannel(canvasChannel);//to open the channel
1301 }
1302
1303 }
1304 }
1305
1306 self.isExpanded(true);
1307 $("#isExpandedField").text('true');
1308 }
1309
1310 self.resetModal = function () {
1311 $('#8Channel-multi').hide();
1312 $('#4Channel-multi').hide();
1313 $('#StreamVideoDivMulti8').hide();
1314 $('#StreamVideoDivMulti').hide();
1315 if (self.isExpanded()) {
1316 self.compress(expandedItem, expandedEvent);
1317 }
1318 }
1319
1320 self.compress = function (item, event) {
1321 if (!self.isExpanded()) {
1322 return;
1323 }
1324 self.Quality(1);//low
1325 var value = 200;
1326 var modal = $(event.target).closest("#stream-modal");
1327 var modalBody = $(event.target).closest(".modal-body");
1328 var modalBodyHeight = modalBody.height();
1329 modalBody.height(modalBody.height() - value + "px");
1330 modal.width(modal.width() - value + "px");
1331 modal.removeClass("model-expand");
1332 if (self.isSingleView()) {
1333 var canvas = modalBody.find("#video-canvas");
1334 canvas.height(canvas.height() - value + "px");
1335 canvas.width(canvas.width() - value + "px");
1336 canvas.removeClass("model-canvas-expand");
1337 var activeStream = self.activeMultiStreamChannels()[0];
1338 if (activeStream) {
1339 self.openStream2(activeStream.channel, false);//to close the channel
1340 self.openStream2(activeStream.channel, false);//to open the channel
1341 }
1342 }
1343 else {
1344 var parentDiv = $(event.target).closest(".col-md-12");
1345 parentDiv.siblings(".col-md-6").css("display", "block");
1346 parentDiv.removeClass("col-md-12");
1347 parentDiv.addClass(" col-md-6");
1348 var canvas = parentDiv.find("canvas");
1349 if (self.channelsCount() == 8) {
1350 canvas.height("100px");
1351 modalBody.height(modalBodyHeight - 59 + "px");
1352 }
1353 else {
1354 canvas.height("200px");
1355 }
1356
1357 parentDiv.parent().siblings(".row").css("display", "block");
1358 canvas.removeClass("model-canvas-expand");
1359 if (canvas[0] && canvas[0].id) {
1360 var canvasId = canvas[0].id;
1361 var canvasChannel = parseInt(canvasId.substr(canvasId.length - 1));
1362 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1363 return a.channel == canvasChannel;
1364 })[0];
1365 if (activeStream) {
1366 self.addChannel(canvasChannel);//to close the channel
1367 self.addChannel(canvasChannel);//to open the channel
1368 }
1369
1370 }
1371 }
1372 self.isExpanded(false);
1373 $("#isExpandedField").text('false');
1374 }
1375
1376 self.setStreamMessage = function (canvasNumber, message) {
1377 switch (canvasNumber) {
1378 case 1:
1379 self.canvas1StreamMessage(message);
1380 break;
1381 case 2:
1382 self.canvas2StreamMessage(message);
1383 break;
1384 case 3:
1385 self.canvas3StreamMessage(message);
1386 break;
1387 case 4:
1388 self.canvas4StreamMessage(message);
1389 break;
1390 case 5:
1391 self.canvas5StreamMessage(message);
1392 break;
1393 case 6:
1394 self.canvas6StreamMessage(message);
1395 break;
1396 case 7:
1397 self.canvas7StreamMessage(message);
1398 break;
1399 case 8:
1400 self.canvas8StreamMessage(message);
1401 break;
1402 }
1403 }
1404
1405 self.disableStreamingBurrons = function () {
1406
1407 Metronic.blockUI({ target: '#stream-modal', animate: true });
1408 setTimeout(function () {
1409 Metronic.unblockUI('#stream-modal');
1410 }, self.streamBlockPeriod);
1411 };
1412
1413 self.openStream = function (channel, canvasNumber) {
1414 //alert('OPEN');
1415
1416 if (!self.streamRecord) {
1417 return;
1418 }
1419 var canvasName = 'video-canvas';
1420
1421 if (canvasNumber) {
1422
1423 if (self.channelsCount() == 8) {
1424 canvasName = 'video-canvas8-' + canvasNumber;
1425 }
1426 else {
1427 canvasName = 'video-canvas-' + canvasNumber;
1428 }
1429 }
1430
1431 self.closeStreamPlayer(channel);
1432 var streamChannels = { '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8' };
1433
1434 var streamChannel = streamChannels[channel];//$('#GlobalStreamChannelId').val();
1435 var requestClientSessionId = SessionId.slice(0, -1) + streamChannel;
1436 var request = {
1437 Channel: streamChannel,
1438 ClientSessionId: requestClientSessionId,
1439 VehicleId: self.streamRecord.VehicleId,
1440 Quality: self.Quality()
1441 };
1442 console.log('request', request);
1443
1444 var activetreamChannel = { channel: channel, canvasNumber: canvasNumber, streamChannel: channel, streamClientSessionId: requestClientSessionId };
1445 self.activeMultiStreamChannels().push(activetreamChannel);
1446
1447 var json = ko.toJSON(request);
1448
1449 self.streamRequesting(true);
1450 self.streamMessage(resx.RequestingStream);
1451 self.setStreamMessage(canvasNumber, resx.RequestingStream);
1452 $.ajax({
1453 url: '../api/streaming/Open',
1454 type: 'POST',
1455 data: json,
1456 contentType: 'application/json',
1457 crossDomain: true,
1458 cache: false,
1459 success: function (data) {
1460
1461 console.log(data);
1462 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1463 return a.channel == channel;
1464 })[0];
1465 if (data.IsOk) {
1466 self.streamName(data.StreamName);
1467 self.streamClientSessionId(data.ClientSessionId);
1468
1469 var canvas = document.getElementById(canvasName);
1470 var url = data.WebsocketUrl;
1471 self.streamPlayer = new JSMpeg.Player(url, { canvas: canvas, pauseWhenHidden: false, decodeFirstFrame: true, videoBufferSize: 2 * 1024 * 1024, poster: '' });
1472
1473
1474 if (activeStream) {
1475 activeStream.streamName = data.StreamName;
1476 activeStream.streamClientSessionId = data.ClientSessionId;
1477 activeStream.streamPlayer = self.streamPlayer;
1478 activeStream.streamChannel = streamChannel;
1479 }
1480
1481
1482 setTimeout(function () {
1483 self.refreshStream(data.StreamName);
1484 }, 1000);
1485 }
1486 if (activeStream) {
1487 self.setStreamMessage(activeStream.canvasNumber, data.Message || data.Error);
1488 }
1489 self.streamMessage(data.Message || data.Error);
1490 if (data.IsOk == false && !data.Message && !data.Error) {
1491
1492 if (activeStream) {
1493 self.setStreamMessage(activeStream.canvasNumber, resx.FailedToOpenStreaming);
1494 }
1495 self.streamMessage(resx.FailedToOpenStreaming);
1496 }
1497 self.streamRequesting(false);
1498 },
1499 fail: function (data) {
1500 alert(resx.Startingfailed);
1501 console.log('fail', data);
1502 },
1503 error: function (data) {
1504 var json = JSON.parse(data.responseText);
1505 alert(resx.Startingerror +' ' + (json.Message || ''));
1506 console.log('error', data);
1507 }
1508 });
1509 };
1510
1511 self.closeStream = function (channel, enableDelete, isFinalClose) {
1512 //alert('CLOSE');
1513 if (self.activeMultiStreamChannels().length == 0) {
1514 return;
1515 }
1516
1517 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1518 return a.channel == channel;
1519 })[0];
1520 var canvasNumber = activeStream.canvasNumber;
1521 if (activeStream.streamPlayer) {
1522 activeStream.streamPlayer.destroy();
1523 activeStream.streamPlayer = null;
1524 }
1525
1526 clearTimeout(activeStream.timerForClose);
1527 activeStream.timerForClose = null;
1528
1529 if (enableDelete) {
1530 var index = self.activeMultiStreamChannels().indexOf(activeStream);
1531 self.activeMultiStreamChannels().splice(index, 1);
1532 }
1533 //if ( !activeStream.streamChannel) {
1534 // return;
1535 //}
1536
1537
1538
1539 var request = {
1540 VehicleId: self.streamRecord.VehicleId,
1541 Channel: activeStream.streamChannel,
1542 ClientSessionId: activeStream.streamClientSessionId,
1543 IsFinalClose: isFinalClose
1544 };
1545
1546
1547 self.setStreamMessage(canvasNumber, resx.Closing);
1548 var json = ko.toJSON(request);
1549
1550 return $.ajax({
1551 url: '../api/streaming/Close',
1552 type: 'POST',
1553 data: json,
1554 contentType: 'application/json',
1555 crossDomain: true,
1556 cache: false,
1557 success: function (data) {
1558 if (data.IsOk) {
1559 self.streamName('');
1560 //self.streamRecord = null;
1561 }
1562 if (self.isSingleView() && data.RequestModel) {
1563 if (self.activeMultiStreamChannels()[0]) {
1564 if (self.activeMultiStreamChannels()[0].streamChannel == data.RequestModel.Channel) {
1565 self.streamMessage(resx.Closed);
1566 }
1567 }
1568 else {
1569 if (activeStream && activeStream.streamChannel == data.RequestModel.Channel) {
1570 self.streamMessage(resx.Closed);
1571 }
1572 }
1573 }
1574
1575
1576
1577 self.setStreamMessage(canvasNumber, resx.Closed);
1578 self.streamRequesting(false);
1579 },
1580 fail: function (data) {
1581 alert(resx.ClosingFailed);
1582 console.log('Closing fail', data);
1583 },
1584 error: function (data) {
1585 var json = JSON.parse(data.responseText);
1586 alert(resx.ClosingError + (json.Message || ''));
1587 console.log('Closing error', data);
1588 }
1589 });
1590 };
1591
1592 self.refreshStream = function (streamName) {
1593 //alert('REFRESH');
1594
1595 var activeChannel = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1596 return a.streamName == streamName;
1597 });
1598
1599 if (activeChannel.length == 0) {
1600 console.log(streamName + " not in active streams");
1601 return;
1602 }
1603
1604 var request = {
1605 VehicleId: self.streamRecord.VehicleId,
1606 Channel: activeChannel[0].channel,
1607 ClientSessionId: activeChannel[0].streamClientSessionId,
1608 StreamName: streamName,
1609 IsHiQuality: 1
1610 };
1611
1612 var json = ko.toJSON(request);
1613
1614 $.ajax({
1615 url: '../api/streaming/Refresh',
1616 type: 'POST',
1617 data: json,
1618 contentType: 'application/json',
1619 crossDomain: true,
1620 cache: false,
1621 success: function (data) {
1622 console.log('refresh result', data);
1623
1624 if (!activeChannel[0] || !activeChannel[0].streamPlayer) {
1625 return;
1626 }
1627 var streamPlayer = activeChannel[0].streamPlayer;
1628 if (streamPlayer != null && streamPlayer.source != null) {
1629 console.log(streamPlayer.source.socket.readyState);
1630 }
1631 if (data.IsOk) {
1632 if (streamPlayer != null && streamPlayer.source != null && streamPlayer.source.socket.readyState == 1) {
1633 self.streamMessage(resx.Streaming);
1634 self.setStreamMessage(activeChannel[0].canvasNumber, resx.Streaming);
1635 var isAutoRecord = true;
1636 if (self.IsStreaming() == false && isAutoRecord == true && self.isSingleView()) {
1637 self.IsStreaming(true)
1638 startRecording();
1639 }
1640 var closeTimeValue = parseFloat(PeriodOfRecording) - 0.08;
1641
1642 if (!activeChannel[0].timerForClose) {
1643 activeChannel[0].timerForClose = setTimeout(function () {
1644 if (self.isSingleView()) {
1645 self.openStream2(activeChannel[0].channel, false);
1646 }
1647 else {
1648 self.addChannel(activeChannel[0].channel);
1649 }
1650
1651 }, closeTimeValue * 60000);
1652 }
1653
1654
1655
1656 setTimeout(function () {
1657 self.refreshStream(streamName);
1658 }, 20000);
1659 } else {
1660 self.streamMessage(resx.EstablishingStreamingConnection);
1661 self.setStreamMessage(activeChannel[0].canvasNumber, resx.EstablishingStreamingConnection);
1662 setTimeout(function () {
1663 self.refreshStream(streamName);
1664 }, 1000);
1665 }
1666 } else {
1667 self.streamMessage(data.message);
1668 self.setStreamMessage(activeChannel[0].canvasNumber, data.message);
1669 self.streamName('');
1670 self.closeStreamPlayer(activeChannel[0].channel);
1671 }
1672 },
1673 fail: function (data) {
1674 alert(resx.RefreshFailed);
1675 console.log('Refresh fail', data);
1676 },
1677 error: function (data) {
1678 var json = JSON.parse(data.responseText);
1679 alert(resx.RefreshError + (json.Message || ''));
1680 console.log('Refresh error', data);
1681 }
1682 });
1683 };
1684
1685 self.CloseStreamandStopRecording = function () {
1686 self.resetModal();
1687 var isAutoRecording = true;
1688
1689 if (isAutoRecording == true && self.IsStreaming() == true && self.isSingleView() == true) {
1690 toggleRecording();
1691 }
1692 else {
1693 self.CloseStreamWindow()
1694 }
1695 }
1696
1697 self.CloseStreamWindow = function () {
1698
1699 for (i = 0; i < self.activeMultiStreamChannels().length; i++) {
1700 self.closeStream(self.activeMultiStreamChannels()[i].channel, false, true);
1701 }
1702 self.activeMultiStreamChannels([]);
1703 clearTimeout(streamRecordTimer);
1704 $("#StreamTitleDiv").empty();
1705 stopRecording();
1706 if (self.IsStreaming() == false) {
1707 $('#stream-modal').modal('toggle');
1708 }
1709 };
1710
1711 self.SaveStreamAndClearTimeOut = function () {
1712 clearTimeout(streamRecordTimer);
1713 SaveStream(self.isSingleView());
1714 if (self.isSingleView() == true) {
1715 self.CloseStreamWindow();
1716 }
1717 self.IsStreaming(false);
1718
1719 };
1720
1721 self.CloseSaveStreamAndClearTimeOut = function () {
1722 clearTimeout(streamRecordTimer);
1723 CloseSaveStream(self.isSingleView());
1724 if (self.isSingleView() == true) {
1725 self.CloseStreamWindow();
1726 }
1727 self.IsStreaming(false);
1728
1729 };
1730
1731
1732
1733 self.streamPlayer1 = null;
1734 self.streamPlayer2 = null;
1735 self.streamPlayer3 = null;
1736 self.streamPlayer4 = null;
1737
1738 self.streamSerial1 = 0;
1739 self.streamSerial2 = 0;
1740 self.streamSerial3 = 0;
1741 self.streamSerial4 = 0;
1742
1743 self.streamChannel = 0;
1744
1745 self.streamName1 = ko.observable('');
1746 self.streamName2 = ko.observable('');
1747 self.streamName3 = ko.observable('');
1748 self.streamName4 = ko.observable('');
1749
1750 self.streamClientSessionId1 = ko.observable('');
1751 self.streamClientSessionId2 = ko.observable('');
1752 self.streamClientSessionId3 = ko.observable('');
1753 self.streamClientSessionId4 = ko.observable('');
1754
1755 self.streamRequesting = ko.observable(false);
1756 self.IsStreaming = ko.observable(false);
1757 self.isSingleView = ko.observable(true);
1758 //self.streamMessage = ko.observable('Live Stream ...');
1759
1760
1761 self.openStream2 = function (channel, switchFromMulti) {
1762 console.log('open stream', channel);
1763 $('.cam').removeClass('cam-active');
1764 $('.cam-elem').removeClass('play-on');
1765
1766 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1767 return a.channel == channel;
1768 })[0];
1769
1770 if (activeStream && !switchFromMulti) {
1771 self.closeStream(channel, true);
1772 self.streamChannel = 0;
1773 } else {
1774 self.closeStreamMulti2();
1775
1776 //disable buttons for 3 seconds
1777 self.disableStreamingBurrons();
1778
1779 setTimeout(function () {
1780 $('.cam.cam-stream-' + channel).addClass('cam-active');
1781 $('.cam-elem.cam-stream-' + channel).addClass('play-on');
1782 self.openStream(channel);
1783 }, self.streamBlockPeriod);
1784
1785 }
1786 };
1787
1788 self.addChannel = function (channel) {
1789
1790 //disable buttons for 3 seconds
1791 self.disableStreamingBurrons();
1792
1793 var canvasNumber = channel;
1794 console.log('add channel in multi mode', channel);
1795 var activeStream = jQuery.grep(self.activeMultiStreamChannels(), function (a) {
1796 return a.channel == channel;
1797 })[0];
1798 if (activeStream) {
1799 self.closeStream(channel, true);
1800 self.streamChannel = 0;
1801 $('.cam.cam-stream-' + channel).removeClass('cam-active');
1802 $('.cam-elem.cam-stream-' + channel).removeClass('play-on');
1803 } else {
1804 if (self.activeMultiStreamChannels().length == 4) {
1805 toastr['info'](resx.info, resx.CantOpenMoreThan4Channels);
1806 return;
1807 }
1808 $('.cam.cam-stream-' + channel).addClass('cam-active');
1809 $('.cam-elem.cam-stream-' + channel).addClass('play-on');
1810 self.openStream(channel, canvasNumber);
1811 }
1812 };
1813
1814
1815
1816
1817
1818
1819 self.closeStreamMulti2 = function () {
1820 var channels = self.multiStreamChannels().sort();
1821 for (i = 0; i < self.activeMultiStreamChannels().length; i++) {
1822
1823 self.closeStream(self.activeMultiStreamChannels()[i].channel, false);
1824 }
1825 self.activeMultiStreamChannels([]);
1826 };
1827
1828 self.streamRequesting2 = ko.observable(false);
1829 self.streamRequestingMulti2 = ko.observable(false);
1830 self.activeChannel2 = ko.observable('');
1831
1832
1833
1834
1835
1836 self.enableSingleView = function () {
1837 self.Quality(1);
1838 SessionId = self.generateSessionId();
1839 self.resetModal();
1840 self.isSingleView(true);
1841 $('#StreamVideoDiv').show();
1842 $('#singleModeStreamMessage').show();
1843 if (self.channelsCount() == 8) {
1844 $('#8Channel').css("display", "block");
1845 $('#8Channel-multi').css("display", "none");
1846 $('#StreamVideoDivMulti8').hide();
1847 $("#streamModalBody").css("height", "553px");
1848 }
1849 else {
1850 $('#4Channel').css("display", "block");
1851 $('#4Channel-multi').hide();
1852 $('#StreamVideoDivMulti').hide();
1853 }
1854 self.streamChannel = 0;
1855 self.openStream2(4, true);
1856
1857 };
1858 self.enableMultiView = function () {
1859 self.Quality(1);
1860 SessionId = self.generateSessionId();
1861 var isAutoRecording = true;
1862 self.resetModal();
1863 self.isSingleView(false);
1864 $('#StreamVideoDiv').hide();
1865 $('#singleModeStreamMessage').hide();
1866 $('.cam').removeClass('cam-active');
1867 $('.cam-elem').removeClass('play-on');
1868
1869 if (self.channelsCount() == 8) {
1870 $('#8Channel').css("display", "none");
1871 $('#8Channel-multi').css("display", "block");
1872 self.multiStreamChannels = ko.observableArray([]);
1873 $('#StreamVideoDivMulti8').show();
1874 $("#streamModalBody").css("height", "612px")
1875 }
1876 else {
1877 $('#4Channel').css("display", "none");
1878 $('#4Channel-multi').show();
1879 $('#StreamVideoDivMulti').show();
1880 }
1881 self.closeStreamMulti2();
1882 if (isAutoRecording == true && self.IsStreaming() == true) {
1883 $('#save-stream-modal').modal();
1884 self.IsStreaming(false);
1885 }
1886
1887
1888
1889 };
1890
1891 self.enableSingleView();
1892
1893}
1894
1895var PageModel = function () {
1896
1897 var self = this;
1898
1899 self.treeData = ko.observable();
1900 self.reportData = ko.observableArray([]);
1901
1902 self.filter = ko.observable(Defaults.Name || '');
1903
1904 self.live_open = ko.observable(false);
1905 self.live_vehicleName = ko.observable('');
1906 self.live_chassisNo = ko.observable('');
1907 self.live_Rfids = ko.observableArray([]);
1908 self.live_speed = ko.observable(0);
1909 self.live_angle = ko.observable(0);
1910 self.live_events_alerts = ko.observable(0);
1911 self.live_events_idling = ko.observable(0);
1912 self.live_events_harshBraking = ko.observable(0);
1913 self.live_lastUpdate = ko.observable('');
1914 self.live_lastRefresh = ko.observable('');
1915 self.live_vehicle = new VehicleStatusModel();
1916 self.isRfidVisibile = ko.observable(false);
1917 var angleDirections = [
1918 { name: resx.N, min: 0, max: 23 },
1919 { name: resx.NE, min: 23, max: 68 },
1920 { name: resx.E, min: 68, max: 113 },
1921 { name: resx.SE, min: 113, max: 158 },
1922 { name: resx.S, min: 158, max: 203 },
1923 { name: resx.SW, min: 203, max: 248 },
1924 { name: resx.W, min: 248, max: 293 },
1925 { name: resx.NW, min: 293, max: 338 },
1926 { name: resx.N, min: 338, max: 361 }
1927 ];
1928
1929 var mapAngle = function (angle) {
1930 for (var i = 0; i < angleDirections.length; i++) {
1931 var ad = angleDirections[i];
1932 if (angle >= ad.min && angle < ad.max) {
1933 return ad.name;
1934 }
1935 }
1936 return angle + '';
1937 }
1938
1939 self.live_angleFormatted = ko.computed(function () {
1940 var value = self.live_angle();
1941 var n = _.toNumber(value);
1942 var result = mapAngle(n);
1943 return result;
1944 });
1945
1946 self.vehicleName = ko.observable('');
1947 self.chassisNo = ko.observable('');
1948 self.Rfids = ko.observableArray([]);
1949
1950 self.vehiclePlateNo = ko.observable('');
1951 self.vehiclePhone = ko.observable('');
1952
1953 self.crewName = ko.observable('');
1954 self.crewRfid = ko.observable('');
1955 self.crewPhone = ko.observable('');
1956
1957 self.from = ko.observable(Defaults.today);
1958 self.to = ko.observable(Defaults.tomorrow);
1959
1960 self.calendarFormat = Defaults.DateFormat == 'DayMonthYear' ? 'dd/mm/yyyy' : 'mm/dd/yyyy';
1961 self.map_from = ko.observable(Defaults.today);
1962 self.map_to = ko.observable(Defaults.tomorrow);
1963
1964 self.page = ko.observable(1);
1965 self.pages = ko.observable(1);
1966 self.pageSize = ko.observable(5);
1967 self.count = ko.observable(0);
1968 self.loading = ko.observable(false);
1969 self.shiftsEnabled = ko.observable(Defaults.IsShiftsEnabled);
1970
1971 self.scrollTo = function () {
1972 if (!self.selectedVehicle) {
1973 return;
1974 }
1975 var vid = '#vehicle_' + self.selectedVehicle.VehicleId;
1976 var container = $('.treeView');
1977 var scrollTo = $(vid);
1978 try {
1979 container.animate({
1980 scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
1981 });
1982 }
1983 catch (err) {
1984 }
1985 };
1986
1987 self.scrollTop = function () {
1988 var container = $('.treeView');
1989 var scrollTo = 0;
1990 container.animate({
1991 scrollTop: 0
1992 });
1993 };
1994
1995 self.onEnter = function (d, e) {
1996 if (e.keyCode === 13) {
1997 self.lastVehicle(0);
1998 self.selectedDriver = '';
1999 self.loadDataForMap();
2000 }
2001 return true;
2002 };
2003
2004 self.onFilter = function (d, e) {
2005 debugger;
2006 self.lastVehicle(0);
2007 self.selectedDriver = '';
2008 self.loadDataForMap();
2009 };
2010
2011 self.formatDateTime = function (date) {
2012 return 'fffffffff';
2013 };
2014
2015 // self.enableControls = ko.observable(true);
2016 self.playAllVideos = function () {
2017 $('video').each(function () {
2018 this.play();
2019 });
2020 $("#btnPlay").css("background-color", "#234e25");
2021 $("#btnPause").css("background-color", "#3e8e41");
2022 $("#btnStop").css("background-color", "#C2272D");
2023 };
2024 self.PauseAllVideos = function () {
2025 $('video').each(function () {
2026 this.pause();
2027 });
2028 $("#btnPlay").css("background-color", "#3e8e41");
2029 $("#btnPause").css("background-color", "#234e25");
2030 $("#btnStop").css("background-color", "#C2272D");
2031 };
2032 self.StopAllVideos = function () {
2033 $('video').each(function () {
2034 this.pause();
2035 this.currentTime = 0;
2036 });
2037 $("#btnPlay").css("background-color", "#3e8e41");
2038 $("#btnPause").css("background-color", "#3e8e41");
2039 $("#btnStop").css("background-color", "#752327");
2040 };
2041
2042
2043
2044 self.CloseVideoWindow = function () {
2045 $("#PlaybackVideoDiv").empty();
2046 $("#PlaybackTitleDiv").empty();
2047 self.streamMessage(resx.LiveStream);
2048 if (self.streamPlayer) {
2049 self.streamPlayer.destroy();
2050 self.streamPlayer = null;
2051 }
2052 };
2053
2054
2055 self.pagerText = ko.computed(function () {
2056 var from = ((self.page() - 1) * (self.pageSize())) + 1;
2057 if (from > self.count()) {
2058 from = self.count();
2059 }
2060 var to = ((self.page()) * (self.pageSize()));
2061 if (to > self.count()) {
2062 to = self.count();
2063 }
2064
2065 return resx.Showing + from + resx.to + to + resx.of + self.count() + resx.entries;
2066 });
2067
2068 self.pagerList = ko.computed(function () {
2069 var length = self.pages();
2070 var current = self.page();
2071
2072 var beforeDots = true;
2073 var afterDots = true;
2074 var list = [];
2075
2076 if (length <= 5) {
2077 for (var i = 1; i <= length; i++) {
2078 list.push(i);
2079 }
2080 beforeDots = false;
2081 afterDots = false;
2082 }
2083 else {
2084 list.push(1);
2085
2086 for (var i = current - 2; i <= current + 2; i++) {
2087 if (i === 2) {
2088 beforeDots = false;
2089 }
2090 if (i === length - 1) {
2091 afterDots = false;
2092 }
2093 if (i == 1 || i == length) {
2094 continue;
2095 }
2096 if (i !== current && (i <= 1 || i >= length)) {
2097 continue;
2098 }
2099 list.push(i);
2100 }
2101
2102 list.push(length);
2103 }
2104
2105 if (beforeDots) {
2106 list.splice(1, 0, -1);
2107 }
2108
2109 if (afterDots) {
2110 list.splice(list.length - 1, 0, -1);
2111 }
2112 return list;
2113 });
2114
2115 self.lastVehicle = ko.observable(0);
2116 self.selectedDriver = '';
2117 self.selectedVehicleId = ko.observable(0);
2118 self.hours = ko.observable(1);
2119 self.time_from = ko.observable(0);
2120 self.time_to = ko.observable(24);
2121 self.time_desc = ko.observable('All Time of Day');
2122 self.vehicles = ko.observableArray([]);
2123 self.lastAlerts = ko.observableArray([]);
2124 self.vehicles_sortby = ko.observable('VehicleName');
2125 self.vehicles_sortby_name = ko.observable(resx.sortby_Name);
2126 self.page_refresh = ko.observable(resx.refresh);
2127 self.selectedArea = ko.observable(resx.area);
2128 self.selectedAreaVehiclesCount = ko.observable(0);
2129 self.mapAreas = ko.observableArray([]);
2130 self.areasOverlay = ko.observableArray([]);
2131 self.vehicles_orderby = ko.observable('asc');
2132 self.vehicles_sorted = ko.observableArray([]);
2133 self.PageNo = 0;
2134 self.NoOfScrolles = 0;
2135
2136
2137
2138 self.vehicles_sort = function () {
2139 var sortby = self.vehicles_sortby();
2140 var orderby = self.vehicles_orderby();
2141 var vehicles = self.vehicles();
2142 StartPoint = 0;
2143 endPoint = (self.PageNo * 40) + 40;
2144
2145 //console.log('sortby', sortby);
2146
2147 var isFunc = false;
2148 if (vehicles.length) {
2149 isFunc = _.isFunction(_.first(vehicles)[sortby]);
2150 }
2151
2152 var sorted = _.chain(vehicles).sortBy(function (x) {
2153 return (isFunc) ? x[sortby]() : x[sortby];
2154 });
2155 if (orderby == 'desc') {
2156 sorted = sorted.reverse();
2157 }
2158 var value = [];
2159 for (var i = StartPoint; i < endPoint; i++) {
2160 if (sorted.value().length > i) {
2161 value.push(sorted.value()[i])
2162 } else {
2163 break;
2164 }
2165
2166 }
2167 self.vehicles_sorted(value);
2168 };
2169
2170 self.sortby = function (field, name) {
2171 var current = self.vehicles_sortby();
2172 var orderby = self.vehicles_orderby();
2173 var new_orderby = (field == 'Name') ? 'asc' : 'desc';
2174 if (field == current) {
2175 new_orderby = (orderby == 'asc') ? 'desc' : 'asc';
2176 }
2177
2178 self.vehicles_sortby(field);
2179 self.vehicles_sortby_name(resx['sortby_' + name]);
2180 self.vehicles_orderby(new_orderby);
2181 //no longer using computed, cannot defer computed
2182 self.vehicles_sort();
2183
2184 if (self.selectedVehicle) {
2185 self.scrollTo();
2186 } else {
2187 self.scrollTop();
2188 }
2189 };
2190
2191 self.nodeClicked = function (model, e) {
2192 console.log('node click', model.type(), model, e.type);
2193 var isVehicleClicked = model.type() === 'vehicle' && model.id && e.type === 'click';
2194 var isTripClicked = model.type() === 'trip' && e.type === 'click';
2195 var isEventClicked = model.type().indexOf('event') == 0 && e.type === 'click';
2196 if (!isVehicleClicked && !isEventClicked && !isTripClicked) {
2197 return;
2198 }
2199 if (isEventClicked) {
2200 var position = new google.maps.LatLng(model.data.crumb.Lat, model.data.crumb.Lng);
2201 if (!app.eventMarker) {
2202 app.eventMarker = placeMarker(position, map, { isEventMarker: true, first: true, data: model.data.crumb });
2203 } else {
2204 app.eventMarker.setPosition(position);
2205 app.eventMarker.setMap(map);
2206 }
2207 if (!app.eventInfobox) {
2208 app.eventInfobox = new InfoBox({
2209 content: '<div class="infobox-wrapper"><div class="infobox"><span>"' + model.name() + '"</span> <span>' + model.details() + '</span></div></div>',
2210 disableAutoPan: false,
2211 maxWidth: 150,
2212 pixelOffset: new google.maps.Size(-140, 0),
2213 zIndex: null,
2214 boxStyle: {
2215 background: "url('../images/map-symbols/tipbox.gif') no-repeat",
2216 opacity: 0.75,
2217 xwidth: "280px"
2218 },
2219 closeBoxMargin: "12px 4px 2px 2px",
2220 closeBoxURL: "../images/map-symbols/close.gif",
2221 infoBoxClearance: new google.maps.Size(1, 1)
2222 });
2223 }
2224
2225 app.eventInfobox.open(map, app.eventMarker);
2226 map.panTo(position);
2227 return;
2228 }
2229 if (isTripClicked) {
2230 if (model.isSelected()) {
2231 return;
2232 }
2233
2234 app.trip_model = model;
2235 var index = model.index();
2236 var siplingNodes = ko.contextFor(e.target).$parents[2].nodes();
2237 for (var i = 0; i < model.parent.length; i++) {
2238 if (index != i) {
2239 var node = siplingNodes[i];
2240 if (node && node.isExpanded) {
2241 node.isExpanded(false);
2242 node.isSelected(false);
2243 }
2244 }
2245 }
2246 model.isSelected(true);
2247
2248 _.forEach(app.markersForVehicle, function (m) {
2249 if (m.marker) {
2250 m.marker.setMap(null);
2251 }
2252 });
2253
2254
2255 if (!app.pathLines) {
2256 app.pathLines = [];
2257 }
2258
2259 for (var i = 0; i < app.pathLines.length; i++) {
2260 app.pathLines[i].setPath([]);
2261 }
2262
2263 app.markersForVehicle = [];
2264
2265 app.markersForVehicle = model.trip.positions;
2266 self.drawTrackingPath(true, true);
2267
2268 var markerA = placeMarker(_.first(model.trip.positions).position, map, { first: false, glow: true, index: 0, alert: 0, eventId: 0, label: 'A', data: model.data.crumb });
2269 var markerB = placeMarker(_.last(model.trip.positions).position, map, { first: false, glow: true, index: 0, alert: 0, eventId: 0, label: 'B', data: model.data.crumb });
2270
2271 app.markersForVehicle = [{ marker: markerA }, { marker: markerB }];
2272
2273 return;
2274 }
2275 var selectedVehicleId = model.id();
2276 if (self.lastVehicle() === selectedVehicleId) {
2277 selectedVehicleId = 0;
2278 }
2279 self.lastVehicle(selectedVehicleId);
2280 self.selectedDriver = '';
2281
2282 self.loadDataForMap();
2283 //var data = {
2284 // vehicleId: model.id()
2285 //};
2286 //var json = ko.toJSON(data);
2287
2288 //$.ajax({
2289 // url: 'Tracking/LastLocations',
2290 // type: 'POST',
2291 // data: json,
2292 // contentType: 'application/json',
2293 // crossDomain: true,
2294 // cache: false,
2295 // success: function (data) {
2296 // self.showLocations(data);
2297 // },
2298 // fail: function (data) {
2299 // alert('Starting failed.');
2300 // console.log('fail', data);
2301 // },
2302 // error: function (data) {
2303 // var json = JSON.parse(data.responseText);
2304 // alert('Starting error. ' + (json.Message || ''));
2305 // console.log('error', data);
2306 // }
2307 //});
2308 }
2309
2310 self.showLocations = function (data, markerBounds) {
2311 //if (app.pathLine) {
2312 // app.pathLine.setMap(null);
2313 // app.pathLine.setVisible(false);
2314 // app.pathLine = null;
2315 //}
2316
2317 if (markersForVehicle && markersForVehicle.length) {
2318 _.forEach(markersForVehicle, function (m) {
2319 m.setMap(null);
2320 m.setVisible(false);
2321 });
2322 markersForVehicle = [];
2323 }
2324
2325 if (markers && markers.length) {
2326 _.forEach(markers, function (m) {
2327 //m.setMap(null);
2328 //m.setVisible(false);
2329 });
2330 //markersForVehicle = [];
2331 }
2332
2333 var markerBounds = markerBounds || new google.maps.LatLngBounds();
2334 _.forEach(data.Locations, function (p, i) {
2335 //var listener = google.maps.event.addListener(map, "idle", function () {
2336 var latlng = new google.maps.LatLng(p.Latitude, p.Longitude);
2337 var marker = placeMarker(latlng, map, { first: i === 0, glow: true, index: i, alert: p.Priority, eventId: p.EventId });
2338
2339 markerBounds.extend(marker.getPosition());
2340 markersForVehicle.push(marker);
2341
2342 var pathPositions = _.map(markersForVehicle, function (m, i) { return { lat: m.position.lat(), lng: m.position.lng(), data: m.data } });
2343 var paths = [];
2344
2345 var lastSpeed = 0;
2346 var currentPath = null;
2347 for (var i = 0; i < pathPositions.length; i++) {
2348 var speed = pathPositions[i].data.Speed;
2349 var overSpeeding = speed >= 100;
2350 var isNewPath = i == 0 || (currentPath.overSpeeding ^ overSpeeding);
2351 if (isNewPath) {
2352 currentPath = { overSpeeding: overSpeeding, path: [pathPositions[i]] };
2353 paths.push(currentPath);
2354 } else {
2355 currentPath.path.push(pathPositions[i]);
2356 }
2357 }
2358
2359 if (!app.pathLines) {
2360 app.pathLines = [];
2361 }
2362
2363 for (var i = 0; i < app.pathLines.length; i++) {
2364 app.pathLines[i].setPath([]);
2365 }
2366
2367 for (var i = 0; i < paths.length; i++) {
2368 var pathLine = app.pathLines[i];
2369 if (paths[i].path.length <= 1) {
2370 var prevPath = paths[i - 1];
2371 var nextPath = paths[i + 1];
2372 if (prevPath) {
2373 paths[i].path.unshift(_.last(prevPath.path));
2374 }
2375 if (nextPath) {
2376 paths[i].path.push(_.first(nextPath.path));
2377 }
2378 }
2379 if (pathLine) {
2380 pathLine.setPath(paths[i].path);
2381 } else {
2382 pathLine = new google.maps.Polyline({
2383 path: paths[i].path,
2384 geodesic: true,
2385 strokeColor: paths[i].overSpeeding ? '#FF6600' : '#4593BC',
2386 strokeOpacity: 0.8,
2387 strokeWeight: 1,
2388 icons: [{
2389 icon: app.lineSymbol,
2390 offset: '100%'
2391 }]
2392 });
2393 pathLine.setMap(map);
2394 app.pathLines.push(pathLine);
2395 }
2396 }
2397
2398 // google.maps.event.removeListener(listener);
2399 //});
2400 });
2401 map.fitBounds(markerBounds);
2402 var listener = google.maps.event.addListener(map, "idle", function () {
2403 if (map.getZoom() > 15) map.setZoom(15);
2404 google.maps.event.removeListener(listener);
2405 });
2406 }
2407
2408 self.loadTree = function (data) {
2409 self.treeData(new NodeModel(data.navTree, self.nodeClicked));
2410 };
2411
2412 var lineSymbol = {
2413 path: google.maps.SymbolPath.CIRCLE,
2414 scale: 7,
2415 strokeColor: '#5696F7',
2416 fillColor: '#ff0000',
2417 strokeWeight: 4,
2418 fillOpacity: 0.75
2419 };
2420 app.lineSymbol = lineSymbol;
2421
2422 var markerSymbol = {
2423 path: google.maps.SymbolPath.CIRCLE,
2424 scale: 8,
2425 strokeColor: '#65D227',
2426 strokeWeight: 3
2427 };
2428
2429 var markerAlertSymbol = {
2430 path: google.maps.SymbolPath.CIRCLE,
2431 scale: 8,
2432 strokeColor: '#F3565B',
2433 strokeWeight: 3
2434 };
2435
2436 var markerEvent2Symbol = {
2437 path: google.maps.SymbolPath.CIRCLE,
2438 scale: 8,
2439 strokeColor: '#FFF',
2440 strokeWeight: 3
2441 };
2442
2443 function createVehicle(crumb, visible) {
2444
2445 // Create marker
2446 var marker = new MarkerWithLabel({
2447 //position: new google.maps.LatLng(crumb.Latitude, crumb.Longitude),
2448 position: new google.maps.LatLng(24.446489999999994, 54.61311999999998),
2449
2450 //map: waypointMap.getMap(),
2451 //icon: getVehicleIcon(crumb.IsDisconnected),
2452 icon: getVehicleIcon(false),
2453 //labelContent: getLabelContent(crumb),
2454 labelContent: getLabelContent('xxxxx'),
2455 labelAnchor: new google.maps.Point(13, 13),
2456 labelClass: 'marker-label',
2457 labelVisible: visible
2458 });
2459
2460 // Set marker id_
2461 //marker.id_ = crumb.CrumbId;
2462 //marker.vehicleId_ = crumb.VehicleId;
2463 //marker.vehicleName_ = crumb.VehicleName;
2464
2465 addToMap(vehicleClusterer, marker);
2466
2467 // Add listener
2468 google.maps.event.addListener(marker, 'click', modalVehicle);
2469
2470 return marker;
2471 }
2472
2473 function addToMap(mclusterer, marker) {
2474 if (mclusterer) {
2475 mclusterer.addMarker(marker, false);
2476 }
2477 else {
2478 marker.setMap(waypointMap.getMap());
2479 }
2480 }
2481
2482 function getVehicleIcon(disconnect) {
2483 return Defaults.icon;
2484 //disconnect ? '@Url.Content("~/images/vehicles/car-no-signal.png")'
2485 // : '@Url.Content("~/images/vehicles/car.png")';
2486 }
2487
2488 function getArrowColor(options, isForShowInfo) {
2489 options = options || {};
2490
2491 var arrowColor = '';
2492
2493 if (options.vehicle) {
2494 if (options.isCurrent) {
2495 arrowColor = '#29AAE3';
2496 } else if (options.vehicle.IsNoSignal) {
2497 arrowColor = '#ff471a';
2498 } else if (options.vehicle.IsNoSignal_White) {
2499 arrowColor = '#999999';
2500 } else if (options.crumb) {
2501 if (options.crumb.IsEngineOn === false) {
2502 arrowColor = '#f6f6f6';
2503 } else {
2504 arrowColor = '#7ec2e7';
2505
2506 if (options.crumb.Speed > 0) {
2507 arrowColor = '#70db70';
2508 }
2509 }
2510 }
2511 }
2512 else {
2513 if (options.alert) {
2514 arrowColor = '#D36557';
2515 }
2516 if (options.eventId == 2) {
2517 arrowColor = ' #CCC ';
2518 }
2519 if (options.isEventMarker) {
2520 arrowColor = '#FDFD00';
2521 }
2522 }
2523 if (isForShowInfo) {
2524 arrowColor = '#fbae17';
2525 }
2526 return arrowColor;
2527
2528 }
2529
2530 function getLabelContent(options, isForShowInfo) {
2531 options = options || {};
2532 var glow = options.glow ? '-glow' : '';
2533
2534 var pulseGlowCss = '', pulseCircleCss = '';
2535 if (options.vehicle) {
2536 if (options.isCurrent) {
2537 pulseGlowCss += ' pulse-glow-current ';
2538 pulseCircleCss += ' pulse-circle-current ';
2539 } else if (options.vehicle.IsNoSignal) {
2540 pulseGlowCss += ' pulse-glow-no-signal-L2 ';
2541 pulseCircleCss += ' pulse-circle-no-signal-L2 ';
2542 } else if (options.vehicle.IsNoSignal_White) {
2543 pulseGlowCss += ' pulse-glow-no-signal-L1 ';
2544 pulseCircleCss += ' pulse-glow-no-signal-L1 ';
2545 } else if (options.crumb) {
2546 if (options.crumb.IsEngineOn === false) {
2547 pulseGlowCss += ' pulse-glow-switched-off ';
2548 pulseCircleCss += ' pulse-circle-switched-off ';
2549 } else {
2550 pulseGlowCss += ' pulse-glow-switched-on ';
2551 pulseCircleCss += ' pulse-circle-switched-on ';
2552
2553 if (options.crumb.Speed > 0) {
2554 pulseGlowCss += ' pulse-glow-moving ';
2555 pulseCircleCss += ' pulse-circle-moving ';
2556 }
2557 }
2558 }
2559 }
2560 else {
2561 if (options.alert) {
2562 pulseGlowCss += ' pulse-glow-alert ';
2563 pulseCircleCss += ' pulse-circle-alert ';
2564 }
2565 if (options.eventId == 2) {
2566 pulseGlowCss += ' pulse-glow-event-2 ';
2567 pulseCircleCss += ' pulse-circle-event-2 ';
2568 }
2569 if (options.isEventMarker) {
2570 pulseGlowCss += ' pulse-glow-event-marker ';
2571 pulseCircleCss += ' pulse-circle-event-marker ';
2572 }
2573 }
2574
2575 if (isForShowInfo) {
2576 pulseGlowCss += ' pulse-glow-Selected ';
2577 pulseCircleCss += ' pulse-circle-Selected ';
2578 }
2579
2580
2581
2582
2583 return '<div class="marker-label-inner clearfix" style="position: relative;padding-top:25px;padding-left:25px;border-radius:50% !important;birder:none;x-border: 1px solid red;">' +
2584 //'<div class="m-icon-bg">' +
2585 // canvas +
2586 //'</div>' +
2587 //'<div class="m-text">' +
2588 // '<div class="m-text-main">' + 'Omar Car (Ruptela) Umniah' + '</div>' +
2589 '<div class="live-icon' + glow + '">' +
2590 '<div class="pulse' + glow + pulseGlowCss + '">' +
2591 '<div class="pulse-circle' + glow + pulseCircleCss + '"></div>' +
2592 '</div>' +
2593 '</div>' +
2594 '</div>' +
2595 '</div>';
2596
2597 }
2598 app.isMarkerSelected = false;
2599 var changeSelectedMarkerColorIcon = function (marker) {
2600 app.isMarkerSelected = true;
2601 if (app.selectedVehicleMarker && app.selectedMarkerLabelContent) {
2602 app.selectedVehicleMarker.set('labelContent', app.selectedMarkerLabelContent);
2603 if (app.enableDirectionMap == true) {
2604 app.selectedVehicleMarker.setIcon(app.selectedMarkerIcon);
2605 }
2606 }
2607
2608 var content = getLabelContent({}, true);
2609 if (app.enableDirectionMap == true && marker && marker.icon) {
2610 var arrowColor = getArrowColor({}, true);
2611 var rotation = marker.icon.rotation;
2612 var icon = {
2613 path: app.directionIconPath,
2614 fillColor: arrowColor,
2615 fillOpacity: 1,
2616 scale: 1,
2617 strokeColor: arrowColor,
2618 strokeWeight: 1,
2619 rotation: rotation,
2620 origin: new google.maps.Point(0, 0),
2621 // The anchor for this image is the base of the flagpole at (0, 32).
2622 anchor: new google.maps.Point(3, 9),
2623 };
2624 app.selectedMarkerIcon = marker.icon;
2625 marker.setIcon(icon);
2626 }
2627 app.selectedVehicleMarker = marker;
2628 app.selectedMarkerLabelContent = marker.labelContent;
2629 marker.set('labelContent', content);
2630 console.log('changeSelectedMarkerColorIcon');
2631 }
2632 var animateCircleTimer = null;
2633 var stopAnimateCircle = function (line) {
2634 //return;
2635 clearInterval(animateCircleTimer);
2636 animateCircleTimer = null;
2637 app.index = 0;
2638 }
2639
2640 var animateCircle = function (lines) {
2641 //return;
2642
2643 var count = 0;
2644 app.index = 0;
2645
2646 if (animateCircleTimer) {
2647 stopAnimateCircle();
2648 }
2649 //if (!(lines && lines.length)) {
2650 // console.log('no line to animate', lines);
2651 // //stopAnimateCircle();
2652 // return;
2653 //}
2654 //animateCircleTimer = window.setInterval(function () {
2655 // count = (count + 1) % 200;
2656
2657 // var icons = line.get('icons');
2658 // icons[0].offset = (count / 2) + '%';
2659 // line.set('icons', icons);
2660 //}, 60);
2661 animateCircleTimer = window.setInterval(function () {
2662 var flag = false;
2663 do {
2664 if (!(lines && lines.length)) {
2665 //console.log('no line to animate', lines);
2666 //stopAnimateCircle();
2667 return;
2668 }
2669
2670 var index = app.index % lines.length;
2671 app.index = index;
2672 var linesSorted = _.sortBy(lines, 'index');
2673 var line = linesSorted[index].polyLine;
2674 var icons = line.get('icons');
2675 if (!icons) {
2676 //console.log('no icons', lines);
2677 app.index++;
2678 count = 0;
2679 ////return;
2680 //flag = true;
2681 //continue;
2682 return;
2683 }
2684 if (icons[0].offset == '150%') {
2685 if (index == 0) {
2686 count = 0;
2687 for (var i = 0; i < lines.length; i++) {
2688 var xicons = lines[i].polyLine.get('icons');
2689 xicons[0].offset = '140%';
2690 }
2691 } else {
2692 app.index++;
2693 count = 0;
2694 //return;
2695 flag = true;
2696 continue;
2697 }
2698 }
2699
2700 var inc = 1 + (10 / line.getPath().length);
2701 //count = (count + 1) % 201;
2702 count = (count + inc);// % 201;
2703 var offset = (count / 2);
2704 icons[0].offset = (count / 2) + '%';
2705 if (offset >= 100) {
2706 //console.log(icons[0].offset);
2707 }
2708 if (offset >= 100) {
2709 icons[0].offset = '150%';
2710 //console.log('120%', app.index);
2711 app.index++;
2712 count = 0;
2713 }
2714 line.set('icons', icons);
2715 } while (flag);
2716 }, 60);
2717 }
2718
2719 app.animateCircle = animateCircle;
2720
2721 var placeMarker = function (position, map, options, live, AddToMapByClusterer) {
2722 var multiplier = 1 / (1 + ((options.index || 0) * 0.05));
2723 //var anchorSize = 12 * multiplier;
2724 //var scaledSize = 24 * multiplier;
2725 var fillOpacity = 0.6 * multiplier;
2726
2727 //var iconUrl = '';
2728 //if (options.first && options.alert) {
2729 // iconUrl = 'icon-red-fill-glow';
2730 //} else if (!options.first && options.alert) {
2731 // iconUrl = 'icon-red-glow';
2732 //} else if (options.first && !options.alert) {
2733 // iconUrl = 'icon-green-fill-glow';
2734 //} else {//(!options.first && !options.alert) {
2735 // iconUrl = 'icon-green-glow';
2736 //}
2737
2738 //if (options.eventId == 2) {
2739 // iconUrl = 'icon-grey';
2740 //}
2741
2742 if (options.first && options.trip) {
2743 var icon = null;
2744 if (false && live) {
2745 icon = { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, scale: 2, fillColor: 'gold', fillOpacity: 0.8, strokeColor: 'gold', rotation: options.angle }
2746 } else {
2747 icon = new google.maps.MarkerImage('../content/trips/marker-icon-A.svg', null, null, new google.maps.Point(20, 36), new google.maps.Size(46, 46));
2748 }
2749 app.position_A = position;
2750 var marker = new google.maps.Marker({ position: position, map: map, icon: icon, optimized: false, zIndex: 10 });
2751 return marker;
2752 }
2753
2754 if (options.last && options.trip) {
2755 var icon = null;
2756 if (live) {
2757 icon = { path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW, scale: 2, fillColor: 'gold', fillOpacity: 0.8, strokeColor: 'gold', rotation: options.angle }
2758 } else {
2759 //
2760 if (!options.tripdetails) {
2761 icon = new google.maps.MarkerImage('../content/trips/marker-icon-B.svg', null, null, new google.maps.Point(20, 36), new google.maps.Size(46, 46))
2762 } else {
2763 icon = new google.maps.MarkerImage('../content/trips/marker-icon-B.svg', null, null, new google.maps.Point(20, 36), new google.maps.Size(46, 46))
2764 //var currentMarker = _.find(app.markersForVehicle, function (c) { return c.isCurrent; });
2765 //currentMarker.marker.setPosition(position);
2766 //return currentMarker.marker;
2767 }
2768 }
2769 var marker = new google.maps.Marker({ position: position, map: map, icon: icon, optimized: false, zIndex: 10 });
2770 return marker;
2771 }
2772
2773 var icon = {
2774 //url: '../images/map-symbols/' + iconUrl + '.svg',
2775 //anchor: new google.maps.Point(anchorSize, anchorSize),
2776 //scaledSize: new google.maps.Size(scaledSize, scaledSize),
2777 fillOpacity: fillOpacity,
2778 icon: {
2779 path: google.maps.SymbolPath.CIRCLE,
2780 scale: 20
2781 }
2782
2783 };
2784
2785 var marker = null;
2786 if (options.first) {
2787
2788 if (app.enableDirectionMap == true && options.data && options.data.Angle !== undefined) {
2789
2790 var arrowColor = getArrowColor(options);
2791 marker = new MarkerWithLabel({
2792 position: position,
2793 icon: {
2794 path: app.directionIconPath,
2795 fillColor: arrowColor,
2796 fillOpacity: 1,
2797 scale: 1,
2798 strokeColor: arrowColor,
2799 strokeWeight: 1,
2800 rotation: options.data.Angle - 90,
2801 origin: new google.maps.Point(0, 0),
2802 // The anchor for this image is the base of the flagpole at (0, 32).
2803 anchor: new google.maps.Point(3, 9),
2804 },
2805 labelContent: getLabelContent(options),
2806 labelAnchor: new google.maps.Point(13, 13),
2807 labelClass: 'marker-label',
2808 labelVisible: true,
2809
2810 });
2811 }
2812 else {
2813 marker = new MarkerWithLabel({
2814 position: position,
2815 icon: getVehicleIcon(false),
2816 labelContent: getLabelContent(options),
2817 labelAnchor: new google.maps.Point(13, 13),
2818 labelClass: 'marker-label',
2819 labelVisible: true,
2820 });
2821 }
2822
2823
2824 if (!AddToMapByClusterer)
2825 marker.setMap(map);
2826
2827 } else {
2828
2829 var symbol = markerSymbol;
2830 if (options.alert) {
2831 symbol = markerAlertSymbol;
2832 }
2833 if (options.eventId == 2) {
2834 symbol = markerEvent2Symbol;
2835 }
2836 var newSymbol = jQuery.extend({}, symbol);
2837 if (options.label) {
2838 newSymbol.strokeWeight = 10;
2839 }
2840
2841 marker = new google.maps.Marker({
2842 position: position,
2843 map: map,
2844 icon: newSymbol,
2845 label: options.label
2846 });
2847 }
2848 return marker;
2849 //map.panTo(position);
2850 }
2851
2852 self.showInfo = function (marker, vehicle, e, live, dateFrom, dateTo) {
2853
2854
2855 if (areaNameInfoWindow) {
2856 areaNameInfoWindow.close();
2857 areaNameInfoWindow = null;
2858 }
2859
2860 var _map = live ? map_live : map;
2861
2862 var id = 'map_infoWnd_' + vehicle.VehicleId;
2863 if (!vehicle.infoWnd) {
2864 if (app.eventInfobox) {
2865 app.eventInfobox.close();
2866 app.eventInfobox = null;
2867 }
2868
2869 if (!app.eventInfobox) {
2870 app.eventInfobox = new InfoBox({
2871 content: $('#infoWnd_template').html().replace('map_infoWnd_x', id),
2872 disableAutoPan: false,
2873 alignBottom: true,
2874 maxWidth: 150,
2875 pan_vertical_offset: 0,
2876 pixelOffset: new google.maps.Size(-240 - 1, -24),
2877 zIndex: null,
2878 boxStyle: {
2879 background: "none",//"url('../images/map-symbols/tipbox.gif') no-repeat",
2880 opacity: 0.75,
2881 xwidth: "280px"
2882 },
2883 //closeBoxMargin: "12px 4px 2px 2px",
2884 closeBoxURL: '<div align="right" style="z-index:10; position: relative; cursor: pointer; background: url(../content/trips/popup/close_btn.svg);width:20px;height:20px;right:-465px;top:15px"></div>', //"../images/map-symbols/close.gif",
2885 closeBoxCustom: true,
2886 infoBoxClearance: new google.maps.Size(10, 10)
2887 });
2888 }
2889
2890 var model = new VehicleStatusModel(vehicle.VehicleId, dateFrom, dateTo);
2891 model.load();
2892
2893 google.maps.event.addListener(app.eventInfobox, 'domready', function () {
2894 var el = document.getElementById(id);
2895 if (el && ko.dataFor(el)) {
2896 ko.cleanNode(el);
2897 ko.applyBindings(model, el);
2898 }
2899 });
2900
2901 google.maps.event.addListener(app.eventInfobox, 'closeclick', function () {
2902 app.isMarkerSelected = false;
2903 if (app.selectedVehicleMarker && app.selectedMarkerLabelContent) {
2904 app.selectedVehicleMarker.set('labelContent', app.selectedMarkerLabelContent);
2905 if (app.enableDirectionMap == true) {
2906 app.selectedVehicleMarker.setIcon(app.selectedMarkerIcon);
2907 }
2908
2909 }
2910 var el = document.getElementById(id);
2911 if (el) {
2912 ko.cleanNode(el);
2913 }
2914 app.eventInfobox = null;
2915
2916
2917 });
2918
2919 app.eventInfobox.open(map, marker);
2920 return app.eventInfobox;
2921
2922
2923
2924 vehicle.infoWnd = new google.maps.InfoWindow({
2925 content: $('#infoWnd_template').html().replace('map_infoWnd_x', id)//'title: ' + self.title()
2926 });
2927
2928 var model = new VehicleStatusModel(vehicle.VehicleId, dateFrom, dateTo);
2929 model.load();
2930
2931 google.maps.event.addListener(vehicle.infoWnd, 'domready', function () {
2932 var el = document.getElementById(id);
2933 if (ko.dataFor(el)) {
2934 ko.cleanNode(el);
2935 }
2936 ko.applyBindings(model, el);
2937 });
2938
2939 google.maps.event.addListener(vehicle.infoWnd, 'closeclick', function () {
2940 var el = document.getElementById(id);
2941 if (el) {
2942 ko.cleanNode(el);
2943 }
2944 vehicle.infoWnd = null;
2945 });
2946 }
2947 vehicle.infoWnd.open(map, marker);
2948 return vehicle.infoWnd;
2949 }
2950
2951 self.showAlert = function (marker, vehicle, alert, live) {
2952 if (!(alert && alert.FirstTime && alert.LastTime)) {
2953 return;
2954 }
2955 //console.log('showAlert', marker, vehicle, alert);
2956 var _map = live ? map_live : map;
2957 //var id = 'map_infoWnd_' + vehicle.VehicleId;
2958 var id = 'alertWnd_template_' + vehicle.VehicleId;
2959 if (true) {
2960 if (true) {
2961 self.closeInfo(live ? app.markerInfoWindow_live : app.markerInfoWindow);
2962 }
2963 if (app.alertInfobox) {
2964 app.alertInfobox.close();
2965 app.alertInfobox = null;
2966 }
2967 if (!app.alertInfobox) {
2968 app.alertInfobox = new InfoBox({
2969 content: $('#alertWnd_template').html().replace('map_alertWnd_x', id),
2970 disableAutoPan: false,
2971 alignBottom: true,
2972 maxWidth: 150,
2973 pan_vertical_offset: 0,
2974 pixelOffset: new google.maps.Size(-240 - 1, -24),
2975 zIndex: null,
2976 boxStyle: {
2977 background: "none",
2978 opacity: 0.75,
2979 xwidth: "280px"
2980 },
2981 //closeBoxMargin: "12px 4px 2px 2px",
2982 closeBoxURL: '<div align="right" style="z-index:10; position: relative; cursor: pointer; background: url(../content/trips/popup/close_btn.svg);width:20px;height:20px;right:-465px;top:15px"></div>', //"../images/map-symbols/close.gif",
2983 closeBoxCustom: true,
2984 infoBoxClearance: new google.maps.Size(10, 10)
2985 });
2986 }
2987
2988 var model = new AlertModel(alert, vehicle.VehicleName);
2989 model.getLocation();
2990
2991 google.maps.event.addListener(app.alertInfobox, 'domready', function () {
2992 var el = document.getElementById(id);
2993 if (el && ko.dataFor(el)) {
2994 ko.cleanNode(el);
2995 ko.applyBindings(model, el);
2996 }
2997 });
2998
2999 google.maps.event.addListener(app.alertInfobox, 'closeclick', function () {
3000 var el = document.getElementById(id);
3001 if (el) {
3002 ko.cleanNode(el);
3003 }
3004 app.alertInfobox = null;
3005 });
3006
3007 app.alertInfobox.open(_map, marker);
3008 return app.alertInfobox;
3009
3010 }
3011 vehicle.infoWnd.open(_map, marker);
3012 return vehicle.infoWnd;
3013 }
3014
3015 self.closeInfo = function (infoWindow) {
3016 if (infoWindow) {
3017 infoWindow.close();
3018 }
3019 if (app.alertInfobox) {
3020 self.closeAlert(app.alertInfobox);
3021 }
3022 };
3023
3024 self.closeAlert = function (alertWindow) {
3025 if (alertWindow) {
3026 alertWindow.close();
3027 }
3028 };
3029
3030 //self.closeInfo = function (marker, vehicle) {
3031 // if (vehicle.infoWnd) {
3032 // vehicle.infoWnd.close();
3033 // }
3034 //};
3035 self.selectedVehicle = null;
3036 self.clicked = function (model, e) {
3037 //console.log('v clicked', model, e);
3038 var deselected = false;
3039 if (self.selectedVehicle) {
3040 self.selectedVehicle.isSelected(false);
3041 deselected = self.selectedVehicle.VehicleId == model.VehicleId;
3042 }
3043 var isSelected = !deselected && !model.isSelected();
3044 model.isSelected(isSelected);
3045 if (isSelected) {
3046 self.selectedVehicle = model;
3047 self.lastVehicle(model.VehicleId);
3048 } else {
3049 if (app.markerInfoWindow) {
3050 app.markerInfoWindow.close();
3051 }
3052
3053 self.selectedVehicle = null;
3054 self.lastVehicle(0);
3055 model.trips([]);
3056 }
3057 self.selectedDriver = '';
3058 self.loadDataForMap({ vehicle: self.selectedVehicle });
3059 };
3060
3061 self.onScroll = function () {
3062
3063 if (self.NoOfScrolles > 15) {
3064 self.PageNo++;
3065 var sortby = self.vehicles_sortby();
3066 var orderby = self.vehicles_orderby();
3067 var vehicles = self.vehicles();
3068 StartPoint = 40 * self.PageNo;
3069 endPoint = StartPoint + 40;
3070
3071 //console.log('sortby', sortby);
3072
3073 var isFunc = false;
3074 if (vehicles.length) {
3075 isFunc = _.isFunction(_.first(vehicles)[sortby]);
3076 }
3077
3078 var sorted = _.chain(vehicles).sortBy(function (x) {
3079 return (isFunc) ? x[sortby]() : x[sortby];
3080 });
3081 if (orderby == 'desc') {
3082 sorted = sorted.reverse();
3083 }
3084 var value = self.vehicles_sorted();
3085 for (var i = StartPoint; i < endPoint; i++) {
3086 if (sorted.value().length > i) {
3087 value.push(sorted.value()[i])
3088 } else {
3089 break;
3090 }
3091
3092 }
3093
3094 self.NoOfScrolles = 0;
3095 self.vehicles_sorted(value);
3096 }
3097 else {
3098 self.NoOfScrolles++;
3099 }
3100 };
3101
3102 //zzzzzzzzzzzzzzzzzz
3103 self.selectedShift = null;
3104 self.selectedTrip = null;
3105 self.shiftClicked = function (model, e) {
3106 if (self.selectedShift && model != self.selectedShift) {
3107 self.selectedShift.isSelected(false);
3108 }
3109 var isSelected = true;
3110 model.isSelected(isSelected);
3111 self.selectedShift = model;
3112 self.selectedDriver = model.driver;
3113 return false;
3114 };
3115
3116 self.tripClicked = function (model, e) {
3117 self.closeInfo(app.markerInfoWindow);
3118 //console.log('t clicked', model, e);
3119 if (self.selectedTrip) {
3120 self.selectedTrip.isSelected(false);
3121 }
3122 var isSelected = true;//!model.isSelected();
3123 model.isSelected(isSelected);
3124 if (isSelected) {
3125 self.selectedTrip = model;
3126 //self.lastVehicle(model.VehicleId);
3127 //console.log('get crumbs and draw path', model);
3128
3129 Metronic.blockUI({ target: '#tab-map-canvas-container', animate: true });
3130
3131 //var data = {
3132 //filter: self.filter(),
3133 //selectedVehicleId: self.lastVehicle() || 0,
3134 //hours: self.hours(),
3135
3136 //fromTime: self.time_from(),
3137 //toTime: self.time_to(),
3138 //fromDate: self.map_from(),
3139 //toDate: self.map_to()
3140 //};
3141
3142 var json = ko.toJSON(self.selectedTrip);
3143
3144 $.ajax({
3145 url: '../Rental/Tracking/TripDetails',
3146 type: 'POST',
3147 data: json,
3148 contentType: 'application/json',
3149 crossDomain: true,
3150 cache: false,
3151 error: function (data, e, x) {
3152 console.log('error', data, e, x);
3153 },
3154 success: function (data, e, x) {
3155 if (!_.isObject(data)) {
3156 window.location = "";
3157 }
3158 if (app.markerInfoWindow) {
3159 app.markerInfoWindow.close();
3160 app.markerInfoWindow = null;
3161 }
3162 if (app.pathLines) {
3163 _.forEach(app.pathLines, function (p) {
3164 p.setMap(null);
3165 p = null;
3166 });
3167 app.pathLines = [];
3168 }
3169 if (app.pathPositions) {
3170 app.pathPositions = [];
3171 }
3172 if (app.markersForVehicle) {
3173 var current = [];
3174 _.forEach(app.markersForVehicle, function (p) {
3175 if (p.isCurrent) {
3176 ////////////////
3177 if (p.marker) {
3178 p.marker.setMap(null);
3179 }
3180 var marker = placeMarker(p.position, map, { first: true, glow: false, vehicle: app.model.selectedVehicle, isCurrent: true });
3181 p.marker = marker;
3182 p.marker.click_handler = marker.addListener('click', function (e) {
3183 if (true) {
3184 self.closeInfo(app.markerInfoWindow);
3185 }
3186
3187 app.markerInfoWindow = self.showInfo(marker, app.model.selectedVehicle, e, null, self.map_from(), self.map_to());
3188 });
3189 /////////////////
3190 current.push(p);
3191 return;
3192 }
3193 if (p.marker) {
3194 p.marker.setMap(null);
3195 }
3196 p = null;
3197 });
3198 app.markersForVehicle = [].concat(current);
3199 }
3200
3201 self.Track = data;
3202
3203 var prevLocation = null;
3204 var trackingData = _.first(data);
3205
3206 //clear markers on refresh
3207 _.forEach(app.markersForVehicle, function (m) {
3208 if (m.marker) {
3209 m.marker.setMap(null);
3210 }
3211 });
3212 app.markersForVehicle = [];
3213
3214 if (trackingData) {
3215 _.forEach(trackingData.TrackingItems, function (c, i) {
3216
3217 var drawResult = self.drawTrackingMarkers(trackingData, i, prevLocation, app.zooms, { trip: true, tripdetails: false });
3218 if (drawResult) {
3219 prevLocation = drawResult;
3220 }
3221 });
3222 self.drawTrackingPath(true, true);
3223 app.trip = trackingData;
3224 }
3225 Metronic.unblockUI('#tab-map-canvas-container');
3226 return;
3227 }
3228 });
3229 } else {
3230 self.selectedTrip = null;
3231 //self.lastVehicle(0);
3232 //model.trips([]);
3233 }
3234 //self.loadDataForMap();
3235 return false;
3236 };
3237
3238 self.getLocationForObs = function (tripId, isFirstAddress, isAddressFetched,address, lat, lng, obs, def, count) {
3239 obs('');
3240 if (isAddressFetched && address && address !== lat + ',' + lng) {
3241 obs(address);
3242 def.resolve();
3243 return;
3244 }
3245
3246 geocoder.geocode(lat, lng, function (data, status) {
3247
3248 if (def) {
3249 def.resolve();
3250 }
3251
3252 if (status === 200) {
3253 if (data.status == 'OVER_QUERY_LIMIT') {
3254 if (count >= 5) {
3255 obs(resx.Nan);
3256 } else {
3257 setTimeout(function () {
3258 if (!count) {
3259 count = 0;
3260 }
3261 count++;
3262 self.getLocationForObs(tripId, isFirstAddress, isAddressFetched,address, lat, lng, obs, def, count);
3263 }, 800);
3264 }
3265 } else {
3266 obs(data.results[0] ? '' + data.results[0].formatted_address + '' : '');
3267
3268 address = data.results[0] ? '' + data.results[0].formatted_address + '' : '';
3269 obs(address);
3270 $.ajax({
3271 url: '../Rental/Tracking/UpdateTripAddress?tripId=' + tripId + '&isFirstAddress=' + isFirstAddress + '&address=' + address,
3272 type: 'POST',
3273 crossDomain: true,
3274 cache: false,
3275 error: function (data, e, x) {
3276
3277 },
3278 success: function (data, e, x) {
3279
3280 }
3281 });
3282 }
3283 }
3284 else {
3285 obs(resx.Nan);
3286 }
3287
3288 });
3289 };
3290
3291 self.time_from.subscribeChanged(function (newv, oldv) {
3292 if (newv == oldv)
3293 return;
3294 self.getTrips();
3295 });
3296
3297 self.time_to.subscribeChanged(function (newv, oldv) {
3298 if (newv == oldv)
3299 return;
3300 self.getTrips();
3301 });
3302
3303 self.map_from.subscribeChanged(function (newv, oldv) {
3304 $('#ToTime').datetimepicker('setStartDate', newv);
3305 if (newv == oldv)
3306 return;
3307 self.getTrips();
3308 });
3309
3310 self.map_to.subscribeChanged(function (newv, oldv) {
3311 $('#FromTime').datetimepicker('setEndDate', newv);
3312 if (newv == oldv)
3313 return;
3314 self.getTrips();
3315 });
3316
3317 self.getTrips = function () {
3318 //if (!self.lastVehicle()) {
3319 // return;
3320 //}
3321
3322 //var v = self.selectedVehicle;
3323 //var v = _.first(self.vehicles(), function (x) { return x.VehicleId == self.selectedVehicle.VehicleId });
3324 //console.log('vvvvvvvvvvvvv', v);
3325
3326 var data = {
3327 filter: self.filter(),
3328 selectedVehicleId: self.lastVehicle() || 0,
3329 hours: self.hours(),
3330
3331 fromTime: self.time_from(),
3332 toTime: self.time_to(),
3333 fromDate: self.map_from(),
3334 toDate: self.map_to()
3335 };
3336 var json = ko.toJSON(data);
3337 self.loading(true);
3338 Metronic.blockUI({ target: '#tab-map-canvas-container', animate: true });
3339
3340 $.ajax({
3341 url: '../Rental/Tracking/Trips',
3342 type: 'POST',
3343 data: json,
3344 contentType: 'application/json',
3345 crossDomain: true,
3346 cache: false,
3347 error: function (data, e, x) {
3348 console.log('error', data, e, x);
3349 },
3350 success: function (data, e, x) {
3351 sidebarFunc(app, self, data);
3352 }
3353 });
3354 };
3355
3356 self.harshDrivingTotalSum = ko.observable(0);
3357 self.idlingTotalSum = ko.observable(0);
3358 self.alertsTotalSum = ko.observable(0);
3359 self.vehicleTotalSum = ko.observable(0);
3360 self.format_lastTime = function (v, crumb, today, yesterday, now) {
3361 var t = crumb;
3362 if (t) {
3363 v.TimeStamp = t.TimeStamp;
3364 var m = moment(t.TimeStamp);
3365 if (!v.lastTime) {
3366 v.lastTime = ko.observable('');
3367 }
3368 var lastTime = '';
3369 if (now.year() == m.year() && m.dayOfYear() >= today) {
3370 var format = settingMapTimeFormats[Defaults.TimeFormat].hms;
3371 lastTime = resx.LastupdateToday + m.format(format);
3372 } else if (now.year() == m.year() && (m.dayOfYear() - 1) >= yesterday) {
3373 var format = settingMapTimeFormats[Defaults.TimeFormat].hms;
3374 lastTime = resx.LastupdateYesterday + m.format(format);
3375 } else {
3376 var format = settingMapDateFormats[Defaults.DateFormat].moment + ' ' + settingMapTimeFormats[Defaults.TimeFormat].hms;
3377 lastTime = resx.LastUpdate + m.format(format);
3378 }
3379 v.lastTime(lastTime);
3380 }
3381 };
3382
3383 self.format_tripCountText = function (v) {
3384 if (!v.tripCountText) {
3385 v.tripCountText = ko.observable('');
3386 }
3387 v.tripCountText(resx.Trips + v.TripCount());
3388 }
3389
3390
3391
3392
3393
3394 self.endLoadMap = function () {
3395 self.loading(false);
3396 if (app.clusterer) {
3397 app.clusterer.clearMarkers();
3398 app.clusterer.map = null;
3399 app.clusterer = null;
3400 }
3401 app.clusterer = new MarkerClusterer(map, [], {
3402 maxZoom: 15,
3403 gridSize: 50
3404 //styles: styles[style]
3405 });
3406 google.maps.event.addListener(app.clusterer, 'clusterclick', function (cluster) {
3407 app.clusterClickedFlag = true;
3408 });
3409
3410
3411 app.clusterer.addMarkers(_.map(app.markers, 'marker'));
3412 Metronic.unblockUI('#tab-map-canvas-container');
3413 };
3414 self.setMarkerIcon = function (marker, options) {
3415 if (!app.enableDirectionMap) {
3416 return;
3417 }
3418 var arrowColor = getArrowColor(options);
3419 var markerIcon = marker.icon;
3420 var rotation = markerIcon.rotation;
3421 if (options.crumb) {
3422 rotation = options.crumb.Angle - 90;
3423 }
3424
3425 var icon = {
3426 path: app.directionIconPath,
3427 fillColor: arrowColor,
3428 fillOpacity: 1,
3429 scale: 1,
3430 strokeColor: arrowColor,
3431 strokeWeight: 1,
3432 rotation: rotation,
3433 origin: new google.maps.Point(0, 0),
3434 // The anchor for this image is the base of the flagpole at (0, 32).
3435 anchor: new google.maps.Point(3, 9),
3436 };
3437 marker.setIcon(icon);
3438 }
3439 self.loadDataForMap = function (options) {
3440
3441 if (!app.disableRefreshingMap) {
3442 options = options || {};
3443 if (options.autoload) {
3444 } else if (options.vehicle) {
3445 options.vehicle.isLoadingTrips(true);
3446 } else {
3447 if (app.markerInfoWindow) {
3448 app.markerInfoWindow.close();
3449 }
3450 self.closeAlert(app.alertInfobox);
3451 app.trip = null;
3452 }
3453 var data = {
3454 filter: self.filter(),
3455 selectedVehicleId: self.lastVehicle() || 0,
3456 hours: self.hours(),
3457
3458 fromTime: self.time_from(),
3459 toTime: self.time_to(),
3460 fromDate: self.map_from(),
3461 toDate: self.map_to(),
3462 vehicleState: $('#ddlVehicleState').val()
3463 };
3464 var json = ko.toJSON(data);
3465 self.loading(true);
3466 Metronic.blockUI({ target: '#tab-map-canvas-container', animate: true });
3467
3468 $.ajax({
3469 url: '../Rental/Tracking/TrackingDataForMap',
3470 type: 'POST',
3471 data: json,
3472 contentType: 'application/json',
3473 crossDomain: true,
3474 cache: false,
3475 error: function (data, e, x) {
3476 console.log('error', data, e, x);
3477 },
3478 success: function (data, e, x) {
3479 if (!_.isObject(data)) {
3480 window.location = "";
3481 }
3482
3483 clearTimeout(self.timer);
3484 self.timer = setTimeout(function () {
3485 self.loadDataForMap({ autoload: true });//self.filter);
3486 }, settingMapRefreshes[Defaults.MapRefreshTime].time);
3487
3488 self.lastAlerts(data.LastAlerts);
3489
3490 if (options && options.autoload) {
3491
3492 var v_hash = {};
3493 _.forEach(data.TrackingAllVehicles, function (t) {
3494 v_hash[t.VehicleId] = t
3495 });
3496
3497 _.forEach(app.markers, function (m) {
3498 var item = v_hash[m.vid];
3499 if (item) {
3500 var crumb = _.first(item.TrackingItems);
3501 var position = new google.maps.LatLng(crumb.Lat, crumb.Lng);
3502 if (m.marker) {
3503 var labelContent = getLabelContent({ glow: true, vehicle: item, crumb: crumb });
3504 m.marker.labelContent = labelContent;
3505 m.marker.setPosition(position);
3506 self.setMarkerIcon(m.marker, { glow: true, vehicle: item, crumb: crumb });
3507 }
3508 }
3509 });
3510
3511 if (app.markersForVehicle && app.markersForVehicle.length) {
3512 var m = app.markersForVehicle[0];
3513 var item = v_hash[m.vid];
3514 if (item) {
3515 var crumb = _.first(item.TrackingItems);
3516 var position = new google.maps.LatLng(crumb.Lat, crumb.Lng);
3517 if (m.marker) {
3518 var labelContent = getLabelContent({ glow: true, vehicle: item, crumb: crumb });
3519 m.marker.labelContent = labelContent;
3520 m.marker.setPosition(position);
3521 self.setMarkerIcon(m.marker, { glow: true, vehicle: item, crumb: crumb });
3522 }
3523 m.position = position;
3524 m.data = crumb;
3525 }
3526 }
3527
3528 var m = moment();
3529 var today = m.dayOfYear();
3530 var yesterday = m.dayOfYear() - 1 || 365;
3531
3532
3533 var harshDrivingSum = 0, idlingSum = 0, alertSum = 0;
3534 _.forEachRight(self.vehicles(), function (v) {
3535 var item = v_hash[v.VehicleId];
3536 if (item) {
3537 var t = _.first(item.TrackingItems);
3538 self.format_lastTime(v, t, today, yesterday, m);
3539 self.format_tripCountText(v);
3540
3541 v.AlertCount(item.AlertCount);
3542 v.HarshBrakingCount(item.HarshBrakingCount);
3543 v.IdlingAlertCount(item.IdlingAlertCount);
3544 v.TripCount(item.TripCount);
3545
3546 harshDrivingSum += (item.HarshBrakingCount || 0);
3547 idlingSum += (item.IdlingAlertCount || 0);
3548 alertSum += (item.AlertCount || 0);
3549 } else {
3550 ko.utils.arrayRemoveItem(self.vehicles(), v);
3551 }
3552 });
3553
3554 self.harshDrivingTotalSum(harshDrivingSum);
3555 self.idlingTotalSum(idlingSum);
3556 self.alertsTotalSum(alertSum);
3557 self.vehicleTotalSum(self.vehicles().length);
3558
3559 if (app.trip) {
3560 var prevLocation = null;
3561
3562 //clear markers on refresh
3563 _.forEach(app.markersForVehicle, function (m) {
3564 if (m.marker) {
3565 m.marker.setMap(null);
3566 }
3567 });
3568 app.markersForVehicle = [];
3569
3570 _.forEach(app.trip.TrackingItems, function (c, i) {
3571 var drawResult = self.drawTrackingMarkers(app.trip, i, prevLocation, app.zooms, { trip: true, tripdetails: true });
3572 if (drawResult) {
3573 prevLocation = drawResult;
3574 }
3575 });
3576 }
3577
3578 self.vehicles_sort();
3579
3580 sidebarFunc(app, self, data);
3581 self.endLoadMap();
3582 if (app.isMarkerSelected) {
3583 changeSelectedMarkerColorIcon(app.selectedVehicleMarker);
3584 }
3585
3586 return;
3587 }
3588
3589 if (polylines) {
3590 for (var i = 0; i < polylines.length; i++) {
3591 polylines[i].setMap(null);
3592 polylines[i] = null;
3593 }
3594 }
3595 //polylines = [];
3596 polylines.splice(0, polylines.length);
3597 // animateLines.splice(0, animateLines.length);
3598
3599 if (!app.zoomHandler) {
3600 app.mapZoom = map.getZoom();
3601
3602 app.zoomHandler = google.maps.event.addDomListener(map, 'zoom_changed', debounce(function () {
3603 var zoom = map.getZoom();
3604 if (zoom === app.mapZoom)
3605 return;
3606
3607 if (app.clusterClickedFlag) {
3608 app.clusterClickedFlag = false;
3609 if (zoom > 17) {
3610 map.setZoom(17);
3611 return;
3612 }
3613 }
3614
3615 app.mapZoom = zoom;
3616
3617 if (app.mapRedrawFlag) {
3618 app.mapRedrawFlag = false;
3619 return;
3620 }
3621 return;
3622
3623 if (app.mapData.SelectedVehicleId) {
3624 _.forEach(app.markersForVehicle, function (m) {
3625 if (m.marker) {
3626 m.marker.setMap(null);
3627 }
3628 });
3629
3630 if (!app.pathLines) {
3631 app.pathLines = [];
3632 }
3633
3634 for (var i = 0; i < app.pathLines.length; i++) {
3635 app.pathLines[i].setPath([]);
3636 }
3637 app.markersForVehicle = [];
3638
3639 var prevLocation = null;
3640 var trackingData = _.first(app.mapData.TrackingSelectedVehicle);
3641 _.forEach(trackingData.TrackingItems, function (c, i) {
3642 var drawResult = self.drawTrackingMarkers(trackingData, i, prevLocation, zoom, {});
3643 if (drawResult) {
3644 prevLocation = drawResult;
3645 }
3646 });
3647 self.drawTrackingPath();
3648 }
3649 }, 700));
3650 }
3651
3652 app.mapData = data;
3653 if (app.eventMarker) {
3654 app.eventMarker.setMap(null);
3655 }
3656 _.forEach(app.markers, function (m) {
3657 m.marker.setMap(null);
3658 });
3659 _.forEach(app.markersForVehicle, function (m) {
3660 if (m.marker) {
3661 m.marker.setMap(null);
3662 }
3663 });
3664
3665 if (!app.pathLines) {
3666 app.pathLines = [];
3667 }
3668
3669 for (var i = 0; i < app.pathLines.length; i++) {
3670 app.pathLines[i].setPath([]);
3671 }
3672 app.markers = [];
3673 app.markersForVehicle = [];
3674
3675 var markerBounds = new google.maps.LatLngBounds();
3676
3677 var tree = [];
3678
3679 var locationFuncs = [];
3680
3681 var harshDrivingSum = 0;
3682 var idlingSum = 0;
3683 var alertSum = 0;
3684 var TotalVechilesSum = 0;
3685 _.forEach(data.TrackingAllVehicles, function (v) {
3686 v.isSelected = ko.observable(v.VehicleId === self.lastVehicle());
3687 v.isLoadingTrips = ko.observable(false);
3688 v.AlertCount = ko.observable(v.AlertCount);
3689 v.HarshBrakingCount = ko.observable(v.HarshBrakingCount);
3690 v.IdlingAlertCount = ko.observable(v.IdlingAlertCount);
3691 v.TripCount = ko.observable(v.TripCount);
3692
3693 harshDrivingSum += (v.HarshBrakingCount() || 0);
3694 idlingSum += (v.IdlingAlertCount() || 0);
3695 alertSum += (v.AlertCount() || 0);
3696 TotalVechilesSum += 1;
3697
3698 if (!v.trips) {
3699 v.trips = ko.observableArray([]);
3700 }
3701 if (!v.shifts) {
3702 v.shifts = ko.observableArray([]);
3703 }
3704
3705 if (v.isSelected()) {
3706 var existing_trips = {};
3707 var existing_shifts = {};
3708 _.forEach(v.trips(), function (t) {
3709 existing_trips[t.TripId] = t;
3710 });
3711 _.forEach(v.shifts(), function (t) {
3712 existing_shifts[t.driver] = t;
3713 });
3714
3715 var shifts = app.shifts = _.chain(data.Trips)
3716 .groupBy('DriverName')
3717 .map(function (t, i) {
3718 return {
3719 driver: i,
3720 Trips: t,
3721 isSelected: ko.observable(false),
3722 trips: ko.observableArray([])
3723 };
3724 })
3725 .orderBy('driver')
3726 .value();
3727
3728 _.forEach(shifts, function (s, ixs) {
3729 var shift = s;
3730 var exist_shift = existing_shifts[s.driver];
3731 if (!exist_shift) {
3732 v.shifts.push(s);
3733 } else {
3734 shift = exist_shift;
3735 }
3736
3737 if (!self.selectedDriver && ixs == 0) {
3738 self.shiftClicked(s);
3739 }
3740 if (self.selectedDriver) {
3741 if (self.selectedDriver == s.driver) {
3742 self.shiftClicked(s);
3743 }
3744 }
3745
3746 //var trips = _.map(data.Trips, function (t, ix) {
3747 var trips = _.map(s.Trips, function (t, ix) {
3748 var exist_trip = existing_trips[t.TripId];
3749 if (exist_trip) {
3750 return exist_trip;
3751 }
3752 t.isSelected = ko.observable(false);
3753 var timeFormat = settingMapTimeFormats[Defaults.TimeFormat].hm;
3754
3755 t.startedOnTimeFormatted = moment(t.StartedOn).format(timeFormat);
3756 t.startedOnDateFormatted = moment(t.StartedOn).format('DD MMM');
3757 t.finishedOnTimeFormatted = moment(t.FinishedOn).format(timeFormat);
3758 t.finishedOnDateFormatted = moment(t.FinishedOn).format('DD MMM');
3759
3760
3761 t.startedOnLocation = ko.observable('');
3762 locationFuncs.push(function (index, d) {
3763 self.getLocationForObs(t.TripId, true, t.IsStartAddressFetched,t.StartAddress, t.StartLat, t.StartLng, t.startedOnLocation, d);
3764 });
3765
3766 t.finishedOnLocation = ko.observable('');
3767 locationFuncs.push(function (index, d) {
3768 self.getLocationForObs(t.TripId, false, t.IsFinishAddressFetched,t.FinishAddress, t.FinishLat, t.FinishLng, t.finishedOnLocation, d);
3769 });
3770
3771 t.finishedOnTimeFormatted = moment(t.FinishedOn).format(timeFormat);
3772 var distance = (t.TotalDistance || (t.FinishDistance - t.StartDistance)) / 1000;
3773 t.DistanceFormatted = app.convertDistance(distance).toFixed(2);
3774
3775 //http://stackoverflow.com/questions/18623783/get-the-time-difference-between-two-datetimes
3776 var ms = moment(t.FinishedOn).diff(moment(t.StartedOn));
3777 var d = moment.duration(ms);
3778 //var s = Math.floor(d.asHours()) + moment.utc(ms).format(":mm:ss");
3779 var hours = '' + Math.floor(d.asHours());
3780 if (hours.length < 2)
3781 hours = '0' + hours;
3782 var s = hours + moment.utc(ms).format(":mm");
3783 t.DurationFormatted = s;
3784
3785 t.AverageSpeedFormatted = (t.SpeedAverage || app.convertSpeed((distance / d.asHours()))).toFixed(2);
3786 if (_.isNaN(t.AverageSpeedFormatted) || t.AverageSpeedFormatted > 300) {
3787 t.AverageSpeedFormatted = 'N/A';
3788 }
3789
3790 t.SpeedUnit = settingMapSpeeds[Defaults.UnitOfSpeed].desc;
3791 t.DistanceUnit = settingMapDistances[Defaults.UnitOfDistance].desc;
3792
3793 v.trips.push(t);
3794 return t;
3795 });
3796
3797 //v.trips(trips);
3798 shift.trips(trips);
3799 });
3800
3801 var index = 0;
3802 var locationProcess = function (index) {
3803 setTimeout(function () {
3804 var promises = [];
3805 var count = 10;
3806 for (var i = index; i < locationFuncs.length && i < index + count; i++) {
3807 var d = $.Deferred();
3808 promises.push(d);
3809 locationFuncs[i](i, d);
3810 }
3811 //console.log('calling geocodes ', promises.length);
3812 if (promises.length) {
3813 $.when.apply(null, promises).then(function () {
3814 locationProcess(index + count);
3815 });
3816 }
3817 }, index == 0 ? 0 : 1000);
3818 };
3819 locationProcess(index);
3820 }
3821
3822 var m = moment();
3823 var today = m.dayOfYear();
3824 var yesterday = m.dayOfYear() - 1 || 365;
3825 var t = _.first(v.TrackingItems);
3826 self.format_lastTime(v, t, today, yesterday, m);
3827 self.format_tripCountText(v);
3828
3829 });
3830
3831 self.vehicles(data.TrackingAllVehicles);
3832 self.harshDrivingTotalSum(harshDrivingSum);
3833 self.idlingTotalSum(idlingSum);
3834 self.alertsTotalSum(alertSum);
3835 self.vehicleTotalSum(TotalVechilesSum);
3836 _.forEach(data.TrackingAllVehicles, function (x, i) {
3837 if (!(x.TrackingItems && x.TrackingItems.length)) {
3838 return;
3839 }
3840
3841 var location = x.TrackingItems[0];
3842 //console.log('latlng', location.Lat, location.Lng);
3843
3844 var events = [], eventsNode = {};
3845 var alerts = [], alertsNode = {};
3846 var nodes = [];
3847
3848 var isSelected = (x.VehicleId === data.SelectedVehicleId);
3849 var prevLocation = null;
3850 var trips = [];
3851 var currentTrip = null;
3852
3853 if (isSelected) {
3854 self.selectedVehicle = x;
3855 self.lastVehicle(x.VehicleId);
3856 self.selectedDriver = '';
3857
3858 var trackingData = _.first(data.TrackingSelectedVehicle) || x;
3859
3860 //clear markers on refresh
3861 _.forEach(app.markersForVehicle, function (m) {
3862 if (m.marker) {
3863 m.marker.setMap(null);
3864 }
3865 });
3866 app.markersForVehicle = [];
3867
3868 _.forEach(trackingData.TrackingItems, function (c, i) {
3869
3870 if (!currentTrip || c.EventId == 1 || c.EventId == 2) {
3871 currentTrip = { positions: [], events: [], alerts: [], include: false };
3872 trips.push(currentTrip);
3873 }
3874
3875 var drawResult = self.drawTrackingMarkers(trackingData, i, prevLocation, app.mapZoom, { vehicle: x });
3876 if (drawResult) {
3877 markerBounds.extend(drawResult.latlng);
3878 prevLocation = drawResult;
3879 currentTrip.positions.push({ markerData: drawResult, position: drawResult.latlng, data: c });
3880 }
3881
3882 if (!currentTrip.include && currentTrip.positions.length) {
3883 var distance = google.maps.geometry.spherical.computeDistanceBetween(_.first(currentTrip.positions).position, _.last(currentTrip.positions).position);
3884 if (distance >= 100) {
3885 currentTrip.include = true;
3886 }
3887 }
3888
3889 var timeFormat = settingMapTimeFormats[Defaults.TimeFormat].hm;
3890
3891 if (c.EventId > 0 && c.EventId !== 4 && c.EventId !== 1 && c.EventId !== 2) {
3892 var event = {
3893 name: c.EventName,
3894 id: c.CrumbId,
3895 details: 'on ' + moment(c.TimeStamp).format(timeFormat),
3896 type: 'event-event',
3897 data: { crumb: c }
3898 };
3899 currentTrip.events.push(event);
3900 events.push(event);
3901
3902 }
3903 _.forEach(c.TrackingAlerts, function (a) {
3904 var alert = {
3905 name: a.Name,
3906 id: c.CrumbId,
3907 details: 'on ' + moment(c.TimeStamp).format(timeFormat),
3908 type: 'event-alert',
3909 data: { crumb: c, alert: a }
3910 };
3911 currentTrip.events.push(alert);
3912 alerts.push(alert);
3913 });
3914 });
3915
3916 app.Trips = trips;
3917 var index = 0;
3918 var timeFormat = settingMapTimeFormats[Defaults.TimeFormat].hm;
3919
3920 for (var i = 0; i < trips.length; i++) {
3921 var first = _.first(trips[i].positions);
3922 var last = _.last(trips[i].positions);
3923
3924 if (!trips[i].include) {
3925 continue;
3926 }
3927
3928 nodes.push({
3929 name: 'Trip',
3930 details: 'from ' + moment(first.data.TimeStamp).format(timeFormat) + ' to ' + moment(last.data.TimeStamp).format(timeFormat),
3931 type: 'trip',
3932 trip: trips[i],//.positions,
3933 parent: nodes,
3934 index: index,
3935 nodes: [{
3936 name: 'Events' + ' (' + trips[i].events.length + ')',
3937 type: 'cat',
3938 nodes: trips[i].events
3939 }, {
3940 name: 'Alerts' + ' (' + trips[i].alerts.length + ')',
3941 type: 'cat',
3942 nodes: trips[i].alerts
3943 }]
3944 });
3945 index++;
3946 }
3947
3948
3949 self.drawTrackingPath();
3950
3951 var selectedMarker = _.first(app.markersForVehicle);
3952 if (selectedMarker) {
3953 selectedMarker.isCurrent = true;
3954 var marker = selectedMarker.marker;
3955 selectedMarker.click_handler = marker.addListener('click', function (e) {
3956 console.log('click marker', x, e, x.isSelected(), self.selectedVehicle);
3957 if (true) {
3958 self.closeInfo(app.markerInfoWindow);
3959 }
3960
3961 app.markerInfoWindow = self.showInfo(marker, x, e, null, self.map_from(), self.map_to());
3962
3963 if (!x.isSelected()) {
3964 if (self.selectedVehicle) {
3965 self.selectedVehicle.isSelected(false);
3966 self.selectedVehicle = null;
3967 }
3968 x.isSelected(true);
3969 self.selectedVehicle = x;
3970 self.lastVehicle(x.VehicleId);
3971 self.selectedDriver = '';
3972 self.scrollTo();
3973 self.getTrips();
3974 }
3975 changeSelectedMarkerColorIcon(marker);
3976 });
3977 changeSelectedMarkerColorIcon(selectedMarker.marker);
3978 }
3979
3980 } else {
3981 ///***
3982 var latlng = new google.maps.LatLng(location.Lat, location.Lng);
3983 var marker = placeMarker(latlng, map, { first: true, glow: false, alert: location.TrackingAlerts.length, eventId: location.EventId, data: location, vehicle: x, crumb: location }, false, true);
3984
3985 marker.click_handler = marker.addListener('click', function (e) {
3986 console.log('click marker', x, e, x.isSelected(), self.selectedVehicle);
3987 changeSelectedMarkerColorIcon(marker);
3988
3989
3990 if (true) {
3991 self.closeInfo(app.markerInfoWindow);
3992 }
3993
3994 app.markerInfoWindow = self.showInfo(marker, x, e, null, self.map_from(), self.map_to());
3995
3996 if (!x.isSelected()) {
3997 if (self.selectedVehicle) {
3998 self.selectedVehicle.isSelected(false);
3999 self.selectedVehicle = null;
4000 }
4001 x.isSelected(true);
4002 self.selectedVehicle = x;
4003 self.lastVehicle(x.VehicleId);
4004 self.selectedDriver = '';
4005 self.scrollTo();
4006 self.getTrips();
4007 }
4008
4009 });
4010
4011 if (data.SelectedVehicleId === 0) {
4012 markerBounds.extend(marker.getPosition());
4013 }
4014
4015 app.markers.push({ marker: marker, vid: x.VehicleId });
4016 }
4017
4018 var timeFormat = settingMapTimeFormats[Defaults.TimeFormat].hm;
4019
4020 tree.push({
4021 name: x.VehicleName,
4022 chassisno: x.ChassisNo,
4023 id: x.VehicleId,
4024 details: 'last update: ' + moment(location.TimeStamp).format(timeFormat),
4025 type: 'vehicle',
4026 alert: location.TrackingAlerts.length,
4027 nodes: nodes,
4028 isSelected: isSelected,
4029 error: x.IsNoSignal
4030 });
4031 });
4032
4033 app.mapRedrawFlag = true;
4034 app.result = tree;
4035
4036 if (!markerBounds.isEmpty()) {
4037 map.fitBounds(markerBounds);
4038 }
4039 var idle_listener = google.maps.event.addListener(map, "idle", function () {
4040 if (map.getZoom() > 17) map.setZoom(17);
4041 google.maps.event.removeListener(idle_listener);
4042 });
4043
4044 if (self.selectedVehicle && _.first(app.markersForVehicle)) {
4045 var info = _.first(app.markersForVehicle);
4046
4047 app.markerInfoWindow = self.showInfo(info.marker, self.selectedVehicle, null, null, self.map_from(), self.map_to());
4048 setTimeout(function () {
4049 map.panBy(0, -50);
4050 var idle_listener = google.maps.event.addListener(map, "idle", function () {
4051 google.maps.event.removeListener(idle_listener);
4052 map.panBy(0, -50);
4053 });
4054 }, 100);
4055 }
4056
4057 self.vehicles_sort();
4058
4059 self.endLoadMap();
4060 return;
4061 if (data.Locations && data.Locations.length) {
4062 self.showLocations(data, markerBounds);
4063 }
4064 self.loading(false);
4065 if (options.vehicle) {
4066 options.vehicle.isLoadingTrips(false);
4067 }
4068 Metronic.unblockUI('#tab-map-canvas-container');
4069 },
4070 fail: function (data) {
4071 alert(resx.Startingfailed);
4072 if (data) console.log('fail', data);
4073 self.loading(false);
4074 if (options.vehicle) {
4075 options.vehicle.isLoadingTrips(false);
4076 }
4077 Metronic.unblockUI('#tab-map-canvas-container');
4078 },
4079 error: function (data) {
4080 if (data) {
4081 try {
4082 var json = JSON.parse(data.responseText);
4083 alert(resx.Startingerror + (json.Message || ''));
4084 console.log('error', data);
4085 }
4086 catch (err) {
4087 }
4088 }
4089 self.loading(false);
4090 if (options.vehicle) {
4091 options.vehicle.isLoadingTrips(false);
4092 }
4093 Metronic.unblockUI('#tab-map-canvas-container');
4094 }
4095 });
4096 }
4097 };
4098
4099 app.zooms = {
4100 //'1': {distance: }
4101 '1': { distance: 50000, locations: 50 },
4102 '2': { distance: 40000, locations: 50 },
4103 '3': { distance: 30000, locations: 50 },
4104 '4': { distance: 25000, locations: 50 },
4105 '5': { distance: 20000, locations: 50 },
4106 '6': { distance: 15000, locations: 40 },
4107 '7': { distance: 12000, locations: 35 },
4108 '8': { distance: 9000, locations: 30 },
4109 '9': { distance: 7000, locations: 25 },
4110 '10': { distance: 4000, locations: 20 },
4111 '11': { distance: 2500, locations: 15 },
4112 '12': { distance: 1000, locations: 10 },
4113 '13': { distance: 600, locations: 10 },
4114 '14': { distance: 500, locations: 10 },
4115 '15': { distance: 400, locations: 10 },
4116 '16': { distance: 200, locations: 15 },
4117 '17': { distance: 120, locations: 20 },
4118 '18': { distance: 120, locations: 25 },
4119 '19': { distance: 120, locations: 35 },
4120 '20': { distance: 120, locations: 50 },
4121 '21': { distance: 120, locations: 60 }
4122 };
4123 var zooms = app.zooms;
4124
4125 self.drawTrackingMarkers = function (trackingData, i, prevLocation, zoom, options) {
4126
4127 options = options || {};
4128 var trip = options.trip;
4129 var live = options.live;
4130
4131 var x = trackingData;
4132 var location = live ? x[0] : x.TrackingItems[0];
4133 var c = live ? trackingData[i] : trackingData.TrackingItems[i];
4134
4135 var _markersForVehicle = live ? app.markersForVehicle_live : app.markersForVehicle;
4136 var _map = live ? map_live : map;
4137
4138 var zoomOptions = zooms[zoom] || zooms[12];
4139 var isLast = live ? trackingData.length - 1 === i : trackingData.TrackingItems.length - 1 === i;
4140 var latlng = new google.maps.LatLng(c.Lat, c.Lng);
4141 var marker = null;
4142 if (options.vehicle) {
4143 app.xxxxxxxxxxxxxxxxxxxxxxxxx = options;
4144 if (options.vehicle.IsNoSignal) {
4145 marker = placeMarker(latlng, _map, { trip: trip, vehicle: options.vehicle, first: true, glow: true, alert: 0, data: c, eventId: 0, crumb: location }, live);
4146 //var icon = new google.maps.MarkerImage('../content/trips/circle_red.svg', null, null, new google.maps.Point(8, 8), new google.maps.Size(14, 14))
4147 //marker = new google.maps.Marker({ position: latlng, map: _map, icon: icon });
4148 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4149 }
4150 else if (options.vehicle.IsNoSignal_White) {
4151 marker = placeMarker(latlng, _map, { trip: trip, vehicle: options.vehicle, first: true, glow: true, alert: 0, data: c, eventId: 0, crumb: location }, live);
4152 //var icon = new google.maps.MarkerImage('../content/trips/circle_yellow.svg', null, null, new google.maps.Point(8, 8), new google.maps.Size(14, 14))
4153 //marker = new google.maps.Marker({ position: latlng, map: _map, icon: icon });
4154 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4155 } else {
4156 marker = placeMarker(latlng, _map, { trip: trip, first: i === 0, vehicle: options.vehicle, last: isLast, glow: isLast, alert: location.TrackingAlerts.length, data: c, eventId: location.EventId, angle: c.Angle, crumb: location }, live);
4157 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4158 }
4159
4160 if (!marker) {
4161 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4162 }
4163 return { latlng: latlng, index: i, data: c };
4164 }
4165
4166 //if (prevLocation && !(i === 0 || isLast)) {
4167 // if (c.Speed < 40 && prevLocation.data.Speed < 40) {
4168 // var distance = google.maps.geometry.spherical.computeDistanceBetween(latlng, prevLocation.latlng);
4169 // if (distance < 150) {
4170 // return null;
4171 // }
4172 // }
4173 //}
4174 if (i === 0 || isLast) {
4175 //A_B markers
4176 var marker = placeMarker(latlng, _map, { trip: trip, tripdetails: options.tripdetails, first: i === 0, last: isLast, glow: isLast, alert: location.TrackingAlerts.length, eventId: location.EventId, data: c, angle: c.Angle, crumb: location }, live);
4177 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4178 if (marker && (i === 0 || isLast)) {
4179 //marker.setZIndex(-99);
4180 marker.addListener('dblclick', function (e) {
4181 marker.setMap(null);
4182 });
4183 }
4184 // cannot click on bottom alert marker when A and B show
4185 if (marker && c.TrackingAlerts && c.TrackingAlerts.length) {
4186 marker.addListener('click', function (e) {
4187 //console.log('ALERT CLICKED', e);
4188 var alert = _.first(c.TrackingAlerts);
4189 alert.data = c;
4190
4191 self.showAlert(marker, app.model.selectedVehicle, alert, live);
4192 });
4193 }
4194 }
4195 if (c.EventId == 3) {
4196 //circle_yellow.svg
4197 var icon = new google.maps.MarkerImage('../content/trips/harsh-driving-fill.svg', null, null, new google.maps.Point(8, 8), new google.maps.Size(14, 14));
4198 var marker = new google.maps.Marker({ position: latlng, map: _map, icon: icon });
4199 marker.addListener('click', function (e) {
4200 //console.log('EVENT CLICKED');
4201 var alert = { FirstTime: c.TimeStamp, Name: resx.HarshBraking };
4202 alert.data = c;
4203
4204 self.showAlert(marker, app.model.selectedVehicle, alert, live);
4205 });
4206 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4207 }
4208
4209 if (c.TrackingAlerts && c.TrackingAlerts.length) {
4210 var alert = _.first(c.TrackingAlerts);
4211 var icon = null;
4212 var alertName = (alert.Name || '').toLowerCase()
4213 if (alertName.indexOf('stationary') >= 0 || alertName.indexOf('idling') >= 0) {
4214 //circle_blue.svg
4215 icon = new google.maps.MarkerImage('../content/trips/idling-fill.svg', null, null, new google.maps.Point(12, 12), new google.maps.Size(20, 20));
4216 } else {
4217 //circle_red.svg
4218 icon = new google.maps.MarkerImage('../content/trips/alerts-fill.svg', null, null, new google.maps.Point(12, 12), new google.maps.Size(20, 20));
4219 }
4220 var marker = new google.maps.Marker({ position: latlng, map: _map, icon: icon });
4221 marker.addListener('click', function (e) {
4222 //console.log('ALERT CLICKED');
4223 alert.data = c;
4224 self.showAlert(marker, app.model.selectedVehicle, alert, live);
4225 });
4226 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4227 }
4228
4229 if (!marker) {
4230 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4231 }
4232 return { latlng: latlng, index: i, data: c };
4233
4234 if (prevLocation) {
4235 var distance = google.maps.geometry.spherical.computeDistanceBetween(latlng, prevLocation.latlng);
4236 }
4237
4238 //if (i === 0 || isLast || distance >= 1000 || i - prevLocation.index >= 10) {
4239 if (i === 0 || isLast || distance >= zoomOptions.distance || i - prevLocation.index >= zoomOptions.locations) {
4240 //console.log('marker added');
4241 var marker = placeMarker(latlng, _map, { first: isLast, glow: isLast, alert: location.TrackingAlerts.length, eventId: location.EventId, crumb: location, data: c });
4242 if (isLast) {
4243 marker.click_handler = marker.addListener('click', function (e) {
4244 //console.log('click marker', e);
4245 //self.showInfo(marker, x, e);
4246 if (live) {
4247 if (app.markerInfoWindow_live) {
4248 self.closeInfo(app.markerInfoWindow_live);
4249 }
4250 app.markerInfoWindow_live = self.showInfo(marker, x, e, live, self.map_from(), self.map_to());
4251 } else {
4252 if (app.markerInfoWindow) {
4253 self.closeInfo(app.markerInfoWindow);
4254 }
4255 app.markerInfoWindow = self.showInfo(marker, x, e, live, self.map_from(), self.map_to());
4256 }
4257 self.closeAlert(app.alertInfobox);
4258 });
4259 }
4260 _markersForVehicle.push({ marker: marker, vid: x.VehicleId, position: latlng, data: c });
4261 //markerBounds.extend(marker.getPosition());
4262 prevLocation = { latlng: latlng, index: i };
4263 return prevLocation;
4264 }
4265 };
4266
4267 self.drawTrackingPath = function (extendBounds, isTrip, live) {
4268 var _markersForVehicle = live ? app.markersForVehicle_live : app.markersForVehicle;
4269 var _map = live ? map_live : map;
4270
4271 var markerBounds = markerBounds || new google.maps.LatLngBounds();
4272 if (live) {
4273 markerBounds = new google.maps.LatLngBounds();
4274 }
4275 var pathPositions = _.map(_markersForVehicle, function (m, i) {
4276 if (m.isCurrent) {
4277 return null;
4278 }
4279 if (extendBounds) {
4280 markerBounds.extend(m.position);
4281 }
4282 return {
4283 lat: m.position.lat(), lng: m.position.lng(), data: m.data, position: m.position
4284 }
4285 });
4286 //var pathPositions = _.map(app.markersForVehicle, function (m, i) { return { lat: m.marker.position.lat(), lng: m.marker.position.lng() } });
4287 if (live) {
4288 app.pathPositions_live = pathPositions;
4289 } else {
4290 app.pathPositions = pathPositions;
4291 }
4292
4293 //var paths = [pathPositions];
4294 var paths = [];
4295 var lastSpeed = 0;
4296 var currentPath = null;
4297 for (var i = 0; i < pathPositions.length; i++) {
4298 if (!pathPositions[i]) {
4299 continue;
4300 }
4301 var speed = pathPositions[i].data.Speed;
4302 var overSpeeding = speed >= 100;
4303 var isNewPath = (!currentPath) || (currentPath.overSpeeding ^ overSpeeding);
4304 if (isNewPath) {
4305 currentPath = { overSpeeding: overSpeeding, path: [pathPositions[i]] };
4306 paths.push(currentPath);
4307 } else {
4308 currentPath.path.push(pathPositions[i]);
4309 }
4310 }
4311
4312 if (live) {
4313 if (!app.pathLines_live) {
4314 app.pathLines_live = [];
4315 }
4316 } else {
4317 if (!app.pathLines) {
4318 app.pathLines = [];
4319 }
4320 }
4321 var _pathLines = live ? app.pathLines_live : app.pathLines;
4322
4323
4324 for (var i = 0; i < _pathLines.length; i++) {
4325 _pathLines[i].setPath([]);
4326 }
4327
4328 for (var i = 0; i < paths.length; i++) {
4329 var pathLine = _pathLines[i];
4330 if (true) { //(paths[i].path.length <= 1) {
4331 var prevPath = paths[i - 1];
4332 var nextPath = paths[i + 1];
4333 if (prevPath) {
4334 paths[i].path.unshift(_.last(prevPath.path));
4335 }
4336 if (nextPath) {
4337 paths[i].path.push(_.first(nextPath.path));
4338 }
4339 }
4340
4341 //var color = isTrip ? (paths[i].overSpeeding ? '#FF6600' : '#4593BC') : '#B9BC8F';
4342 var color = isTrip ? (paths[i].overSpeeding ? '#FF6600' : '#39B54A') : '#B9BC8F';
4343 paths[i].color = color;
4344
4345 if (pathLine) {
4346 pathLine.setPath(paths[i].path);
4347 pathLine.setOptions({ strokeColor: color });
4348 pathLine.setMap(_map);
4349 } else {
4350 pathLine = new google.maps.Polyline({
4351 path: paths[i].path,
4352 geodesic: true,
4353 strokeColor: color,
4354 strokeOpacity: 0.8,
4355 strokeWeight: 2,
4356 icons: [{
4357 icon: app.lineSymbol,
4358 offset: '100%'
4359 }]
4360 });
4361
4362 if (false && live) {
4363 pathLine.setMap(_map);
4364 } else {
4365 //runSnapToRoad(paths[i].path, null, { color: color, speeding: paths[i].overSpeeding });
4366 }
4367
4368 if (false && live) {
4369 _pathLines.push(pathLine);
4370 } else {
4371 if (pathLine.length > 100) {
4372 _pathLines.push(pathLine);
4373
4374 } else {
4375 _pathLines.push(pathLine);
4376 }
4377 }
4378 }
4379 }
4380
4381 //short trip, less than 10 seconds
4382 if (isTrip) {
4383 if (self.selectedTrip) {
4384 var diff = moment(app.model.selectedTrip.FinishedOn).diff(moment(app.model.selectedTrip.StartedOn), 'seconds');
4385 if (diff < 10) {
4386 paths = [];
4387 }
4388 }
4389 }
4390
4391 if (true || !live) {
4392 //alert('draw');
4393 var index = 0;
4394 clearPolylines();
4395 var locationProcess = function (index) {
4396 setTimeout(function () {
4397 var promises = [];
4398 var max = 10;
4399 var count = 0;
4400
4401 for (var i = index; promises.length < 10; i++) {
4402 if (!(i < paths.length && i < index + max)) {
4403 break;
4404 }
4405 var current_path = paths[i].path;
4406
4407 if (i > 0) {
4408 //console.info('add last item from prev', _.last(paths[i - 1].path));
4409 current_path.unshift(_.last(paths[i - 1].path));
4410 }
4411 if (i < paths.length - 2) {
4412 //console.info('add first item from next', _.first(paths[i + 1].path));
4413 current_path.push(_.first(paths[i + 1].path));
4414 }
4415
4416 count++;
4417 var point_index = 0;
4418 //console.info('pre snapping', i, current_path.length, _.first(current_path), _.last(current_path));
4419 while (point_index < current_path.length) {
4420 //var path_100 = paths[i].path.splice(point_index, 100);
4421
4422 //if (paths[i].path.length) {
4423 // paths[i].path.unshift(_.last(path_100));
4424 //}
4425
4426 var d = $.Deferred();
4427 promises.push(d);
4428 //console.info('snapping', i, paths[i].path.length, point_index, path_100.length, _.first(path_100), _.last(path_100));
4429 //console.log('added index', gLineCounter);
4430 runSnapToRoad(current_path, i, point_index, point_index + 90, d, { color: paths[i].color, overSpeeding: paths[i].overSpeeding, path: paths[i], snap: Defaults.IsTripSnapped, map: _map, index: gLineCounter++ });
4431 point_index += 90 - 1;
4432 }
4433 }
4434 //console.log('calling geocodes ', promises.length);
4435 if (promises.length) {
4436 $.when.apply(null, promises).then(function () {
4437 locationProcess(index + count);
4438 });
4439 }
4440 }, index == 0 ? 0 : 1000);
4441 };
4442 locationProcess(index);
4443 }
4444
4445 if (extendBounds) {
4446 if (live) {
4447 app.bounds = markerBounds;
4448 } else {
4449 _map.fitBounds(markerBounds);
4450 }
4451 }
4452 _map.panBy(1, 0);
4453
4454 //console.log("let's animate!");
4455 //animateCircle(app.pathLine);
4456 //animateCircle(animateLines);
4457 };
4458
4459 self.loadReport = function (container, url, model, e) {
4460 console.log(container, url, model, e);
4461 $('#report-viewer').attr('src', url + '?embedded=true');
4462 };
4463
4464 function activateTab(tab) {
4465 $('.nav-tabs a[href="#' + tab + '"]').tab('show');
4466 };
4467
4468 var formatDate = function (value, format) {
4469 if (!value) {
4470 return '';
4471 }
4472 var m = moment(value);
4473 if (m.year() < 2000) {
4474 return '';
4475 }
4476 var result = m.format(format);
4477 return result;
4478 };
4479
4480 self.Contracts = ko.observableArray([]);
4481 self.ContractPage = ko.observable(1);
4482 self.ContractVehicleId = ko.observable(0);
4483 self.ContractFrom = ko.observable(moment('2016-01-01'));
4484 self.ContractTo = ko.observable(moment('2017-01-01'));
4485 self.ContractName = ko.observable('');
4486 self.ContractNumber = ko.observable('');
4487 self.ContractDeviceIMEI = ko.observable('');
4488 self.ContractSimCard = ko.observable('');
4489
4490 self.loadContractData = function (model, event, index) {
4491 var data = {
4492 page: index || 1,
4493
4494 ContractVehicleId: self.ContractVehicleId(),
4495 ContractFrom: self.ContractFrom(),
4496 ContractTo: self.ContractTo(),
4497 ContractName: self.ContractName(),
4498 ContractNumber: self.ContractNumber(),
4499 ContractDeviceIMEI: self.ContractDeviceIMEI(),
4500 ContractSimCard: self.ContractSimCard()
4501 };
4502
4503 var json = ko.toJSON(data);
4504 Metronic.blockUI({ target: '#tab-contract-report-container', animate: true });
4505
4506 $.ajax({
4507 url: 'Tracking/GetContracts',
4508 type: 'POST',
4509 data: json,
4510 contentType: 'application/json',
4511 crossDomain: true,
4512 cache: false,
4513 success: function (data) {
4514 if (!_.isObject(data)) {
4515 window.location = "";
4516 }
4517 //alert('Testing started successfully.');
4518 //console.log('success', data);
4519
4520 self.page(data.Page || 1);
4521 self.pages(data.Pages || 1);
4522 self.pageSize(data.PageSize || 1);
4523 self.count(data.Count || 1);
4524
4525 self.Contracts([]);
4526 _.forEach(data.Contracts, function (x) {
4527 x.isOpen = ko.observable(false);
4528 x.CreatedOnFormatted = formatDate(x.CreatedOn, 'DD/MM/YYYY HH:mm');
4529 x.StartOnFormatted = formatDate(x.StartOn, 'DD/MM/YYYY');
4530 x.ClosedOnFormatted = formatDate(x.ClosedOn, 'DD/MM/YYYY');
4531 x.ExpireOnFormatted = formatDate(x.ExpireOn, 'DD/MM/YYYY');
4532
4533 _.forEach(x.Details, function (d) {
4534 d.ActionOnFormatted = formatDate(d.ActionOn, 'DD/MM/YYYY HH:mm');
4535 });
4536
4537 self.Contracts.push(x);
4538 });
4539 Metronic.unblockUI('#tab-contract-report-container');
4540 },
4541 fail: function (data) {
4542 alert(resx.Startingfailed);
4543 console.log('fail', data);
4544 Metronic.unblockUI('#tab-contract-report-container');
4545 },
4546 error: function (data) {
4547 var json = JSON.parse(data.responseText);
4548 alert(resx.Startingerror + (json.Message || ''));
4549 console.log('error', data);
4550 Metronic.unblockUI('#tab-contract-report-container');
4551 }
4552 });
4553 }
4554
4555
4556 self.loadDataForReport = function (model, event, index) {
4557 //console.log('on click', model, event, index);
4558 //
4559 var data = {
4560 page: index || 1,//self.page(),
4561
4562 from: self.from(),
4563 to: self.to(),
4564
4565 crewName: self.crewName(),
4566 crewPhone: self.crewPhone(),
4567 crewRfid: self.crewRfid(),
4568
4569 vehicleName: self.vehicleName(),
4570 ChassisNo: self.chassisNo(),
4571 vehiclePhone: self.vehiclePhone(),
4572 vehiclePlateNo: self.vehiclePlateNo()
4573 };
4574
4575 var json = ko.toJSON(data);
4576 Metronic.blockUI({ target: '#tab-report-container', animate: true });
4577
4578 $.ajax({
4579 url: 'Tracking/TrackingDataForReport',
4580 type: 'POST',
4581 data: json,
4582 contentType: 'application/json',
4583 crossDomain: true,
4584 cache: false,
4585 success: function (data) {
4586 //alert('Testing started successfully.');
4587 //console.log('success', data);
4588
4589 self.page(data.Page || 1);
4590 self.pages(data.Pages || 1);
4591 self.pageSize(data.PageSize || 1);
4592 self.count(data.Count || 1);
4593
4594 self.reportData([]);
4595 app.xxx = data.Data;
4596 _.forEach(data.Data, function (x) {
4597 x.isOpen = ko.observable(false);
4598 x.FirstLatLng = 'Lat: ' + x.FirstLat + ', Lng:' + x.FirstLng;
4599 x.LastLatLng = 'Lat: ' + x.LastLat + ', Lng:' + x.LastLng;
4600 x.Date = moment(x.FirstTime).format('DD/MM/YYYY');
4601 x.FirstTimeFormatted = moment(x.FirstTime).format('DD/MM/YYYY HH:mm');
4602 x.LastTimeFormatted = moment(x.LastTime).format('DD/MM/YYYY HH:mm');
4603 x.address = ko.observable('');
4604
4605 geocoder.geocode(x.FirstLat, x.FirstLng, function (data, status) {
4606 if (status === 200) {
4607 x.address(data.results[0] ? '<span class="label label-sm label-primary" style="white-space: pre-wrap; color: #337ab7; background: #eee;">' + data.results[0].formatted_address + '</span>' : '');
4608 }
4609 else {
4610 x.address('<span class="label label-sm label-danger">' + resx.Nan + '</span>');
4611 }
4612 });
4613
4614 x.RfidList = [];
4615 var rfidListGrouped = app.groupBy(x.RfidItems, 'Rfid', 'k', 'v');
4616 _.forEach(rfidListGrouped, function (r) {
4617 var lastIndex = r.v.length - 1;
4618 var rfidItem = {
4619 Rfid: r.k,
4620
4621 RfidFirstLat: r.v[0].RfidLat,
4622 RfidFirstLng: r.v[0].RfidLng,
4623 RfidFirstLatLng: 'Lat: ' + r.v[0].RfidLat + ', Lng:' + r.v[0].RfidLng,
4624 RfidFirstScannedOn: moment(r.v[0].RfidScannedOn).format('DD/MM/YYYY HH:mm'),
4625
4626 RfidLastLat: r.v[lastIndex].RfidLat,
4627 RfidLastLng: r.v[lastIndex].RfidLng,
4628 RfidLastLatLng: 'Lat: ' + r.v[lastIndex].RfidLat + ', Lng:' + r.v[lastIndex].RfidLng,
4629 RfidLastScannedOn: moment(r.v[lastIndex].RfidScannedOn).format('DD/MM/YYYY HH:mm'),
4630
4631 RfidName: r.v[0].RfidName,
4632 RfidMobileNo: r.v[0].RfidMobileNo,
4633 RfidAddress: ko.observable('<span class="label label-sm label-info">' + resx.Fetchingaddress + '</span>')
4634 };
4635 x.RfidList.push(rfidItem);
4636 });
4637
4638 x.hasBeenOpenFlag = false;
4639 x.isOpen.subscribe(function (v) {
4640 if (x.hasBeenOpenFlag)
4641 return;
4642 if (!v)
4643 return;
4644
4645 x.hasBeenOpenFlag = true;
4646
4647 _.forEach(x.RfidList, function (t) {
4648 geocoder.geocode(t.RfidFirstLat, t.RfidFirstLng, function (data, status) {
4649 if (status === 200) {
4650 t.RfidAddress(data.results[0] ? '<span class="label label-sm label-primary" style="white-space: pre-wrap; color: #337ab7; background: #eee;">' + data.results[0].formatted_address + '</span>' : '');
4651 }
4652 else {
4653 t.RfidAddress('<span class="label label-sm label-danger">' + resx.Nan + '</span>');
4654 }
4655 });
4656 });
4657 });
4658 x.RfidList = _.sortBy(x.RfidList, function (x) { return x.Rfid; });
4659 self.reportData.push(x);
4660 self.reportData
4661 });
4662 Metronic.unblockUI('#tab-report-container');
4663 },
4664 fail: function (data) {
4665 alert(resx.Startingfailed);
4666 console.log('fail', data);
4667 Metronic.unblockUI('#tab-report-container');
4668 },
4669 error: function (data) {
4670 var json = JSON.parse(data.responseText);
4671 alert(resx.Startingerror + (json.Message || ''));
4672 console.log('error', data);
4673 Metronic.unblockUI('#tab-report-container');
4674 }
4675 });
4676 }
4677
4678 self.printView = ko.observable(false);
4679
4680 self.printViewToggle = function () {
4681 var newflag = !self.printView();
4682 _.forEach(self.reportData(), function (x) {
4683 x.isOpen(newflag);
4684 });
4685 self.printView(newflag);
4686 };
4687
4688 self.printViewText = ko.computed(function () {
4689 var flag = self.printView();
4690 return flag ? 'Collapse All' : 'Expand All';
4691 });
4692
4693 self.exportCsv = function () {
4694 var data = {
4695 from: self.from(),
4696 to: self.to(),
4697
4698 crewName: self.crewName(),
4699 crewPhone: self.crewPhone(),
4700 crewRfid: self.crewRfid(),
4701
4702 vehicleName: self.vehicleName(),
4703 ChassisNo: self.chassisNo(),
4704 vehiclePhone: self.vehiclePhone(),
4705 vehiclePlateNo: self.vehiclePlateNo()
4706 };
4707
4708 var json = ko.toJSON(data);
4709 app.download('Tracking/exportCsv', 'options', json);
4710 return;
4711 };
4712
4713 app.convertDistance = function (dist) {
4714 var m = settingMapDistances[Defaults.UnitOfDistance].m;
4715 var result = (dist * m);
4716 return result;
4717 };
4718
4719 app.convertSpeed = function (speed) {
4720 var m = settingMapSpeeds[Defaults.UnitOfSpeed].m;
4721 var result = (speed * m);
4722 return result;
4723 };
4724
4725 self.timer = null;
4726 var firstTime = true;
4727 self.loadAuto = function (first) {
4728 //if (self.timer) {
4729 // clearInterval(timer);
4730 // self.timer = null;
4731 //}
4732 if (first) {
4733 self.loadDataForMap();//self.filter);
4734 }
4735 //self.timer =
4736 // setTimeout(function () {
4737 // self.loadDataForMap({ autoload: true });//self.filter);
4738 //}, settingMapRefreshes[Defaults.MapRefreshTime].time);
4739 //$('#page_refresh_lbl').text('Refresh ' + settingMapRefreshes[Defaults.MapRefreshTime].desc);
4740 self.page_refresh(resx.refreshText + ' ' + settingMapRefreshes[Defaults.MapRefreshTime].desc);
4741
4742 }
4743
4744 self.selectArea = function (area) {
4745 self.selectedArea(area.Name);
4746 var areaOverlay = $.grep(self.areasOverlay(), function (item, i) {
4747 return item.id == area.Id;
4748 })[0];
4749 var shape = JSON.parse(area.Shape);
4750 overlayIO.setCenter(shape.type, areaOverlay.overlay, map);
4751
4752 var vehicles = $.grep(app.markers, function (item, i) {
4753 return overlayIO.isInTheArea(item.marker.position, shape.type, areaOverlay.overlay, map);
4754 });
4755 self.selectedAreaVehiclesCount(vehicles.length);
4756 }
4757
4758
4759 self.refreshby = function (value, name) {
4760
4761
4762 self.page_refresh(resx['refreshby_' + name]);
4763
4764 //if (self.timer) {
4765 // clearInterval(self.timer);
4766 // self.timer = null;
4767 //}
4768
4769 self.loadDataForMap();//self.filter);
4770 var time = 60000;
4771 if (value == '0') {
4772
4773 Defaults.MapRefreshTime = "FiveSecond";
4774 }
4775 if (value == '30') {
4776
4777 Defaults.MapRefreshTime = "ThirtySecond";
4778 }
4779 else if (value == '1') {
4780
4781 Defaults.MapRefreshTime = "OneMinute";
4782 }
4783 else if (value == '2') {
4784
4785 Defaults.MapRefreshTime = "TwoMinute";
4786 }
4787 else if (value == '5') {
4788
4789 Defaults.MapRefreshTime = "FiveMinute";
4790 }
4791 // self.timer =
4792 //setTimeout(function () {
4793 // self.loadDataForMap({ autoload: true });//self.filter);
4794 //}, settingMapRefreshes[Defaults.MapRefreshTime].time);
4795
4796
4797 };
4798
4799
4800 self.loadForInterval = function (time) {
4801 //if (self.timer) {
4802 // clearInterval(self.timer);
4803 // self.timer = null;
4804 //}
4805 //if (first) {
4806 // self.loadDataForMap();//self.filter);
4807 // //self.timer =
4808 // setTimeout(function () {
4809 // self.loadDataForMap({ autoload: true });//self.filter);
4810 // }, settingMapRefreshes[Defaults.MapRefreshTime].time);
4811 //}
4812 }
4813
4814
4815
4816
4817
4818
4819
4820 self.loadAreas = function () {
4821 $.ajax({
4822 url: 'Tracking/GetAreas',
4823 type: 'POST',
4824 data: '',
4825 contentType: 'application/json',
4826 crossDomain: true,
4827 cache: false,
4828 success: function (areas) {
4829 app.model.areas = areas;
4830 app.model.mapAreas(areas);
4831 var maps = [map, map_live];
4832 var overlays = [];
4833 _.forEach(areas, function (a) {
4834 var shape = JSON.parse(a.Shape);
4835 shape.Name = a.Name;
4836 shape.Description = a.Description;
4837 _.forEach(maps, function (m) {
4838 var overlay = overlayIO.out(shape, m, true);
4839 var options = {
4840 draggable: true,
4841 editable: true,
4842 fillColor: overlay.get('fillColor'),
4843 strokeColor: overlay.get('strokeColor'),
4844 strokeWeight: overlay.get('strokeWeight')
4845 };
4846
4847 waypointMap.drawing.init({
4848 circleOptions: options,
4849 polygonOptions: options,
4850 rectangleOptions: options,
4851 });
4852
4853 overlay.setEditable(false);
4854 overlay.setDraggable(false);
4855 overlays.push({ overlay: overlay, id: a.Id });
4856 });
4857 app.model.areasOverlay(overlays);
4858 });
4859 },
4860 fail: function (data) {
4861 alert(resx.loadareasfailed);
4862 console.log('fail', data);
4863 },
4864 error: function (data) {
4865 var json = JSON.parse(data.responseText);
4866 alert(resx.loadareaserror + (json.Message || ''));
4867 console.log('error', data);
4868 }
4869 });
4870
4871 };
4872}
4873
4874var pageModel = new PageModel();
4875app.model = pageModel;
4876
4877pageModel.loadTree({});
4878//pageModel.loadDataForMap();
4879pageModel.loadAreas();
4880pageModel.loadAuto(true);
4881
4882
4883ko.applyBindings(pageModel, document.getElementById("mainPage"));
4884
4885var slider = document.getElementById('slider');
4886
4887
4888noUiSlider.create(slider, {
4889 connect: true,//'lower',
4890 //tooltips: [true],
4891 start: [0, 24],
4892 step: 1,
4893 range: {
4894 'min': 0,
4895 'max': 24
4896 },
4897 format: {
4898 to: function (value) {
4899 return parseInt(value).toString() + ' Hours';
4900 },
4901 from: function (value) {
4902 return value.replace(' Hours', '');
4903 }
4904 }
4905});
4906
4907var sliderTimes = {};
4908resx.till = ' till ';
4909
4910slider.noUiSlider.on('update', debounce(function (values, handle) {
4911 var value_from = values[0].replace(' Hours', '');
4912 var value_to = values[1].replace(' Hours', '');
4913
4914
4915 if (false && value_from == '0' && value_to == '24') {
4916 app.model.time_desc('All Time of Day');
4917 } else {
4918 var vfrom = parseInt(value_from);
4919 var vto = parseInt(value_to);
4920 var append_from = ' ';
4921 var append_to = ' ';
4922
4923 if (Defaults.TimeFormat == 'TwelveHour') {
4924 append_from = ' AM ';
4925 append_to = ' AM ';
4926
4927 if (vfrom >= 12) {
4928 append_from = ' PM ';
4929 if (vfrom > 12) {
4930 value_from = '' + (vfrom - 12);
4931 }
4932 }
4933 if (vto >= 12) {
4934 append_to = ' PM ';
4935 if (vto > 12) {
4936 value_to = '' + (vto - 12);
4937 }
4938 }
4939 }
4940
4941 var text_to = value_to + ':00';
4942 if (value_to == '24') {
4943 text_to = '23:59';
4944 }
4945 if (vto == 24 && Defaults.TimeFormat == 'TwelveHour') {
4946 text_to = '11:59';
4947 }
4948 app.model.time_desc('' + value_from + ':00 ' + append_from + resx.till + text_to + append_to);
4949 }
4950}, 50));
4951
4952
4953slider.noUiSlider.on('change', debounce(function (values, handle) {
4954 var value_from = values[0].replace(' Hours', '');
4955 var value_to = values[1].replace(' Hours', '');
4956
4957 var old_time_from = app.model.time_from();
4958 var old_time_to = app.model.time_to();
4959
4960 app.model.time_from(value_from);
4961 app.model.time_to(value_to);
4962
4963 if (false && value_from == '0' && value_to == '24') {
4964 app.model.time_desc('All Time of Day');
4965 } else {
4966 var vfrom = parseInt(value_from);
4967 var vto = parseInt(value_to);
4968 var append_from = ' ';
4969 var append_to = ' ';
4970
4971 if (Defaults.TimeFormat == 'TwelveHour') {
4972 append_from = ' AM ';
4973 append_to = ' AM ';
4974
4975 if (vfrom >= 12) {
4976 append_from = ' PM ';
4977 if (vfrom > 12) {
4978 value_from = '' + (vfrom - 12);
4979 }
4980 }
4981 if (vto >= 12) {
4982 append_to = ' PM ';
4983 if (vto > 12) {
4984 value_to = '' + (vto - 12);
4985 }
4986 }
4987 }
4988
4989 var text_to = value_to + ':00';
4990 if (value_to == '24') {
4991 text_to = '23:59';
4992 }
4993 if (vto == 24 && Defaults.TimeFormat == 'TwelveHour') {
4994 text_to = '11:59';
4995 }
4996 //app.model.time_desc('' + value_from + ':00 till ' + text_to);
4997 app.model.time_desc('' + value_from + ':00 ' + append_from + resx.till + text_to + append_to);
4998 }
4999
5000 var isChanged = (old_time_from != value_from) || (old_time_to != value_to);
5001
5002 if (app.mapData && app.mapData.SelectedVehicleId && isChanged) {
5003 app.model.loadDataForMap();
5004 }
5005}, 250));
5006
5007
5008var clusterersPath = Defaults.clustererPath;
5009var vcOptions = {
5010 styles: [
5011 { width: 52, height: 52, url: clusterersPath + 'c1.png' },
5012 { width: 55, height: 55, url: clusterersPath + 'c2.png' },
5013 { width: 65, height: 65, url: clusterersPath + 'c3.png' },
5014 { width: 77, height: 77, url: clusterersPath + 'c4.png' },
5015 { width: 89, height: 89, url: clusterersPath + 'c5.png' }
5016 ],
5017 //gridSize: 50,
5018 maxZoom: 14
5019}
5020
5021var pcOptions = {
5022 styles: [
5023 { width: 52, height: 52, url: clusterersPath + 'p1.png' },
5024 { width: 55, height: 55, url: clusterersPath + 'p2.png' },
5025 { width: 65, height: 65, url: clusterersPath + 'p3.png' },
5026 { width: 77, height: 77, url: clusterersPath + 'p4.png' },
5027 { width: 89, height: 89, url: clusterersPath + 'p5.png' }
5028 ],
5029 //gridSize: 50,
5030 maxZoom: 14
5031}
5032
5033
5034
5035
5036
5037function createVehicle(crumb, visible) {
5038
5039 // Create marker
5040 var marker = new MarkerWithLabel({
5041 //position: new google.maps.LatLng(crumb.Latitude, crumb.Longitude),
5042 position: new google.maps.LatLng(24.446489999999994, 54.61311999999998),
5043
5044 //map: waypointMap.getMap(),
5045 //icon: getVehicleIcon(crumb.IsDisconnected),
5046 icon: getVehicleIcon(false),
5047 //labelContent: getLabelContent(crumb),
5048 labelContent: getLabelContent('xxxxx'),
5049 labelAnchor: new google.maps.Point(13, 13),
5050 labelClass: 'marker-label',
5051 labelVisible: visible
5052 });
5053
5054 // Set marker id_
5055 //marker.id_ = crumb.CrumbId;
5056 //marker.vehicleId_ = crumb.VehicleId;
5057 //marker.vehicleName_ = crumb.VehicleName;
5058
5059 addToMap(vehicleClusterer, marker);
5060
5061 // Add listener
5062 google.maps.event.addListener(marker, 'click', modalVehicle);
5063
5064 return marker;
5065}
5066
5067function addToMap(mclusterer, marker) {
5068 if (mclusterer) {
5069 mclusterer.addMarker(marker, false);
5070 }
5071 else {
5072 marker.setMap(waypointMap.getMap());
5073 }
5074}
5075
5076function getVehicleIcon(disconnect) {
5077 return Defaults.icon;
5078 //disconnect ? '@Url.Content("~/images/vehicles/car-no-signal.png")'
5079 // : '@Url.Content("~/images/vehicles/car.png")';
5080}
5081
5082//function getLabelContent(options) {
5083// //var canvas = crumb.IsEngineOn === true ? '<canvas class="engine-on bg-green" />' : '<canvas class="engine-off bg-red" />';
5084// options = options || {};
5085// var glow = options.glow ? '-glow' : '';
5086// console.log('glow', glow);
5087
5088// return '<div class="marker-label-inner clearfix" style="position: relative;padding-top:25px;padding-left:25px;border-radius:50% !important;birder:none;x-border: 1px solid red;">' +
5089// //'<div class="m-icon-bg">' +
5090// // canvas +
5091// //'</div>' +
5092// //'<div class="m-text">' +
5093// // '<div class="m-text-main">' + crumb.VehicleName + '</div>' +
5094// '<div class="live-icon' + glow + '">' +
5095// '<div class="pulse' + glow + '">' +
5096// '<div class="pulse-circle' + glow + '"></div>' +
5097// '</div>' +
5098// '</div>' +
5099// '</div>' +
5100// '</div>';
5101
5102//}
5103
5104function infoWindow(marker, content) {
5105 var infoWnd = new google.maps.InfoWindow({
5106 content: content//$('#infoWnd_template').html().replace('map_infoWnd_x', id)//'title: ' + self.title()
5107 });
5108 infoWnd.open(map, marker);
5109}
5110
5111
5112function modalVehicle() {
5113 var $this = this;
5114 var modalData = $('#modal-data');
5115
5116 $('#overlay-modal').modal();
5117
5118 $('.modal-title').html($this.vehicleName_);
5119
5120 // TODO: more code cleaning
5121 // Clear old data
5122 modalData.html('');
5123 if (modalMarker) {
5124 modalMarker.setMap(null);
5125 modalMarker = null;
5126 }
5127
5128 Metronic.blockUI({ target: '#modal-data', animate: true });
5129
5130 $.ajax({
5131 url: Defaults.crumbActionUrl,
5132 contentType: 'application/json; charset=utf-8',
5133 data: {
5134 crumbId: $this.id_
5135 },
5136 type: 'GET'
5137 }).done(function (result) {
5138
5139 var position = $this.getPosition();
5140
5141 modalMarker = new google.maps.Marker({
5142 position: position,
5143 map: modalMap,
5144 icon: $this.getIcon()
5145 });
5146
5147 modalMap.panTo(modalMarker.getPosition());
5148 modalMap.setZoom(15);
5149 modalData.html(result);
5150
5151 geocoder.geocode(position.lat(), position.lng(), function (data, status) {
5152 if (status === 200) {
5153 $('#span-address').html(data.results[0] ? data.results[0].formatted_address : '');
5154 }
5155 else {
5156 $('#span-address').html('N/A');
5157 }
5158 });
5159
5160 }).fail(function (response) {
5161 }).always(function () {
5162 Metronic.unblockUI('#modal-data');
5163 });
5164}