2020-12-02 22:37:01 +01:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>FTracker Data</title>
|
|
|
|
<meta name="theme-color" content="#c50e1f">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
|
|
|
<style>
|
|
|
|
html, body {
|
|
|
|
margin: 0;
|
|
|
|
height: 100%;
|
|
|
|
font-family: sans-serif;
|
|
|
|
}
|
|
|
|
header {
|
|
|
|
height: calc(42px - 16px);
|
|
|
|
padding: 8px;
|
|
|
|
}
|
|
|
|
main {
|
|
|
|
height: calc(100% - 42px);
|
|
|
|
vertical-align: top;
|
|
|
|
}
|
|
|
|
main > section {
|
2020-12-03 00:28:06 +01:00
|
|
|
height: calc(100% - 32px);
|
|
|
|
display: inline-block;
|
|
|
|
vertical-align: top;
|
|
|
|
}
|
|
|
|
main > .viewheader {
|
2020-12-02 22:37:01 +01:00
|
|
|
display: inline-block;
|
|
|
|
vertical-align: top;
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
main > section.names, #nameheader {
|
2020-12-02 22:37:01 +01:00
|
|
|
width: 127px;
|
2020-12-03 00:28:06 +01:00
|
|
|
overflow: hidden;
|
2020-12-02 22:37:01 +01:00
|
|
|
border-right: 1px solid gray;
|
2020-12-03 00:28:06 +01:00
|
|
|
font-weight: bold;
|
|
|
|
text-transform: capitalize;
|
2020-12-02 22:37:01 +01:00
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
main #names {
|
|
|
|
padding-bottom: 32px;
|
|
|
|
}
|
|
|
|
main > section.times, #timeheader {
|
2020-12-02 22:37:01 +01:00
|
|
|
width: calc(100% - 128px);
|
2020-12-03 00:28:06 +01:00
|
|
|
overflow: hidden;
|
2020-12-02 22:37:01 +01:00
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.scroll {
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
overflow: scroll;
|
2020-12-02 22:37:01 +01:00
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.row, .row #timelabels {
|
2020-12-02 22:37:01 +01:00
|
|
|
position: relative;
|
2020-12-03 00:28:06 +01:00
|
|
|
height: 32px;
|
2020-12-02 22:37:01 +01:00
|
|
|
background-size: 60px 100%;
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.names .row:nth-child(even) { background: #ddd; }
|
|
|
|
.names .row:nth-child(odd) { background: #eee; }
|
|
|
|
.times .row:nth-child(even) {
|
2020-12-02 22:37:01 +01:00
|
|
|
background-image: linear-gradient(to right, #bbb 1px, #ddd 1px);
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.times .row:nth-child(odd) {
|
2020-12-02 22:37:01 +01:00
|
|
|
background-image: linear-gradient(to right, #bbb 1px, #eee 1px);
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.row span {
|
2020-12-02 22:37:01 +01:00
|
|
|
padding: 7px;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.times span, #timeheader span {
|
2020-12-02 22:37:01 +01:00
|
|
|
position: absolute;
|
|
|
|
background: #c50e1f;
|
|
|
|
color: #ddd;
|
|
|
|
margin-right: 16px;
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
.viewheader.row {
|
|
|
|
height: 31px;
|
|
|
|
background: #ddd !important;
|
|
|
|
border-bottom: 1px solid gray;
|
|
|
|
}
|
|
|
|
.viewheader span {
|
|
|
|
background: none !important;
|
|
|
|
color: #444 !important;
|
2020-12-02 22:37:01 +01:00
|
|
|
padding-left: 4px;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<header>
|
|
|
|
Start: <input type="datetime-local" id="start" value="2020-12-01T00:00" onchange="renderData()">
|
|
|
|
Ende: <input type="datetime-local" id="end" onchange="renderData()">
|
|
|
|
Raum: <input type="text" id="room" placeholder=".* (regex)" onchange="renderData()">
|
|
|
|
</header>
|
|
|
|
<main>
|
2020-12-03 00:28:06 +01:00
|
|
|
<div class="row viewheader" id="nameheader">
|
|
|
|
<span><b>Names</b></span>
|
|
|
|
</div><!--
|
|
|
|
--><div class="row viewheader" id="timeheader">
|
|
|
|
<div id="timelabels"></div>
|
|
|
|
</div>
|
|
|
|
<section class="names">
|
|
|
|
<div id="names"></div>
|
|
|
|
</section><!--
|
|
|
|
--><section class="times">
|
|
|
|
<div class="scroll">
|
|
|
|
<div id="times"></div>
|
|
|
|
</div>
|
|
|
|
</section>
|
2020-12-02 22:37:01 +01:00
|
|
|
</main>
|
|
|
|
<script>
|
|
|
|
var data = null;
|
2020-12-03 00:28:06 +01:00
|
|
|
|
|
|
|
var names = document.querySelector('main #names')
|
|
|
|
var times = document.querySelector('main #times')
|
|
|
|
|
2020-12-02 22:37:01 +01:00
|
|
|
function renderData() {
|
|
|
|
|
|
|
|
if (data == null) {
|
|
|
|
alert('No data found.')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-12-03 00:28:06 +01:00
|
|
|
names = document.querySelector('main #names')
|
|
|
|
times = document.querySelector('main #times')
|
2020-12-02 22:37:01 +01:00
|
|
|
|
2020-12-03 00:28:06 +01:00
|
|
|
names.innerHTML = ''
|
|
|
|
times.innerHTML = ''
|
2020-12-02 22:37:01 +01:00
|
|
|
|
|
|
|
var startInput = document.querySelector('input#start')
|
|
|
|
var endInput = document.querySelector('input#end')
|
|
|
|
var roomInput = document.querySelector('input#room')
|
|
|
|
|
|
|
|
var startDate = new Date(startInput.value)
|
|
|
|
var endDate = new Date(endInput.value)
|
|
|
|
var roomRE = new RegExp(roomInput.value || '.*')
|
|
|
|
|
|
|
|
var tc = new Date(startDate.getTime())
|
|
|
|
var content = ''
|
|
|
|
while (tc < endDate) {
|
|
|
|
var h = tc.getHours()
|
|
|
|
var t = (h == 0) ?
|
|
|
|
'<b>'+tc.getDate()+'.'+(tc.getMonth()+1)+'.</b>' :
|
|
|
|
h+':00'
|
|
|
|
var left = ((tc - startDate) / (1000 * 60))
|
|
|
|
content += '<span style="left:'+left+'px;">'+t+'</span>'
|
|
|
|
tc.setTime(tc.getTime() + (60*60*1000));
|
|
|
|
}
|
2020-12-03 00:28:06 +01:00
|
|
|
var timeheader = document.getElementById('timelabels')
|
2020-12-02 22:37:01 +01:00
|
|
|
timeheader.innerHTML = content
|
|
|
|
|
2020-12-03 00:28:06 +01:00
|
|
|
var viewwidth = ((endDate - startDate) / (1000 * 60))
|
|
|
|
timeheader.style.width = viewwidth + 'px'
|
|
|
|
times.style.width = viewwidth + 'px'
|
|
|
|
|
|
|
|
var rowCount = 0
|
2020-12-02 22:37:01 +01:00
|
|
|
|
|
|
|
for (var [name, list] of Object.entries(data)) {
|
|
|
|
|
|
|
|
var row = document.createElement('div')
|
|
|
|
row.classList.add('row')
|
|
|
|
|
|
|
|
var rowHasRoom = false
|
|
|
|
|
|
|
|
for (entry of list) {
|
|
|
|
|
|
|
|
if (entry.room.match(roomRE) == null)
|
|
|
|
continue
|
|
|
|
|
|
|
|
rowHasRoom = true
|
|
|
|
|
|
|
|
arrD = new Date(entry.arrival)
|
|
|
|
depD = entry.departure ? new Date(entry.departure) : endDate
|
|
|
|
|
|
|
|
// Minutes since start date / beginning
|
|
|
|
var arr = (arrD - startDate) / (1000 * 60)
|
|
|
|
var dep = (depD - startDate) / (1000 * 60)
|
|
|
|
var dur = dep - arr
|
|
|
|
|
|
|
|
var block = document.createElement('span')
|
|
|
|
block.innerHTML = entry.room
|
|
|
|
block.style.left = arr + 'px' // 1px/min
|
|
|
|
block.style.width = (dur-14) + 'px' // 1px/min
|
|
|
|
|
|
|
|
row.appendChild(block)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rowHasRoom) {
|
|
|
|
var vname = name.replace('-', ' ')
|
|
|
|
names.innerHTML += '<div class="row"><span>'+vname+'</span></div>'
|
|
|
|
times.appendChild(row)
|
2020-12-03 00:28:06 +01:00
|
|
|
rowCount += 12
|
2020-12-02 22:37:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-12-03 00:28:06 +01:00
|
|
|
//var viewheight = rowCount * 32;
|
|
|
|
//times.style.height = viewheight + 'px'
|
|
|
|
|
|
|
|
var tw = document.querySelector('main .scroll')
|
2020-12-02 22:37:01 +01:00
|
|
|
tw.scrollLeft = tw.scrollWidth
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function saveData(rdata) {
|
|
|
|
|
|
|
|
data = rdata.reduce((acc, entry) => {
|
|
|
|
var name = entry.name
|
|
|
|
delete entry.name
|
|
|
|
acc[name] = [...acc[name] || [], entry];
|
|
|
|
return acc;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
console.log(data)
|
|
|
|
renderData()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadData() {
|
|
|
|
|
|
|
|
fetch('/data')
|
|
|
|
.then(res => {
|
|
|
|
if (Math.floor(res.status / 100) == 2)
|
|
|
|
return res.json()
|
|
|
|
else
|
|
|
|
res.text().then(function (text) {
|
|
|
|
alert(text + "\nRestart your browser (yes, all tabs and windows) to relogin")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.then(rdata => saveData(rdata))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-12-03 14:33:55 +01:00
|
|
|
function localISOTimeMinutes(date) {
|
2020-12-02 22:37:01 +01:00
|
|
|
|
2020-12-03 14:33:55 +01:00
|
|
|
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(':')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
document.querySelector('input#end').value = localISOTimeMinutes(new Date())
|
2020-12-02 22:37:01 +01:00
|
|
|
|
2020-12-03 00:28:06 +01:00
|
|
|
var scrollbox = document.querySelector('.scroll')
|
|
|
|
var timehead = document.querySelector('#timeheader')
|
|
|
|
var namebox = document.querySelector('section.names')
|
|
|
|
scrollbox.onscroll = function() {
|
|
|
|
timehead.scrollLeft = scrollbox.scrollLeft
|
|
|
|
namebox.scrollTop = scrollbox.scrollTop
|
|
|
|
}
|
|
|
|
|
2020-12-02 22:37:01 +01:00
|
|
|
loadData()
|
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|