Implement initial tour.

This commit is contained in:
Starbeamrainbowlabs 2019-06-11 15:35:31 +01:00
parent bc3c631c89
commit fa433c88b0
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
6 changed files with 193 additions and 7 deletions

View file

@ -6,13 +6,16 @@ import 'leaflet.markercluster';
// We're using the git repo for now until an update is released, and rollup doesn't like that apparently
import CreateElement from '../../node_modules/dom-create-element-query-selector/src/index.js';
import tabs from 'tabs';
import Emitter from 'event-emitter-es6';
import Config from './Config.mjs';
import DeviceReadingDisplay from './DeviceReadingDisplay.mjs';
import GetFromUrl from './Helpers/GetFromUrl.mjs';
class LayerDeviceMarkers {
class LayerDeviceMarkers extends Emitter {
constructor(in_map, in_device_data) {
super();
this.map = in_map;
this.device_data = in_device_data;
@ -72,6 +75,8 @@ class LayerDeviceMarkers {
delete device_info.longitude;
event.popup.setContent(this.render_device_info(device_info));
this.emit("marker-popup-opened");
}
render_device_info(device_info) {

View file

@ -63,7 +63,7 @@ class MapManager {
// .then(() => console.info("[map] Time dimension initialised."));
this.ui = new UI(Config, this);
this.ui.setup().then(() => console.log("[map] Settings initialised."));
this.ui.setup().then(() => console.log("[map] UI setup complete."));
}
async setup_overlay() {

155
client_src/js/Tour.mjs Normal file
View file

@ -0,0 +1,155 @@
"use strict";
import Sheperd from 'shepherd.js';
import '../../node_modules/shepherd.js/dist/css/shepherd-theme-default.css';
class Tour {
constructor(in_map_manager) {
this.map_manager = in_map_manager;
}
create_tour() {
this.tour = new Sheperd.Tour({
useModalOverlay: true,
defaultStepOptions: {
// Default settings for steps go here
}
});
this.tour.addStep("welcome", {
text: "Welcome to the air quality web interface! Press next to get a short tour.",
buttons: this.get_buttons(false, true)
});
this.tour.addStep("map", {
text: "Each device has a blue marker. The shape a marker is located in changes colour depending on the value of the measure it reported.",
attachTo: {
element: "#map",
on: "bottom"
},
buttons: this.get_buttons()
});
this.tour.addStep("guage", {
text: "This guage is a key to the colour of the shapes underneath the device markers.",
attachTo: {
element: document.querySelector("#canvas-guage"),
on: "left"
},
buttons: this.get_buttons()
});
this.tour.addStep("reading-type", {
text: "Devices report multiple types of measurement. Change to another reading type now.",
attachTo: {
element: document.querySelector("select").parentNode,
on: "top"
},
advanceOn: { selector: "select", event: "change" },
buttons: this.get_buttons(true)
});
this.tour.addStep("reading-type-complete", {
text: "Hey, the map changed! Some devices only report certain types of measurement, and different measurements have different colour scales.",
attachTo: { element: "#map", on: "bottom" },
buttons: this.get_buttons()
});
this.tour.addStep("layer-showhide", {
text: "You can show and hide the device markers and the heatmap here.",
attachTo: {
element: ".leaflet-control-layers",
on: "left"
},
buttons: this.get_buttons()
});
this.tour.addStep("map-controls", {
text: "You can control the zoom level and go fullscreen here. You can also zoom with your mouse wheel if you have one, and pan by clicking and dragging.",
attachTo: {
element: ".leaflet-top.leaflet-left",
on: "right"
},
buttons: this.get_buttons()
});
this.tour.addStep("device-graph", {
text: "By clicking a blue marker, you can view additional information about that device. Not all device are actively reporting data. Try clicking one now.",
attachTo: {
element: "#map",
on: "top"
},
buttons: this.get_buttons(true)
}).on("show", (() => {
this.map_manager.device_markers.once("marker-popup-opened", this.tour.next.bind(this.tour));
}).bind(this));
this.tour.addStep("device-graph-a", {
text: "This is a device information popup. By default it displays recent data that the device has reported on the line graph, but you can control this with the blue buttons.",
attachTo: {
element: ".popup-device",
on: "right"
},
buttons: this.get_buttons()
});
this.tour.addStep("device-graph-b", {
text: "By clicking here, you can see the specification of the device, including its software, sensor models, exact location, more. Click this now.",
attachTo: {
element: ".tabs :first-child",
on: "left"
},
advanceOn: { selector: ".tabs :first-child a", event: "click" },
buttons: this.get_buttons(true)
});
this.tour.addStep("report-bug", {
text: "If you find a bug, you can report it by clicking this button.",
attachTo: {
element: "button[value='Report bug']",
on: "right"
},
buttons: this.get_buttons()
});
this.tour.addStep("changelog", {
text: "The changelog will be automatically shown every time this web interface updates. Click the version information here to review it again at other times.",
attachTo: {
element: "button[value~='built']",
on: "right"
},
buttons: this.get_buttons()
});
this.tour.addStep("complete", {
text: "Tour complete!\nIf you need any additional assistance, let us know :-)",
buttons: [{ text: "Done", action: this.tour.next }]
});
}
run_once() {
if(!window.localStorage.has("completed_tour"))
this.run();
window.localStorage.setItem("completed_tour", (new Date()).toISOString());
}
run() {
if(typeof this.tour == "undefined")
this.create_tour();
this.tour.start();
}
get_buttons(no_continue = false, no_prev = false) {
let next = { text: "Next", action: this.tour.next },
prev = { text: "Previous", action: this.tour.back },
exit = { text: "Exit", action: this.tour.cancel };
let result = [];
if(!no_prev) result.push(prev);
if(!no_continue) result.push(next);
result.push(exit);
return result;
}
}
export default Tour;

View file

@ -6,6 +6,16 @@ import NanoModal from 'nanomodal';
import Config from './Config.mjs';
import GetFromUrl from './Helpers/GetFromUrl.mjs';
import Tour from './Tour.mjs';
function show_nanomodal(html) {
return new Promise((resolve, _reject) => {
let modal = NanoModal(html);
modal.onHide(resolve);
modal.show();
});
}
async function show_changelog(only_if_changed) {
let current_version = `${Config.version}, built ${Config.build_date.toDateString()}`;
console.log(`[UI] Comparing current '${current_version}' to '${localStorage.getItem("last_seen_version")}'`);
@ -15,9 +25,8 @@ async function show_changelog(only_if_changed) {
}
console.log("[UI] Showing changelog");
NanoModal(
await GetFromUrl(`${Config.api_root}?action=changelog`)
).show();
await show_nanomodal(await GetFromUrl(`${Config.api_root}?action=changelog`));
localStorage.setItem("last_seen_version", current_version);
return true;
}
@ -29,6 +38,8 @@ class UI {
this.ui_panel = new SmartSettings("Settings");
// this.ui_panel.watch((event) => console.log(event));
this.tour = new Tour(this.map_manager);
}
async setup() {
@ -64,7 +75,9 @@ class UI {
]);
this.ui_panel.setIndex("Reading Type", this.reading_types.findIndex((type) => type.short_descr == "PM25"));
await show_changelog(true);
await this.tour.run();
}
}

13
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "air-quality-mapper",
"version": "0.9.1",
"version": "0.10.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -48,6 +48,12 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
"@types/event-emitter-es6": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@types/event-emitter-es6/-/event-emitter-es6-1.1.0.tgz",
"integrity": "sha512-A0010GUMSopVYUlDdzhYAD8Z2qGC2hG2H32IHy554NpGEHmsx8M6/lLZRRqxXCxLq28aYrmaZtGwDJjeNXbTDQ==",
"dev": true
},
"@types/geojson": {
"version": "7946.0.7",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
@ -1120,6 +1126,11 @@
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
"event-emitter-es6": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/event-emitter-es6/-/event-emitter-es6-1.1.5.tgz",
"integrity": "sha1-75UxGy4Xqjm+djsDHOSvfunLeEk="
},
"expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",

View file

@ -1,6 +1,6 @@
{
"name": "air-quality-mapper",
"version": "0.10",
"version": "0.10.0",
"description": "The web interface and JSON api for the ConnectedHumber Air Quality Monitoring Project.",
"private": true,
"main": "index.mjs",
@ -22,6 +22,7 @@
"chroma-js": "^2.0.3",
"d3-delaunay": "^4.1.5",
"dom-create-element-query-selector": "github:hekigan/dom-create-element-query-selector",
"event-emitter-es6": "^1.1.5",
"iso8601-js-period": "^0.2.1",
"leaflet": "^1.5.1",
"leaflet-fullscreen": "^1.0.2",
@ -37,6 +38,7 @@
"@types/chart.js": "^2.7.53",
"@types/chroma-js": "^1.4.1",
"@types/d3-delaunay": "^4.1.0",
"@types/event-emitter-es6": "^1.1.0",
"@types/leaflet": "^1.4.4",
"@types/leaflet-fullscreen": "^1.0.4",
"nightdocs": "^1.0.5",