Settings split according to chart

routes/api.js
   - check type of sensor
   - translate error message

app.js
   - debug = false at i18n

public/javascripts/chart_utilities.js
   - setter/getter for current Tab

public/javascripts/global.js
   - settings dialog completely rearranged
   - if only sensorid is given, check type

routes/index.js
   - set language to global variable

views/index.pug
   - reaggange settings dialog
   - translate 'Error'

views/layout.pug
   - load new datepicker (vanillajs-datepicker)

public/javascripts/map.js
   - fetching from server refactored to function
   - reenable tabs after leaving map

charts/preparecharts
   - typo

public/javascripts/showcharts.js
   - loadAll extended to  load also live and map

public/stylesheets/style.sass
   - a few changes for settinds dialog

locales/[de|en]
   - added a few words

charts/utilities.js
   - setter and getter for language
This commit is contained in:
rxf
2023-05-09 16:10:07 +02:00
parent 58e25bf468
commit 4cea325f56
16 changed files with 190 additions and 106 deletions
+16 -1
View File
@@ -15,7 +15,7 @@ let stucols = 1; // Anzeige nur Balken (StundenMittel)
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 = 0; // active TAB number
let activeTab = 'maptab'; // active TAB ID
export let peaklim = 70; // threshold for peak count
export const url = '/api'
@@ -197,3 +197,18 @@ export const showTabs = () => {
document.querySelector('#navi').style.display = 'block'
}
export const setCurrentTab = (tab) => {
activeTab = tab
}
export const getCurrentTab = () => {
return activeTab
}
export const fetchfromserver = async (url) => {
const ret = await fetch(url)
.catch(e => {
showError(e)
});
return await ret.json()
}
+82 -38
View File
@@ -3,16 +3,14 @@
import * as map from './map.js'
import * as dt from './datetime.js'
import {logerror, logit} from './logit.js'
import {tabtable, loadAll, showChart} from './showcharts.js'
import {loadAll, showChart} from './showcharts.js'
import { DateTime } from './luxon.min.js'
import {setCurrentTab, getCurrentTab, showError, fetchfromserver} from "./chart_utilities.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
@@ -23,10 +21,10 @@ import { DateTime } from './luxon.min.js'
peak: 70,
weeks: 4,
datetime: '',
seldate: 'today',
seldate: '',
refresh: 0,
sid: ''
}
let currentTab = ''
// END global variables
@@ -34,56 +32,94 @@ import { DateTime } from './luxon.min.js'
// Register events
// Every input with value check
const checkPlausibility = (id, min, max) => {
document.getElementById(id).addEventListener('change', function() {
let v = parseInt(this.value)
if(v < min) this.value = min
if (v > max) this.value = max
})
}
checkPlausibility('nbrofdays', 1, 10)
checkPlausibility('peaklim', 10, 130)
checkPlausibility('olderthan', 0, 52)
// Button 'Save' pressed
document.querySelector('#btnSave').addEventListener('click', async () => {
const selDate = document.getElementById('startday').value
let starttime
if (selDate === 'today') {
starttime = DateTime.now().toISO()
params.datetime = ''
if ((selDate === 'today') || (selDate === 'heute') || (DateTime.now().toFormat('yyyy-MM-dd') === selDate)) {
starttime = ''
} else {
starttime = DateTime.fromFormat(selDate, 'yyyy-MM-dd').toISO()
params.datetime = starttime
starttime = DateTime.fromFormat(selDate, 'yyyy-MM-dd').toUTC().toISO()
}
params.datetime = starttime
params.seldate = selDate
const span = document.getElementById('nbrofdays').value
const peak = document.getElementById('peaklim').value
const weeks = document.getElementById('olderthan').value
console.log(starttime, span, peak)
if(span < 10) {
params.span = span
}
if(peak < 130 ) {
params.peak = peak
}
if (weeks < 52) {
params.weeks = weeks
}
params.span = parseInt(document.getElementById('nbrofdays').value)
params.peak = parseInt(document.getElementById('peaklim').value)
params.weeks = parseInt(document.getElementById('olderthan').value)
let newlng = document.querySelector('#sellan input:checked').id
let oldlng = localStorage.getItem('curlang')
localStorage.setItem('curlang', newlng)
if(newlng !== oldlng) {
location.reload()
}
if(params.sid !== undefined) {
await loadAll(params)
}
await loadAll(params,0)
// ToDo:
// Load ALL incl. MAP und LIVE hier, d.h. an loadAll einen zusätzlichen Parameter übergeben
// if(params.sid !== undefined) {
// await loadAll(params)
// }
})
// Btn 'Settings' pressed
document.querySelector('#btnSet').addEventListener('click', () => {
// document.querySelector('#dialogSettings .modal-dialog .modal-content .modal-body').setHTML('Das ist das Setting')
const curtab = getCurrentTab()
let myModal = new bootstrap.Modal(document.getElementById('dialogSettings'), {backdrop: 'static'})
flatpickr('#startday', {
maxDate: 'today',
minDate: new Date().fp_incr(-365),
const lang = localStorage.getItem('curlang')
const elem = document.querySelector('#startday')
const datepicker = new Datepicker(elem, {
buttonClass: 'btn',
autoHide: true,
format: 'yyyy-mm-dd',
language: lang,
maxDate: new Date(),
minDate: new Date(new Date().setDate(new Date().getDate() - 365)),
defaultViewDate: new Date(),
todayButton: true,
todayButtonMode: 1
})
document.getElementById('startday').value = params.seldate
document.getElementById('nbrofdays').value = params.span
document.getElementById('peaklim').value = params.peak
document.getElementById('olderthan').value = params.weeks
// select different infos depoending on the selcted tab
// first clear all
document.querySelector('#stday').style.display = 'inline'
document.querySelector('#nbday').style.display = 'none'
document.querySelector('#pklim').style.display = 'none'
document.querySelector('#odth').style.display = 'none'
if(curtab === 'maptab') {
document.querySelector('#stday').style.display = 'none'
document.querySelector('#odth').style.display = 'inline'
}
if(curtab === 'livetab') {
document.querySelector('#nbday').style.display = 'inline'
}
if(
(curtab === 'houravgtab') || (curtab === 'dayavgtab')) {
document.querySelector('#pklim').style.display = 'inline'
}
myModal.show()
})
const getSensorType = async (sid) => {
let url = `/api/getoneproperty?sensorid=${sid}`
const data = await fetchfromserver(url)
return data.props.type
}
// main function:
// show the map if called w/o any parameter
@@ -93,8 +129,10 @@ import { DateTime } from './luxon.min.js'
const currentLang = localStorage.getItem('curlang')
if(currentLang === 'en') {
document.querySelector('#en').checked = true
params.seldate = 'today'
} else {
document.querySelector('#de').checked = true
params.seldate = 'heute'
}
console.log(currentLang)
history.pushState({}, '', '/')
@@ -107,10 +145,9 @@ import { DateTime } from './luxon.min.js'
triggerEl.addEventListener('click', function (event) {
event.preventDefault()
tabTrigger.show()
currentTab = event.currentTarget.id
if (currentTab === 'maptab') {
map.showMap(params, sysparams)
// document.querySelector('#sellan').style.display = 'inline'
setCurrentTab(event.currentTarget.id)
if (getCurrentTab() === 'maptab') {
map.showMap(params)
}
})
})
@@ -121,17 +158,24 @@ import { DateTime } from './luxon.min.js'
const csid = parseInt(sysparams.csid)
if(csid !== -1) {
// check, if sid is of right type (noise)
const typ = await getSensorType(csid)
if (typ !== 'noise') {
// wrong sensor type
showError('Sensor ID ' + csid + ' is not of type noise')
return
}
let triggerEl = document.querySelector('#livetab')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
params.sid = csid
let ok = await showChart(params, 'live', 'dlive')
setCurrentTab('livetab')
if (ok) {
await loadAll(params)
}
} else {
// show the map
document.querySelector('#sellan').style.display = 'inline'
map.showMap(params,sysparams)
map.showMap(params)
}
}
+17 -19
View File
@@ -3,6 +3,7 @@
import * as dt from './datetime.js'
import * as utils from "./chart_utilities.js"
import { showChart, loadAll } from './showcharts.js'
import {fetchfromserver} from "./chart_utilities.js";
let map = null
let bounds
@@ -14,7 +15,7 @@ const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#328
const dba = [100, 80, 60, 40, 20, 0, -999];
const APIURL = '/api/getmapdata?'
export async function showMap(params, sysparams) {
export async function showMap(params) {
utils.removeTabs()
if(map && map.remove) {
map.off();
@@ -29,7 +30,7 @@ export async function showMap(params, sysparams) {
map.on('moveend', async function () {
bounds = map.getBounds()
await buildMarkers(bounds)
await buildMarkers(params)
});
let legend = L.control({position: 'bottomright'})
@@ -48,17 +49,20 @@ export async function showMap(params, sysparams) {
};
legend.addTo(map)
let lastdate = await buildMarkers()
let lastdate = await buildMarkers(params)
showLastDate(lastdate);
map.on('popupopen', function () {
document.querySelector('.speciallink').addEventListener('click', async function (x) {
console.log(`Event clicked: ${clickedSensor}`)
document.querySelector('#navi').style.display = 'block'
utils.showTabs()
document.querySelector('#odth').style.display = 'none'
document.querySelector('#nbday').style.display = 'inline'
params.sid = clickedSensor
let triggerEl = document.querySelector('#livetab')
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
localStorage.setItem('activeTab', 'livetab')
utils.setCurrentTab('livetab')
let ok = await showChart(params, 'live', 'dlive')
if (ok) {
await loadAll(params)
@@ -160,19 +164,14 @@ function buildIcon(color, n, indoor) {
}
export async function buildMarkers() {
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 ret = await fetch(url)
.catch(e => {
console.log(e)
});
let sensors = await ret.json()
let sensors = await fetchfromserver(url)
if (!sensors.err) {
let markers = L.markerClusterGroup({
spiderfyOnMaxZoom: true,
@@ -190,9 +189,11 @@ export async function buildMarkers() {
});
for (let x of sensors.values) {
if (x.value <= -4) {
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),
@@ -249,6 +250,7 @@ export async function buildMarkers() {
}
/*
async function getCoords(city) {
let url = NOMINATIM_URL + city;
const response = await axios.get(encodeURI(url));
@@ -262,16 +264,12 @@ async function setCenter(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 ret = await fetch(url)
.catch(e => {
console.log(e)
});
let sensors = await ret.json()
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})`)
+20 -13
View File
@@ -2,7 +2,7 @@ import {logerror} from "./logit.js";
import * as utils from "./chart_utilities.js";
import { DateTime } from './luxon.min.js'
import * as map from "./map.js";
import {showError} from "./chart_utilities.js";
import {fetchfromserver, showError} from "./chart_utilities.js";
// table to distribute the different charts
export const tabtable = [
@@ -55,13 +55,13 @@ export async function showChart(params, typ, container) {
return this.axis.defaultLabelFormatter.call(this);
}
}
const curlang = localStorage.getItem('curlang')
const url = `/api/getsensordata?sensorid=${params.sid}&data=${typ}&span=${params.span}&datetime=${params.datetime.slice(0,-10)}&peak=${params.peak}&lng=en`
let ret = await fetch(url)
.catch(e => {
logerror(e)
});
let erg = await ret.json()
let url = `/api/getsensordata?sensorid=${params.sid}&data=${typ}&datetime=${params.datetime}`
if (typ === 'live') {
url += `&span=${params.span}`
} else if ((typ === 'havg') || (typ === 'davg')) {
url += `&peak=${params.peak}`
}
let erg = await fetchfromserver(url)
if (!erg.err) {
erg.options.xAxis.labels.formatter = xformat
erg.options.tooltip.formatter = form
@@ -96,12 +96,19 @@ export async function showChart(params, typ, container) {
}
}
export const loadAll = async (params) => {
export const loadAll = async (params, start = 2) => {
console.log('now load all in Background')
for (let i = 1; i < tabtable.length; i++) {
let ok = await showChart(params, tabtable[i].type, tabtable[i].container)
if (!ok) {
break;
if (start == 0) {
map.showMap(params)
start++
}
if (params.sid !== -1) {
utils.showTabs()
for (let i = start; i < tabtable.length; i++) {
let ok = await showChart(params, tabtable[i].type, tabtable[i].container)
if (!ok) {
break;
}
}
}
}
+2 -2
View File
@@ -201,7 +201,7 @@ footer #author #versn {
}
#nbrofdays, #peaklim, #olderthan {
width: 10%;
width: 13%;
}
.addit {
@@ -244,7 +244,7 @@ footer #author #versn {
background-color: #FFFFFF;
}
#sellan {
#stday, #nbday, #pklim, #odth {
display: none;
}
+1 -1
View File
@@ -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;;;AAEF;EACE;;;AAGF;EACE;EACA;EACA;EACA","file":"style.css"}
{"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","file":"style.css"}
+5 -2
View File
@@ -192,7 +192,7 @@ footer
width: 40%
#nbrofdays, #peaklim, #olderthan
width: 10%
width: 13%
.addit
width: 20%
@@ -226,9 +226,12 @@ footer
color: $navtab-color
background-color: #FFFFFF
#sellan
// for settings: set all to 'none'
#stday, #nbday, #pklim, #odth
display: none
// for first page to show 'Loading ...'
#first
display: flex