WIP WIP prepared for Geiger
This commit is contained in:
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/bin/www.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -36,6 +36,12 @@ app.use(i18nextMiddleware.handle(i18next));
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'pug');
|
||||
|
||||
app.get('*', (req, res, next) => {
|
||||
const subdom = req.headers.host.split('.')
|
||||
app.set('category',subdom[0])
|
||||
next()
|
||||
})
|
||||
|
||||
app.use(logger('dev'));
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
|
||||
@@ -24,7 +24,7 @@ export const liveData = (params, values, req) => {
|
||||
let cnt = 0
|
||||
values.forEach((x) => {
|
||||
let dat = new Date(x.datetime).getTime()
|
||||
iu series1.push([dat, x.values.noise_LAeq])
|
||||
series1.push([dat, x.values.noise_LAeq])
|
||||
series2.push([dat, x.values.noise_LA_max])
|
||||
series3.push([dat, x.values.noise_LA_min]) // put data and value into series array
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"NoiseMeasurement": "Lärm-Messung",
|
||||
"GeigerMeasurement": "Radioactivitäts-Messung",
|
||||
"Settings": "Einstellungen",
|
||||
"Info": "Info",
|
||||
"StartDate": "Start Datum",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"NoiseMeasurement": "Noise Measurement",
|
||||
"GeigerMeasurement": "Radioactivity Measurement",
|
||||
"Settings": "Settings",
|
||||
"Info": "Info",
|
||||
"StartDate": "Start date",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -11,10 +11,10 @@ let optSidsArray = []; // Arrray der letzten 5 Einträge
|
||||
let nbrofdaysforavg = 8; // Stundenmittel Anzahl Tagte (default = 5)
|
||||
let nbrofdaysfordaynight = 30; // use 30 days or day/night graphic
|
||||
let stucols = 1; // Anzeige nur Balken (StundenMittel)
|
||||
let activeTab = 'maptab'; // active TAB ID
|
||||
|
||||
export const noise_ymin = 30; // lowest value on y-axis for noise
|
||||
export const noise_ymax = 120; // highest value on y-axis for noise
|
||||
let activeTab = 'maptab'; // active TAB ID
|
||||
export let peaklim = 70; // threshold for peak count
|
||||
|
||||
export const url = '/api'
|
||||
@@ -164,7 +164,7 @@ export async function addSensorID2chart(chart, sensor, width) {
|
||||
let indoor = sensor.indoor || false
|
||||
let addr = await addAddress(sensor.sid)
|
||||
let sens = chart.renderer.label(
|
||||
`Sensor: <span class="bigger">${sensor.sid}</span> ${indoor ? ' (indoor)' : ''} ${addr}`,
|
||||
`Sensor: <span class="bigger">${sensor.sid}</span> ${indoor ? ' (indoor)' : ''} ${addr.street}, ${addr.plz} ${addr.city}`,
|
||||
width / 2 - 100, 65,
|
||||
'text', 0, 0, true)
|
||||
.css({
|
||||
@@ -177,7 +177,8 @@ export async function addSensorID2chart(chart, sensor, width) {
|
||||
}
|
||||
|
||||
export const showError = (err) => {
|
||||
document.querySelector('#dialogError .modal-dialog .modal-content .modal-body').setHTML(err)
|
||||
let e = document.querySelector('#dialogError .modal-dialog .modal-content .modal-body')
|
||||
e.innerHTML = err
|
||||
let myModal = new bootstrap.Modal(document.getElementById('dialogError'))
|
||||
myModal.show()
|
||||
}
|
||||
|
||||
Vendored
+2
File diff suppressed because one or more lines are too long
+32
-248
@@ -3,267 +3,51 @@
|
||||
import * as dt from './datetime.js'
|
||||
import * as utils from "./chart_utilities.js"
|
||||
import { showChart, loadAll } from './showcharts.js'
|
||||
import {fetchfromserver, addAddress} from "./chart_utilities.js";
|
||||
import * as mapn from './map_noise.js'
|
||||
import * as mapg from './map_geiger.js'
|
||||
import * as mapu from './map_utilities.js'
|
||||
|
||||
let map = null
|
||||
let bounds
|
||||
let popuptext = ''
|
||||
let clickedSensor = 0
|
||||
let clickedcoords = {}
|
||||
|
||||
const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080'];
|
||||
const dba = [100, 80, 60, 40, 20, 0, -999];
|
||||
const APIURL = '/api/getmapdata?'
|
||||
const mapparams = {
|
||||
map: null,
|
||||
bounds: null,
|
||||
popuptext: '',
|
||||
clickedSensor: 0,
|
||||
APIURL: '/api/getmapdata?',
|
||||
MAXZOOM: 19
|
||||
}
|
||||
|
||||
export async function showMap(params) {
|
||||
if(sysparams.category === 'laerm') {
|
||||
utils.removeTabs()
|
||||
if(map && map.remove) {
|
||||
map.off();
|
||||
map.remove();
|
||||
if(mapparams.map && mapparams.map.remove) {
|
||||
mapparams.map.off();
|
||||
mapparams.map.remove();
|
||||
}
|
||||
map = L.map('map', {scrollWheelZoom: false}).setView(params.center, parseInt(params.zoom))
|
||||
}
|
||||
mapparams.map = L.map('map', {scrollWheelZoom: false}).setView(params.center, parseInt(params.zoom))
|
||||
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
maxZoom: mapparams.MAXZOOM,
|
||||
attribution: '© <a href="http://www.js.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
}).addTo(map)
|
||||
bounds = map.getBounds();
|
||||
}).addTo(mapparams.map)
|
||||
mapparams.bounds = mapparams.map.getBounds();
|
||||
|
||||
map.on('moveend', async function () {
|
||||
bounds = map.getBounds()
|
||||
await buildMarkers(params)
|
||||
mapparams.map.on('moveend', async function () {
|
||||
mapparams.bounds = mapparams.map.getBounds()
|
||||
await buildMarkers(params, mapparams)
|
||||
});
|
||||
|
||||
let legend = L.control({position: 'bottomright'})
|
||||
legend.onAdd = function (map) {
|
||||
let div = L.DomUtil.create('div', 'info legend')
|
||||
let div_color = L.DomUtil.create('div', 'info legend inner', div)
|
||||
div_color.innerHTML += 'dbA<br />';
|
||||
// loop through our density intervals and generate a label with a colored square for each interval
|
||||
for (let i = 0; i < dba.length - 1; i++) {
|
||||
div_color.innerHTML +=
|
||||
'<i style="background:' + colorscale[i] + '"></i>' +
|
||||
' ' + dba[i] + (i == 0 ? '+' : '') + '<br />'
|
||||
if(sysparams.category === 'laerm') {
|
||||
mapn.buildLegend(mapparams)
|
||||
}
|
||||
div_color.innerHTML += ' <i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline'
|
||||
return div
|
||||
};
|
||||
legend.addTo(map)
|
||||
|
||||
let lastdate = await buildMarkers(params)
|
||||
showLastDate(lastdate);
|
||||
let lastdate = await buildMarkers(params, mapparams)
|
||||
mapu.showLastDate(lastdate, mapparams);
|
||||
}
|
||||
|
||||
|
||||
function getColor(d) {
|
||||
let val = parseInt(d);
|
||||
for (let i = 0; i < dba.length; i++) {
|
||||
if (val >= dba[i]) {
|
||||
return (colorscale[i]);
|
||||
}
|
||||
const buildMarkers = async (params, mapparams) => {
|
||||
if(sysparams.category === 'laerm') {
|
||||
return mapn.buildMarkers(params, mapparams)
|
||||
} else if(sysparams.category === 'multigeiger') {
|
||||
return mapg.buildMarkers(params, mapparams)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function calcPolygon(bounds) {
|
||||
return L.polygon([[bounds.getNorth(), bounds.getWest()], [bounds.getNorth(), bounds.getEast()], [bounds.getSouth(), bounds.getEast()], [bounds.getSouth(), bounds.getWest()]], {
|
||||
color: 'black',
|
||||
fillOpacity: 0.5
|
||||
});
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
// With all Markers in cluster (markers) calculate the median
|
||||
// of the values. With this median fetch the color and return it.
|
||||
// If there are 'offline' sensors (value == -1) strip then before
|
||||
// calculating the median. If there are only offline sensor, return
|
||||
// color of value==-1 (dark gray).
|
||||
function getMedian(markers) {
|
||||
markers.sort(function (a, b) { // first sort, the lowest first
|
||||
let y1 = a.options.value;
|
||||
let y2 = b.options.value;
|
||||
if (y1 < y2) {
|
||||
return -1;
|
||||
}
|
||||
if (y2 < y1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
// console.log(markers);
|
||||
let i = 0; // now find the 'offlines' (value == -1)
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
if (markers[i].options.value > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
markers.splice(0, i); // remove these from array
|
||||
let lang = markers.length;
|
||||
if (lang > 1) { //
|
||||
if ((lang % 2) == 1) { // uneven ->
|
||||
return getColor(markers[(Math.floor(lang / 2))].options.value); // median is in the middle
|
||||
} else { // evaen ->
|
||||
lang = lang / 2; // median is mean of both middle values
|
||||
// console.log(lang);
|
||||
let wert = (markers[lang - 1].options.value +
|
||||
markers[lang].options.value) / 2;
|
||||
return getColor(wert);
|
||||
}
|
||||
} else if (lang == 1) { // only one marker -> return its color
|
||||
return getColor(markers[0].options.value);
|
||||
}
|
||||
return getColor(-1); // only offlines
|
||||
}
|
||||
|
||||
|
||||
function buildIcon(color, n, indoor) {
|
||||
let x = 100;
|
||||
if (n < 10) {
|
||||
x = 200;
|
||||
} else if (n < 100) {
|
||||
x = 150;
|
||||
}
|
||||
let txtColor = "black";
|
||||
if (color == colorscale[5]) {
|
||||
txtColor = "white"
|
||||
}
|
||||
let circIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
|
||||
'<circle cx="300" cy="300" r="250" fill="' + color + '" stroke="black" stroke-width="20" />';
|
||||
if (n !== 0) {
|
||||
circIcon +=
|
||||
'<text id="marker_text" x="' + x + '" ' +
|
||||
'y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" ' +
|
||||
'fill="' + txtColor + '">' + n + '</text>';
|
||||
}
|
||||
if(indoor) {
|
||||
circIcon += '<line x1="125" y1="475" x2="475" y2="125" stroke="black" stroke-width="20" />'
|
||||
}
|
||||
circIcon += '</svg>';
|
||||
let circIconUrl = encodeURI("data:image/svg+xml," + circIcon).replace(new RegExp('#', 'g'), '%23');
|
||||
return circIconUrl;
|
||||
}
|
||||
|
||||
|
||||
export async function buildMarkers(params) {
|
||||
// debug_log('buildMarkers(bounds)');
|
||||
const box = {
|
||||
west: bounds.getWest(), south: bounds.getSouth(),
|
||||
east: bounds.getEast(), north: bounds.getNorth()
|
||||
}
|
||||
const url = APIURL + `type=noise&box=${bounds.toBBoxString()}`
|
||||
let sensors = await fetchfromserver(url)
|
||||
if (!sensors.err) {
|
||||
let markers = L.markerClusterGroup({
|
||||
spiderfyOnMaxZoom: true,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: true,
|
||||
// disableClusteringAtZoom: 14,
|
||||
iconCreateFunction: function (cluster) {
|
||||
let mymarkers = cluster.getAllChildMarkers();
|
||||
let color = getMedian(mymarkers);
|
||||
return new L.Icon({
|
||||
iconUrl: buildIcon(color, cluster.getChildCount(), 0),
|
||||
iconSize: [35, 35]
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
for (let x of sensors.values) {
|
||||
if ((params.weeks > 0) && (x.weeks > params.weeks))
|
||||
continue
|
||||
// if (x.value <= -4) {
|
||||
// continue
|
||||
// }
|
||||
let marker = L.marker([x.location[1], x.location[0]], {
|
||||
icon: new L.Icon({
|
||||
iconUrl: buildIcon(getColor(parseInt(x.value)), 0, x.indoor),
|
||||
iconSize: [35, 35],
|
||||
}),
|
||||
name: x.id,
|
||||
value: x.value,
|
||||
url: '/graph?sid=' + x.id,
|
||||
lastseen: dt.formatISODate(x.lastseen),
|
||||
indoor: x.indoor
|
||||
})
|
||||
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params)) // define click- and
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
map.addLayer(markers);
|
||||
return sensors.lastdate
|
||||
} else {
|
||||
utils.showError(sensors.err)
|
||||
}
|
||||
}
|
||||
|
||||
async function bauPopupText(item, txts) {
|
||||
let addr = await addAddress(item.name)
|
||||
let offlinetext = `
|
||||
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
|
||||
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
|
||||
|
||||
let normaltext = `
|
||||
<tr></tr><tr><td>LA_max:</td><td>${item.value}</td></tr>`
|
||||
|
||||
let popuptext = `
|
||||
<div id="infoTitle">
|
||||
<h4>${txts.sensor}: ${item.name}</h4>
|
||||
<div class="addr">${addr}</div>
|
||||
<div id="infoTable">
|
||||
<table>
|
||||
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
|
||||
${item.value < 0 ? offlinetext : normaltext}
|
||||
</table>
|
||||
<div id="infoBtn">
|
||||
<a href="#" class="speciallink">${txts.showchart}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return popuptext
|
||||
}
|
||||
|
||||
async function onMarkerClick(e, click, txts, params) {
|
||||
let item = e.target.options;
|
||||
let popuptext = await bauPopupText(item, txts)
|
||||
e.target.bindPopup(popuptext).openPopup(); // show the popup
|
||||
let link = document.querySelector('.speciallink')
|
||||
link.addEventListener('click', async function (ev) {
|
||||
console.log(`Event clicked: ${clickedSensor}`)
|
||||
params.sid = item.name
|
||||
let ok = await showChart(params, 'live', 'dlive')
|
||||
if (ok) {
|
||||
let triggerEl = document.querySelector(`#livetab`)
|
||||
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
|
||||
utils.setCurrentTab('livetab')
|
||||
params.center = [e.latlng.lat, e.latlng.lng]
|
||||
map.setView([e.latlng.lat, e.latlng.lng]);
|
||||
ev.preventDefault()
|
||||
await loadAll(params)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// add address to PopUp
|
||||
/*
|
||||
async function getCoords(city) {
|
||||
let url = NOMINATIM_URL + city;
|
||||
const response = await axios.get(encodeURI(url));
|
||||
const data = response.data;
|
||||
return data[0];
|
||||
}
|
||||
|
||||
// Map auf Stadt setzen
|
||||
async function setCenter(adr) {
|
||||
let data = await getCoords(adr);
|
||||
map.setView([parseFloat(data.lat), parseFloat(data.lon)]);
|
||||
console.log(data);
|
||||
}
|
||||
*/
|
||||
|
||||
// Show the last date below tha map grafics
|
||||
async function showLastDate(ld) {
|
||||
const url = APIURL + 'type=noise'
|
||||
let sensors = await fetchfromserver(url)
|
||||
document.querySelector('#mapdate').innerText = `${sensors.valfromtxt} ${dt.formatISODate(ld).slice(0,-3)}`
|
||||
document.querySelector('#actsensors').innerText = `${sensors.actsensors} ${sensors.registered}`
|
||||
// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
import * as dt from './datetime.js'
|
||||
import * as utils from "./chart_utilities.js"
|
||||
import { showChart, loadAll } from './showcharts.js'
|
||||
import * as mapu from './map_utilities.js'
|
||||
|
||||
const colorscale = ['#d73027','#fc8d59','#fee08b','#ffffbf','#d9ef8b','#91cf60','#1a9850', '#808080'];
|
||||
const grades = [ 10, 5, 2, 1, 0.5, 0.2, 0.1, -999];
|
||||
const cpms = [1482, 741, 296, 148, 74, 30, 15, -999];
|
||||
|
||||
const sv_factor = {'SBM-20': 1 / 2.47, 'SBM-19': 1 / 9.81888, 'Si22G': 0.081438};
|
||||
|
||||
let showOnlySi22G = false;
|
||||
|
||||
export function getColor(d) {
|
||||
let erg = d3.scaleLinear()
|
||||
.domain([0.05, 0.1, 0.2, 0.5, 5])
|
||||
.range(["#267A45", "#66FA5F", "#F8Fc00","#FF0000","#9000FF"])
|
||||
.clamp(true);
|
||||
return d < -1 ? '#9ECDEA' : d==-1 ? '#7F7F7F' : d==0 ? '#333333' : erg(d);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************
|
||||
* buildMarkers
|
||||
*
|
||||
* fetch data for MArkers from 'mapdata' and create
|
||||
* all the markers, that are visibile within bounds
|
||||
* and plot them on the map.
|
||||
* Use the ClusterGroup-Library to cluster the markers
|
||||
*
|
||||
* params:
|
||||
* bounds find markers within this bounds
|
||||
* return:
|
||||
* all markers plotted on map
|
||||
*******************************************************/
|
||||
export async function buildMarkers(params, mpp) {
|
||||
const url = mpp.APIURL + `type=radioactivity&box=${mpp.bounds.toBBoxString()}`
|
||||
let sensors = await utils.fetchfromserver(url)
|
||||
if (!sensors.err) {
|
||||
// if (markersAll) {
|
||||
// mpp.map.removeLayer(markersAll);
|
||||
// }
|
||||
let markers = L.markerClusterGroup({
|
||||
spiderfyOnMaxZoom: true,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: true,
|
||||
// disableClusteringAtZoom: 14,
|
||||
iconCreateFunction: function (cluster) {
|
||||
let mymarkers = cluster.getAllChildMarkers();
|
||||
let color = getMedian(mymarkers); // calc median of markers in cluster and use that color
|
||||
// return L.divIcon({ html: '<b>' + cluster.getChildCount() + '</b>' });
|
||||
return new L.Icon({
|
||||
iconUrl: buildIcon(color, cluster.getChildCount()),
|
||||
iconSize: [35, 35]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
for (let x of sensors.values) {
|
||||
if (x.location == undefined) { // if there is no location defined ...
|
||||
continue; // ... skip this sensor
|
||||
} // otherwise create marker
|
||||
if ((x.name != "Radiation Si22G") && showOnlySi22G) {
|
||||
continue;
|
||||
}
|
||||
if ((params.weeks > 0) && (x.weeks > params.weeks)) {
|
||||
continue
|
||||
}
|
||||
let uSvph = x.value < 0 ? -1 : x.value / 60 * sv_factor[x.name.slice(10)];
|
||||
let curcolor = getColor(uSvph > 0 ? x.indoor ? -2 : uSvph : uSvph);
|
||||
|
||||
let marker = L.marker([x.location[1], x.location[0]], {
|
||||
name: x.id,
|
||||
icon: new L.Icon({
|
||||
iconUrl: buildIcon(curcolor),
|
||||
iconSize: [35, 35]
|
||||
}),
|
||||
value: x.value,
|
||||
mSvph: uSvph,
|
||||
url: '/' + x.id,
|
||||
rohr: x.name.slice(10),
|
||||
indoor: x.indoor,
|
||||
lastseen: dt.formatISODate(x.lastseen)
|
||||
})
|
||||
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params, mpp)) // define click- and
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
mpp.map.addLayer(markers);
|
||||
return sensors.lastdate
|
||||
} else {
|
||||
utils.showError(sensors.err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
let pos = map.latLngToLayerPoint(marker.getLatLng()).round();
|
||||
|
||||
marker.setZIndexOffset(100 - pos.y);
|
||||
// if clicked on the marker fill popup with address and click function
|
||||
marker.on('click', async function () {
|
||||
let addr = await holAddress(marker);
|
||||
marker.setPopupContent((getPopUp(marker,addr)));
|
||||
$('#btnshwgrafic').click(() => {
|
||||
map.closePopup();
|
||||
// if(window.matchMedia("(orientation:portrait").matches) {
|
||||
// showError(5,"goto Landscape")
|
||||
// } else {
|
||||
showGrafik(clickedSensor);
|
||||
// }
|
||||
});
|
||||
});
|
||||
marker.bindPopup(`Loading adresse data`); // and bind the popup text
|
||||
if (marker.options.value != -2) {
|
||||
markersAll.addLayer(marker);
|
||||
} else {
|
||||
console.log(`Too old Sensor: ${marker.options.name}`);
|
||||
}
|
||||
}
|
||||
mpp.map.addLayer(markersAll);
|
||||
}
|
||||
*/
|
||||
|
||||
function buildIcon(color, n, indoor) {
|
||||
let x = 100;
|
||||
if (n < 10) {
|
||||
x = 200;
|
||||
} else if (n < 100) {
|
||||
x = 150;
|
||||
}
|
||||
let txtColor = "black";
|
||||
if (color == colorscale[5]) {
|
||||
txtColor = "white"
|
||||
}
|
||||
let icon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
|
||||
'<circle cx="300" cy="300" r="300" fill="' + color + '"/>' +
|
||||
'<circle cx="300" cy="300" r="50"/>' +
|
||||
'<path stroke="#000" stroke-width="175" fill="none" stroke-dasharray="171.74" d="M382,158a164,164 0 1,1-164,0"/>';
|
||||
if (n !== undefined) {
|
||||
icon +=
|
||||
'<text id="marker_text" x="' + x + '" y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" fill="white">' + n + '</text>';
|
||||
}
|
||||
icon += '</svg>';
|
||||
return encodeURI("data:image/svg+xml," + icon).replace(new RegExp('#', 'g'), '%23');
|
||||
}
|
||||
|
||||
// With all Markers in cluster (markers) calculate the median
|
||||
// of the values. With this median fetch the color and return it.
|
||||
// If there are 'offline' sensors (value == -1) strip then before
|
||||
// calculating the median. If there are only offline sensor, return
|
||||
// color of value==-1 (dark gray).
|
||||
function getMedian(markers) {
|
||||
markers.sort(function (a, b) { // first sort, the lowest first
|
||||
let y1 = a.options.mSvph;
|
||||
let y2 = b.options.mSvph;
|
||||
if (y1 < y2) {
|
||||
return -1;
|
||||
}
|
||||
if (y2 < y1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
// console.log(markers);
|
||||
let i = 0; // now find the 'offlines' (mSvph == -1)
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
if (markers[i].options.mSvph > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
markers.splice(0, i); // remove these from array
|
||||
let lang = markers.length;
|
||||
if (lang > 1) { //
|
||||
if ((lang % 2) == 1) { // uneven ->
|
||||
return getColor(markers[(Math.floor(lang / 2))].options.mSvph); // median is in the middle
|
||||
} else { // evaen ->
|
||||
lang = lang / 2; // median is mean of both middle mSvphs
|
||||
// console.log(lang);
|
||||
let wert = (markers[lang - 1].options.mSvph +
|
||||
markers[lang].options.mSvph) / 2;
|
||||
return getColor(wert);
|
||||
}
|
||||
} else if (lang == 1) { // only one marker -> return its color
|
||||
return getColor(markers[0].options.mSvph);
|
||||
}
|
||||
return getColor(-1); // only offlines
|
||||
}
|
||||
|
||||
async function bauPopupText(item, txts) {
|
||||
let addr = ''
|
||||
let offlinetext = `
|
||||
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
|
||||
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
|
||||
|
||||
let normaltext = `
|
||||
<tr></tr><tr><td>cpm:</td><td>${item.value}</td></tr>
|
||||
<tr></tr><tr><td>µSvph:</td><td>${item.mSvph}</td></tr>`
|
||||
let popuptext = `
|
||||
<div id="infoTitle">
|
||||
<h4>${txts.sensor}: ${item.name}</h4>
|
||||
<div class="addr">${addr}</div>
|
||||
<div id="infoTable">
|
||||
<table>
|
||||
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
|
||||
${item.value < 0 ? offlinetext : normaltext}
|
||||
</table>
|
||||
<div id="infoBtn">
|
||||
<a href="#" class="speciallink">${txts.showchart}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return popuptext
|
||||
}
|
||||
|
||||
async function onMarkerClick(e, click, txts, params, mpp) {
|
||||
let item = e.target.options;
|
||||
let popuptext = await bauPopupText(item, txts)
|
||||
e.target.bindPopup(popuptext).openPopup(); // show the popup
|
||||
let addr = await utils.addAddress(item.name)
|
||||
document.querySelector('#infoTitle .addr').innerHTML = `${addr.street}<br />${addr.plz} ${addr.city}`
|
||||
let link = document.querySelector('.speciallink')
|
||||
link.addEventListener('click', async function (ev) {
|
||||
console.log(`Event clicked: ${mpp.clickedSensor}`)
|
||||
params.sid = item.name
|
||||
let ok = await showChart(params, 'live', 'dlive')
|
||||
if (ok) {
|
||||
let triggerEl = document.querySelector(`#livetab`)
|
||||
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
|
||||
utils.setCurrentTab('livetab')
|
||||
params.center = [e.latlng.lat, e.latlng.lng]
|
||||
mpp.map.setView([e.latlng.lat, e.latlng.lng]);
|
||||
ev.preventDefault()
|
||||
await loadAll(params)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
import * as dt from './datetime.js'
|
||||
import * as utils from "./chart_utilities.js"
|
||||
import { showChart, loadAll } from './showcharts.js'
|
||||
import * as mapu from './map_utilities.js'
|
||||
|
||||
export const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080'];
|
||||
const dba = [100, 80, 60, 40, 20, 0, -999];
|
||||
|
||||
export function getColor(d) {
|
||||
let val = parseInt(d);
|
||||
for (let i = 0; i < dba.length; i++) {
|
||||
if (val >= dba[i]) {
|
||||
return (colorscale[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const buildLegend = (mpp) => {
|
||||
let legend = L.control({position: 'bottomright'})
|
||||
legend.onAdd = function () {
|
||||
let div = L.DomUtil.create('div', 'info legend')
|
||||
let div_color = L.DomUtil.create('div', 'info legend inner', div)
|
||||
div_color.innerHTML += 'dbA<br />';
|
||||
// loop through our density intervals and generate a label with a colored square for each interval
|
||||
for (let i = 0; i < dba.length - 1; i++) {
|
||||
div_color.innerHTML +=
|
||||
'<i style="background:' + colorscale[i] + '"></i>' +
|
||||
' ' + dba[i] + (i == 0 ? '+' : '') + '<br />'
|
||||
}
|
||||
div_color.innerHTML += ' <i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline'
|
||||
return div
|
||||
};
|
||||
legend.addTo(mpp.map)
|
||||
}
|
||||
|
||||
export async function buildMarkers(params, mpp) {
|
||||
const url = mpp.APIURL + `type=noise&box=${mpp.bounds.toBBoxString()}`
|
||||
let sensors = await utils.fetchfromserver(url)
|
||||
if (!sensors.err) {
|
||||
let markers = L.markerClusterGroup({
|
||||
spiderfyOnMaxZoom: true,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: true,
|
||||
// disableClusteringAtZoom: 14,
|
||||
iconCreateFunction: function (cluster) {
|
||||
let mymarkers = cluster.getAllChildMarkers();
|
||||
let color = getMedian(mymarkers);
|
||||
return new L.Icon({
|
||||
iconUrl: buildIcon(color, cluster.getChildCount(), 0),
|
||||
iconSize: [35, 35]
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
for (let x of sensors.values) {
|
||||
if ((params.weeks > 0) && (x.weeks > params.weeks)) {
|
||||
continue
|
||||
}
|
||||
// if (x.value <= -4) {
|
||||
// continue
|
||||
// }
|
||||
let marker = L.marker([x.location[1], x.location[0]], {
|
||||
icon: new L.Icon({
|
||||
iconUrl: buildIcon(getColor(parseInt(x.value)), 0, x.indoor),
|
||||
iconSize: [35, 35],
|
||||
}),
|
||||
name: x.id,
|
||||
value: x.value,
|
||||
url: '/graph?sid=' + x.id,
|
||||
lastseen: dt.formatISODate(x.lastseen),
|
||||
indoor: x.indoor
|
||||
})
|
||||
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params, mpp)) // define click- and
|
||||
markers.addLayer(marker);
|
||||
}
|
||||
mpp.map.addLayer(markers);
|
||||
return sensors.lastdate
|
||||
} else {
|
||||
utils.showError(sensors.err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function buildIcon(color, n, indoor) {
|
||||
let x = 100;
|
||||
if (n < 10) {
|
||||
x = 200;
|
||||
} else if (n < 100) {
|
||||
x = 150;
|
||||
}
|
||||
let txtColor = "black";
|
||||
if (color == colorscale[5]) {
|
||||
txtColor = "white"
|
||||
}
|
||||
let icon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
|
||||
'<circle cx="300" cy="300" r="250" fill="' + color + '" stroke="black" stroke-width="20" />';
|
||||
if (n !== 0) {
|
||||
icon +=
|
||||
'<text id="marker_text" x="' + x + '" ' +
|
||||
'y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" ' +
|
||||
'fill="' + txtColor + '">' + n + '</text>';
|
||||
}
|
||||
if(indoor) {
|
||||
icon += '<line x1="125" y1="475" x2="475" y2="125" stroke="black" stroke-width="20" />'
|
||||
}
|
||||
icon += '</svg>';
|
||||
return encodeURI("data:image/svg+xml," + icon).replace(new RegExp('#', 'g'), '%23');
|
||||
}
|
||||
|
||||
|
||||
async function bauPopupText(item, txts) {
|
||||
let addr = ''
|
||||
let offlinetext = `
|
||||
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
|
||||
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
|
||||
|
||||
let normaltext = `
|
||||
<tr></tr><tr><td>LA_max:</td><td>${item.value}</td></tr>`
|
||||
let popuptext = `
|
||||
<div id="infoTitle">
|
||||
<h4>${txts.sensor}: ${item.name}</h4>
|
||||
<div class="addr">${addr}</div>
|
||||
<div id="infoTable">
|
||||
<table>
|
||||
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
|
||||
${item.value < 0 ? offlinetext : normaltext}
|
||||
</table>
|
||||
<div id="infoBtn">
|
||||
<a href="#" class="speciallink">${txts.showchart}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
return popuptext
|
||||
}
|
||||
|
||||
async function onMarkerClick(e, click, txts, params, mpp) {
|
||||
let item = e.target.options;
|
||||
let popuptext = await bauPopupText(item, txts)
|
||||
e.target.bindPopup(popuptext).openPopup(); // show the popup
|
||||
let addr = await utils.addAddress(item.name)
|
||||
document.querySelector('#infoTitle .addr').innerHTML = `${addr.street}<br />${addr.plz} ${addr.city}`
|
||||
let link = document.querySelector('.speciallink')
|
||||
link.addEventListener('click', async function (ev) {
|
||||
console.log(`Event clicked: ${mpp.clickedSensor}`)
|
||||
params.sid = item.name
|
||||
let ok = await showChart(params, 'live', 'dlive')
|
||||
if (ok) {
|
||||
let triggerEl = document.querySelector(`#livetab`)
|
||||
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
|
||||
utils.setCurrentTab('livetab')
|
||||
params.center = [e.latlng.lat, e.latlng.lng]
|
||||
mpp.map.setView([e.latlng.lat, e.latlng.lng]);
|
||||
ev.preventDefault()
|
||||
await loadAll(params)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// With all Markers in cluster (markers) calculate the median
|
||||
// of the values. With this median fetch the color and return it.
|
||||
// If there are 'offline' sensors (value == -1) strip then before
|
||||
// calculating the median. If there are only offline sensor, return
|
||||
// color of value==-1 (dark gray).
|
||||
function getMedian(markers, value) {
|
||||
markers.sort(function (a, b) { // first sort, the lowest first
|
||||
let y1 = a.options.value;
|
||||
let y2 = b.options.value;
|
||||
if (y1 < y2) {
|
||||
return -1;
|
||||
}
|
||||
if (y2 < y1) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
// console.log(markers);
|
||||
let i = 0; // now find the 'offlines' (value == -1)
|
||||
for (i = 0; i < markers.length; i++) {
|
||||
if (markers[i].options.value > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
markers.splice(0, i); // remove these from array
|
||||
let lang = markers.length;
|
||||
if (lang > 1) { //
|
||||
if ((lang % 2) == 1) { // uneven ->
|
||||
return getColor(markers[(Math.floor(lang / 2))].options.value); // median is in the middle
|
||||
} else { // evaen ->
|
||||
lang = lang / 2; // median is mean of both middle values
|
||||
// console.log(lang);
|
||||
let wert = (markers[lang - 1].options.value +
|
||||
markers[lang].options.value) / 2;
|
||||
return getColor(wert);
|
||||
}
|
||||
} else if (lang == 1) { // only one marker -> return its color
|
||||
return getColor(markers[0].options.value);
|
||||
}
|
||||
return getColor(-1); // only offlines
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import * as mapn from './map_noise.js';
|
||||
import * as mapg from './map_geiger.js';
|
||||
import * as utils from "./chart_utilities.js"
|
||||
import * as dt from './datetime.js'
|
||||
|
||||
function getColor(d, mapparams) {
|
||||
if(sysparams.category === 'laerm') {
|
||||
return mapn.getColor(d, mapparams)
|
||||
} else if(sysparams.category === 'multigeiger') {
|
||||
return mapg.getColor(d, mapparams)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Show the last date below tha map grafics
|
||||
export async function showLastDate(ld, mpp) {
|
||||
let url
|
||||
if(sysparams) {
|
||||
url = mpp.APIURL + 'type=noise'
|
||||
} else {
|
||||
url = mpp.APIURL + 'type=radiactivity'
|
||||
}
|
||||
let sensors = await utils.fetchfromserver(url)
|
||||
document.querySelector('#mapdate').innerText = `${sensors.valfromtxt} ${dt.formatISODate(ld).slice(0,-3)}`
|
||||
document.querySelector('#actsensors').innerText = `${sensors.actsensors} ${sensors.registered}`
|
||||
// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`)
|
||||
}
|
||||
@@ -63,7 +63,9 @@ export async function showChart(params, typ, container) {
|
||||
}
|
||||
let erg = await fetchfromserver(url)
|
||||
if (!erg.err) {
|
||||
if(sysparams.category === 'laerm') {
|
||||
utils.showTabs()
|
||||
}
|
||||
document.querySelector('#odth').style.display = 'none'
|
||||
document.querySelector('#nbday').style.display = 'inline'
|
||||
erg.options.xAxis.labels.formatter = xformat
|
||||
|
||||
@@ -39,7 +39,17 @@ header #h1name {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
header #h1datum {
|
||||
header #buttonsRight {
|
||||
float: right;
|
||||
margin-right: 1%;
|
||||
}
|
||||
header #buttonsRight #btnSet {
|
||||
margin-right: 20px;
|
||||
}
|
||||
header #buttonsRight #btnHelp {
|
||||
margin-right: 20px;
|
||||
}
|
||||
header #buttonsRight #h1datum {
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -52,18 +62,12 @@ header #h1datum {
|
||||
}
|
||||
#fenster #navi {
|
||||
float: left;
|
||||
margin-left: 1%;
|
||||
}
|
||||
#fenster #buttonsRight {
|
||||
float: right;
|
||||
margin-right: 1%;
|
||||
}
|
||||
#fenster #buttonsRight #btnSet {
|
||||
margin-right: 20px;
|
||||
margin-left: 0.5vw;
|
||||
}
|
||||
|
||||
#map {
|
||||
margin-left: 0.5vw;
|
||||
margin-top: -50px;
|
||||
width: 98vw;
|
||||
height: 80vh;
|
||||
border-radius: 10px;
|
||||
@@ -265,4 +269,6 @@ footer #author #versn {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=style.css.map */
|
||||
.highcharts-container {
|
||||
margin-top: -10px;
|
||||
}/*# sourceMappingURL=style.css.map */
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sourceRoot":"","sources":["style.sass"],"names":[],"mappings":"AAYA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;EACA;EAEA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE,kBA9BoB;;AAgCpB;EACE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;EACA;;AACA;EACE;;;AAEN;EACE;EAEA;EACA;EACA,eA5Ec;EA6Ed;EACA;EACA;;AAEA;EACE;EACA;EACA;;AACF;EACE;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AACF;EACE;EACA;;;AAEJ;EACE,kBAhGoB;;AAkGpB;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;;;AAGN;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;;AAEF;EACE;EACA;;;AAGF;EAEE;;;AAGF;EACE;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;IACE;;;AAEJ;EACE,kBAnNa;EAoNb;;;AAEF;EACE,OAvNa;EAwNb;;;AAGF;EACE;;;AAKF;EACE;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA","file":"style.css"}
|
||||
{"version":3,"sources":["style.sass","style.css"],"names":[],"mappings":"AAYA;EACE,uDAAA;EACA,eAAA;EACA,WAAA;EACA,iBAAA;EACA,kBAAA;EACA,YAAA;ACXF;;ADcA;EACE,YAAA;ACXF;;ADaA;EACE,YAAA;EACA,WAAA;EACA,kBAAA;EAEA,eAAA;EACA,YAAA;EACA,kBAAA;ACXF;;ADaA;EACE,cAAA;ACVF;;ADYA;EACE,2BA9BoB;ACqBtB;ADWE;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,cAAA;ACTJ;ADWE;EACE,eAAA;EACA,WAAA;EACA,WAAA;EACA,gBAAA;ACTJ;ADWE;EACE,YAAA;EACA,gBAAA;ACTJ;ADUI;EACE,kBAAA;ACRN;ADSI;EACE,kBAAA;ACPN;ADQI;EACE,YAAA;EACA,eAAA;ACNN;;ADQA;EACE,kBAAA;EACA,iBAAA;EACA,gBAAA;EACA,WAAA;ACLF;ADOE;EACE,WAAA;EACA,kBAAA;ACLJ;;ADOA;EACE,kBAAA;EACA,iBAAA;EACA,WAAA;EACA,YAAA;EACA,mBA7Ec;EA8Ed,0BAAA;EACA,gBAAA;EACA,UAAA;ACJF;ADME;EACE,YAAA;EACA,kBAAA;EACA,uBAAA;ACJJ;ADKE;EACE,gBAAA;EACA,kBAAA;ACHJ;;ADMA;EACE,WAAA;EACA,cAAA;EACA,sBAAA;EACA,cAAA;ACHF;ADKE;EACE,UAAA;EACA,WAAA;ACHJ;ADIE;EACE,gBAAA;EACA,gBAAA;ACFJ;;ADIA;EACE,2BAlGoB;ACiGtB;ADGE;EACE,cAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,iBAAA;EACA,YAAA;ACDJ;ADGI;EACE,WAAA;ACDN;ADGI;EACE,YAAA;ACDN;;ADIA;EACE,gBAAA;EACA,uCAAA;EACA,oCAAA;EACA,uCAAA;EACA,kBAAA;ACDF;;ADGA;EACE,eAAA;EACA,WAAA;ACAF;;ADEA;EACE,iBAAA;EACA,WAAA;EACA,eAAA;ACCF;;ADCA;EACE,WAAA;EACA,YAAA;EACA,WAAA;EACA,iBAAA;EACA,UAAA;ACEF;;ADAA;EACE,iBAAA;ACGF;;ADDA;EACE,kBAAA;EACA,eAAA;ACIF;;ADFA;EACE,gBAAA;ACKF;;ADHA;EACE,WAAA;EACA,YAAA;EACA,YAAA;ACMF;;ADJA;EACE,UAAA;ACOF;;ADLA;EACE,qBAAA;ACQF;;ADNA;EACE,SAAA;ACSF;;ADNA;EACE,gBAAA;ACSF;;ADPA;EACE,UAAA;EACA,WAAA;ACUF;;ADPA;EAEE,WAAA;ACSF;;ADNA;EACE,WAAA;EACA,cAAA;ACSF;;ADPA;EACE,WAAA;EACA,qBAAA;EACA,mBAAA;ACUF;;ADRA;EACE,UAAA;ACWF;;ADTA;EACE,UAAA;ACYF;;ADVA;EACE,UAAA;EACA,sBAAA;ACaF;;ADXA;EACE,cAAA;ACcF;;ADZA;EACE,YAAA;EACA,gBAAA;EACA,eAAA;EACA,uBAAA;EACA,0CAAA;ACeF;;ADbA;EACE,kBAAA;ACgBF;;ADdA;EACE,YAAA;ACiBF;;ADfA;EACE;IACE,aAAA;ECkBF;AACF;ADjBA;EACE,yBArNa;EAsNb,WAAA;ACmBF;;ADjBA;EACE,cAzNa;EA0Nb,yBAAA;ACoBF;;ADjBA;EACE,aAAA;ACoBF;;ADfA;EACE,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,kBAAA;ACkBF;;ADhBA;EACE,iBAAA;EACA,mBAAA;ACmBF;;ADjBA;EACE,eAAA;EACA,iBAAA;ACoBF;;ADjBA;EACE,iBAAA;ACoBF","file":"style.css"}
|
||||
@@ -49,6 +49,13 @@ header
|
||||
float: left
|
||||
text-align: left
|
||||
|
||||
#buttonsRight
|
||||
float: right
|
||||
margin-right: 1%
|
||||
#btnSet
|
||||
margin-right: 20px
|
||||
#btnHelp
|
||||
margin-right: 20px
|
||||
#h1datum
|
||||
float: right
|
||||
margin-top: 5px
|
||||
@@ -61,17 +68,11 @@ header
|
||||
|
||||
#navi
|
||||
float: left
|
||||
margin-left: 1%
|
||||
|
||||
#buttonsRight
|
||||
float: right
|
||||
margin-right: 1%
|
||||
#btnSet
|
||||
margin-right: 20px
|
||||
margin-left: 0.5vw
|
||||
|
||||
#map
|
||||
margin-left: 0.5vw
|
||||
// margin-top: 15px
|
||||
margin-top: -50px
|
||||
width: 98vw
|
||||
height: 80vh
|
||||
border-radius: $corner-radius
|
||||
@@ -87,6 +88,7 @@ header
|
||||
margin-top: 10px
|
||||
text-align: center
|
||||
|
||||
|
||||
#mapdateactsens
|
||||
width: 98vw
|
||||
font-size: 70%
|
||||
@@ -246,3 +248,6 @@ footer
|
||||
.bigger
|
||||
font-size: 120%
|
||||
font-weight: bold
|
||||
|
||||
.highcharts-container
|
||||
margin-top: -10px
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
body {
|
||||
font-family: Verdana, "Lucida Sans Unicode", sans-serif;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-top: 5px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0000EE;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: lightgray;
|
||||
}
|
||||
header #hline1 {
|
||||
margin: 0px 1vw 5px 1vw;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
header #h1name {
|
||||
font-size: 148%;
|
||||
clear: both;
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
header #h1datum {
|
||||
float: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#fenster {
|
||||
margin-left: 0.5vw;
|
||||
background: white;
|
||||
padding-top: 5px;
|
||||
width: 99vw;
|
||||
}
|
||||
#fenster #navi {
|
||||
float: left;
|
||||
margin-left: 1%;
|
||||
}
|
||||
#fenster #buttonsRight {
|
||||
float: right;
|
||||
margin-right: 1%;
|
||||
}
|
||||
#fenster #buttonsRight #btnSet {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#map {
|
||||
clear: both;
|
||||
height: 80vh;
|
||||
z-index: 0;
|
||||
border-top: solid 1px black;
|
||||
border-bottom: solid 1px black;
|
||||
margin-top: 45px
|
||||
}
|
||||
|
||||
|
||||
img.leaflet-tile {
|
||||
filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
-webkit-filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
}
|
||||
|
||||
/*
|
||||
#map {
|
||||
margin-left: 0.5vw;
|
||||
width: 98vw;
|
||||
height: 80vh;
|
||||
border-radius: 10px;
|
||||
border: solid 1px seagreen;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
*/
|
||||
#map #infoTable table, #map #infoTable tr, #map #infoTable td {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
border: none !important;
|
||||
}
|
||||
#map #infoBtn {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#map_geiger {
|
||||
margin-left: -0.5vw;
|
||||
width: 101%;
|
||||
height: 80vh;
|
||||
border: solid 1px seagreen;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
#map_geiger img.leaflet-tile {
|
||||
filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
-webkit-filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
}
|
||||
#map_geiger #infoTable table, #map_geiger #infoTable tr, #map_geiger #infoTable td {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
border: none !important;
|
||||
}
|
||||
#map_geiger #infoBtn {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#mapdateactsens {
|
||||
width: 98vw;
|
||||
font-size: 70%;
|
||||
padding: 10px 0 10px 0;
|
||||
overflow: auto;
|
||||
}
|
||||
#mapdateactsens #mapdate, #mapdateactsens #actsensors {
|
||||
width: 33%;
|
||||
float: left;
|
||||
}
|
||||
#mapdateactsens #actsensors {
|
||||
text-align: left;
|
||||
margin-left: 1vw;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: lightgray;
|
||||
}
|
||||
footer #author {
|
||||
font-size: 80%;
|
||||
width: 98vw;
|
||||
margin: auto;
|
||||
padding-bottom: 30px;
|
||||
padding-top: 10px;
|
||||
height: 50px;
|
||||
}
|
||||
footer #author #mailadr {
|
||||
float: left;
|
||||
}
|
||||
footer #author #versn {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 6px 8px;
|
||||
font: 12px Arial, Helvetica, sans-serif;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.info h4 {
|
||||
margin: 0 0 5px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.legend {
|
||||
font-family: arial, sans-serif;
|
||||
color:black;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
height: 35%;
|
||||
width: 130px;
|
||||
z-index: 999;
|
||||
background-color: rgba(238,238,238,0.80);
|
||||
border: solid 1px black;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#legend-inner-cpm {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
bottom: 15px;
|
||||
z-index: 1001;
|
||||
pointer-events: none;
|
||||
height: 90%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .gradient {
|
||||
opacity: 0.8;
|
||||
width: 20px;
|
||||
/* background: -webkit-linear-gradient(bottom, #00796b 0%, #00796b 16%, #f9a825 32%, #e65100 48%, #dd2c00 72%, #dd2c00 80%, #8c0084 100%); */
|
||||
background: -webkit-linear-gradient(bottom, #9ECDEA 0%, #9ECDEA 8%, #7F7F7F 8%, #7F7F7F 16%, #00796b 16%, #f9a825 44%, #e65100 58%, #dd2c00 72%, #dd2c00 86%, #8c0084 100%);
|
||||
/* background: linear-gradient(to top, #00796b 0%, #00796b 16%, #f9a825 32%, #e65100 48%, #dd2c00 72%, #dd2c00 80%, #8c0084 100%); */
|
||||
background: linear-gradient(to top, #9ECDEA 0%, #9ECDEA 8%, #7F7F7F 8%, #7F7F7F 16%,
|
||||
#267A45 16%,
|
||||
#66FA5F 30%,
|
||||
#F8Fc00 44%,
|
||||
#FF0000 58%,
|
||||
#9000FF 100%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels {
|
||||
width: 150px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label {
|
||||
position: absolute;
|
||||
-webkit-transform: translateY(50%);
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label1 {
|
||||
position: absolute;
|
||||
-webkit-transform: translateY(50%);
|
||||
transform: translateY(50%);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label:before {
|
||||
content: '\2013 ';
|
||||
}
|
||||
|
||||
.ndmarker {
|
||||
position: absolute;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
||||
#dlive, #dhour, #dday, #ddaynight, #dlden {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
#dialogError {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border: red solid 2px;
|
||||
}
|
||||
|
||||
.highcharts-tooltip {
|
||||
zIndex: 5;
|
||||
}
|
||||
|
||||
.settings {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.thelabels {
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.theInputs {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.rows {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.column {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#startday {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
#nbrofdays, #peaklim, #olderthan {
|
||||
width: 13%;
|
||||
}
|
||||
|
||||
.addit {
|
||||
width: 20%;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
.klein {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.infoTafel th, td {
|
||||
margin: auto;
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
border: 1px solid black;
|
||||
background-color: rgba(238, 238, 238, 0.6);
|
||||
}
|
||||
|
||||
.infoTafel th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.infoTafel tr {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 700px) {
|
||||
.infoTafel, .legend {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.nav-tabs .nav-item .nav-link {
|
||||
background-color: #2D6AF8;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-item .nav-link.active {
|
||||
color: #2D6AF8;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
#stday, #nbday, #pklim, #odth {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#first {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.addr {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.bigger {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}/*# sourceMappingURL=style.css.map */
|
||||
Executable
+692
@@ -0,0 +1,692 @@
|
||||
htnml {
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font: 14px Montserrat Helvetica, Arial, sans-serif;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#fenster {
|
||||
margin-left: 0.5vw;
|
||||
background: white;
|
||||
padding-top: 5px;
|
||||
width: 99vw;
|
||||
}
|
||||
#fenster #navi {
|
||||
float: left;
|
||||
margin-left: 1%;
|
||||
}
|
||||
#fenster #buttonsRight {
|
||||
float: right;
|
||||
margin-right: 1%;
|
||||
}
|
||||
#fenster #buttonsRight #btnSet {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
|
||||
#meldung {
|
||||
margin : auto;
|
||||
/* width: 100%; */
|
||||
text-align: center;
|
||||
background-color: #DDDDDD;
|
||||
padding-top: 30px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
clear: both;
|
||||
/* margin: auto; */
|
||||
margin-top: 10px;
|
||||
margin-right: 20px;
|
||||
/* text-align: right; */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#buttonsLeft {
|
||||
width: 48%;
|
||||
float: left;
|
||||
/* margin-bottom: 5px; */
|
||||
margin-left: 15px;
|
||||
/* border: 1px solid blue; */
|
||||
}
|
||||
|
||||
#buttonsRight {
|
||||
text-align: right;
|
||||
width: 45%;
|
||||
float: right;
|
||||
/* margin-bottom: 5px; */
|
||||
margin-right: 15px;
|
||||
/* border: 1px solid blue; */
|
||||
}
|
||||
|
||||
#buttright {
|
||||
justify-content:flex-end;
|
||||
}
|
||||
|
||||
nav { display: flex;}
|
||||
|
||||
|
||||
#btninfo {
|
||||
/* float: right; */
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
#btnda, #btnmo, #btnwe {
|
||||
width: 80px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.mybuttons{
|
||||
height: 30px;
|
||||
font-size: 95%;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.myinputs{
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#btnlegende {
|
||||
margin-right: 20px;
|
||||
margin-top: 2px;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
#btnTST {
|
||||
margin-right: 20px;
|
||||
margin-top: 2px;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
#btnset {
|
||||
margin-right: 10px;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
#btnshwgrafic {
|
||||
magin: auto;
|
||||
}
|
||||
|
||||
/* Grafik-Fenster */
|
||||
|
||||
#placeholderFS_1 {
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
#placeholderBME {
|
||||
width: 100%;
|
||||
margin-top: -10px;
|
||||
|
||||
}
|
||||
|
||||
.infoTafel th,td {
|
||||
margin: auto;
|
||||
text-align: left;
|
||||
padding: 0 10px;
|
||||
border: 1px solid black;
|
||||
background-color: rgba(238,238,238,0.6) ! important;
|
||||
}
|
||||
|
||||
.infoTafel th {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.infoTafel tr {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.errTafel {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.errTafelsmall {
|
||||
font-size:75%;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#author {
|
||||
font-size:80%;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 5px;
|
||||
background: #DDD;
|
||||
|
||||
}
|
||||
|
||||
#mailadr {
|
||||
float: left;
|
||||
margin-left: 2%;
|
||||
}
|
||||
|
||||
#versn {
|
||||
float: right;
|
||||
margin-right: 2%;
|
||||
}
|
||||
|
||||
#help {
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
#sensors {
|
||||
margin: 30px auto;
|
||||
align:center;
|
||||
}
|
||||
|
||||
#sensors td, #sensors th{
|
||||
text-align: center;
|
||||
width: 200px;
|
||||
}
|
||||
#fstb {
|
||||
padding-top: 30px;
|
||||
}
|
||||
#alert {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#map {
|
||||
clear: both;
|
||||
height: 90vh;
|
||||
z-index: 0;
|
||||
border-top: solid 1px black;
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#mapdate {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
#nosensor {
|
||||
text-align: center;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hrefsimu {
|
||||
color: blue;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
#fehlersensoren {
|
||||
}
|
||||
|
||||
/*
|
||||
#infoTable table, #infoTable tr, #infoTable td {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
border: none !important;
|
||||
}
|
||||
*/
|
||||
|
||||
#popuptext {
|
||||
width : 150px;
|
||||
/* height: 150px; */
|
||||
}
|
||||
|
||||
#infoTable table, #infoTable tr, #infoTable td {
|
||||
background-color: palegreen;
|
||||
border:none !important;
|
||||
margin: auto;
|
||||
font-weight: bold;
|
||||
width: 100px;
|
||||
text-align: center;
|
||||
/* font-size:110%;*/
|
||||
}
|
||||
|
||||
#inforohr {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/*
|
||||
#infoBtn {
|
||||
margin: 10px 0 0 25px;
|
||||
font-size: 120%;
|
||||
}
|
||||
*/
|
||||
|
||||
#fehlerexplain {
|
||||
margin-left: 30px;
|
||||
padding: 5px;
|
||||
border: solid 2px red;
|
||||
}
|
||||
|
||||
/*label, input { display: block; }
|
||||
*/
|
||||
|
||||
/*
|
||||
radio {
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
mrgin-right: 10px;
|
||||
disaplay: inline;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#page-mask {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.highcharts-tooltip span {
|
||||
background-color: white;
|
||||
opacity: 1;
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
|
||||
#errorDialog {
|
||||
color: red;
|
||||
}
|
||||
|
||||
::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||
color: lightgray;
|
||||
opacity: 1; /* Firefox */
|
||||
}
|
||||
|
||||
:-ms-input-placeholder { /* Internet Explorer 10-11 */
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
::-ms-input-placeholder { /* Microsoft Edge */
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
#underymax {
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
#alarm {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
#datumtxt {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: 170px;
|
||||
right: 25px;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.ui-widget-content a {
|
||||
color: blue;
|
||||
/* Überschreibt das default in jquery (das ist nicht blau) */
|
||||
}
|
||||
|
||||
/*
|
||||
#stat_table {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
#stat_table tr:hover {
|
||||
background-color: #ffff99;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
|
||||
#stat_table caption {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#stat_table table, #stat_table th {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
#stat_table th {
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
background-color: green;
|
||||
color: white;
|
||||
}
|
||||
*/
|
||||
.w25, .w10 {
|
||||
text-align:right;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
#body2 {
|
||||
border-top: 3px green solid;
|
||||
}
|
||||
|
||||
.bord1 {
|
||||
border-top: 2px black solid;
|
||||
}
|
||||
|
||||
.setting_head {
|
||||
background-color: blue;
|
||||
color: white;
|
||||
padding-left: 20px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#avgselect {
|
||||
margin-left:30px;
|
||||
}
|
||||
|
||||
#lueber {
|
||||
margin-left: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.ui-dialog {
|
||||
z-index:1000 !important;
|
||||
}
|
||||
|
||||
.cb {
|
||||
/* background-color: #86bc24;
|
||||
opacity: 0.8; */
|
||||
font-size: 130%;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
height: 40px;
|
||||
border: solid 2px #B5B5B5;
|
||||
}
|
||||
.centerbutt {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 6px 8px;
|
||||
font: 12px Arial, Helvetica, sans-serif;
|
||||
background: rgba(255,255,255,0.8);
|
||||
box-shadow: 0 0 15px rgba(0,0,0,0.2);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.info h4 {
|
||||
margin: 0 0 5px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
|
||||
img.leaflet-tile {
|
||||
filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
-webkit-filter: grayscale(85%) saturate(150%) hue-rotate(180deg) contrast(90%) brightness(110%);
|
||||
|
||||
}
|
||||
|
||||
.mapbox {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#overlay {
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0px;
|
||||
border: 2px #86bc24 solid;
|
||||
width: 710px;
|
||||
/* height: 100%; */
|
||||
background-color: white;
|
||||
display: none;
|
||||
}
|
||||
|
||||
button.btnlink {
|
||||
background:none;border:none;
|
||||
color: blue;
|
||||
margin-left: 15px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#loading {
|
||||
position : absolute;
|
||||
top: 200px;
|
||||
left: 200px;
|
||||
display: none;
|
||||
width: 200px;
|
||||
color: blue;
|
||||
border: 1px solid blue;
|
||||
text-align: center;
|
||||
z-index:20;
|
||||
background-color:lightcyan;
|
||||
vertical-align: center;
|
||||
}
|
||||
|
||||
.ib {
|
||||
background-color: #86bc24;
|
||||
opacity: 0.8;
|
||||
border: none;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 200%;
|
||||
margin: 4px 2px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.infobutt {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
#marker_text {
|
||||
font-family: Verdana, 'Lucida Sans Unicode', sans-serif;
|
||||
}
|
||||
|
||||
.my-custom-control {
|
||||
padding:5px 10px;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
line-height: 15px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.my-custom-control:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
select {
|
||||
/* background-color: #86bc24;
|
||||
opacity: 0.8; */
|
||||
font-size: 130%;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
width: 130px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.dropdown-.menue {
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
.navbg {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
.ui-dialog {
|
||||
z-index:1000000000;
|
||||
top: 0; left: 0;
|
||||
margin: auto;
|
||||
position: fixed;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.ui-dialog .ui-dialog-content {
|
||||
flex: 1;
|
||||
}
|
||||
.ui-dialog .ui-dialog-buttonpane {
|
||||
background:white;
|
||||
}
|
||||
*/
|
||||
|
||||
.has-search .form-control {
|
||||
padding-left: 2.375rem;
|
||||
}
|
||||
|
||||
.has-search .form-control-feedback {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
display: block;
|
||||
width: 2.375rem;
|
||||
height: 2.375rem;
|
||||
line-height: 2.375rem;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
/*
|
||||
@media (max-width: 576px) {
|
||||
.legend {
|
||||
display:none;
|
||||
}
|
||||
#btnlegende {
|
||||
display:inline;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
.dropdown-menu {
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#popuptext, #infoaddr, #akwpopuptext{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#infoBtn {
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
#newmapcenter {
|
||||
width: 250px;
|
||||
height: 33px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.spspan {
|
||||
float: right;
|
||||
margin-right: 6px;
|
||||
margin-top: -25px;
|
||||
}
|
||||
|
||||
.input-icon{
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: calc(50% - 0.5em); /* Keep icon in center of input, regardless of the input height */
|
||||
}
|
||||
.input-wrapper{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#indoor {
|
||||
font-weight: bold;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.ndmarker {
|
||||
position: absolute;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#splashChecklabel {
|
||||
margin-top: 9px;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.legend {
|
||||
font-family: arial, sans-serif;
|
||||
color:black;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
height: 35%;
|
||||
width: 130px;
|
||||
z-index: 999;
|
||||
background-color: rgba(238,238,238,0.80);
|
||||
border: solid 1px black;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#legend-inner-cpm {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
bottom: 15px;
|
||||
z-index: 1001;
|
||||
pointer-events: none;
|
||||
height: 90%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .gradient {
|
||||
opacity: 0.8;
|
||||
width: 20px;
|
||||
/* background: -webkit-linear-gradient(bottom, #00796b 0%, #00796b 16%, #f9a825 32%, #e65100 48%, #dd2c00 72%, #dd2c00 80%, #8c0084 100%); */
|
||||
background: -webkit-linear-gradient(bottom, #9ECDEA 0%, #9ECDEA 8%, #7F7F7F 8%, #7F7F7F 16%, #00796b 16%, #f9a825 44%, #e65100 58%, #dd2c00 72%, #dd2c00 86%, #8c0084 100%);
|
||||
/* background: linear-gradient(to top, #00796b 0%, #00796b 16%, #f9a825 32%, #e65100 48%, #dd2c00 72%, #dd2c00 80%, #8c0084 100%); */
|
||||
background: linear-gradient(to top, #9ECDEA 0%, #9ECDEA 8%, #7F7F7F 8%, #7F7F7F 16%,
|
||||
#267A45 16%,
|
||||
#66FA5F 30%,
|
||||
#F8Fc00 44%,
|
||||
#FF0000 58%,
|
||||
#9000FF 100%);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels {
|
||||
width: 150px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label {
|
||||
position: absolute;
|
||||
-webkit-transform: translateY(50%);
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label1 {
|
||||
position: absolute;
|
||||
-webkit-transform: translateY(50%);
|
||||
transform: translateY(50%);
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
#legend-inner-cpm .labels .label:before {
|
||||
content: '\2013 ';
|
||||
}
|
||||
|
||||
#bandgapregion {
|
||||
margin-left: 50px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
#kraftw, #togwind {
|
||||
margin-left: 30px;
|
||||
}
|
||||
+26
-7
@@ -5,12 +5,19 @@ import { setLanguage } from '../charts/utilities.js'
|
||||
const router = express.Router()
|
||||
const { name, version, date } = pkg
|
||||
|
||||
const renderOpts = (sid) => {
|
||||
const renderOpts = (sid, cat) => {
|
||||
let tit = 'Feinstaub'
|
||||
if(cat === 'multigeiger') {
|
||||
tit = 'Geiger'
|
||||
} else if (cat == 'laerm') {
|
||||
tit = 'Lärm'
|
||||
}
|
||||
return {
|
||||
title: name,
|
||||
title: tit,
|
||||
version: version,
|
||||
date: date.slice(0,10),
|
||||
csensor: sid
|
||||
csensor: sid,
|
||||
category: cat
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +26,16 @@ let i18n;
|
||||
const translate = (x) => {
|
||||
return i18n.t(x)
|
||||
}
|
||||
|
||||
const getIndex = (cat) => {
|
||||
if (cat === 'laerm') {
|
||||
return 'index_noise'
|
||||
} else if (cat === 'multigeiger') {
|
||||
return 'index_geiger'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* GET home page. If there is no parameter 'lng=xx', check stored language and call
|
||||
te page again with correct language (chglang.js))
|
||||
*/
|
||||
@@ -28,9 +45,9 @@ router.get('/', function(req, res, next) {
|
||||
res.render('chglang')
|
||||
} else {
|
||||
i18n = req.i18n
|
||||
let opts = renderOpts(-1)
|
||||
let opts = renderOpts(-1, req.app.get('category'))
|
||||
setLanguage(req.query.lng)
|
||||
res.render('index', opts)
|
||||
res.render(getIndex(opts.category), opts)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -43,11 +60,13 @@ router.get('/', function(req, res, next) {
|
||||
|
||||
router.get('/:sid', async function(req, res, next) {
|
||||
const sid = req.params.sid
|
||||
let opts
|
||||
if(isNaN(sid)) {
|
||||
res.render('index', renderOpts(-1))
|
||||
opts = renderOpts(-1, req.app.get('category'))
|
||||
} else {
|
||||
res.render('index', renderOpts(sid))
|
||||
opts = renderOpts(sid, req.app.get('category'))
|
||||
}
|
||||
res.render(getIndex(opts.category), opts)
|
||||
})
|
||||
|
||||
//export default router
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
header
|
||||
#hline1
|
||||
#h1name #{t("GeigerMeasurement")}
|
||||
#h1datum
|
||||
|
||||
#fenster
|
||||
#buttonsRight
|
||||
button.btn.btn-primary#btnSet(value='set') #{t("Settings")}
|
||||
button.btn.btn-primary#btnHelp(value='help') #{t("Info")}
|
||||
|
||||
#map
|
||||
#legendcontainer
|
||||
.legend#legendcpm
|
||||
#legend-inner-cpm
|
||||
.gradient
|
||||
.labels
|
||||
.label(style="bottom: 100%;") >= 5 µSv/h
|
||||
.label(style="bottom: 86%;") 2
|
||||
.label(style="bottom: 72%;") 1
|
||||
.label(style="bottom: 58%;") 0.5
|
||||
.label(style="bottom: 44%;") 0.2
|
||||
.label(style="bottom: 30%;") 0.1
|
||||
.label(style="bottom: 17%;") 0.05
|
||||
.label1(style="bottom: 10%;") offline
|
||||
.label1(style="bottom: 2%;") indoor
|
||||
#mapdateactsens
|
||||
#actsensors
|
||||
#mapdate
|
||||
|
||||
|
||||
#overlay
|
||||
#loading Lade die Daten ...
|
||||
#placeholderFS_1
|
||||
#placeholderBME
|
||||
|
||||
// Error-Dialog
|
||||
.modal.fade#dialogError(tabindex="-1" role="dialog" aria-labelledby="Error" aria-hidden="true")
|
||||
.modal-dialog.modal-dialog-centered(role="document")
|
||||
.modal-content
|
||||
.modal-header
|
||||
h5.modal-title.dialogErrorTitle #{t("Error")}
|
||||
button(type="button" class="close" data-bs-dismiss="modal" aria-label="Close")
|
||||
span(aria-hidden="true") ×
|
||||
.modal-body
|
||||
.modal-footer
|
||||
//button(type="button" class="btn btn-secondary" data-bs-dismiss="modal") Close
|
||||
// button(type="button" class="btn btn-primary") Save changes
|
||||
|
||||
|
||||
// Settings-Dialog
|
||||
.modal.fade#dialogSettings(tabindex="-1" role="dialog" aria-labelledby="Settings" aria-hidden="true")
|
||||
.modal-dialog.modal-dialog-centered(role="document")
|
||||
.modal-content
|
||||
.modal-header
|
||||
h5.modal-title.dialogErrorTitle #{t("Settings")}
|
||||
button(type="button" class="close" data-bs-dismiss="modal" aria-label="Close")
|
||||
span(aria-hidden="true") ×
|
||||
.modal-body.settings
|
||||
.rows
|
||||
.column#stday
|
||||
label.thelabels(for='startday') #{t("StartDate")}:
|
||||
input.theInputs#startday(name='startday' )
|
||||
.column
|
||||
.column#nbday
|
||||
label.thelabels(for='nbrofdays')
|
||||
| #{t("NumberOfDays")}:<br />
|
||||
// span.klein (#{t("Only_for_live_chart")})
|
||||
input.theInputs#nbrofdays(type = 'number' name = 'nbrofdays', min="1", max="10")
|
||||
span.klein (max. 10)
|
||||
.column#pklim
|
||||
label.thelabels(for='peaklim')
|
||||
| #{t("Count_peaks_over")}
|
||||
input.theInputs#peaklim(type = 'number' name = 'peaklim', min="10", max="130")
|
||||
| dbA
|
||||
span.klein (max. 130)
|
||||
.column#odth
|
||||
label.thelabels(for='olderthan')
|
||||
| #{t("RemoveFromMap")}
|
||||
input.theInputs#olderthan(type = 'number' name = 'olderthan', min="0", max="52")
|
||||
| #{t("weeks")}
|
||||
span.klein (max. 52)
|
||||
.column
|
||||
.column#sellan
|
||||
label.thelabels
|
||||
| #{t("Language")}:
|
||||
.form-check.form-check-inline
|
||||
input#de.form-check-input(type="radio" name="lanbut")
|
||||
label.form-check-label(for='de') Deutsch
|
||||
.form-check.form-check-inline
|
||||
input#en.form-check-input(type="radio" name="lanbut", checked)
|
||||
label.form-check-label(for="en") English
|
||||
.modal-footer
|
||||
button.btn.btn-secondary(type="button" data-bs-dismiss="modal") #{t("Close")}
|
||||
button#btnSave.btn.btn-primary(type="button" data-bs-dismiss="modal") #{t("Save_changes")}
|
||||
|
||||
|
||||
// Error-Dialog
|
||||
.modal.fade#dialogReset(tabindex="-1" role="dialog" aria-labelledby="Error" aria-hidden="true")
|
||||
.modal-dialog.modal-dialog-centered(role="document")
|
||||
.modal-content
|
||||
.modal-header
|
||||
h5.modal-title.dialogErrorTitle Info
|
||||
button(type="button" class="close" data-bs-dismiss="modal" aria-label="Close")
|
||||
span(aria-hidden="true") ×
|
||||
.modal-body
|
||||
.modal-footer
|
||||
//button(type="button" class="btn btn-secondary" data-bs-dismiss="modal") Close
|
||||
button(type="button" class="btn btn-primary" data-bs-dismiss="modal") OK
|
||||
@@ -11,6 +11,9 @@ block content
|
||||
header
|
||||
#hline1
|
||||
#h1name #{t("NoiseMeasurement")}
|
||||
#buttonsRight
|
||||
button.btn.btn-primary#btnSet(value='set') #{t("Settings")}
|
||||
button.btn.btn-primary#btnHelp(value='help') #{t("Info")}
|
||||
#h1datum
|
||||
|
||||
#fenster
|
||||
@@ -28,10 +31,6 @@ block content
|
||||
button.nav-link#daynighttab(data-bs-toggle="tab" data-bs-target="#t_daynight" type="button" role="tab" aria-controls="daynight" aria-selected="true") #{t("Day_Night")}
|
||||
li.nav-item(role='presentation')
|
||||
button.nav-link#ldentab(data-bs-toggle="tab" data-bs-target="#t_lden" type="button" role="tab" aria-controls="lden" aria-selected="true") L<sub>DEN</sub>-Index
|
||||
#buttonsRight
|
||||
button.btn.btn-primary#btnSet(value='set') #{t("Settings")}
|
||||
button.btn.btn-primary#btnHelp(value='help') #{t("Info")}
|
||||
|
||||
.tab-content#thetabs
|
||||
.tab-pane.fade.show.active#t_map(role="tabpanel" aria-labelledby="map-tab")
|
||||
#map
|
||||
+10
-4
@@ -12,14 +12,19 @@ html
|
||||
link(rel='stylesheet', href='/stylesheets/MarkerCluster.css')
|
||||
// link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr@4.6.13/dist/flatpickr.min.css")
|
||||
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.3.1/dist/css/datepicker.min.css")
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
|
||||
script.
|
||||
let sysparams = {
|
||||
const sysparams = {
|
||||
version: '#{version}',
|
||||
date: '#{date}',
|
||||
csid: '#{csensor}'
|
||||
}
|
||||
csid: '#{csensor}',
|
||||
category: '#{category}'
|
||||
};
|
||||
|
||||
if category === 'multigeiger'
|
||||
link(rel='stylesheet', href='/stylesheets/style_geiger.css')
|
||||
else
|
||||
link(rel='stylesheet', href='/stylesheets/style.css')
|
||||
|
||||
body
|
||||
#wrapper
|
||||
@@ -40,4 +45,5 @@ html
|
||||
script(src="https://code.highcharts.com/highcharts.js")
|
||||
script(src="https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.3.1/dist/js/datepicker-full.min.js")
|
||||
script(src="https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.3.1/dist/js/locales/de.js")
|
||||
script(src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js")
|
||||
script(type="module" src="/javascripts/global.js")
|
||||
Reference in New Issue
Block a user