WIP WIP WIP ** first git - markers work as expected

This commit is contained in:
rxf
2023-03-14 17:34:48 +01:00
commit b270370105
29 changed files with 2399 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules
log
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/laerm_web_sensorapi.iml" filepath="$PROJECT_DIR$/.idea/laerm_web_sensorapi.iml" />
</modules>
</component>
</project>
Generated
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>
+11
View File
@@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="bin/www" type="NodeJSConfigurationType" node-parameters="--experimental-json-modules" path-to-js-file="bin/www.js" working-dir="$PROJECT_DIR$">
<envs>
<env name="DEBUG" value="laerm-web-sensorapi:*" />
</envs>
<EXTENSION ID="com.jetbrains.nodejs.run.NodeStartBrowserRunConfigurationExtension">
<browser url="http://localhost:3000/" />
</EXTENSION>
<method v="2" />
</configuration>
</component>
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="true">
<option name="arguments" value="$FileName$:$FileNameWithoutExtension$.css" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="sass" />
<option name="immediateSync" value="false" />
<option name="name" value="Sass" />
<option name="output" value="$FileNameWithoutExtension$.css:$FileNameWithoutExtension$.css.map" />
<option name="outputFilters">
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="program" value="$PROJECT_DIR$/node_modules/sass/sass.js" />
<option name="runOnExternalChanges" value="false" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="true" />
<option name="workingDir" value="$FileDir$" />
<envs />
</TaskOptions>
</component>
</project>
+47
View File
@@ -0,0 +1,47 @@
import createError from 'http-errors'
import logger from 'morgan'
import express from 'express'
import cookieParser from 'cookie-parser'
import path from 'path'
import { fileURLToPath } from 'url';
const app = express()
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import indexRouter from './routes/index.js'
// import getdataRouter from './routes/getdata.js'
// import putdataRouter from './routes/putdata.js'
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
// app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
export default app
Executable
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env node
/**
* Module dependencies.
*/
import app from '../app.js'
import Debug from 'debug'
import http from 'http'
const debug = Debug('laerm-web-sensorapi:server')
/* var app = require('../app');
var debug = require('debug')('laerm-web-sensorapi:server');
var http = require('http');
*/
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);
if (isNaN(port)) {
// named pipe
return val;
}
if (port >= 0) {
// port number
return port;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
+1394
View File
File diff suppressed because it is too large Load Diff
+23
View File
@@ -0,0 +1,23 @@
{
"name": "laerm-web-sensorapi",
"version": "3.0.0",
"date": "2023-03-14 16:30 UTC",
"private": true,
"scripts": {
"start": "node bin/www.js >>log/laerm_web.log 2>&1"
},
"type": "module",
"bin": {
"www": "./bin/www.js"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"cors": "^2.8.5",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"pug": "2.0.0-beta11",
"sass": "^1.58.3"
}
}
+15
View File
@@ -0,0 +1,15 @@
// all date and time functions
import { DateTime } from './luxon.min.js'
// Show date and time (every minute)
export const showDate = (sofort) => {
let d = DateTime.now()
if(sofort || d.second === 0) {
$('#h1datum').text(d.toFormat('yyyy-MM-dd HH:mm'))
}
}
export const formatJSDate = (d) => {
return DateTime.fromJSDate(d).toFormat('yyyy-LL-dd HH:mm:ss')
}
+45
View File
@@ -0,0 +1,45 @@
// Client side javascript
"use strict"
import * as map from './map.js'
import * as dt from './datetime.js'
$(async() => {
// global constants
const Stuttgart = [48.779, 9.16]
const MAXROWS_IN_TABLE = 1000
const defaultStartime = '2023-01-01 00:00'
// END global constants
// global variables
let params = { // set defaults
drawlines: false,
nbrentries: 0,
device: '',
coordinates: false,
center: Stuttgart,
zoom: 13,
refresh: 0,
starttime: '2023-01-01T00:00:00Z', //date2ISO(defaultStartime),
endtime: '2023-03-01T00:00:00Z' //date2ISO(emptyTimes.emptyHMtime)
}
// END global variables
async function main() {
// show dat/time at start
dt.showDate(true)
// and show date/time every minute
setInterval(() => dt.showDate(false), 1000)
// show version and version-date
$('#versn').text(`Version: ${sysparams.version} vom ${sysparams.date.slice(0,10)}`)
// show the map
map.showMap(params)
await map.buildMarkers()
}
main().catch(console.error)
})
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+300
View File
@@ -0,0 +1,300 @@
// all function related to the map
import * as dt from './datetime.js'
let map
let bounds
let popuptext = ''
const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080'];
const dba = [100, 80, 60, 40, 20, 0, -999];
export const showMap = (params) => {
map = L.map('map',{ scrollWheelZoom: false}).setView(params.center, parseInt(params.zoom))
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="http://www.js.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map)
bounds = map.getBounds();
map.on('moveend', async function () {
bounds = map.getBounds()
await buildMarkers(bounds)
});
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>' +
'&nbsp;&nbsp;' + dba[i] + (i == 0 ? '+' : '') + '<br />'
}
div_color.innerHTML += '&nbsp;<i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline'
return div
};
legend.addTo(map)
}
function getColor(d) {
let val = parseInt(d);
for (let i = 0; i < dba.length; i++) {
if (val >= dba[i]) {
return (colorscale[i]);
}
}
}
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
});
;
}
async function plotMap(cid, poly) {
// if sensor nbr is give, find coordinates, else use Stuttgart center
debug_log('plotMap()');
let myLatLng;
if (cid != -1) {
myLatLng = await getSensorKoords(cid);
} else {
let stgt = await getCoords('Stuttgart');
myLatLng = {lat: parseFloat(stgt.lat), lng: parseFloat(stgt.lon)};
}
// generate map centered on Stuttgart
map = L.map('map').setView(myLatLng, firstZoom);
L.tileLayer('https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png', {
maxZoom: 17,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
bounds = map.getBounds();
map.scrollWheelZoom.disable();
map.on('moveend', async function () {
bounds = map.getBounds();
await buildMarkers(bounds)
});
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>' +
'&nbsp;&nbsp;' + dba[i] + (i == 0 ? '+' : '') + '<br />';
}
div_color.innerHTML += '&nbsp;<i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline';
return div;
};
legend.addTo(map);
let infobutton = L.control({position: 'topright'});
infobutton.onAdd = function (map) {
let div = L.DomUtil.create('div');
div.innerHTML = '<button class="cb centerbutt">neu zentrieren</button>';
div.onclick = function () {
dialogCenter.dialog('open');
console.log('Clicked on Zentrieren');
}
return div;
}
infobutton.addTo(map);
if (useStgtBorder) {
fetchStuttgartBounds();
}
if (myLatLng.error != undefined) {
showError(3, "Kein Lärmsensor", cid);
} else {
await buildMarkers(bounds);
map.on('popupopen', function () {
$('.speciallink').click(function (x) {
showGrafik(clickedSensor);
});
});
}
}
// 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 != -1) {
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 !== 0) {
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() {
// debug_log('buildMarkers(bounds)');
const box = {
west: bounds.getWest(), south: bounds.getSouth(),
east: bounds.getEast(), north: bounds.getNorth()
}
const url = `http://localhost:3004/getmapdata?type=noise&box=${bounds.toBBoxString()}`
let ret = await fetch(url)
.catch(e => {
console.log(e)
});
let sensors = await ret.json()
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) {
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.formatJSDate(x.lastseen),
indoor: x.indoor
})
.on('click', e => onMarkerClick(e, true)) // define click- and
.bindPopup(popuptext); // and bint the popup text
markers.addLayer(marker);
}
map.addLayer(markers);
showLastDate(sensors.lastDate);
}
async function onMarkerClick(e, click) {
let item = e.target.options;
let clickedSensor = item.name;
let offlinetext = `
<tr><td colspan="2"><span style="color:red;">offline</span></td></tr>
<tr><td>Last seen:</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>Sensor: ${item.name}</h4>
<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">Grafik anzeigen</a>
</div>
</div>
</div>`
let popup = e.target.getPopup();
popup.setContent(popuptext); // set text into popup
e.target.openPopup(); // show the popup
if (click == true) { // if we clicked
e.target.closePopup(); // show the 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);
}
@@ -0,0 +1,60 @@
.marker-cluster-small {
background-color: rgba(181, 226, 140, 0.6);
}
.marker-cluster-small div {
background-color: rgba(110, 204, 57, 0.6);
}
.marker-cluster-medium {
background-color: rgba(241, 211, 87, 0.6);
}
.marker-cluster-medium div {
background-color: rgba(240, 194, 12, 0.6);
}
.marker-cluster-large {
background-color: rgba(253, 156, 115, 0.6);
}
.marker-cluster-large div {
background-color: rgba(241, 128, 23, 0.6);
}
/* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
background-color: rgb(181, 226, 140);
}
.leaflet-oldie .marker-cluster-small div {
background-color: rgb(110, 204, 57);
}
.leaflet-oldie .marker-cluster-medium {
background-color: rgb(241, 211, 87);
}
.leaflet-oldie .marker-cluster-medium div {
background-color: rgb(240, 194, 12);
}
.leaflet-oldie .marker-cluster-large {
background-color: rgb(253, 156, 115);
}
.leaflet-oldie .marker-cluster-large div {
background-color: rgb(241, 128, 23);
}
.marker-cluster {
background-clip: padding-box;
border-radius: 20px;
}
.marker-cluster div {
width: 30px;
height: 30px;
margin-left: 5px;
margin-top: 5px;
text-align: center;
border-radius: 15px;
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.marker-cluster span {
line-height: 30px;
}
+14
View File
@@ -0,0 +1,14 @@
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}
.leaflet-cluster-spider-leg {
/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
}
+109
View File
@@ -0,0 +1,109 @@
body {
font-family: Verdana, "Lucida Sans Unicode", sans-serif;
font-size: 16px;
width: 100%;
margin-left: auto;
margin-right: auto;
height: 100%;
background-color: rgb(146, 154, 146);
}
html {
height: 100%;
}
#wrapper {
margin: auto;
width: 100%;
text-align: center;
background-color: #e9e9e9;
margin-top: 5px;
height: 100%;
position: relative;
}
a {
color: #0000EE;
}
header {
width: 98%;
margin: auto;
}
header #hline1 {
width: 98%;
margin: 0px auto 0px;
padding-top: 10px;
}
header #h1name {
font-size: 148%;
clear: both;
float: left;
text-align: left;
}
header #h1datum {
float: right;
}
#map {
margin-left: 1vw;
margin-top: 5px;
width: 98vw;
height: 66vh;
border-radius: 10px;
border: solid 1px seagreen;
overflow: hidden;
z-index: 1;
}
#author {
font-size: 80%;
width: 95%;
margin: auto;
padding-bottom: 30px;
padding-top: 10px;
}
#author #mailadr {
float: left;
}
#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 {
line-height: 18px;
color: #555;
font-size: 110%;
}
.legend i {
width: 18px;
height: 18px;
float: left;
margin-right: 0px;
opacity: 1;
}
.leglabel {
padding-top: 20px;
}
.ndmarker {
position: absolute;
font-size: 24px;
}
/*# sourceMappingURL=style.css.map */
+1
View File
@@ -0,0 +1 @@
{"version":3,"sourceRoot":"","sources":["style.sass"],"names":[],"mappings":"AAUA;EACE;EACA;EACA;EACA;EACA;EACA;EACA,kBAfW;;;AAiBb;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA,eA1Dc;EA2Dd;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEF;EACE;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA","file":"style.css"}
+107
View File
@@ -0,0 +1,107 @@
$corner-radius: 10px
$border-color: seagreen
$background: rgb(146, 154, 146)
$divcolor: rgb(162, 227, 162)
$table-stripes: rgb(157, 179, 157)
$fieldset-color: rgb(208, 235, 208)
$button-color: darkslategrey
$checkboxsize: 1.5
$inboxwidth: 70px
body
font-family: Verdana, 'Lucida Sans Unicode', sans-serif
font-size: 16px
width: 100%
margin-left: auto
margin-right: auto
height: 100%
background-color: $background
html
height: 100%
#wrapper
margin: auto
width: 100%
text-align: center
background-color: #e9e9e9
margin-top: 5px
height: 100%
position: relative
a
color: #0000EE
header
width: 98%
margin: auto
#hline1
width: 98%
margin: 0px auto 0px
padding-top: 10px
#h1name
font-size: 148%
clear: both
float: left
text-align: left
#h1datum
float: right
#map
margin-left: 1vw
margin-top: 5px
width: 98vw
height: 66vh
border-radius: $corner-radius
border: solid 1px $border-color
overflow: hidden
z-index: 1
#author
font-size: 80%
width: 95%
margin: auto
padding-bottom: 30px
padding-top: 10px
#mailadr
float: left
#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
line-height: 18px
color: #555
font-size: 110%
.legend i
width: 18px
height: 18px
float: left
margin-right: 0px
opacity: 1
.leglabel
padding-top: 20px
.ndmarker
position: absolute
font-size: 24px
+16
View File
@@ -0,0 +1,16 @@
import express from 'express'
import pkg from '../package.json' assert { type: "json" }
const router = express.Router()
const { name, version, date } = pkg
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', {
title: name,
version: version,
date: date
})
})
export default router
+9
View File
@@ -0,0 +1,9 @@
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
+6
View File
@@ -0,0 +1,6 @@
extends layout
block content
h1= message
h2= error.status
pre #{error.stack}
+10
View File
@@ -0,0 +1,10 @@
extends layout
block content
header
#hline1
#h1name Lärm-Messung
#h1datum
#map
+48
View File
@@ -0,0 +1,48 @@
doctype html
html
head
title= title
meta(name="viewport" content="width=device-width, initial-scale=1" charset="utf-8")
link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous")
link(rel="stylesheet" href="https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"
integrity="sha256-kLaT2GOSpHechhsozzB+flnD+zUyjE2LlfWPgU04xyI="
crossorigin="")
link(rel='stylesheet', href='/stylesheets/MarkerCluster.css')
link(rel='stylesheet', href='/stylesheets/style.css')
script.
let sysparams = {
version: '#{version}',
date: '#{date}'
}
let urlParams = {
// drawlines: '#{drawlines}' === 'true',
// starttime: '#{starttime}',
// endtime: '#{endtime}',
// nbrentries: '#{nbrentries}',
// device: '#{device}',
// coordinates: '#{coordinates}' === 'true',
// center: JSON.parse('#{center}'),
// zoom: '#{zoom}',
// refresh: '#{refresh}'
}
body
#wrapper
block content
#author
#mailadr
a(href="mailto:rexfue@gmail.com") mailto:rexfue@gmail.com
#versn
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous")
script(src="https://code.jquery.com/jquery-3.6.4.min.js"
integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous")
script(src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js"
integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM="
crossorigin="")
script(src="/javascripts/leaflet.markercluster.js")
script(type="module" src="/javascripts/global.js")