| Line 470... |
Line 470... |
| 470 |
clearMapOverlays();
|
470 |
clearMapOverlays();
|
| 471 |
|
471 |
|
| 472 |
var bounds = new google.maps.LatLngBounds();
|
472 |
var bounds = new google.maps.LatLngBounds();
|
| 473 |
var hasPoints = false;
|
473 |
var hasPoints = false;
|
| 474 |
var visitIdx = 0;
|
474 |
var visitIdx = 0;
|
| 475 |
var visitCoords = [];
|
- |
|
| 476 |
|
475 |
|
| 477 |
// Pre-compute first/last valid path point as fallback for punch records with no coordinates
|
476 |
// Pre-compute first/last valid path point as fallback for punch records with no coordinates
|
| 478 |
var firstPathLat = null, firstPathLng = null;
|
477 |
var firstPathLat = null, firstPathLng = null;
|
| 479 |
var lastPathLat = null, lastPathLng = null;
|
478 |
var lastPathLat = null, lastPathLng = null;
|
| 480 |
for (var pi = 0; pi < pathPoints.length; pi++) {
|
479 |
for (var pi = 0; pi < pathPoints.length; pi++) {
|
| Line 500... |
Line 499... |
| 500 |
}
|
499 |
}
|
| 501 |
|
500 |
|
| 502 |
hasPoints = true;
|
501 |
hasPoints = true;
|
| 503 |
var pos = { lat: lat, lng: lng };
|
502 |
var pos = { lat: lat, lng: lng };
|
| 504 |
bounds.extend(pos);
|
503 |
bounds.extend(pos);
|
| 505 |
visitCoords.push(pos);
|
- |
|
| 506 |
|
504 |
|
| 507 |
var label = v.markType === 'PUNCHIN' ? 'P' : (v.markType === 'PUNCHOUT' ? 'X' : String(++visitIdx));
|
505 |
var label = v.markType === 'PUNCHIN' ? 'P' : (v.markType === 'PUNCHOUT' ? 'X' : String(++visitIdx));
|
| 508 |
var marker = new google.maps.Marker({
|
506 |
var marker = new google.maps.Marker({
|
| 509 |
position: pos,
|
507 |
position: pos,
|
| 510 |
map: liveTrackingMap,
|
508 |
map: liveTrackingMap,
|
| Line 534... |
Line 532... |
| 534 |
})(marker, infoContent);
|
532 |
})(marker, infoContent);
|
| 535 |
|
533 |
|
| 536 |
liveTrackingMap._markers.push(marker);
|
534 |
liveTrackingMap._markers.push(marker);
|
| 537 |
}
|
535 |
}
|
| 538 |
|
536 |
|
| 539 |
// Draw actual road path between visits using Directions API
|
- |
|
| 540 |
if (visitCoords.length >= 2) {
|
- |
|
| 541 |
var origin = visitCoords[0];
|
- |
|
| 542 |
var destination = visitCoords[visitCoords.length - 1];
|
- |
|
| 543 |
var waypoints = [];
|
- |
|
| 544 |
for (var wi = 1; wi < visitCoords.length - 1; wi++) {
|
- |
|
| 545 |
waypoints.push({ location: visitCoords[wi], stopover: true });
|
- |
|
| 546 |
}
|
- |
|
| 547 |
|
- |
|
| 548 |
var directionsService = new google.maps.DirectionsService();
|
- |
|
| 549 |
var directionsRenderer = new google.maps.DirectionsRenderer({
|
- |
|
| 550 |
map: liveTrackingMap,
|
- |
|
| 551 |
suppressMarkers: true,
|
- |
|
| 552 |
polylineOptions: {
|
- |
|
| 553 |
strokeColor: '#8e44ad',
|
- |
|
| 554 |
strokeOpacity: 0.7,
|
- |
|
| 555 |
strokeWeight: 4
|
- |
|
| 556 |
},
|
- |
|
| 557 |
preserveViewport: true
|
- |
|
| 558 |
});
|
- |
|
| 559 |
liveTrackingMap._directionsRenderer = directionsRenderer;
|
- |
|
| 560 |
|
- |
|
| 561 |
directionsService.route({
|
- |
|
| 562 |
origin: origin,
|
- |
|
| 563 |
destination: destination,
|
- |
|
| 564 |
waypoints: waypoints,
|
- |
|
| 565 |
travelMode: google.maps.TravelMode.DRIVING,
|
- |
|
| 566 |
optimizeWaypoints: false
|
- |
|
| 567 |
}, function (result, status) {
|
- |
|
| 568 |
if (status === 'OK') {
|
- |
|
| 569 |
directionsRenderer.setDirections(result);
|
- |
|
| 570 |
}
|
- |
|
| 571 |
});
|
- |
|
| 572 |
}
|
- |
|
| 573 |
|
- |
|
| 574 |
// Draw GPS tracked path with red dots + connecting line
|
537 |
// Draw GPS tracked path with red dots + connecting line
|
| 575 |
var totalGpsDistanceM = 0;
|
538 |
var totalGpsDistanceM = 0;
|
| 576 |
var accuracySum = 0;
|
539 |
var accuracySum = 0;
|
| 577 |
var accuracyCount = 0;
|
540 |
var accuracyCount = 0;
|
| 578 |
var stopsDetected = [];
|
541 |
var stopsDetected = [];
|
| Line 763... |
Line 726... |
| 763 |
} else {
|
726 |
} else {
|
| 764 |
infoHtml += ' | <span style="color:#999;"><i class="fa fa-exclamation-triangle"></i> No GPS data yet</span>';
|
727 |
infoHtml += ' | <span style="color:#999;"><i class="fa fa-exclamation-triangle"></i> No GPS data yet</span>';
|
| 765 |
}
|
728 |
}
|
| 766 |
|
729 |
|
| 767 |
infoHtml += ' | <span style="color:#e74c3c;"><i class="fa fa-arrow-right" style="font-size:10px;"></i></span> GPS Trail';
|
730 |
infoHtml += ' | <span style="color:#e74c3c;"><i class="fa fa-arrow-right" style="font-size:10px;"></i></span> GPS Trail';
|
| 768 |
if (visitCoords.length > 1) {
|
- |
|
| 769 |
infoHtml += ' | <span style="background:#8e44ad; display:inline-block; width:14px; height:3px; vertical-align:middle; margin:0 2px;"></span> Route';
|
- |
|
| 770 |
}
|
- |
|
| 771 |
var battery = data.batteryLevel;
|
731 |
var battery = data.batteryLevel;
|
| 772 |
if (battery !== null && battery !== undefined) {
|
732 |
if (battery !== null && battery !== undefined) {
|
| 773 |
var batteryColor = battery > 50 ? '#27ae60' : (battery > 20 ? '#f39c12' : '#e74c3c');
|
733 |
var batteryColor = battery > 50 ? '#27ae60' : (battery > 20 ? '#f39c12' : '#e74c3c');
|
| 774 |
var batteryIcon = battery > 50 ? 'fa-battery-full' : (battery > 20 ? 'fa-battery-half' : 'fa-battery-quarter');
|
734 |
var batteryIcon = battery > 50 ? 'fa-battery-full' : (battery > 20 ? 'fa-battery-half' : 'fa-battery-quarter');
|
| 775 |
infoHtml += ' | <span style="color:' + batteryColor + ';"><i class="fa ' + batteryIcon + '"></i> Battery: <strong>' + battery + '%</strong></span>';
|
735 |
infoHtml += ' | <span style="color:' + batteryColor + ';"><i class="fa ' + batteryIcon + '"></i> Battery: <strong>' + battery + '%</strong></span>';
|
| Line 806... |
Line 766... |
| 806 |
document.head.appendChild(s);
|
766 |
document.head.appendChild(s);
|
| 807 |
}
|
767 |
}
|
| 808 |
|
768 |
|
| 809 |
var liveTrackingUsername = '';
|
769 |
var liveTrackingUsername = '';
|
| 810 |
|
770 |
|
| 811 |
/*function startAutoRefresh() {
|
- |
|
| 812 |
stopAutoRefresh();
|
- |
|
| 813 |
if ($('#autoRefreshToggle').is(':checked') && liveTrackingUserId) {
|
- |
|
| 814 |
liveTrackingInterval = setInterval(function () {
|
- |
|
| 815 |
loadLiveTracking(liveTrackingUserId, liveTrackingUsername);
|
- |
|
| 816 |
}, 30000);
|
- |
|
| 817 |
}
|
- |
|
| 818 |
}
|
- |
|
| 819 |
|
- |
|
| 820 |
function stopAutoRefresh() {
|
- |
|
| 821 |
if (liveTrackingInterval) {
|
- |
|
| 822 |
clearInterval(liveTrackingInterval);
|
- |
|
| 823 |
liveTrackingInterval = null;
|
- |
|
| 824 |
}
|
- |
|
| 825 |
}*/
|
- |
|
| 826 |
|
- |
|
| 827 |
$(document).on('click.livetrack', '.live-tracking-btn', function () {
|
771 |
$(document).on('click.livetrack', '.live-tracking-btn', function () {
|
| 828 |
liveTrackingUserId = $(this).data('userid');
|
772 |
liveTrackingUserId = $(this).data('userid');
|
| 829 |
liveTrackingUsername = $(this).data('username');
|
773 |
liveTrackingUsername = $(this).data('username');
|
| 830 |
$('#liveTrackingModalTitle').html('<img src="${rc.contextPath}/resources/images/salesman.png" style="height:24px; vertical-align:middle; margin-right:6px;"> Live Tracking - ' + liveTrackingUsername);
|
774 |
$('#liveTrackingModalTitle').html('<img src="${rc.contextPath}/resources/images/salesman.png" style="height:24px; vertical-align:middle; margin-right:6px;"> Live Tracking - ' + liveTrackingUsername);
|
| 831 |
$('#liveTrackingInfo').html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
|
775 |
$('#liveTrackingInfo').html('<div class="text-center"><i class="fa fa-spinner fa-spin"></i> Loading...</div>');
|