Merge pull request #40 from vas-dav/web

Final changes
This commit is contained in:
Miisa Ekholm 2022-10-28 09:17:00 +03:00 committed by GitHub
commit 7a46f5a528
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 449 additions and 299 deletions

View File

@ -9,59 +9,53 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js" defer></script>
<script src="main.js" defer></script> <script src="main.js" defer></script>
<script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script> <script src="https://cdn.socket.io/socket.io-3.0.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript" defer></script>
</head> </head>
<body onload="updateChart(), checkMode(), getStartValues()"> <body onload="checkUser(), checkMode(), getStartValues(), updateChart()">
<header> <header>
<h1>ESP-Ventilation</h1> <h1>ABB Ventilation Controller</h1>
</header>
<div class="logout"> <div class="logout">
<p id="user"></p> <p id="user"></p>
<form id="log_out" method="post" action="/logout"> <form id="log_out" method="post" action="/logout">
<input id="btn_log_out" type="submit" value="Log out"> <input id="btn_log_out" type="submit" value="Log out">
</form> </form>
</div> </div>
</header> <div class="upper">
<main> <main>
<div class="modes">
<br>
<div class="buttons">
<input type="radio" class="custom-radio" id="m_auto" name="mode" value="Automatic" checked="true">
<label for="m_auto">Automatic</label><br>
</div>
<div class="buttons">
<input type="radio" class="custom-radio" id="m_man" name="mode" value="Manual">
<label for="m_man">Manual</label><br><br>
</div>
</div>
<div class="login"> <div class="login">
<form id="login-form" method="post" action="/"> <form id="login-form" method="post" action="/">
<br> <br>
<p id="pwd-warn">Wrong username or password</p> <p id="pwd-warn">Wrong username or password</p>
<p id="form-warn">All fields must be filled!</p> <p id="form-warn">All fields must be filled!</p>
<p>You must log in to access manual mode<br>Please give your credentials:</p> <p>You must log in to change settings<br>Please give your credentials:</p>
<input type="text" name="username" id="username" placeholder="Username" required> <input type="text" name="username" id="username" placeholder="Username" required>
<br><br> <br><br>
<input type="password" name="password" id="password" placeholder="Password" required> <input type="password" name="password" id="password" placeholder="Password" required>
<br><br> <br><br>
<input type="submit" name="btn_login" id="btn_login" value="Login"> <input type="submit" name="btn_login" id="btn_login" value="Login">
<br> <br><br>
<p id="acc" style="font-weight:normal">If you don't have account, please contact the site administrator</p> <p id="acc" style="font-weight:normal">If you don't have an account, please contact your administrator</p>
<br> <br>
</form> </form>
</div> </div>
<div class="modes">
<div id="buttons">
<input type="radio" class="custom-radio" id="m_auto" name="mode" value="Automatic" checked="true">
<label for="m_auto" id="auto_label">Automatic</label><br>
</div>
<div id="buttons">
<input type="radio" class="custom-radio" id="m_man" name="mode" value="Manual">
<label for="m_man" id="man_label">Manual</label><br><br>
</div>
</div>
<br> <br>
<p id="mon-warn">Fan is not settled in required time!</p>
<div class="set_values"> <div class="set_values">
<div class="field"> <div class="field">
<div class="ofield"> <div class="ofield">
<div id="pr_div"> <div id="pr_div">
<h3>Set pressure value</h3> <h3>Set pressure value</h3>
<output class="set_output" id="set_press">10 Pa</output> <output class="set_output" id="set_press">0 Pa</output>
<input class="slider" id="pressure" type="range" value="10" max="120" oninput="set_press.value = this.value + ' Pa'"> <input class="slider" id="pressure" type="range" value="0" max="120" oninput="set_press.value = this.value + ' Pa'">
</div> </div>
</div> </div>
</div> </div>
@ -75,7 +69,10 @@
</div> </div>
</div> </div>
</div> </div>
<br><br>
</main>
<aside>
<p id="mon-warn">Fan is not settled in required time!</p>
<div class="get_values"> <div class="get_values">
<fieldset id="monitor"> <fieldset id="monitor">
<legend style="font-size: 20px;"><b>Monitor</b></legend> <legend style="font-size: 20px;"><b>Monitor</b></legend>
@ -116,28 +113,24 @@
</div> </div>
</fieldset> </fieldset>
</div> </div>
</main> </aside>
</div>
<aside>
<br> <br>
<div class="lower">
<div class="chart-container" id="chart-cont">
<h2>Data History</h2> <h2>Data History</h2>
<br> <span id="chart_warn">No data found for selected period.</span>
<div class="chart-container"> <div class="filter">
<span id="chart_warning" style="display:none; color: red;">Not enough data to show the chosen period. Showing all values.</span> <label>Select period:</label><br>
<div class="dropdown"> <label for="start-time">Start time:</label>
<label for="data">Select period:</label> <input type="datetime-local" id="start-time" name="start-time" min="" max="" value="">
<select name="data" id="data"> <label for="end-time">End time:</label>
<option value="0">All</option> <input type="datetime-local" id="end-time" name="end-time" min="" max="" value="">
<option value="1">10 min</option> <button id="btn_reset">Reset</button>
<option value="2">30 min</option>
<option value="3">60 min</option>
</select>
</div> </div>
<canvas id="dataChart" width="600px" height="300px"></canvas> <canvas id="dataChart" width="600px" height="300px"></canvas>
</div> </div>
<br><br> <div id="user-table">
<div class="user-table">
<h2>User Log History</h2> <h2>User Log History</h2>
<table> <table>
<thead> <thead>
@ -151,7 +144,6 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<br><br> </div>
</aside>
</body> </body>
</html> </html>

