From e914c6d2e1e044bb35008edd8ebe08091b8aa03a Mon Sep 17 00:00:00 2001 From: Ramon Gutierrez Date: Tue, 28 Jan 2020 21:51:32 +0800 Subject: [PATCH] Add customer jo tracking view #315 --- config/packages/security.yaml | 5 + config/routes/job_order.yaml | 5 + public/assets/css/style.css | 27 ++++ public/assets/js/tracker_map.js | 182 ++++++++++++++++++++++++++ src/Controller/JobOrderController.php | 26 ++++ templates/base_minimal.html.twig | 70 ++++++++++ templates/job-order/tracker.html.twig | 95 ++++++++++++++ 7 files changed, 410 insertions(+) create mode 100644 public/assets/js/tracker_map.js create mode 100644 templates/base_minimal.html.twig create mode 100644 templates/job-order/tracker.html.twig diff --git a/config/packages/security.yaml b/config/packages/security.yaml index c8deb304..dc9aa78d 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -21,6 +21,11 @@ security: methods: [GET] security: false + tracker: + pattern: ^\/track\/ + methods: [GET] + security: false + api: pattern: ^\/api\/ security: false diff --git a/config/routes/job_order.yaml b/config/routes/job_order.yaml index 139b208f..bfd41df9 100644 --- a/config/routes/job_order.yaml +++ b/config/routes/job_order.yaml @@ -201,3 +201,8 @@ jo_ajax_popup: controller: App\Controller\JobOrderController::popupInfo methods: [GET] +jo_tracker: + path: /track/{id} + controller: App\Controller\JobOrderController::tracker + methods: [GET] + diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 051d2143..140966da 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -331,4 +331,31 @@ span.has-danger, .map-div-icon i.awesome { margin: 12px auto; font-size: 17px; +} +.map-info { + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + z-index: 9999; + padding: 1.5em; + width: 100%; +} + +.map-info > .m-portlet { + margin-bottom: 0; +} + +.map-info .m-portlet__body { + padding: 1.5rem; +} + +.map-info .rider-image { + width: 4.8rem; + border-radius: 50%; +} + +.map-info .m-badge { + border-radius: 0; +} \ No newline at end of file diff --git a/public/assets/js/tracker_map.js b/public/assets/js/tracker_map.js new file mode 100644 index 00000000..ecf3df41 --- /dev/null +++ b/public/assets/js/tracker_map.js @@ -0,0 +1,182 @@ +class DashboardMap { + constructor(options, rider_markers, cust_markers) { + this.options = options; + this.rider_markers = rider_markers; + this.cust_markers = cust_markers; + + // layer groups + this.layer_groups = { + 'rider_available': L.layerGroup(), + 'rider_active_jo': L.layerGroup(), + 'customer': L.layerGroup() + }; + } + + initialize() { + // main map + this.map = L.map(this.options.div_id).setView( + [this.options.center_lat, this.options.center_lng], + this.options.zoom + ); + + // add tile layer + var streets = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', { + attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', + maxZoom: 18, + id: 'mapbox/streets-v11', + accessToken: this.options.access_token + }).addTo(this.map); + + // layer groups + this.layer_groups.rider_available.addTo(this.map); + this.layer_groups.rider_active_jo.addTo(this.map); + this.layer_groups.customer.addTo(this.map); + + // base layer + var baseMaps = { + 'Streets': streets + }; + + // overlay layer + return this.map; + } + + putMarker(id, lat, lng, markers, icon, layer_group, popup_url) { + var my = this; + // existing marker + if (markers.hasOwnProperty(id)) { + markers[id].setLatLng(L.latLng(lat, lng)); + return; + } + + // new marker + markers[id] = L.marker( + [lat, lng], + { icon: icon } + ).bindPopup('Loading...') + .addTo(layer_group); + + // bind ajax for popup + markers[id].on('click', function(e) { + var popup = e.target.getPopup(); + var url = popup_url.replace('[id]', id); + console.log(url); + $.get(url).done(function(data) { + popup.setContent(data); + popup.update(); + }); + }); + } + + putCustomerMarker(id, lat, lng) { + this.putMarker( + id, + lat, + lng, + this.cust_markers, + this.options.icons.customer, + this.layer_groups.customer, + this.options.cust_popup_url + ); + } + + removeCustomerMarker(id) { + console.log('removing customer marker for ' + id); + var layer_group = this.layer_groups.customer; + var markers = this.cust_markers; + + // no customer marker with that id + if (!markers.hasOwnProperty(id)) { + console.log('no such marker to remove'); + return; + } + + layer_group.removeLayer(markers[id]); + } + + putRiderAvailableMarker(id, lat, lng) { + this.putMarker( + id, + lat, + lng, + this.rider_markers, + this.options.icons.rider_available, + this.layer_groups.rider_available, + this.options.rider_popup_url + ); + } + + putRiderActiveJOMarker(id, lat, lng) { + this.putMarker( + id, + lat, + lng, + this.rider_markers, + this.options.icons.rider_active_jo, + this.layer_groups.rider_active_jo, + this.options.rider_popup_url + ); + } + + loadLocations(location_url) { + console.log(this.rider_markers); + var my = this; + $.ajax({ + url: location_url, + }).done(function(response) { + // clear all markers + my.layer_groups.rider_available.clearLayers(); + my.layer_groups.rider_active_jo.clearLayers(); + my.layer_groups.customer.clearLayers(); + + // get riders and job orders + var riders = response.riders; + var jos = response.jos; + + // job orders + $.each(jos, function(id, data) { + var lat = data.latitude; + var lng = data.longitude; + + my.putCustomerMarker(id, lat, lng); + }); + + // riders + $.each(riders, function(id, data) { + var lat = data.latitude; + var lng = data.longitude; + + if (data.has_jo) + my.putRiderActiveJOMarker(id, lat, lng); + else + my.putRiderAvailableMarker(id, lat, lng); + }); + + /* + $.each(riders, function(rider_id, rider_data) { + // rider location + var point = rider_data['loc']; + var lat = point[0]; + var lng = point[1]; + + // customer location + var cloc = rider_data['cust_loc']; + var clat = cloc[0]; + var clng = cloc[1]; + + // create rider markers + if (rider_data['has_jo']) { + var jo_data = rider_data['jo']; + + // my.putCustomerMarker(jo_data['id'], clat, clng); + my.putRiderActiveJOMarker(rider_id, lat, lng); + } else { + my.putRiderAvailableMarker(rider_id, lat, lng); + } + }); + */ + + // console.log(rider_markers); + }); + } +} diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 039ea37d..c92638a4 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -4,6 +4,7 @@ namespace App\Controller; use App\Ramcar\JOStatus; use App\Ramcar\InvoiceCriteria; +use App\Ramcar\CMBServiceType; use App\Entity\CustomerVehicle; use App\Entity\Promo; @@ -23,6 +24,9 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; +use Doctrine\ORM\EntityManagerInterface; +use App\Service\RiderTracker; + use Catalyst\MenuBundle\Annotation\Menu; class JobOrderController extends Controller @@ -922,4 +926,26 @@ class JobOrderController extends Controller return $this->render('job-order/popup.html.twig', [ 'jo' => $jo ]); } + + /** + * @ParamConverter("jo", class="App\Entity\JobOrder") + */ + public function tracker( + EntityManagerInterface $em, + RiderTracker $rider_tracker, + GISManagerInterface $gis_manager, + JobOrder $jo + ) + { + if ($jo === null) + return new Response('No job order data'); + + // get map + $params['jo'] = $jo; + $params['rider'] = $jo->getRider(); + $params['service_type'] = CMBServiceType::getName($jo->getServiceType()); + $params['map_js_file'] = $gis_manager->getJSInitFile(); + + return $this->render('job-order/tracker.html.twig', $params); + } } diff --git a/templates/base_minimal.html.twig b/templates/base_minimal.html.twig new file mode 100644 index 00000000..8a51bcc6 --- /dev/null +++ b/templates/base_minimal.html.twig @@ -0,0 +1,70 @@ +{% import 'menu.html.twig' as menu %} + + + + + + + {% block title %}{% trans %}block_title{% endtrans %}{% endblock %} + + + + + + + + + + + + + + + + + + + + + + + + + {% block stylesheets %} + + {% endblock %} + + + + + + + {% block body %}{% endblock %} + + + + + + + + + + + + + + + + {% block scripts %}{% endblock %} + + + diff --git a/templates/job-order/tracker.html.twig b/templates/job-order/tracker.html.twig new file mode 100644 index 00000000..42f18746 --- /dev/null +++ b/templates/job-order/tracker.html.twig @@ -0,0 +1,95 @@ +{% extends 'base_minimal.html.twig' %} + +{% block body %} +
+
+
+
+
+
+ +
+
Order #{{ jo.getID }}
+
{{ rider.getFullName }}
+
{{ service_type }}
+
+
+
+
+
+
+{% endblock %} + +{% block scripts %} + + + +{{ include('map/' ~ map_js_file) }} + +{% endblock %} \ No newline at end of file