2018-06-30 16:20:54 +02:00
|
|
|
|
|
|
|
import * as domlib from '../domlib';
|
|
|
|
import * as gui from '../gui';
|
|
|
|
import * as socket from '../socket';
|
|
|
|
import * as store from '../store';
|
|
|
|
import config from '../config';
|
|
|
|
import View from '../view';
|
|
|
|
import {singelton as notify} from '../element/notify';
|
|
|
|
import {FromNowAgo} from '../lib';
|
|
|
|
//import '../../node_modules/leaflet/dist/leaflet.js';
|
|
|
|
//import '../../node_modules/leaflet-ajax/dist/leaflet.ajax.min.js';
|
|
|
|
//import '../../node_modules/moment/min/moment.min.js';
|
|
|
|
|
|
|
|
export class NodeView extends View {
|
|
|
|
|
|
|
|
constructor () {
|
|
|
|
super();
|
|
|
|
|
|
|
|
const title = domlib.newAt(this.el, 'h1'),
|
|
|
|
lastseen = domlib.newAt(this.el, 'p'),
|
|
|
|
hostname = domlib.newAt(this.el, 'p'),
|
|
|
|
owner = domlib.newAt(this.el, 'p'),
|
|
|
|
mapEl = domlib.newAt(this.el, 'div');
|
|
|
|
|
2018-07-21 18:46:19 +02:00
|
|
|
this.currentNodeIsRendered = false;
|
|
|
|
|
2018-06-30 16:20:54 +02:00
|
|
|
this.titleName = domlib.newAt(title, 'span');
|
|
|
|
title.appendChild(document.createTextNode(' - '));
|
|
|
|
this.titleID = domlib.newAt(title, 'i');
|
|
|
|
|
|
|
|
|
|
|
|
domlib.newAt(lastseen, 'span').innerHTML = 'Lastseen: ';
|
|
|
|
this.ago = domlib.newAt(lastseen, 'span');
|
|
|
|
|
|
|
|
domlib.newAt(hostname, 'span').innerHTML = 'Hostname: ';
|
|
|
|
this.hostnameInput = domlib.newAt(hostname, 'input');
|
|
|
|
this.hostnameInput.setAttribute('placeholder', 'Hostname');
|
|
|
|
this.hostnameInput.addEventListener('focusin', () => {
|
|
|
|
this.editing = true;
|
|
|
|
});
|
|
|
|
this.hostnameInput.addEventListener('focusout', () => {
|
|
|
|
this.editing = false;
|
|
|
|
|
2018-07-15 21:09:39 +02:00
|
|
|
const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID),
|
|
|
|
localNodeCopy = Object.assign({}, node);
|
2018-06-30 16:20:54 +02:00
|
|
|
|
2018-07-15 21:09:39 +02:00
|
|
|
localNodeCopy.hostname = this.hostnameInput.value;
|
|
|
|
socket.sendnode(localNodeCopy);
|
2018-06-30 16:20:54 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
domlib.newAt(owner, 'span').innerHTML = 'Owner: ';
|
|
|
|
this.ownerInput = domlib.newAt(owner, 'input');
|
|
|
|
this.ownerInput.setAttribute('placeholder', 'Owner');
|
|
|
|
this.ownerInput.addEventListener('focusin', () => {
|
|
|
|
this.editing = true;
|
|
|
|
});
|
|
|
|
this.ownerInput.addEventListener('focusout', () => {
|
|
|
|
this.editing = false;
|
|
|
|
|
2018-07-15 21:09:39 +02:00
|
|
|
const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID),
|
|
|
|
localNodeCopy = Object.assign({}, node);
|
2018-06-30 16:20:54 +02:00
|
|
|
|
2018-07-15 21:09:39 +02:00
|
|
|
localNodeCopy.owner = this.ownerInput.value;
|
|
|
|
socket.sendnode(localNodeCopy);
|
2018-06-30 16:20:54 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
mapEl.style.height = '300px';
|
|
|
|
|
|
|
|
this.map = L.map(mapEl).setView(config.map.view.bound, config.map.view.zoom);
|
|
|
|
|
|
|
|
L.tileLayer(config.map.tileLayer, {
|
|
|
|
'maxZoom': config.map.maxZoom
|
|
|
|
}).addTo(this.map);
|
|
|
|
|
|
|
|
this.geoJsonLayer = L.geoJson.ajax(config.map.geojson.url,
|
|
|
|
config.map.geojson);
|
|
|
|
this.geoJsonLayer.addTo(this.map);
|
|
|
|
|
|
|
|
this.marker = L.marker(config.map.view.bound, {'draggable': true,
|
|
|
|
'opacity': 0.5}).addTo(this.map);
|
|
|
|
|
|
|
|
this.marker.on('dragstart', () => {
|
|
|
|
this.editing = true;
|
|
|
|
});
|
|
|
|
|
|
|
|
this.marker.on('dragend', () => {
|
|
|
|
this.editing = false;
|
|
|
|
const pos = this.marker.getLatLng();
|
|
|
|
|
|
|
|
this.updatePosition(pos.lat, pos.lng);
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.btnGPS = domlib.newAt(this.el, 'span');
|
2018-07-19 22:53:30 +02:00
|
|
|
if (navigator.geolocation) {
|
|
|
|
this.btnGPS.classList.add('btn');
|
|
|
|
this.btnGPS.innerHTML = 'Start follow position';
|
|
|
|
this.btnGPS.addEventListener('click', () => {
|
|
|
|
if (this.editLocationGPS != null) {
|
|
|
|
if (this.gpsPosition) {
|
|
|
|
this.updatePosition(this.gpsPosition.latitude, this.gpsPosition.longitude);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.gpsStatusText.innerHTML = "";
|
|
|
|
}
|
|
|
|
this.btnGPS.innerHTML = 'Start follow position';
|
|
|
|
navigator.geolocation.clearWatch(this.editLocationGPS);
|
|
|
|
this.editLocationGPS = null;
|
|
|
|
return;
|
2018-07-16 19:02:11 +02:00
|
|
|
}
|
2018-07-19 22:53:30 +02:00
|
|
|
|
|
|
|
this.gpsPosition = null;
|
|
|
|
this.btnGPS.innerHTML = 'Stop following';
|
|
|
|
this.gpsStatusText.innerHTML = "waiting for location...";
|
2018-06-30 16:20:54 +02:00
|
|
|
this.editLocationGPS = navigator.geolocation.watchPosition((position) => {
|
2018-07-16 19:02:11 +02:00
|
|
|
this.gpsStatusText.innerHTML = "GPS location at " +
|
|
|
|
new Date(position.timestamp).toLocaleTimeString() + ": " +
|
|
|
|
position.coords.latitude.toFixed(5) + " / " +
|
|
|
|
position.coords.longitude.toFixed(5);
|
|
|
|
|
2018-07-15 23:23:56 +02:00
|
|
|
this.gpsPosition = position.coords;
|
2018-06-30 16:20:54 +02:00
|
|
|
const latlng = [position.coords.latitude, position.coords.longitude];
|
|
|
|
|
|
|
|
this.marker.setLatLng(latlng);
|
|
|
|
this.map.setView(latlng);
|
|
|
|
}, (error) => {
|
|
|
|
switch (error.code) {
|
|
|
|
case error.TIMEOUT:
|
|
|
|
notify.send('error', 'Find Location timeout');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.error('a navigator geolocation error: ', error);
|
|
|
|
}
|
|
|
|
},
|
2018-07-19 22:53:30 +02:00
|
|
|
{
|
|
|
|
'enableHighAccuracy': true,
|
|
|
|
'maximumAge': 30000,
|
|
|
|
'timeout': 27000
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.btnGPS.innerHTML = '(Browser does not support geo-location)';
|
|
|
|
}
|
2018-07-16 19:02:11 +02:00
|
|
|
this.gpsStatusText = domlib.newAt(this.el, 'span');
|
|
|
|
this.gpsStatusText.classList.add('withTextMargins');
|
2018-07-21 19:43:26 +02:00
|
|
|
|
|
|
|
this.resetLocationBtn = domlib.newAt(this.el, 'span');
|
|
|
|
this.resetLocationBtn.classList.add('btn');
|
|
|
|
this.resetLocationBtn.innerHTML = 'Reset Location';
|
|
|
|
this.resetLocationBtn.addEventListener('click', () => {
|
2018-07-22 21:40:13 +02:00
|
|
|
if (confirm("Reset location of this node?")) {
|
|
|
|
const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID),
|
|
|
|
localNodeCopy = Object.assign({}, node);
|
|
|
|
|
|
|
|
localNodeCopy.location = null;
|
|
|
|
this.currentNodeIsRendered = false;
|
|
|
|
socket.sendnode(localNodeCopy);
|
|
|
|
}
|
2018-07-21 19:43:26 +02:00
|
|
|
});
|
2018-06-30 16:20:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
updatePosition (lat, lng) {
|
2018-07-15 21:09:39 +02:00
|
|
|
const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID),
|
|
|
|
localNodeCopy = Object.assign({}, node),
|
2018-07-15 23:23:56 +02:00
|
|
|
newLat = lat || this.gpsPosition.latitude || false,
|
|
|
|
newlng = lng || this.gpsPosition.longitude || false;
|
2018-06-30 16:20:54 +02:00
|
|
|
|
|
|
|
if (!newLat || !newlng) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-15 21:09:39 +02:00
|
|
|
localNodeCopy.location = {
|
2018-06-30 16:20:54 +02:00
|
|
|
'latitude': newLat,
|
|
|
|
'longitude': newlng
|
|
|
|
};
|
2018-07-15 21:09:39 +02:00
|
|
|
socket.sendnode(localNodeCopy);
|
2018-06-30 16:20:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
|
|
|
this.geoJsonLayer.refresh();
|
|
|
|
this.titleID.innerHTML = this.currentNodeID;
|
2018-07-15 21:09:39 +02:00
|
|
|
const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID),
|
2018-06-30 16:20:54 +02:00
|
|
|
startdate = new Date();
|
|
|
|
|
|
|
|
if (!node) {
|
2018-07-15 21:09:39 +02:00
|
|
|
console.log(`internal error: node not found: ${this.currentNodeID}`);
|
2018-06-30 16:20:54 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
startdate.setMinutes(startdate.getMinutes() - config.node.offline);
|
|
|
|
if (new Date(node.lastseen) < startdate) {
|
|
|
|
this.ago.classList.add('offline');
|
|
|
|
this.ago.classList.remove('online');
|
|
|
|
} else {
|
|
|
|
this.ago.classList.remove('offline');
|
|
|
|
this.ago.classList.add('online');
|
|
|
|
}
|
|
|
|
this.ago.innerHTML = `${FromNowAgo(node.lastseen)} (${node.lastseen})`;
|
2018-07-15 22:16:23 +02:00
|
|
|
|
2018-06-30 16:20:54 +02:00
|
|
|
this.titleName.innerHTML = node.hostname;
|
|
|
|
|
2018-07-15 22:16:23 +02:00
|
|
|
if (!this.editing) { // don't change input fields while user is editing
|
|
|
|
this.hostnameInput.value = node.hostname;
|
|
|
|
this.ownerInput.value = node.owner;
|
2018-06-30 16:20:54 +02:00
|
|
|
|
2018-07-15 22:46:37 +02:00
|
|
|
if (this.editLocationGPS == null && node.location && node.location.latitude && node.location.longitude) {
|
2018-07-15 22:16:23 +02:00
|
|
|
// eslint-disable-next-line one-var
|
|
|
|
const latlng = [node.location.latitude, node.location.longitude];
|
|
|
|
|
|
|
|
this.map.setView(latlng);
|
|
|
|
this.marker.setLatLng(latlng);
|
|
|
|
this.marker.setOpacity(1);
|
|
|
|
this.map.invalidateSize();
|
2018-07-21 18:46:19 +02:00
|
|
|
this.currentNodeIsRendered = true;
|
2018-07-15 22:16:23 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-21 18:46:19 +02:00
|
|
|
|
|
|
|
if (!this.currentNodeIsRendered) {
|
|
|
|
this.map.setView(config.map.view.bound);
|
|
|
|
this.marker.setLatLng(config.map.view.bound);
|
|
|
|
this.marker.setOpacity(0.5);
|
|
|
|
this.map.invalidateSize();
|
|
|
|
this.currentNodeIsRendered = true;
|
|
|
|
}
|
2018-06-30 16:20:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
setNodeID (nodeID) {
|
|
|
|
this.currentNodeID = nodeID;
|
2018-07-21 18:46:19 +02:00
|
|
|
this.currentNodeIsRendered = false;
|
2018-06-30 16:20:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|