2020-12-01 13:08:40 +01:00
<!DOCTYPE html>
< html >
< head >
< title > FTracker< / title >
2020-12-01 15:34:09 +01:00
< meta name = "theme-color" content = "#c50e1f" >
< meta name = "viewport" content = "width=device-width, initial-scale=1, maximum-scale=1" >
< style >
html, body {
margin: 0;
padding: 0;
height: 100%;
background: #ddd;
font-family: sans-serif;
}
h1 {
margin: 0;
padding: 16px;
text-transform: uppercase;
color: #eee;
background: #c50e1f;
text-align: center;
}
form {
padding: 16px;
2020-12-05 19:26:02 +01:00
max-width: 512px;
margin: auto;
2020-12-01 15:34:09 +01:00
}
label {
display: block;
font-size: 16px;
margin-bottom: 16px;
color: #444;
}
label#agreelabel {
height: 32px;
line-height: 32px;
}
label span {
width: calc(100% - 50px);
display: inline-block;
vertical-align: middle;
line-height: normal;
}
input {
border: none;
padding: 16px;
2020-12-01 17:38:37 +01:00
margin: 4px 0;
2020-12-01 15:34:09 +01:00
font-size: 16px;
}
input[type=text] {
color: #000;
width: calc(100% - 32px);
}
2020-12-09 17:19:04 +01:00
input[type=submit], input[type=button] {
2020-12-01 15:34:09 +01:00
background: #c50e1f;
text-transform: uppercase;
font-weight: bold;
color: #fff;
width: 100%;
2020-12-05 19:26:02 +01:00
cursor: pointer;
2020-12-09 16:17:58 +01:00
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
2020-12-01 15:34:09 +01:00
}
input[type=checkbox] {
transform: translateY(-3px);
float: left;
height: 32px;
width: 32px;
margin-right: 8px;
}
2020-12-01 17:38:37 +01:00
.request {
display: block;
position: fixed;
background: #ddd;
top: 16px;
left: 16px;
width: calc(100% - 32px);
box-shadow: 0 1px 4px 0;
}
input[type=datetime-local] {
width: calc(100% - 24px);
padding: 12px;
font-size: 12px;
background: #fff;
}
2020-12-01 15:34:09 +01:00
< / style >
2020-12-01 13:08:40 +01:00
< script >
2020-12-01 15:44:14 +01:00
// 1st script, prepares values needed for writing document
2020-12-01 13:08:40 +01:00
var cbt = {
2020-12-01 14:06:05 +01:00
'arrival': 'I have read and will adhere to the < a href = "/guidelines" target = "_blank" > protection guidelines< / a > ',
2020-12-01 13:08:40 +01:00
'departure': 'I have cleaned my workspace'
}
function getParams() {
var h = document.location.href
var qparam = h.split('?')[1] || null
2020-12-03 22:28:14 +01:00
if (qparam == null)
2020-12-01 13:08:40 +01:00
return null
var vals = qparam.split('=')
2020-12-03 22:28:14 +01:00
if (vals.length < 2 | | ! cbt . hasOwnProperty ( vals [ 0 ] ) )
2020-12-01 13:08:40 +01:00
return null
return {
action: vals[0],
room: vals[1]
}
}
var qp = getParams()
< / script >
< / head >
< body >
2020-12-01 15:34:09 +01:00
< h1 > < script >
2020-12-03 22:28:14 +01:00
if (qp)
document.write(qp.action + "< br > Room " + qp.room)
else
document.write('FTracker< br > V1')
2020-12-01 15:34:09 +01:00
< / script > < / h1 >
2020-12-01 17:38:37 +01:00
< form id = "mainform" >
2020-12-01 15:34:09 +01:00
< label >
Full Name:< br >
< input type = "text" name = "name" id = "name" placeholder = "John Doe" required >
< / label >
< label id = "agreelabel" >
< input type = "checkbox" name = "agree" id = "agree" required >
2020-12-03 22:28:14 +01:00
< span > < script >
document.write(qp ? cbt[qp.action] : '')
< / script > < / span >
2020-12-01 15:34:09 +01:00
< / label >
< input type = "submit" >
< / form >
2020-12-01 13:08:40 +01:00
< script >
2020-12-03 22:28:14 +01:00
var mform = document.getElementById('mainform')
if (qp == null) {
mform.innerHTML = 'This is a web app to track which people\
were in the same rooms at which times in order to backtrace\
potential viral infections.< br > < br > \
If you\'ve reached this page that either means your\'re\
testing things or something has gone quite wrong with the\
URL.< br > \
In the former case: Yay it works! In the latter you should\
probably contact an admin or a dev nearby :(< br > < br > \
Here are a few links for testing:< br > \
< a href = "/view" > View Data< / a > , \
2020-12-05 19:26:02 +01:00
< a href = "/QRgen" > Door Sign Generator< / a > , \
2020-12-03 22:28:14 +01:00
< a href = "/?arrival=42" > Test Arrival< / a > , \
< a href = "/?departure=42" > Test Departure< / a > < br > < br > \
2020-12-05 19:42:55 +01:00
© 2020 made by < a target = "_blank" href = "mailto:o.winkels@fasttube.de" > Oskar< / a > \
2020-12-05 19:26:02 +01:00
for < a target = "_blank" href = "//fasttube.de" > FaSTTUBe< / a > .< br > \
2020-12-03 22:28:14 +01:00
For source code & licensing see < a href = "//git.fasttube.de/FaSTTUBe/ftracker" > git repo< / a > '
}
2020-12-01 13:29:29 +01:00
// Prefill the name field if it was successfully entered before
var savedName = localStorage.getItem('name')
2020-12-03 22:28:14 +01:00
if (savedName & & qp)
2020-12-01 13:29:29 +01:00
document.getElementById('name').value = savedName
2020-12-01 15:44:14 +01:00
// 2nd script, server API communication
2020-12-01 17:38:37 +01:00
var name, agreed
mform.onsubmit = function(e) {
2020-12-01 13:08:40 +01:00
e.preventDefault()
2020-12-01 17:38:37 +01:00
name = e.srcElement[0].value
agreed = e.srcElement[1].checked
sendMainData()
}
function sendMainData() {
2020-12-01 13:29:29 +01:00
2020-12-01 15:44:14 +01:00
// POST JSON. See docs/API.md
2020-12-01 13:08:40 +01:00
var payload = (qp.action == 'arrival') ?
{
'room': qp.room,
2020-12-01 13:29:29 +01:00
'name': name,
'agreetoguidelines': agreed
2020-12-01 13:08:40 +01:00
} :
{
2020-12-01 13:29:29 +01:00
'name': name,
'cleanedworkspace': agreed
2020-12-01 13:08:40 +01:00
}
2020-12-01 17:38:37 +01:00
post("/" + qp.action, payload)
}
function post(url, payload) {
2020-12-01 13:29:29 +01:00
2020-12-01 17:38:37 +01:00
console.log("Sending payload:", payload)
return fetch(url, {
2020-12-01 13:08:40 +01:00
method: "POST",
body: JSON.stringify(payload)
}).then(res => {
2020-12-01 17:38:37 +01:00
handleResponse(res)
})
}
function handleResponse(res) {
console.log("Request complete! response:", res)
if (Math.floor(res.status / 100) == 2) {
// Success
mform = document.getElementById('mainform')
mform.innerHTML = "< h2 > Done. Thanks!< / h2 > "
localStorage.setItem('name', name)
} else if (res.status == 409) {
// Conflict, more data requested
handleRequest(res)
} else {
// Any other generic error
res.text().then(function (text) {
alert(text)
})
2020-12-01 15:44:14 +01:00
2020-12-01 17:38:37 +01:00
}
2020-12-01 15:44:14 +01:00
2020-12-01 17:38:37 +01:00
}
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
function handleRequestSubmit(e, json) {
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
e.preventDefault()
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
var input = e.srcElement[0].value
var iso = new Date(input).toISOString()
2020-12-01 15:44:14 +01:00
2020-12-01 17:38:37 +01:00
// POST JSON. See docs/API.md
var payload = (json.request == 'arrival') ?
{
'room': qp.room,
'name': name,
'arrival': iso,
'agreetoguidelines': agreed
} :
{
'name': name,
'departure': iso,
'cleanedworkspace': agreed
}
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
return post("/" + json.request, payload)
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
}
2020-12-03 14:33:55 +01:00
function localISOTimeMinutes(date) {
var tzoffset = date.getTimezoneOffset() * 60000; //offset in milliseconds
var localISOTime = (new Date(date - tzoffset)).toISOString().slice(0, -1);
return localISOTime.split(':').slice(0,2).join(':')
}
2020-12-01 17:38:37 +01:00
function handleRequest(res) {
var reqt = {
'arrival': 'You probably forgot to sign in when you arrived. Please enter your arrival time now:',
'departure': 'You probably forgot to sign out when you left. Please enter your departure time now:'
}
mform.innerHTML = "< h2 > Processing Request...< / h2 > "
res.json().then(function (json) {
2020-12-01 13:08:40 +01:00
2020-12-01 17:38:37 +01:00
var aInfo = ''
var minD = ''
2020-12-09 17:19:04 +01:00
var doubleT = ''
2020-12-01 17:38:37 +01:00
if (json.request == 'departure') {
var d = new Date(json.arrival.time)
var dInfo = d.toString('en-GB').split(' ').slice(0,5).join(' ')
aInfo = `Your last arrival was on < b > ${dInfo}< / b > in room < b > ${json.arrival.room}< / b > .`
2020-12-03 14:33:55 +01:00
minD = `min="${localISOTimeMinutes(d)}"`
2020-12-09 17:19:04 +01:00
if (new Date() - d < 3 * 60 * 1000 ) {
doubleT = '< b style = "color:red" > Your last sign in was less than 3 minutes ago. You might be accidentally trying to sign in twice. If you don\'t intend to log 2 arrivals within the last 3 minutes, please abort below.< / b > '
}
2020-12-01 13:08:40 +01:00
}
2020-12-01 17:38:37 +01:00
2020-12-03 14:33:55 +01:00
var now = localISOTimeMinutes(new Date())
2020-12-01 17:38:37 +01:00
document.body.innerHTML +=
`< div class = "request" >
< h1 > ${json.request} missing!< / h1 >
< form id = "reqform" >
< label >
${reqt[json.request]}
< input type = "datetime-local" id = "datetime" $ { minD } max = "${now}" required >
${aInfo}
< / label >
2020-12-09 17:19:04 +01:00
${doubleT}
2020-12-01 17:38:37 +01:00
< input type = "submit" >
2020-12-09 17:19:04 +01:00
< input type = "button" value = "Abort" onclick = "document.body.innerHTML='<h1>Aborted</h1><form>Nothing was logged.<br>You can close this tab/window now.</form>'" >
2020-12-01 17:38:37 +01:00
< / form >
< / div > `
rform = document.getElementById('reqform')
rform.onsubmit = async function(e) {
await handleRequestSubmit(e, json)
document.querySelector('.request').remove()
setTimeout(sendMainData, 200)
}
2020-12-01 13:08:40 +01:00
})
2020-12-01 17:38:37 +01:00
2020-12-01 13:08:40 +01:00
}
< / script >
< / body >
< / html >