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'); this.currentNodeIsRendered = false; 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; const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID), localNodeCopy = Object.assign({}, node); localNodeCopy.hostname = this.hostnameInput.value; socket.sendnode(localNodeCopy); }); 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; const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID), localNodeCopy = Object.assign({}, node); localNodeCopy.owner = this.ownerInput.value; socket.sendnode(localNodeCopy); }); 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'); 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; } this.gpsPosition = null; this.btnGPS.innerHTML = 'Stop following'; this.gpsStatusText.innerHTML = "waiting for location..."; this.editLocationGPS = navigator.geolocation.watchPosition((position) => { this.gpsStatusText.innerHTML = "GPS location at " + new Date(position.timestamp).toLocaleTimeString() + ": " + position.coords.latitude.toFixed(5) + " / " + position.coords.longitude.toFixed(5); this.gpsPosition = position.coords; 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); } }, { 'enableHighAccuracy': true, 'maximumAge': 30000, 'timeout': 27000 }); }); } else { this.btnGPS.innerHTML = '(Browser does not support geo-location)'; } this.gpsStatusText = domlib.newAt(this.el, 'span'); this.gpsStatusText.classList.add('withTextMargins'); this.resetLocationBtn = domlib.newAt(this.el, 'span'); this.resetLocationBtn.classList.add('btn'); this.resetLocationBtn.innerHTML = 'Reset Location'; this.resetLocationBtn.addEventListener('click', () => { 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); } }); } updatePosition (lat, lng) { const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID), localNodeCopy = Object.assign({}, node), newLat = lat || this.gpsPosition.latitude || false, newlng = lng || this.gpsPosition.longitude || false; if (!newLat || !newlng) { return; } localNodeCopy.location = { 'latitude': newLat, 'longitude': newlng }; socket.sendnode(localNodeCopy); } render () { this.geoJsonLayer.refresh(); this.titleID.innerHTML = this.currentNodeID; const node = store.getNode(this.currentNodeID) || store.createNode(this.currentNodeID), startdate = new Date(); if (!node) { console.log(`internal error: node not found: ${this.currentNodeID}`); 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})`; this.titleName.innerHTML = node.hostname; if (!this.editing) { // don't change input fields while user is editing this.hostnameInput.value = node.hostname; this.ownerInput.value = node.owner; if (this.editLocationGPS == null && node.location && node.location.latitude && node.location.longitude) { // 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(); this.currentNodeIsRendered = true; } } 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; } } setNodeID (nodeID) { this.currentNodeID = nodeID; this.currentNodeIsRendered = false; } }