[client] Refactor to support new HTTP API changes

This commit is contained in:
Starbeamrainbowlabs 2019-04-16 18:08:15 +01:00
parent 530876ab5f
commit deb02b0ede
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
4 changed files with 72 additions and 18 deletions

View file

@ -0,0 +1,43 @@
"use strict";
import Config from './Config.mjs';
import GetFromUrl from './Helpers/GetFromUrl.mjs';
/**
* Handles and caches data about devices.
*/
class DeviceData {
/**
* Creates a new DeviceData class instance.
*/
constructor() {
this.devices = [];
}
/**
* Fetches the device data from the server.
* @return {Promise} A promise that resolves when the data has been fetched from the server.
*/
async setup() {
this.devices = JSON.parse(await GetFromUrl(
`${Config.api_root}?action=list-devices`
));
// Create a map to help us lookup ids faster
this.device_map = new Map();
for(let device of this.devices)
this.device_map.set(device.id, device);
}
/**
* Looks up a device by its id.
* @param {Number} device_id The ID of the device to return
* @return {object} The info about the device with the specified id.
*/
get_by_id(device_id) {
return this.device_map.get(device_id);
}
}
export default DeviceData;

View file

@ -12,8 +12,9 @@ import DeviceReadingDisplay from './DeviceReadingDisplay.mjs';
import GetFromUrl from './Helpers/GetFromUrl.mjs'; import GetFromUrl from './Helpers/GetFromUrl.mjs';
class LayerDeviceMarkers { class LayerDeviceMarkers {
constructor(in_map) { constructor(in_map, in_device_data) {
this.map = in_map; this.map = in_map;
this.device_data = in_device_data;
// Create a new clustering layer // Create a new clustering layer
this.layer = L.markerClusterGroup({ this.layer = L.markerClusterGroup({
@ -22,14 +23,12 @@ class LayerDeviceMarkers {
} }
async setup() { async setup() {
// Fetch the device list
let device_list = JSON.parse(await GetFromUrl(
`${Config.api_root}?action=list-devices&only-with-location=yes`
));
// Add a marker for each device // Add a marker for each device
for (let device of device_list) { for (let device of this.device_data.devices) {
// If the device doesn't have a location, we're not interested
// FUTURE: We might be able to displaymobile devices by adding additional logic here
if(typeof device.latitude != "number" || typeof device.longitude != "number")
continue;
this.add_device_marker(device); this.add_device_marker(device);
} }

View file

@ -11,8 +11,9 @@ class LayerHeatmap {
* Creates a new heatmap manager wrapper class fort he given map. * Creates a new heatmap manager wrapper class fort he given map.
* @param {L.Map} in_map The leaflet map to attach to. * @param {L.Map} in_map The leaflet map to attach to.
*/ */
constructor(in_map) { constructor(in_map, in_device_data) {
this.map = in_map; this.map = in_map;
this.device_data = in_device_data;
this.overlay_config = { this.overlay_config = {
radius: Config.heatmap.blob_radius, radius: Config.heatmap.blob_radius,
@ -101,6 +102,13 @@ class LayerHeatmap {
* @param {object[]} readings_list The array of data points to display. * @param {object[]} readings_list The array of data points to display.
*/ */
set_data(readings_list) { set_data(readings_list) {
// Substitute in the device locations
for(let reading of readings_list) {
let device_info = this.device_data.get_by_id(reading.device_id);
reading.latitude = device_info.latitude;
reading.longitude = device_info.longitude;
}
let data_object = { let data_object = {
max: 0, max: 0,
data: readings_list data: readings_list

View file

@ -9,6 +9,7 @@ import Config from './Config.mjs';
import LayerDeviceMarkers from './LayerDeviceMarkers.mjs'; import LayerDeviceMarkers from './LayerDeviceMarkers.mjs';
import LayerHeatmap from './LayerHeatmap.mjs'; import LayerHeatmap from './LayerHeatmap.mjs';
import LayerHeatmapGlue from './LayerHeatmapGlue.mjs'; import LayerHeatmapGlue from './LayerHeatmapGlue.mjs';
import DeviceData from './DeviceData.mjs';
import UI from './UI.mjs'; import UI from './UI.mjs';
class MapManager { class MapManager {
@ -16,7 +17,7 @@ class MapManager {
console.log(Config); console.log(Config);
} }
setup() { async setup() {
// Create the map // Create the map
this.map = L.map("map", { this.map = L.map("map", {
fullscreenControl: true, fullscreenControl: true,
@ -40,14 +41,16 @@ class MapManager {
this.map.attributionControl.addAttribution("<a href='https://github.com/ConnectedHumber/Air-Quality-Web/'>Air Quality Web</a> by <a href='https://starbeamrainbowlabs.com/'>Starbeamrainbowlabs</a>"); this.map.attributionControl.addAttribution("<a href='https://github.com/ConnectedHumber/Air-Quality-Web/'>Air Quality Web</a> by <a href='https://starbeamrainbowlabs.com/'>Starbeamrainbowlabs</a>");
// Load the device information
this.device_data = new DeviceData();
await this.device_data.setup();
console.log("[map] Device data loaded");
// Add the device markers // Add the device markers
console.info("[map] Loading device markers...."); console.info("[map] Loading device markers....");
this.setup_device_markers().then(() => { this.setup_device_markers()
console.info("[map] Device markers loaded successfully."); .then(() => console.info("[map] Device markers loaded successfully."))
.then(this.setup_layer_control.bind(this));
// Display a layer controller
this.setup_layer_control();
});
// Add the heatmap // Add the heatmap
console.info("[map] Loading heatmap...."); console.info("[map] Loading heatmap....");
@ -59,6 +62,7 @@ class MapManager {
this.ui = new UI(Config, this); this.ui = new UI(Config, this);
this.ui.setup().then(() => console.log("[map] Settings initialised.")); this.ui.setup().then(() => console.log("[map] Settings initialised."));
} }
setup_time_dimension() { setup_time_dimension() {
@ -97,12 +101,12 @@ class MapManager {
} }
async setup_device_markers() { async setup_device_markers() {
this.device_markers = new LayerDeviceMarkers(this.map); this.device_markers = new LayerDeviceMarkers(this.map, this.device_data);
await this.device_markers.setup(); await this.device_markers.setup();
} }
async setup_heatmap() { async setup_heatmap() {
this.heatmap = new LayerHeatmap(this.map); this.heatmap = new LayerHeatmap(this.map, this.device_data);
// TODO: Use leaflet-timedimension here // TODO: Use leaflet-timedimension here
// TODO: Allow configuration of the different reading types here // TODO: Allow configuration of the different reading types here