From c753be54cb9a1f6a4259ccbb519307678370c807 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Sat, 25 Jan 2020 01:57:15 +0800 Subject: [PATCH] Refactor dashboard map js to use classes #299 --- composer.json | 1 + composer.lock | 60 +++++++++++- public/assets/js/dashboard_map.js | 114 ++++++++++++++++++++++ public/assets/js/map_mqtt.js | 81 ++++++++++++++++ symfony.lock | 3 + templates/home.html.twig | 151 +++++++++++------------------ templates/map/initOpenStreetMap.js | 139 -------------------------- 7 files changed, 315 insertions(+), 234 deletions(-) create mode 100644 public/assets/js/dashboard_map.js create mode 100644 public/assets/js/map_mqtt.js diff --git a/composer.json b/composer.json index e118abfc..7219d070 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "predis/predis": "^1.1", "sensio/framework-extra-bundle": "^5.1", "setasign/fpdf": "^1.8", + "symfony/asset": "^4.0", "symfony/console": "^4.0", "symfony/debug": "^4.0", "symfony/filesystem": "^4.0", diff --git a/composer.lock b/composer.lock index b3630199..a1172379 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "4873ae3fd18db755bc9bf395bbbfb141", + "content-hash": "b101ecfbc1f6f2270f0e8ad326035b7e", "packages": [ { "name": "catalyst/auth-bundle", @@ -2411,6 +2411,62 @@ ], "time": "2016-01-01T17:47:15+00:00" }, + { + "name": "symfony/asset", + "version": "v4.4.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/asset.git", + "reference": "2c67c89d064bfb689ea6bc41217c87100bb94c17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/asset/zipball/2c67c89d064bfb689ea6bc41217c87100bb94c17", + "reference": "2c67c89d064bfb689ea6bc41217c87100bb94c17", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "symfony/http-foundation": "^3.4|^4.0|^5.0", + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "suggest": { + "symfony/http-foundation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Asset\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Asset Component", + "homepage": "https://symfony.com", + "time": "2020-01-04T13:00:46+00:00" + }, { "name": "symfony/cache", "version": "v4.3.1", @@ -5344,6 +5400,7 @@ "code", "zf2" ], + "abandoned": "laminas/laminas-code", "time": "2018-08-13T20:36:59+00:00" }, { @@ -5398,6 +5455,7 @@ "events", "zf2" ], + "abandoned": "laminas/laminas-eventmanager", "time": "2018-04-25T15:33:34+00:00" } ], diff --git a/public/assets/js/dashboard_map.js b/public/assets/js/dashboard_map.js new file mode 100644 index 00000000..f50c7520 --- /dev/null +++ b/public/assets/js/dashboard_map.js @@ -0,0 +1,114 @@ +class DashboardMap { + constructor(options, rider_markers, cust_markers) { + this.options = options; + this.rider_markers = rider_markers; + this.cust_markers = cust_markers; + + // layer groups + this.lg_avail_rider = L.layerGroup(); + this.lg_jo_rider = L.layerGroup(); + this.lg_cust = 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.lg_avail_rider.addTo(this.map); + this.lg_jo_rider.addTo(this.map); + this.lg_cust.addTo(this.map); + + // base layer + var baseMaps = { + 'Streets': streets + }; + + // overlay layer + var overlayMaps = { + 'Available Riders' : this.lg_avail_rider, + 'JO Riders' : this.lg_jo_rider, + 'Customers' : this.lg_cust + } + + L.control.layers(baseMaps, overlayMaps).addTo(this.map); + + return this.map; + } + + loadLocations(location_url) { + console.log(this.rider_markers); + var my = this; + $.ajax({ + url: location_url, + }).done(function(response) { + // clear all markers + my.lg_avail_rider.clearLayers(); + my.lg_jo_rider.clearLayers(); + my.lg_cust.clearLayers(); + // get riders and mark + var riders = response.riders; + + $.each(riders, function(rider_id, rider_data) { + // rider location + var point = rider_data['loc']; + var lat = point[0]; + var long = point[1]; + + // customer location + var cloc = rider_data['cust_loc']; + var clat = cloc[0]; + var clong = cloc[1]; + + // create rider markers + if (rider_data['has_jo']) { + var jo_data = rider_data['jo']; + + my.rider_markers[rider_id] = L.marker([lat, long], { icon: my.options.icons.rider_active_jo }).bindPopup('Loading...'); + my.cust_markers[jo_data['id']] = L.marker([clat, clong], { icon: my.options.icons.customer }).bindPopup('Loading...'); + + my.lg_cust.addLayer(my.cust_markers[jo_data['id']]); + my.lg_jo_rider.addLayer(my.rider_markers[rider_id]); + + // customer popup ajax + my.cust_markers[jo_data['id']].on('click', function(e) { + var popup = e.target.getPopup(); + var url = my.options.cust_popup_url.replace('[id]', jo_data['id']); + console.log(url); + $.get(url).done(function(data) { + popup.setContent(data); + popup.update(); + }); + }); + } else { + my.rider_markers[rider_id]= L.marker([lat, long], { icon: my.options.icons.rider_available }).bindPopup('Loading...'); + my.lg_avail_rider.addLayer(my.rider_markers[rider_id]); + } + + // ajax loading of rider popup + my.rider_markers[rider_id].on('click', function(e) { + var popup = e.target.getPopup(); + var url = my.options.rider_popup_url.replace('[id]', rider_id); + console.log(url); + $.get(url).done(function(data) { + popup.setContent(data); + popup.update(); + }); + }); + }); + + // console.log(rider_markers); + }); + } +} diff --git a/public/assets/js/map_mqtt.js b/public/assets/js/map_mqtt.js new file mode 100644 index 00000000..39272c4f --- /dev/null +++ b/public/assets/js/map_mqtt.js @@ -0,0 +1,81 @@ +class MapEventHandler { + constructor(options, rider_markers, cust_markers) { + this.options = options; + this.rider_markers = rider_markers; + this.cust_markers = cust_markers; + } + + connect(user_id, host, port) { + var d = new Date(); + var client_id = "dash-" + user_id + "-" + d.getMonth() + "-" + d.getDate() + "-" + d.getHours() + "-" + d.getMinutes() + "-" + d.getSeconds() + "-" + d.getMilliseconds(); + console.log(client_id); + + this.mqtt = new Paho.MQTT.Client(host, port, client_id); + var options = { + useSSL: true, + timeout: 3, + onSuccess: this.onConnect, + }; + + this.mqtt.onMessageArrived = this.onMessage; + + console.log('connecting to mqtt server...'); + this.mqtt.connect(options); + + return this.mqtt; + } + + onConnect() { + console.log('connected!'); + + this.mqtt.subscribe(this.options.channels.rider_location); + } + + onMessage(msg) { + // console.log(msg); + console.log('received message'); + + var channel = msg.destinationName; + var chan_split = channel.split('/'); + var payload = msg.payloadString; + + // handle different channels + switch (chan_split[0]) { + case "rider": + this.handleRider(chan_split, payload); + break; + } + } + + handleRider(chan_split, payload) { + console.log("rider message"); + switch (chan_split[2]) { + case "location": + console.log("got location for rider " + chan_split[1] + " - " + payload); + pl_split = payload.split(':'); + console.log(pl_split); + + // check for correct format + if (pl_split.length != 2) + break; + + var lat = parseFloat(pl_split[0]); + var lng = parseFloat(pl_split[1]); + + // move marker + console.log(this.rider_markers[chan_split[1]]); + + // check if marker exists + if (this.rider_markers.hasOwnProperty(chan_split[1])) { + // marker's there, move it + this.rider_markers[chan_split[1]].setLatLng(L.latLng(lat, lng)); + } else { + // no marker, make one + console.log('creating marker'); + // TODO: make it add to the correct map layer + this.rider_markers[chan_split[1]]= L.marker([lat, lng], { icon: this.options.icons.rider_available }).addTo(map);; + } + break; + } + } +} diff --git a/symfony.lock b/symfony.lock index 88d10d33..576e49fd 100644 --- a/symfony.lock +++ b/symfony.lock @@ -152,6 +152,9 @@ "setasign/fpdf": { "version": "1.8.1" }, + "symfony/asset": { + "version": "v4.4.3" + }, "symfony/cache": { "version": "v4.0.2" }, diff --git a/templates/home.html.twig b/templates/home.html.twig index f55fe863..e0b77426 100644 --- a/templates/home.html.twig +++ b/templates/home.html.twig @@ -13,111 +13,74 @@ {% block scripts %} + + +{{ include('map/' ~ map_js_file) }} - -{{ include('map/' ~ map_js_file) }} - - - {% endblock %} diff --git a/templates/map/initOpenStreetMap.js b/templates/map/initOpenStreetMap.js index 358b91d4..8eab44bd 100644 --- a/templates/map/initOpenStreetMap.js +++ b/templates/map/initOpenStreetMap.js @@ -2,142 +2,3 @@ integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""> - -