View File

@ -12,7 +12,15 @@ const mqtt = require('mqtt');
const session = require('express-session'); const session = require('express-session');
const bcrypt = require('bcrypt') const bcrypt = require('bcrypt')
const client = mqtt.connect('mqtt://127.0.0.1:1883', {clientId: 'node_server', clean: true}) const client = mqtt.connect('mqtt://192.168.1.254:1883',
{username: 'SmartIotMQTT',
password: 'SmartIot',
clientId: 'node_server',
clean: true,
connectTimeout: 8000,
reconnectPeriod: 1000,
})
//const client = mqtt.connect('mqtt://127.0.0.1:1883', {clientId: 'node_server', clean: true})
let newData; let newData;
let user; let user;
let msg; let msg;
@ -46,14 +54,10 @@ function write(data, filePath) {
} }
function getTime(){ function getTime(){
let today = new Date(); let day = new Date();
let day = ("0" + today.getDate()).slice(-2); day = new Date(day.getTime() - day.getTimezoneOffset()*60000);
let month = ("0" + (today.getMonth() + 1)).slice(-2); let today = day.toISOString().replace('T', ' ').slice(0,19);
let hours = ("0" + today.getHours()).slice(-2); return today;
let mins = ("0" + today.getMinutes()).slice(-2);
let secs = ("0" + today.getSeconds()).slice(-2);
let timestamp = (day + '.' + month + '.' + today.getFullYear() + ' ' + hours + '.' + mins + '.' + secs).toString();
return timestamp;
} }
client.on('connect', ()=>{ client.on('connect', ()=>{
@ -62,14 +66,13 @@ client.on('connect', ()=>{
client.subscribe('controller/status', (err)=>{ client.subscribe('controller/status', (err)=>{
if(err){ if(err){
console.log('Subscription failed') console.log('Subscription failed ' + err);
} }
}); });
io.on('connection', (socket)=>{ io.on('connection', (socket)=>{
console.log("User " + socket.id + " connected"); console.log("User " + socket.id + " connected");
socket.on('setting', (arg)=> { socket.on('setting', (arg)=> {
let data = JSON.stringify(arg);
client.publish("controller/settings", JSON.stringify(arg), { qos: 2, retain: false }, (error)=>{ client.publish("controller/settings", JSON.stringify(arg), { qos: 2, retain: false }, (error)=>{
if(error){ if(error){
console.log(error); console.log(error);
@ -80,9 +83,6 @@ io.on('connection', (socket)=>{
client.on('message', async (topic, message) =>{ client.on('message', async (topic, message) =>{
newData = JSON.parse(message); newData = JSON.parse(message);
console.log(newData);
io.emit('data', newData);
let info = []; let info = [];
try { try {
info = await read('data.json'); info = await read('data.json');
@ -91,6 +91,7 @@ client.on('message', async (topic, message) =>{
newData['ts'] = now; newData['ts'] = now;
info.push(newData); info.push(newData);
write(info, 'data.json'); write(info, 'data.json');
io.emit('data', newData);
}); });
@ -98,15 +99,6 @@ app.get('/', (req, res)=>{
res.sendFile(path.join(__dirname + '/index.html')); res.sendFile(path.join(__dirname + '/index.html'));
}) })
app.get('/data', async (req, res) => {
try {
const data = await read('data.json');
res.json(data);
} catch (e) {
res.status(404).send(e);
}
});
app.get('/register', (req,res)=>{ app.get('/register', (req,res)=>{
res.send(` res.send(`
<h1>Register</h1> <h1>Register</h1>
@ -132,14 +124,20 @@ app.post('/', async (req,res)=>{
if(bcrypt.compareSync(password, pwd)){ if(bcrypt.compareSync(password, pwd)){
let now = getTime(); let now = getTime();
let d = now.slice(8,10);
let m = now.slice(5,7);
let y = now.slice(0,4);
let t = now.slice(11, 19);
let stamp = d + '.' + m + '.' + y + ' ' + t;
//console.log(stamp);
req.session.userId = username; req.session.userId = username;
req.session.startTime = now; req.session.startTime = stamp;
console.log('Password is correct'); console.log('Password is correct');
user = req.session.userId; user = req.session.userId;
io.emit('user', user); io.emit('user', user);
sesUser = user; sesUser = user;
sesStart = req.session.startTime; sesStart = req.session.startTime;
res.status(205); res.redirect('/');
} }
else{ else{
msg = 'wrong'; msg = 'wrong';
@ -183,7 +181,12 @@ app.post('/register', async (req,res) =>{
app.post('/logout',async (req, res) =>{ app.post('/logout',async (req, res) =>{
let now = getTime(); let now = getTime();
req.session.endTime = now; let d = now.slice(8,10);
let m = now.slice(5,7);
let y = now.slice(0,4);
let t = now.slice(11, 19);
let stamp = d + '.' + m + '.' + y + ' ' + t;
req.session.endTime = stamp;
let sesEnd = req.session.endTime; let sesEnd = req.session.endTime;
let log = []; let log = [];
try { try {
@ -196,6 +199,7 @@ app.post('/logout',async (req, res) =>{
"Login": sesStart, "Login": sesStart,
"Logout": sesEnd "Logout": sesEnd
} }
console.log(newLog);
log.unshift(newLog); log.unshift(newLog);
write(log, 'user_log.json'); write(log, 'user_log.json');
@ -208,7 +212,7 @@ app.post('/logout',async (req, res) =>{
}); });
}); });
/*
app.get('/data', async (req, res) => { app.get('/data', async (req, res) => {
try { try {
const data = await read('data.json'); const data = await read('data.json');
@ -217,6 +221,5 @@ app.get('/data', async (req, res) => {
res.status(404).send(e); res.status(404).send(e);
} }
}); });
*/
server.listen(3000, () => console.log('Server listening on port 3000')); server.listen(3000, () => console.log('Server listening on port 3000'));

View File

@ -1,3 +1,4 @@
const automode = document.getElementById('m_auto'); const automode = document.getElementById('m_auto');
const manmode = document.getElementById('m_man'); const manmode = document.getElementById('m_man');
const s_pressure = document.getElementById('pressure'); //slider const s_pressure = document.getElementById('pressure'); //slider
@ -12,7 +13,10 @@ const canvas = document.getElementById('dataChart');
const filter = document.getElementById('data'); const filter = document.getElementById('data');
const submit = document.getElementById('btn_login'); const submit = document.getElementById('btn_login');
const log_out = document.getElementById('btn_log_out'); const log_out = document.getElementById('btn_log_out');
let data_miss = false; const start = document.getElementById('start-time');
const end = document.getElementById('end-time');
const reset = document.getElementById('btn_reset');
let user; let user;
let pointerX = -1; let pointerX = -1;
let pointerY = -1; let pointerY = -1;
@ -21,18 +25,23 @@ let lastY = 0;
let counter = 0; let counter = 0;
let lastSpeed = 0; let lastSpeed = 0;
let notSettled = 0; let notSettled = 0;
let day = new Date();
day = new Date(day.getTime() - day.getTimezoneOffset()*60000);
let today = day.toISOString().slice(0,16);
start.value = today.replace('T', ' ') + ':00';
end.value = today.replace('T', ' ') + ':00';
let start_time = new Date(start.value).getTime();
let end_time = new Date(end.value).getTime();
const socket = io(); const socket = io();
socket.on('connection'); socket.on('connection');
socket.on('data', (data) =>{ socket.on('data', (data) =>{
if(data.auto === true){ if(data.error === true){
s_pressure.value = data.setpoint; document.getElementById('mon-warn').style.display = 'block';
document.getElementById('set_press').value = s_pressure.value + ' Pa';
} }
if(data.auto === false){ else{
s_speed.value = data.setpoint; document.getElementById('mon-warn').style.display = 'none';
document.getElementById('set_speed').value = s_speed.value + ' %';
} }
g_pressure.value = data.pressure; g_pressure.value = data.pressure;
g_co.value = data.co2; g_co.value = data.co2;
@ -40,16 +49,14 @@ socket.on('data', (data) =>{
g_speed.value = data.speed; g_speed.value = data.speed;
g_temp.value = data.temp; g_temp.value = data.temp;
updateChart(); updateChart();
checkData();
checkFan();
circleColor(); circleColor();
}); });
socket.on('pwd', (data) =>{ socket.on('pwd', (data) =>{
if(data){ if(data){
automode.checked = true; sessionStorage.setItem('reload', true);
document.getElementById('login-form').style.display = "block"; document.location.reload();
document.getElementById('pwd-warn').style.display = "block";
} }
}); });
@ -59,6 +66,32 @@ socket.on('user', (data) =>{
sessionStorage.setItem('loggedIn', 'true'); sessionStorage.setItem('loggedIn', 'true');
}); });
reset.addEventListener('click', e =>{
e.preventDefault();
start.value = today.replace('T', ' ') + ':00';
end.value = today.replace('T', ' ') + ':00';
start_time = new Date(start.value).getTime();
end_time = new Date(end.value).getTime();
//start.value = today.replace('T', ' ') + ':00';
//end.value = today.replace('T', ' ') + ':00';
updateChart();
})
start.addEventListener('change', e =>{
e.preventDefault();
start_time = start.value + ':00';
start_time = new Date(start_time).getTime();
updateChart();
});
end.addEventListener('change', e =>{
e.preventDefault();
end_time = end.value + ':00';
end_time = new Date(end_time).getTime();
updateChart();
});
s_pressure.addEventListener('input', e =>{ s_pressure.addEventListener('input', e =>{
e.preventDefault(); e.preventDefault();
sendPressure(); sendPressure();
@ -70,20 +103,34 @@ s_speed.addEventListener('input', e =>{
}); });
automode.addEventListener('click', () =>{ automode.addEventListener('click', () =>{
if(!sessionStorage.getItem('loggedIn')){
document.getElementById('login-form').style.display = "block";
document.getElementsByClassName('modes').style.display = "none";
document.getElementsByClassName('set_values').style.display = "none";
}
else{
document.getElementById('login-form').style.display = "none"; document.getElementById('login-form').style.display = "none";
s_pressure.disabled = false; s_pressure.disabled = false;
document.getElementById('pr_div').style.opacity = 1; document.getElementById('pr_div').style.opacity = 1;
s_speed.disabled = true; s_speed.disabled = true;
document.getElementById('sp_div').style.opacity = 0.4; document.getElementById('sp_div').style.opacity = 0.4;
}
}) })
manmode.addEventListener('click', () =>{ manmode.addEventListener('click', () =>{
if(!sessionStorage.getItem('loggedIn')){ if(!sessionStorage.getItem('loggedIn')){
document.getElementById('login-form').style.display = "block"; document.getElementById('login-form').style.display = "block";
document.getElementById('sp_div').style.display = "none";
document.getElementById('pr_div').style.display = "none";
document.getElementById('m_auto').style.display = "none";
document.getElementById('m_man').style.display = "none";
document.getElementById('auto_label').style.display = "none";
document.getElementById('man_label').style.display = "none";
} }
else{ else{
document.getElementById('login-form').style.display = "none";
document.getElementById('sp_div').style.opacity = 1; document.getElementById('sp_div').style.opacity = 1;
s_speed.disabled = false; s_speed.disabled = false;
@ -92,11 +139,6 @@ manmode.addEventListener('click', () =>{
} }
}) })
filter.addEventListener('change', e =>{
e.preventDefault();
updateChart();
})
submit.addEventListener('click', e =>{ submit.addEventListener('click', e =>{
if(document.getElementById('username').value && document.getElementById('password').value){ if(document.getElementById('username').value && document.getElementById('password').value){
document.getElementById('login-form').style.display = "none"; document.getElementById('login-form').style.display = "none";
@ -112,6 +154,7 @@ document.getElementById('password').addEventListener('click', ()=>{
}); });
log_out.addEventListener('click', () =>{ log_out.addEventListener('click', () =>{
console.log('log out clicked');
localStorage.clear(); localStorage.clear();
sessionStorage.clear(); sessionStorage.clear();
}) })
@ -155,20 +198,6 @@ function circleColor(){
} }
} }
function checkFan(){
if(lastSpeed !== g_speed.value){
notSettled += 1;
lastSpeed = g_speed.value;
}
else{
notSettled = 0;
document.getElementById('mon-warn').style.display = 'none';
}
if(notSettled > 12){
document.getElementById('mon-warn').style.display = 'block';
}
}
function logOutUser(){ function logOutUser(){
if(document.cookie){ if(document.cookie){
log_out.click(); log_out.click();
@ -182,7 +211,7 @@ document.onmousemove = function(event) {
setInterval(activityCheck, 1000); setInterval(activityCheck, 1000);
function activityCheck() { function activityCheck() {
if(document.cookie){ if(sessionStorage.getItem('loggedIn')){
if(pointerX - lastX === 0 && pointerY - lastY === 0){ if(pointerX - lastX === 0 && pointerY - lastY === 0){
counter = counter + 1; counter = counter + 1;
} }
@ -197,33 +226,64 @@ function activityCheck() {
} }
} }
function checkMode(){ function checkUser(){
if(sessionStorage.getItem('reload')){
document.getElementById('login-form').style.display = "block";
document.getElementById('pwd-warn').style.display = "block";
sessionStorage.removeItem('reload');
}
if(document.cookie && sessionStorage.getItem('loggedIn')){ if(document.cookie && sessionStorage.getItem('loggedIn')){
document.getElementById('login-form').style.display = "none";
document.getElementById('user').style.display = "block"; document.getElementById('user').style.display = "block";
document.getElementById('user').innerHTML = 'Signed in user: ' + localStorage.getItem('user'); document.getElementById('user').innerHTML = 'Signed in user: ' + localStorage.getItem('user');
document.getElementById('btn_log_out').style.display = "block"; document.getElementById('btn_log_out').style.display = "block";
document.getElementById('user').style.display = "block";
document.getElementById('user').innerHTML = 'Signed in user: ' + localStorage.getItem('user');
document.getElementById('btn_log_out').style.display = "block";
document.getElementById('user-table').style.width = "45%";
document.getElementById('chart-cont').style.width = "50%";
manmode.checked = true; if(manmode.checked = true){
s_pressure.disabled = true; s_pressure.disabled = true;
document.getElementById('pr_div').style.opacity = 0.4; document.getElementById('pr_div').style.opacity = 0.4;
s_speed.disabled = false; s_speed.disabled = false;
} }
else{ if(automode.checked = true){
automode.checked = true;
s_speed.disabled = true; s_speed.disabled = true;
document.getElementById('sp_div').style.opacity = 0.4; document.getElementById('sp_div').style.opacity = 0.4;
s_pressure.disabled = false; s_pressure.disabled = false;
document.getElementById('user').style.display = "none"; }
document.getElementById('btn_log_out').style.display = "none"; }
else{
document.getElementById('login-form').style.display = "block";
document.getElementById('sp_div').style.display = "none";
document.getElementById('pr_div').style.display = "none";
document.getElementById('m_auto').style.display = "none";
document.getElementById('m_man').style.display = "none";
document.getElementById('auto_label').style.display = "none";
document.getElementById('man_label').style.display = "none";
document.getElementById('user-table').style.display = "none";
document.getElementById('chart-cont').style.width = "95%";
} }
} }
function checkData(){ function checkMode(){
if(data_miss){ if(document.cookie && sessionStorage.getItem('loggedIn')){
document.getElementById('chart_warning').style.display = "block"; automode.checked = true;
s_speed.disabled = true;
document.getElementById('sp_div').style.opacity = 0.4;
document.getElementById('pr_div').style.opacity = 1;
s_pressure.disabled = false;
} }
if(!data_miss){ else{
document.getElementById('chart_warning').style.display = "none"; document.getElementById('login-form').style.display = "block";
document.getElementById('sp_div').style.display = "none";
document.getElementById('pr_div').style.display = "none";
document.getElementById('m_auto').style.display = "none";
document.getElementById('m_man').style.display = "none";
document.getElementById('auto_label').style.display = "none";
document.getElementById('man_label').style.display = "none";
document.getElementById('user-table').style.display = "none";
} }
} }
@ -237,6 +297,54 @@ function sendSpeed(){
socket.emit('setting', speed); socket.emit('setting', speed);
} }
function updateChart(){
async function fetchData(){
const response = await fetch('data.json');
const data = await response.json();
if(data.length !== 0){
let min = data[0].ts;
let max = data[data.length-1].ts;
start.min = min.slice(0, 16);
start.max = max.slice(0, 16);
end.min = min.slice(0, 16);
end.max = max.slice(0, 16);
}
const datapoints = data.filter(d => {
if((end_time-start_time) !== 0){
return (new Date(d.ts).getTime() >= start_time && new Date(d.ts).getTime() <= end_time)
}
else{
return data;
}
})
return datapoints;
};
fetchData().then(datapoints => {
if(datapoints.length === 0)
{
document.getElementById('chart_warn').style.display = "block";
}
const time = datapoints.map((index) => {
return index.ts;
});
const co = datapoints.map((index) => {
return index.co2;
});
const pressure = datapoints.map((index) => {
return index.pressure;
});
const rh = datapoints.map((index) => {
return index.rh;
});
myChart.config.data.labels = time;
myChart.config.data.datasets[0].data = co;
myChart.config.data.datasets[1].data = pressure;
myChart.config.data.datasets[2].data = rh;
myChart.update();
});
};
const data = { const data = {
datasets: [{ datasets: [{
label: 'CO2', label: 'CO2',
@ -318,73 +426,13 @@ const config = {
} }
}//, },
//aspectRatio: 1 aspectRatio: 2
} }
}; };
const myChart = new Chart(canvas, config); const myChart = new Chart(canvas, config);
function updateChart(){
async function fetchData(){
let datasize = 0;
let data_per_min = 12;
let datapoints;
await fetch('/data')
.then(res => res.json())
.then(data =>{
console.log(data.length);
datapoints = data.filter((elem, index)=>{
switch(parseInt(filter.value))
{
case 0: //all
datasize = data.length;
break;
case 1: //10min
datasize = 10*data_per_min;
break;
case 2: //30min
datasize = 30*data_per_min;
break;
case 3: //1 hour
datasize = 60*data_per_min;
break;
}
if(datasize > data.length){
data_miss = true;
}
else{
data_miss = false;
}
return index >= data.length -datasize;
});
});
return datapoints;
};
fetchData().then(datapoints => {
const time = datapoints.map((time) => {
return time.ts;
});
const co = datapoints.map((time) => {
return time.co2;
});
const pressure = datapoints.map((time) => {
return time.pressure;
});
const rh = datapoints.map((time) => {
return time.rh;
});
myChart.config.data.labels = time;
myChart.config.data.datasets[0].data = co;
myChart.config.data.datasets[1].data = pressure;
myChart.config.data.datasets[2].data = rh;
myChart.update();
checkData();
});
};
fetch('user_log.json') fetch('user_log.json')
.then((res)=>{ .then((res)=>{
return res.json(); return res.json();
@ -404,8 +452,8 @@ fetch('user_log.json')
placeholder.innerHTML = out; placeholder.innerHTML = out;
}); });
function getStartValues(){ async function getStartValues(){
fetch('data.json') await fetch('data.json')
.then((res) =>{ .then((res) =>{
return res.json(); return res.json();
}) })

View File

@ -11,7 +11,7 @@ body {
padding-bottom: 5px; padding-bottom: 5px;
} }
main { main {
margin-top: 100px; margin-top: 50px;
padding-bottom: 20px; padding-bottom: 20px;
display: block; display: block;
position: relative; position: relative;
@ -21,11 +21,27 @@ main {
aside { aside {
width: 100%; width: 100%;
background-color: #F6FFF8; background-color: #F6FFF8;
margin-bottom: 50px;
}
.upper{
display: flex;
flex-wrap: wrap;
width: 100%;
}
.lower{
display: flex;
flex-wrap: wrap;
flex-direction: column;
width: 100%;
margin-bottom: 50px;
} }
header { header {
width: 100%; width: 100%;
height: 150px; height: 100px;
color: black;
} }
h1 { h1 {
padding-top: 40px; padding-top: 40px;
@ -51,12 +67,13 @@ h4{
text-align: center; text-align: center;
} }
.dropdown{ .filter{
position: relative; font-weight: bolder;
float: right;
} }
.logout{ .logout{
margin-left: 20px; margin-left: 20px;
margin-top: 35px;
} }
#btn_log_out{ #btn_log_out{
margin-bottom: 10px; margin-bottom: 10px;
@ -68,6 +85,14 @@ h4{
display: none; display: none;
} }
#btn_reset{
position: relative;
float: right;
border-radius: 5px;
background-color: #CCE3DE;
border: 0.5px solid;
}
#user{ #user{
display: none; display: none;
font-weight: bolder; font-weight: bolder;
@ -77,6 +102,11 @@ h4{
background-color: red; background-color: red;
} }
.login{
margin-top: 50px;
padding-top: 50px;
}
#login-form:valid #btn_login{ #login-form:valid #btn_login{
background-color: mediumseagreen; background-color: mediumseagreen;
} }
@ -89,6 +119,7 @@ h4{
font-weight: bolder; font-weight: bolder;
border-radius: 10px; border-radius: 10px;
display: none; display: none;
} }
#acc{ #acc{
@ -96,6 +127,12 @@ h4{
margin: auto; margin: auto;
} }
#chart_warn{
display: none;
text-align: center;
color: red;
}
#mon-warn{ #mon-warn{
height: 20px; height: 20px;
text-align: center; text-align: center;
@ -120,9 +157,8 @@ h4{
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: space-evenly; justify-content: space-evenly;
margin: 20px; margin: auto;
padding: 20px; width: 85%;
width: 80%;
} }
fieldset { fieldset {
@ -176,7 +212,8 @@ fieldset {
background-color: gray; background-color: gray;
} }
.buttons{ #buttons{
display: block;
font-size: 25px; font-size: 25px;
font-weight: bolder; font-weight: bolder;
width: 12ch; width: 12ch;
@ -186,6 +223,7 @@ fieldset {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding-top: 30px;
} }
.set_values{ .set_values{
@ -195,6 +233,10 @@ fieldset {
justify-content: space-evenly; justify-content: space-evenly;
} }
.sp_div{
display: block;
}
.get_values{ .get_values{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@ -226,30 +268,32 @@ fieldset {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
width: 150px; width: 200px;
} }
.chart-container{ #chart-cont{
position: relative; display: block;
width: 700px; width: 90%;
height: 350px;
margin: auto; margin: auto;
margin-bottom: 30px;
} }
canvas{ canvas{
border-radius: 10px; border-radius: 10px;
border: 1px solid black; border: 1px solid black;
background-color: white; background-color: white;
} }
.user-table{ #user-table{
display: block;
margin-bottom: 50px; margin-bottom: 50px;
width: 50%;
margin: auto;
} }
table{ table{
background-color: #CCE3DE; background-color: #CCE3DE;
width: 700px; width: 90%;
margin: auto; margin: auto;
border-collapse: collapse; border-collapse: collapse;
} }
@ -274,10 +318,13 @@ output {
width: 50%; width: 50%;
} }
aside { aside {
margin-top: 100px; margin-top: 50px;
background: #F6FFF8; background: #F6FFF8;
width: 50%; width: 50%;
} }
.lower{
flex-direction: row;
}
} }
input[type="radio"] { input[type="radio"] {

View File

@ -1,15 +1,75 @@
[ [
{
"id": 15,
"UserId": "Miisa",
"Login": "27.10.2022 18:51:43",
"Logout": "27.10.2022 18:54:01"
},
{
"id": 14,
"UserId": "Jaakko",
"Login": "27.10.2022 16:59:26",
"Logout": "27.10.2022 17:00:54"
},
{
"id": 13,
"UserId": "Miisa",
"Login": "27.10.2022 16:56:19",
"Logout": "27.10.2022 16:59:03"
},
{
"id": 12,
"UserId": "Miisa",
"Login": "27.10.2022 16:54:23",
"Logout": "27.10.2022 16:54:33"
},
{
"id": 11,
"UserId": "Miisa",
"Login": "27.10.2022 14:18:53",
"Logout": "27.10.2022 14:19:30"
},
{
"id": 10,
"UserId": "Miisa",
"Login": "27.10.2022 14:17:45",
"Logout": "27.10.2022 14:18:42"
},
{
"id": 9,
"UserId": "Miisa",
"Login": "27.10.2022 14:15:43",
"Logout": "27.10.2022 14:16:01"
},
{
"id": 8,
"UserId": "Miisa",
"Login": "27.10.2022 14:14:49",
"Logout": "27.10.2022 14:15:06"
},
{
"id": 7,
"UserId": "Miisa",
"Login": "27.10.2022 14:12:33",
"Logout": "27.10.2022 14:14:10"
},
{
"id": 6,
"UserId": "Miisa",
"Login": "27.10.2022 13:29:52",
"Logout": "27.10.2022 13:30:54"
},
{ {
"id": 5, "id": 5,
"UserId": "Miisa", "UserId": "Miisa",
"Login": "25.10.2022 20.19.50", "Login": "27.10.2022 08:10:40",
"Logout": "25.10.2022 20.19.55" "Logout": "27.10.2022 08:11:42"
}, },
{ {
"id": 4, "id": 4,
"UserId": "Miisa", "UserId": "Miisa",
"Login": "25.10.2022 20.18.27", "Login": "27.10.2022 07:55:06",
"Logout": "25.10.2022 20.18.43" "Logout": "27.10.2022 07:56:01"
}, },
{ {
"id": 3, "id": 3,