From be8d3641163f42ff3ea4e8d3060e57e504f1ced8 Mon Sep 17 00:00:00 2001 From: rxf Date: Mon, 20 Mar 2023 20:01:26 +0100 Subject: [PATCH] Live Chart woks --- public/javascripts/chart_live.js | 265 ++++++++++++++++++++++++++ public/javascripts/chart_utilities.js | 194 +++++++++++++++++++ public/javascripts/global.js | 40 +++- public/javascripts/logit.js | 12 ++ public/javascripts/map.js | 76 ++++---- public/stylesheets/style.css | 57 ++++-- public/stylesheets/style.css.map | 2 +- public/stylesheets/style.sass | 67 +++++-- views/index.pug | 33 ++-- views/layout.pug | 10 +- 10 files changed, 663 insertions(+), 93 deletions(-) create mode 100644 public/javascripts/chart_live.js create mode 100644 public/javascripts/chart_utilities.js create mode 100644 public/javascripts/logit.js diff --git a/public/javascripts/chart_live.js b/public/javascripts/chart_live.js new file mode 100644 index 0000000..7c4456c --- /dev/null +++ b/public/javascripts/chart_live.js @@ -0,0 +1,265 @@ +// Show the live data chart +import {logit, logerror} from './logit.js' +import * as utils from './chart_utilities.js' + +// ****************************************************************** +// PlotDayLive_Noise +// ****************************************************************** + +let noise_ymin = 30; // lowest value on y-axis for noise +let noise_ymax = 120; // highest value on y-axis for noise +let activeTab = 0; // active TAB number +let peaklim = 70; // threshold for peak count + + +export const showLive = (params) => { + PlotDayLive_Noise(37833) +} + +export const PlotDayLive_Noise = async (sid) => { + + let series1 = [] + let series2 = [] + let series3 = [] + + // ave the current (actual) values here + let aktVal = {} + + // read the data from the server + const url = `http://localhost:3004/getsensordata?type=noise&sensorid=${sid}` + let ret = await fetch(url) + .catch(e => { + logerror(e) + }); + let sensors = await ret.json() + let lastidx = sensors.count-1 + // Put values into the arrays + let cnt = 0 + sensors.values.forEach((x) => { + let dat = new Date(x.datetime).getTime() + series1.push([dat, x.noise_LAeq]) + series2.push([dat, x.noise_LA_max]) + series3.push([dat, x.noise_LA_min]) // put data and value into series array + }) + + if (sensors.values.length != 0) { + // Aktuelle Werte speichern + aktVal['LAeq'] = sensors.values[lastidx].noise_LAeq + aktVal['LAMax'] = sensors.values[lastidx].noise_LA_max + aktVal['LAMin'] = sensors.values[lastidx].noise_LA_min + + // InfoTafel füllen + let infoTafel = + '' + + '' + + '' + + '' + infoTafel += + '' + + '' + infoTafel += + '' + + '' + infoTafel += + '
Aktuelle Werte
LAeq' + (aktVal.LAeq).toFixed(1) + 'dbA
LAmin' + (aktVal.LAMin).toFixed(0) + 'dbA
LAmax' + (aktVal.LAMax).toFixed(0) + 'dbA
' + + '' + } + let txtMeldung = false + + + // Plot-Options + let options = utils.createGlobObtions() + + let series_LAeq = { + name: 'LAeq', + data: series1, + color: utils.colors.eq, + yAxis: 0, + zIndex: 1, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(238,223,236)'], + [1, 'rgb(238,223,236)'] + ] + }, + } + + let series_LAMax = { + name: 'LAmax', + data: series2, + color: utils.colors.max, + yAxis: 0, + zIndex: 0, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(255,233,236)'], + [1, 'rgb(255,233,236)'] + ] + }, +// fillOpacity: 0.2, + } + + let series_LAMin = { + name: 'LAmin', + data: series3, + color: utils.colors.min, + yAxis: 0, + zIndex: 6, + marker: { + enabled: false, + symbol: 'square', + }, + visible: true, + fillColor: { + linearGradient: [0, 600, 0, 0], + stops: [ + [0, 'rgb(219,216,217)'], + [1, 'rgb(219,216,217)'] + ] + }, + } + + let yAxis_LAeq = { // 1 + title: { + text: 'dbA', + style: { + color: 'black' + } + }, + max: noise_ymax, + min: noise_ymin, +// opposite: true, + tickAmount: 10, + useHTML: true, + } + + options.series = [] + options.yAxis = [] + options.series[0] = series_LAeq + options.series[1] = series_LAMin + options.title.text = 'Noise level for one day' + options.subtitle.useHTML = true + options.subtitle.text = '2.5min log. average values
 ' + options.series[2] = series_LAMax +// options.yAxis[2] = yAxis_LAMin + options.yAxis[0] = yAxis_LAeq +// options.yAxis[1] = yAxis_LAMax + options.chart.zoomType = 'x' + options.chart.type = 'area' + options.chart.resetZoomButton= { + position: { + align: 'left', + verticalAlign: 'bottom', + x: 20, + y: -50, + }, + relativeTo: 'chart' + } + + + let noDataTafel = '
' + + 'Für heute liegen leider keine Daten vor!
Bitte den Sensor überprüfen!\'
' + + '
' + + + let navy = 20 + let navbreit = 55 + let navtxt = ['-24h', '-12h', 'live', '+12h', '+24h'] + let navtime = [-24, -12, 0, 12, 24] + + let chr = Highcharts.chart('dlive', options, function (chart) { + utils.addSensorID2chart(chart, sensors.props, document.getElementById('dlive').offsetWidth) + // let breit = $(window).width() + // let navx = breit-350 + // chart.renderer.label( + // infoTafel, + // breit - 250, + // 78, 'rect', 0, 0, true) + // .css({ + // fontSize: '10pt', + // color: 'green' + // }) + // .attr({ + // zIndex: 5, + // }).add() + // for (let i = 0; i < navtxt.length; i++) { + // renderPfeil(i, chart, navx + (i * navbreit), navy, navtxt[i], navtime[i]) + // } + if (txtMeldung == true) { + let labeText = '' + let errtext = chart.renderer.label( + noDataTafel, + 250, + 120, 'rect', 0, 0, true) + .css({ + fontSize: '18pt', + color: 'red' + }) + .attr({ + zIndex: 1000, + stroke: 'black', + 'stroke-width': 2, + fill: 'white', + padding: 10, + }).add() + } + }) +} + +let butOpts = [ + {fill: 'lightblue', r: 2}, + {fill: 'blue', r: 2, style: {color: 'white'}}, + {fill: 'lightblue', r: 2}, + {fill: 'lightblue', r: 2} +] + + +function renderPfeil(n, chart, x, y, txt, time) { + chart.renderer.button(txt, x, y, null, butOpts[0], butOpts[1], butOpts[2], butOpts[3]) + .attr({ + id: 'button' + n, + zIndex: 3, + width: 30, + }) + .on('click', function () { + prevHour(time) + }) + .add() +} + +function prevHour(hours) { + console.log("Zurück um ", hours, "Stunden") + let start + if (startDay == "") { + start = moment() + start.subtract(24, 'h') + } else { + start = moment(startDay) + } + let mrk = moment() + mrk.subtract(24, 'h') + let startDay = "" + if (hours < 0) { + start.subtract(Math.abs(hours), 'h') + startDay = start.format("YYYY-MM-DDTHH:mm:ssZ") + } else if (hours > 0) { + start.add(hours, 'h') + if (!start.isAfter(mrk)) { + startDay = start.format("YYYY-MM-DDTHH:mm:ssZ") + } + } + doPlot('live', startDay) +} + diff --git a/public/javascripts/chart_utilities.js b/public/javascripts/chart_utilities.js new file mode 100644 index 0000000..31cc58f --- /dev/null +++ b/public/javascripts/chart_utilities.js @@ -0,0 +1,194 @@ +// Utility routine for plotting the data + +import {DateTime} from './luxon.min.js' +export const colors = {'eq': '#0000FF', 'max': '#FF0000', 'min': '#008000', 'peaks': '#DAA520'}; + +// Defaults für die Mittelwertbildungen +const refreshRate = 5; // Grafik so oft auffrischen (in Minuten) +let txtMeldung = false; // falls keine Daten da sind, Text melden +const avgTime = 30; // defaul average time für particulate matter +let doUpdate = true; // update every 5 min +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) + + +export function createGlobObtions() { + var globObject = {}; + + // Options, die für alle Plots identisch sind + globObject = { + chart: { + height: 600, +// width: 1000; + spacingRight: 20, + spacingLeft: 20, + spacingTop: 25, + backgroundColor: { + linearGradient: [0, 400, 0, 0], + stops: [ + [0, '#eee'],//[0, '#ACD0AA'], //[0, '#A18D99'], // [0, '#886A8B'], // [0, '#F2D0B5'], + [1, '#fff'] + ] + }, + type: 'line', + borderWidth: '2', + events: { + selection: function (event) { + if (event.xAxis) { + doUpdate = false; + } else { + doUpdate = true; + } + } + } + }, + title: { +// text: 'Feinstaub über 1 Tag', + align: 'left', + style: {'fontSize': '25px'}, + useHTML: true, + }, + subtitle: { + text: 'Gemessene Werte und ' + avgTime + 'min-gleitende Mittelwerte', + align: 'left', + }, + tooltip: { + valueDecimals: 1, + backgroundColor: 0, + borderWidth: 0, + borderRadius: 0, + useHTML: true, + formatter: function () { + return '
' + + DateTime.fromMillis(this.x, {zone: 'utc'}).toFormat('dd.LL HH:mm:ss') + '
' + + '● ' + + this.series.name + ':  ' + + Highcharts.numberFormat(this.y, 1) + + '
'; + } + }, + xAxis: { + type: 'datetime', + title: { + text: 'date/time', + }, + gridLineWidth: 2, + labels: { + formatter: function () { + let v = this.axis.defaultLabelFormatter.call(this); + if (v.indexOf(':') == -1) { + return '' + v + ''; + } else { + return v; + } + } + }, + }, + legend: { + enabled: true, + layout: 'horizontal', +// verticalAlign: 'top', + borderWidth: 1, + align: 'center', + }, + plotOptions: { + series: { + animation: false, + turboThreshold: 0, + marker: { + enabled: false, + }, + }, + } + }; + return globObject; +} + +function calcWeekends(data, isyear) { + var weekend = []; + var oldDay = 8; + for (var i = 0; i < data.length; i++) { + var mom = moment(data[i].date); + if (isyear) { + mom = moment(data[i]._id) + } + var day = mom.day(); + var st = mom.startOf('day'); + if (day != oldDay) { + if (day == 6) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } else if (day == 0) { + weekend.push({ + color: 'rgba(169,235,158,0.4)', + from: st.valueOf(), + to: st.add(1, 'days').valueOf(), + zIndex: 0 + }) + } + oldDay = day; + } + } + return weekend; +} + +function calcDays(data, isyear) { + var days = []; + if (data.length == 0) { + return days + } + var oldday = moment(data[0].date).day(); + if (isyear) { + oldday = moment(data[0]._id).day(); + } + for (var i = 0; i < data.length; i++) { + var m = moment(data[i].date); + if (isyear) { + m = moment(data[i]._id); + } + var tag = m.day() + if (tag != oldday) { + m.startOf('day'); + days.push({color: 'lightgray', value: m.valueOf(), width: 1, zIndex: 2}); + oldday = tag; + } + } + return days; +}; + +function getIndoor(sensor) { + let p = new Promise(function (resolve, reject) { + let url = '/api/getdata?data=props&sensorid=' + sensor; + $.get(url, (data, err) => { + if (err != 'success') { + resolve(false) + } else { + resolve(data.values[0].indoor == 1) + } + }) + }) + return p +} + +export async function addSensorID2chart(chart, props, width) { + console.log('widht: ',width); + let indoor = props.location[0].indoor + console.log('indoor: ',indoor) + let sens = chart.renderer.label( + `Sensor: ${props._id} ${indoor ? ' (indoor)' : ''}`, + width / 2 - 100, 65, + 'text', 0, 0, true) + .css({ + fontSize: '12pt', + 'font-weight': 'bold', + }) + .attr({ + zIndex: 5, + }).add(); +} diff --git a/public/javascripts/global.js b/public/javascripts/global.js index 9918eab..b519791 100644 --- a/public/javascripts/global.js +++ b/public/javascripts/global.js @@ -3,8 +3,11 @@ import * as map from './map.js' import * as dt from './datetime.js' +import {logit} from './logit.js' +import * as chart_live from './chart_live.js' + +(async () => { -(async function () { // global constants const Stuttgart = [48.779, 9.16] const MAXROWS_IN_TABLE = 1000 @@ -25,21 +28,49 @@ import * as dt from './datetime.js' } // END global variables - +const tabtable = [ + {id: 'kartentab', func: map.showMap}, + {id: 'livetab', func: chart_live.showLive}, + // {id: 'houravgtab', func: chart_houravg.showHouravg}, + // {id: 'dayavgtab', func: chart_dayavg.showDayavg}, + // {id: 'daynighttab', func: chart_daynight.showDaynight}, + // {id: 'ldentab', func: chart_lden.showLden}, +] async function main() { // initialise tabs - let triggerTabList = [].slice.call(document.querySelectorAll('#myTab a')) + let triggerTabList = [].slice.call(document.querySelectorAll('.nav-link')) triggerTabList.forEach(function (triggerEl) { let tabTrigger = new bootstrap.Tab(triggerEl) triggerEl.addEventListener('click', function (event) { event.preventDefault() tabTrigger.show() + for(let x of tabtable) { + if (x.id === event.currentTarget.id) { + x.func(params) + } + } + logit(`tab chaned to ${event.currentTarget.id}`) }) }) - // show dat/time at start + // var triggerEl = document.querySelector('#tablist a[href="#profile"]') + // bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name + // + // var triggerFirstTabEl = document.querySelector('#tablist li:first-child a') + // bootstrap.Tab.getInstance(triggerFirstTabEl).show() // Select first tab + + + // let nl = document.querySelectorAll('.nav-link') + // for (let x of nl) { + // x.addEventListener('click', (event) => { + // event.preventDefault() + // console.log(event) + // }) + // } + + dt.showDate(true) // and show date/time every minute setInterval(() => dt.showDate(false), 1000) @@ -49,7 +80,6 @@ import * as dt from './datetime.js' // show the map map.showMap(params) - await map.buildMarkers() } main().catch(console.error) diff --git a/public/javascripts/logit.js b/public/javascripts/logit.js new file mode 100644 index 0000000..2453df0 --- /dev/null +++ b/public/javascripts/logit.js @@ -0,0 +1,12 @@ +import { DateTime } from './luxon.min.js' + +export function logit(str) { + let s = `${DateTime.now().toISO()} => ${str}`; + console.log(s); +} + +export function logerror(str) { + let s = `${DateTime.utc().toISO()} => *** ERROR *** ${str}`; + console.log(s); +} + diff --git a/public/javascripts/map.js b/public/javascripts/map.js index c088112..953ae70 100644 --- a/public/javascripts/map.js +++ b/public/javascripts/map.js @@ -9,7 +9,7 @@ let popuptext = '' const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080']; const dba = [100, 80, 60, 40, 20, 0, -999]; -export const showMap = (params) => { +export const showMap = async (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, @@ -37,7 +37,8 @@ export const showMap = (params) => { return div }; legend.addTo(map) - + let lastdate = await buildMarkers() + showLastDate(lastdate); } @@ -58,7 +59,7 @@ function calcPolygon(bounds) { }); ; } - +/* async function plotMap(cid, poly) { // if sensor nbr is give, find coordinates, else use Stuttgart center debug_log('plotMap()'); @@ -132,7 +133,7 @@ async function plotMap(cid, poly) { } } - +*/ // With all Markers in cluster (markers) calculate the median // of the values. With this median fetch the color and return it. @@ -151,7 +152,7 @@ function getMedian(markers) { } return 0; }); - console.log(markers); + // 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) { @@ -165,7 +166,7 @@ function getMedian(markers) { 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); + // console.log(lang); let wert = (markers[lang - 1].options.value + markers[lang].options.value) / 2; return getColor(wert); @@ -250,8 +251,7 @@ export async function buildMarkers() { markers.addLayer(marker); } map.addLayer(markers); -// ToDo showLastDate(sensors.lastDate); - + return sensors.lastdate } async function onMarkerClick(e, click) { @@ -299,36 +299,48 @@ async function setCenter(adr) { console.log(data); } -/* -// Show the last date below tha map grafics -async function showLastDate(dt) { - const url = `http://localhost:3004/getproperties?type=noise&box=${bounds.toBBoxString()}` +// Show the last date below tha map grafics +async function showLastDate(ld) { + // const url = `http://localhost:3004/getproperties?type=noise&box=${bounds.toBBoxString()}` + // + // let ret = await fetch(url) + // .catch(e => { + // console.log(e) + // }); + // let sensors = await ret.json() + // + // let url = '/api/getdata'; + // let ld = moment(dt); + // let last = ld.subtract(1,'h') + // let erg; + // let allsens + // try { + // erg = await $.getJSON(url + `?data=props&last=1900-01-01`); + // allsens = erg.count + // erg = await $.getJSON(url + `?data=props&last=${last.format('YYYY-MM-DD HH:mm')}`); + // if ((erg != undefined) && (erg.values[0].error != undefined)) { + // showError(3,erg.values[0].error,aktsensorid); + // return; + // } + // } + // catch(e) { + // console.log(e) + // } + // fetch all sensors + const url = `http://localhost:3004/getmapdata?type=noise` let ret = await fetch(url) .catch(e => { console.log(e) }); let sensors = await ret.json() - - let url = '/api/getdata'; - let ld = moment(dt); - let last = ld.subtract(1,'h') - let erg; - let allsens - try { - erg = await $.getJSON(url + `?data=props&last=1900-01-01`); - allsens = erg.count - erg = await $.getJSON(url + `?data=props&last=${last.format('YYYY-MM-DD HH:mm')}`); - if ((erg != undefined) && (erg.values[0].error != undefined)) { - showError(3,erg.values[0].error,aktsensorid); - return; + let actsensors = 0 + for (let x of sensors.values) { + if (x.value >= 0) { + actsensors++ } } - catch(e) { - console.log(e) - } - $('#mapdate').html('Werte von ' + ld.format('YYYY-MM-DD HH:mm')); - $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`) + document.querySelector('#mapdate').innerText = 'Values from ' + dt.formatISODate(ld).slice(0,-3) + document.querySelector('#actsensors').innerText = `Active sensors: ${actsensors} (registered: ${sensors.count})` +// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`) } - - */ \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index d815efa..51977e6 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -5,7 +5,6 @@ body { margin-left: auto; margin-right: auto; height: 100%; - background-color: rgb(146, 154, 146); } html { @@ -16,7 +15,6 @@ html { margin: auto; width: 100%; text-align: center; - background-color: #e9e9e9; margin-top: 5px; height: 100%; position: relative; @@ -27,13 +25,13 @@ a { } header { - width: 98%; - margin: auto; + background-color: lightgray; } header #hline1 { - width: 98%; - margin: 0px auto 0px; + margin: 0px 1vw 0px 1vw; padding-top: 10px; + padding-bottom: 10px; + overflow: auto; } header #h1name { font-size: 148%; @@ -47,9 +45,10 @@ header #h1datum { } #fenster { - margin-top: 45px; - background: lightgray; + margin-left: 0.5vw; + background: white; padding-top: 5px; + width: 99vw; } #fenster #navi { float: left; @@ -64,10 +63,9 @@ header #h1datum { } #map { - margin-left: 1vw; - margin-top: 5px; + margin-left: 0.5vw; width: 98vw; - height: 66vh; + height: 80vh; border-radius: 10px; border: solid 1px seagreen; overflow: hidden; @@ -83,17 +81,36 @@ header #h1datum { text-align: center; } -#author { +#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: 95%; + width: 98vw; margin: auto; padding-bottom: 30px; padding-top: 10px; + height: 50px; } -#author #mailadr { +footer #author #mailadr { float: left; } -#author #versn { +footer #author #versn { float: right; } @@ -133,4 +150,14 @@ header #h1datum { font-size: 24px; } +.tab-pane { + margin-top: 44px; +} + +#dlive, #dhour, #dday, #ddaynight, #dlden { + width: 98vw; + height: 100%; + margin: auto; +} + /*# sourceMappingURL=style.css.map */ diff --git a/public/stylesheets/style.css.map b/public/stylesheets/style.css.map index fdec3aa..fd0c87b 100644 --- a/public/stylesheets/style.css.map +++ b/public/stylesheets/style.css.map @@ -1 +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;EACA;;;AAEJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;EACA;;AACA;EACE;;;AAEN;EACE;EACA;EACA;EACA;EACA,eAzEc;EA0Ed;EACA;EACA;;AAEA;EACE;EACA;EACA;;AACF;EACE;EACA;;;AAGJ;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"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["style.sass"],"names":[],"mappings":"AAWA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAEF;EACE;EACA;EACA;EAEA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE,kBA7BoB;;AA+BpB;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,eA3Ec;EA4Ed;EACA;EACA;;AAEA;EACE;EACA;EACA;;AACF;EACE;EACA;;;AAEJ;EACE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AACF;EACE;EACA;;;AAEJ;EACE,kBA/FoB;;AAiGpB;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","file":"style.css"} \ No newline at end of file diff --git a/public/stylesheets/style.sass b/public/stylesheets/style.sass index 104e690..fe98585 100644 --- a/public/stylesheets/style.sass +++ b/public/stylesheets/style.sass @@ -5,6 +5,7 @@ $divcolor: rgb(162, 227, 162) $table-stripes: rgb(157, 179, 157) $fieldset-color: rgb(208, 235, 208) $button-color: darkslategrey +$header_footer_color: lightgray $checkboxsize: 1.5 $inboxwidth: 70px @@ -15,7 +16,7 @@ body margin-left: auto margin-right: auto height: 100% - background-color: $background +// background-color: $background html height: 100% @@ -24,7 +25,7 @@ html margin: auto width: 100% text-align: center - background-color: #e9e9e9 + // background-color: #e9e9e9 margin-top: 5px height: 100% position: relative @@ -33,13 +34,13 @@ a color: #0000EE header - width: 98% - margin: auto + background-color: $header_footer_color #hline1 - width: 98% - margin: 0px auto 0px + margin: 0px 1vw 0px 1vw padding-top: 10px + padding-bottom: 10px + overflow: auto #h1name font-size: 148% @@ -52,9 +53,10 @@ header margin-top: 5px #fenster - margin-top: 45px - background: lightgray + margin-left: 0.5vw + background: white padding-top: 5px + width: 99vw #navi float: left @@ -67,10 +69,10 @@ header margin-right: 20px #map - margin-left: 1vw - margin-top: 5px + margin-left: 0.5vw + // margin-top: 15px width: 98vw - height: 66vh + height: 80vh border-radius: $corner-radius border: solid 1px $border-color overflow: hidden @@ -84,19 +86,35 @@ header margin-top: 10px text-align: center +#mapdateactsens + width: 98vw + font-size: 70% + padding: 10px 0 10px 0 + overflow: auto -#author - font-size: 80% - width: 95% - margin: auto - padding-bottom: 30px - padding-top: 10px - - #mailadr + #mapdate, #actsensors + width: 33% float: left + #actsensors + text-align: left + margin-left: 1vw - #versn - float: right +footer + background-color: $header_footer_color + + #author + font-size: 80% + width: 98vw + margin: auto + padding-bottom: 30px + padding-top: 10px + height: 50px + + #mailadr + float: left + + #versn + float: right .info @@ -129,3 +147,10 @@ header position: absolute font-size: 24px +.tab-pane + margin-top: 44px + +#dlive, #dhour, #dday, #ddaynight, #dlden + width: 98vw + height: 100% + margin: auto diff --git a/views/index.pug b/views/index.pug index 1a92f6e..469a76f 100644 --- a/views/index.pug +++ b/views/index.pug @@ -12,15 +12,15 @@ block content li.nav-item(role='presentation') button.nav-link.active#kartentab(data-bs-toggle="tab" data-bs-target="#t_map" type="button" role="tab" aria-controls="map" aria-selected="true") Map li.nav-item(role='presentation') - button.nav-link.active#livetab(data-bs-toggle="tab" data-bs-target="#t_live" type="button" role="tab" aria-controls="live" aria-selected="true") Live + button.nav-link#livetab(data-bs-toggle="tab" data-bs-target="#t_live" type="button" role="tab" aria-controls="live" aria-selected="true") Live li.nav-item(role='presentation') - button.nav-link.active#houravgtab(data-bs-toggle="tab" data-bs-target="#t_houravg" type="button" role="tab" aria-controls="houravg" aria-selected="true") Hour_AVG + button.nav-link#houravgtab(data-bs-toggle="tab" data-bs-target="#t_houravg" type="button" role="tab" aria-controls="houravg" aria-selected="true") Hour_AVG li.nav-item(role='presentation') - button.nav-link.active#dayavgtab(data-bs-toggle="tab" data-bs-target="#t_dayavg" type="button" role="tab" aria-controls="dayavg" aria-selected="true") Day_AVG + button.nav-link#dayavgtab(data-bs-toggle="tab" data-bs-target="#t_dayavg" type="button" role="tab" aria-controls="dayavg" aria-selected="true") Day_AVG li.nav-item(role='presentation') - button.nav-link.active#daynightab(data-bs-toggle="tab" data-bs-target="#t_daynight" type="button" role="tab" aria-controls="daynight" aria-selected="true") Day_Night + button.nav-link#daynightab(data-bs-toggle="tab" data-bs-target="#t_daynight" type="button" role="tab" aria-controls="daynight" aria-selected="true") Day_Night li.nav-item(role='presentation') - button.nav-link.active#ldenab(data-bs-toggle="tab" data-bs-target="#t_lden" type="button" role="tab" aria-controls="lden" aria-selected="true") LDEN-Index + button.nav-link#ldenab(data-bs-toggle="tab" data-bs-target="#t_lden" type="button" role="tab" aria-controls="lden" aria-selected="true") LDEN-Index #buttonsRight button.btn.btn-primary#btnSet(value='set') Settings button.btn.btn-primary#btnHelp(value='help') Info @@ -28,13 +28,16 @@ block content .tab-content#thetabs .tab-pane.fade.show.active#t_map(role="tabpanel" aria-labelledby="map-tab") #map MapTAB - .tab-pane.fade.show.active#t_live(role="tabpanel" aria-labelledby="map-tab") - #placeholderNOI1 LiveTAB - .tab-pane.fade.show.active#t_houravg(role="tabpanel" aria-labelledby="map-tab") - #placeholderNOI2 HourTAB - .tab-pane.fade.show.active#t_dayavg(role="tabpanel" aria-labelledby="map-tab") - #placeholderNOI3 DayTAB - .tab-pane.fade.show.active#t_daynight(role="tabpanel" aria-labelledby="map-tab") - #placeholderNOI4 DayNightTAB - .tab-pane.fade.show.active#t_lden(role="tabpanel" aria-labelledby="map-tab") - #placeholderNOI5 LdenTAB + #mapdateactsens + #actsensors + #mapdate + .tab-pane.fade#t_live(role="tabpanel" aria-labelledby="live-tab") + #dlive LiveTAB + .tab-pane.fade#t_houravg(role="tabpanel" aria-labelledby="map-tab") + #dhour HourTAB + .tab-pane.fade#t_dayavg(role="tabpanel" aria-labelledby="map-tab") + #dday DayTAB + .tab-pane.fade#t_daynight(role="tabpanel" aria-labelledby="map-tab") + #ddaynight DayNightTAB + .tab-pane.fade#t_lden(role="tabpanel" aria-labelledby="map-tab") + #dlden LdenTAB diff --git a/views/layout.pug b/views/layout.pug index 6cd4cd3..4c7e8d4 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -32,10 +32,11 @@ html body #wrapper block content - #author - #mailadr - a(href="mailto:rexfue@gmail.com") mailto:rexfue@gmail.com - #versn + footer + #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") @@ -43,4 +44,5 @@ html integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin="") script(src="/javascripts/leaflet.markercluster.js") + script(src="https://code.highcharts.com/highcharts.js") script(type="module" src="/javascripts/global.js") \ No newline at end of file