Improved result tables and added dark mode. General improvements.

This commit is contained in:
Trygve 2020-10-10 15:27:48 +02:00
parent 4843e664b1
commit 8648094fa9
4 changed files with 303 additions and 98 deletions

View File

@ -1,47 +1,216 @@
body{
font-family: "Red Hat Display", Myriad, Cantarell, "Noto Sans", "Liberation Sans","Trebuchet MS", Arial, Helvetica, sans-serif;
:root {
--accent-color-dark: #045d56;
--button-color-dark: #045d56;
--text-accent-color-dark: #1eb980;
--table-border-dark: #00000000;
--tr-color-dark: #1e1e1e;
--tr-nth-color-dark: #121212;
--table-highlight-dark: #616161;
--dark-background-color: #121212;
--dark-text-color: #eeeeee;
}
body.theme-dark {
--background-color: var(--dark-background-color);
--text-color: var(dark-text-color);
}
body{
--accent-color:#303f9f;
--button-color: #303f9f;
--text-accent-color:#303f9f;
--table-border: #e0e0e0;
--table-highlight: #c5cae9;;
--tr-nth-color: #f2f2f2;
--tr-color: none;
--background-color: #ffffff;
--text-color: #000000;
font-family: "Noto Sans", "Liberation Sans","Trebuchet MS", Arial, Helvetica, sans-serif;
background-color: var(--background-color);
color: var(--text-color);
font-size: 1.2rem;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 10%;
background-color: var(--accent-color);
color: white;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
box-shadow: 0 .5rem 1.2rem rgba(0,0,0,.15) !important;
}
.header-brand{
font-weight: 700;
}
header div{
display: inline-block;
align-items: center;
text-align: center;
}
header .spacer{
margin-left: auto;
align-items: center;
}
table {
border-collapse: collapse;
line-height: 1.1rem;
}
td, th {
border: 1px solid rgb(192, 192, 192);
padding: 0.8rem;
}
tr {
transition: 0.1s;
}
tr:nth-child(even){background-color: #f2f2f2;}
border-collapse: collapse;
line-height: 1.1rem;
font-weight: 410;
margin: 0.8rem;
border-radius: 0.4rem;
overflow: hidden;
box-shadow: 0 .5rem 1.2rem rgba(0,0,0,.15) !important;
}
tr:hover {
background-color: #c5cae9;
}
tr:visited {
background-color:#c5cae9;
}
th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
}
h4 {
font-size: 20px;
margin-bottom: 6px;
margin-top: 20px;
font-weight: 600;
}
.hiddendiv {
display:none;
}
.nav-link{
font-weight: 700;
}
.fade{
transition: 0.13s;
}
td, th {
padding: 0.8rem;
padding-left: 0.3rem;
padding-right: 0.3rem;
}
tr {
transition: 0.1s;
background-color: var(--tr-color);
}
tr:nth-child(even){background-color: var(--tr-nth-color);}
.button4:hover {background-color: #e7e7e7;}
tr:hover {
background-color: var(--table-highlight);
box-shadow: 0 .8rem 1.8rem rgba(0,0,0,.15) !important;
}
tr:visited {
background-color:var(--table-highlight);
}
th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4CAF50;
color: white;
}
h4 {
font-size: 20px;
margin-bottom: 6px;
margin-top: 20px;
margin-left: 0.9rem;
font-weight: 600;
}
.all-result{
display: -ms-flexbox;
-ms-flex-direction: column;
-ms-flex-wrap: wrap;
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 50vw;
gap: 1rem;
font-size: 1rem;
}
.all-result-div{
max-width: 25%;
padding: 0 4px;
}
.all-result-div h4{
margin-left: auto;
font-size: 1.4rem;
}
@media only screen and (max-width: 1200px){
.all-result{
display: flex;
flex-direction: row;
flex-wrap: wrap;
height: auto;
gap: 1rem;
}
.all-result-div{
max-width: 100%;
padding: 0px;
margin-left: auto;
margin-right: auto;
}
body{
font-size: 1rem;
}
}
.hiddendiv {
display:none;
}
.nav-link {
font-weight: 600;
transition: 0.3s;
}
.nav-link:hover {
box-shadow: 0 .5rem 1rem rgba(0,0,0,.15) !important;
}
.button4:hover {
background-color: #e7e7e7;
}
.StatusDiv{
color: #ffffffa2;
}
.nav-pills .nav-link{
border-radius: .25rem;
color: var(--text-accent-color);
}
.nav-pills .nav-link.active{
color: #fff;
background-color: var(--button-color);
}
.result-div{
width: max-content;
margin: auto;
}
.table-labels{
font-weight: 900;
font-size: 1.2rem;
}
@media only screen and (max-width: 600px) {
header {
flex-wrap: wrap;
padding-left: 0.2rem;
padding-right: 0.2rem;
}
.StatusDiv{
margin-left: auto;
}
.header-brand {
align-self: flex-start;
width: 100%;
}
.ResultTable{
width: 100%;
margin: 0px;
}
.result-div{
width: 100%;
margin: 0px;
}
.result-div h4{
margin: 0px;
}
.all-result-div{
width: 100%;
}
.club-collum{
display: none;
}
}
@media (prefers-color-scheme: dark) {
body.theme-auto {
--background-color: var(--dark-background-color);
--text-color: var(--dark-text-color);
--tr-nth-color: var(--tr-nth-color-dark);
--table-border: var(--table-border-dark);
--table-highlight: var(--table-highlight-dark);
--accent-color: var(--accent-color-dark);
--text-accent-color: var(--text-accent-color-dark);
--tr-color: var(--tr-color-dark);
--button-color: var(--button-color-dark);
}
}

138
index.php Normal file → Executable file
View File

@ -11,7 +11,18 @@
<link rel="stylesheet" href="common/main.css">
</head>
<body>
<body class="theme-auto">
<header>
<div id="header-brand">
<img src="./common/kok-144x144.png" width="30" height="30" class="d-inline-block align-top" alt="" loading="lazy">
Liveresultater
</div>
<div class="spacer"></div>
<div class="StatusDiv" id="lastUpdate">status</div>
<div class="StatusDiv" id="lastMessage">status</div>
</header>
<!--
<nav class="navbar navbar-dark shadow" style="background-color: #303f9f;">
<div class="container-fluid">
<a class="navbar-brand" href="#">
@ -29,6 +40,8 @@
</div>
</nav>
-->
<div class="container alert alert-warning hiddendiv" role="alert" id="ConnectionAlert">
Du har mistet kontakten med serveren. Last inn sida nytt får å koble til igjen <button type="button" class="btn btn-warning" onclick="location.reload()">Last inn nytt</button>
</div>
@ -42,7 +55,7 @@
<div class="tab-content" id="classes-tab-content">
<div class="tab-pane fade show active" id="alle" role="tabpanel" aria-labelledby="alle">
<div class="container" id="alle-cont"></div>
<div class="all-result" id="alle-cont"></div>
</div>
</div>
@ -51,33 +64,26 @@
<script>
var tabsCreated = false;
function createTabs(tabArray) {
function createTabs(tabArray, tabNameArray) {
for (let i = 0; i < tabArray.length; i++) {
let startStrTab = '<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-toggle="tab"'
let StrTab = startStrTab + 'id="' + tabArray[i] + '-tab" href="#' + tabArray[i] + '" aria-controls="' + tabArray[i] + '" aria-selected="false">' + tabArray[i].replace(/_/g, " ") + '</a></li>';
let StrCont = '<div class="tab-pane fade show" id="' + tabArray[i] + '" role="tabpanel" aria-labelledby="' + tabArray[i] + '-tab"></div>'
console.log(tabNameArray)
let StrTab = startStrTab + 'id="' + tabArray[i] + '-tab" href="#' + tabArray[i] + '" aria-controls="' + tabArray[i] + '" aria-selected="false">' + tabNameArray[i].Class.Name + '</a></li>';
let StrCont = '<div class="result-div tab-pane fade show" id="' + tabArray[i] + '" role="tabpanel" aria-labelledby="' + tabArray[i] + '-tab"></div>'
document.getElementById("classes-tabs").innerHTML += StrTab;
document.getElementById("classes-tab-content").innerHTML += StrCont;
tabsCreated = true;
}
}
function diff_minutes(dt2, dt1) {
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
function TimeFormater(stamp) {
//diff /= 60;
let minutes = Math.floor(diff / 60);
let seconds = diff - minutes * 60;
let hours = Math.floor(diff / 3600);
let minutes = Math.floor(stamp / 60);
let seconds = stamp - minutes * 60;
let hours = Math.floor(stamp / 3600);
return minutes + ":" + seconds;
}
function diff_timestamp(dt2, dt1) {
let diff = (dt2.getTime() - dt1.getTime()) / 1000;
return diff;
}
function sortTable(tableToCheck) {
var table, rows, switching, i, x, y, shouldSwitch;
table = document.getElementById(tableToCheck);
@ -98,9 +104,7 @@
x = rows[i].getElementsByTagName("td")[2];
y = rows[i + 1].getElementsByTagName("td")[2];
// Check if the two rows should switch place:
console.log(parseInt(x.className, 10));
console.log(parseInt(y.className, 10));
if (parseInt(x.className, 10) > parseInt(y.className, 10)) {
if (parseInt(x.persTime, 10) > parseInt(y.persTime, 10)) {
// If so, mark as a switch and break the loop:
shouldSwitch = true;
break;
@ -113,8 +117,8 @@
switching = true;
}
}
for (i = 0; i < (rows.length); i++) {
rows[i].getElementsByTagName("td")[0].innerHTML = i+1;
for (i = 1; i < (rows.length); i++) {
rows[i].getElementsByTagName("td")[0].innerHTML = i+1+".";
}
}
@ -124,40 +128,77 @@
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let xmlObj = JSON.parse(this.responseText);
var classesArray = [];
for (let i = 0; i < xmlObj.ClassResult.length; i++) {
classesArray[i] = xmlObj.ClassResult[i].Class.Name.replace(/ /g, "_");;
classesArray[i] = xmlObj.ClassResult[i].Class.Name.replace(/ |\//g, "_");;
}
console.log(classesArray);
if (tabsCreated == false) {
createTabs(classesArray);
createTabs(classesArray, xmlObj.ClassResult);
}
document.getElementById("alle-cont").innerHTML = "";
//create tables
for (let i = 0; i < xmlObj.ClassResult.length; i++) {
let resultTable = '<table class="container" id="'+classesArray[i].replace(/ /g, "_")+'-table">'
let tableLabels = '<tr class="table-labels"><td></td><td>Løper</td><td class="club-collum">Klubb</td><td>Tid</td><td>Diff</td></tr>';
let resultTable = '<table class="ResultTable " id="'+classesArray[i]+'-table">'+tableLabels;
let winnerTime;
resultTable += '<h4>'+xmlObj.ClassResult[i].Class.Name+'</h4>';
for (let k = 0; k < xmlObj.ClassResult[i].PersonResult.length; k++) {
resultTable += '<tr><td id="Ranking"></td>'
resultTable += '<tr><td id="Ranking"></td>';
//add name
resultTable += "<td>" + xmlObj.ClassResult[i].PersonResult[k].Person.Name.Given + " " + xmlObj.ClassResult[i].PersonResult[k].Person.Name.Family + "</td>"
let d1 = new Date(xmlObj.ClassResult[i].PersonResult[k].Result.FinishTime);
let d2 = new Date(xmlObj.ClassResult[i].PersonResult[k].Result.StartTime);
let timeUsed = diff_minutes(d1, d2);
resultTable += '<td class="'+diff_timestamp(d1, d2)+'">' + timeUsed + '</td>'
resultTable += "</tr>"
//add club
if (xmlObj.ClassResult[i].PersonResult[k].Organisation.Name!='[object Object]'){
resultTable += '<td class="club-collum">' + xmlObj.ClassResult[i].PersonResult[k].Organisation.Name + '</td>'
}
else{
resultTable += '<td class="club-collum">' + "" + '</td>'
}
let timeUsedStamp = xmlObj.ClassResult[i].PersonResult[k].Result.Time;
let timeUsed = TimeFormater(timeUsedStamp);
console.log(xmlObj.ClassResult[i].PersonResult[k].Result.Status );
//Check if person is dsq and add uime
let persStatus = xmlObj.ClassResult[i].PersonResult[k].Result.Status;
if (persStatus == 'OK') {
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + timeUsed + '</td>'
}
else if (persStatus == 'Disqualified') {
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + 'DSQ' +'</td>';
}
else if (persStatus == 'Active'){
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + 'Ikke i mål' +'</td>';
}
else {
resultTable += '<td persTime="'+timeUsedStamp+'" persStatus="'+xmlObj.ClassResult[i].PersonResult[k].Result.Status+'">' + persStatus +'</td>';
}
//add time difference to winner
if (!xmlObj.ClassResult[i].PersonResult[k].Result.Position){
resultTable += '<td>' + "" + '</td>'
}
else if (xmlObj.ClassResult[i].PersonResult[k].Result.Position!=1){
let timeDiff = xmlObj.ClassResult[i].PersonResult[k].Result.Time-winnerTime;
resultTable += '<td>+' + TimeFormater(timeDiff) + '</td>'
}
else if (xmlObj.ClassResult[i].PersonResult[k].Result.Position=1){
winnerTime = xmlObj.ClassResult[i].PersonResult[k].Result.Time;
resultTable += '<td>' + "" + '</td>'
}
resultTable += "</tr>";
}
document.getElementById(classesArray[i].replace(/ /g, "_")).innerHTML = resultTable;
resultTable += "</table>"
console.log(classesArray[i].replace(/ /g, "_")+'-table');
sortTable(classesArray[i].replace(/ /g, "_")+'-table');
document.getElementById(classesArray[i].replace(/ |\//g, "_")).innerHTML = resultTable;
sortTable(classesArray[i].replace(/ |\//g, "_")+'-table');
document.getElementById("alle-cont").innerHTML += '<div class="all-result-div">'+resultTable.replace(/-table/g, "-all-table")+'</div>';
sortTable(classesArray[i].replace(/ |\//g, "_")+'-all-table');
}
console.log(xmlObj)
//console.log(xmlObj)
}
};
xmlhttp.open("GET", "xmlToJson.php", true);
@ -177,7 +218,6 @@
// Will display time in 10:30:23 format
var formattedTime = hours + ':' + minutes.substr(-2) + ':' + seconds.substr(-2);
return formattedTime;
}
@ -191,16 +231,12 @@
statusArray = event.data.split(",");
lastMessage = parseInt(statusArray[3], 10);
console.log(statusArray);
//document.getElementById("result").innerHTML += event.data + "<br>";
document.getElementById("lastUpdate").innerHTML = "Siste oppdatering: " + mkTimeStr(statusArray[1]);
document.getElementById("lastMessage").innerHTML = "Siste melding fra server: " + mkTimeStr(statusArray[2]);
//document.getElementById("liveresult").innerHTML = event.data + "<br>";
document.getElementById("lastMessage").innerHTML = "Siste sjekket: " + mkTimeStr(statusArray[2]);
updateInt = parseInt(statusArray[0], 10);
console.log(updateInt);
if (window.lastUpdate + 5 < parseInt(statusArray[1], 10)) {
//check if update has accured
if (parseInt(statusArray[1], 10) + 6 > parseInt(statusArray[2], 10)) {
updateInt = 1;
}
if (lastUpdate == undefined) {
@ -208,6 +244,7 @@
}
console.log(statusArray);
//update results
if (updateInt == 1) {
loadresults()
console.log("Update!!!!! :=)");
@ -244,5 +281,4 @@
<script src="common/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
</html>

4
updater.php Normal file → Executable file
View File

@ -16,7 +16,7 @@ header('Access-Control-Expose-Headers: X-Events');
include 'lastSavedChange.php';
$resultFile = "ttime-res/Resultater.xml";
$resultFile = "resultater/Resultater.xml";
//load variable from last check
$lastChange = filemtime($resultFile);
$time = date('r');
@ -31,7 +31,7 @@ if ($lastSavedChange<$lastChange){
$var_str = var_export($lastChange, true);
$var = "<?php\n\n\$lastSavedChange = $var_str;\n\n?>";
file_put_contents('lastSavedChange.php', $var, LOCK_EX);
$objXmlDocument = simplexml_load_file("ttime-res/Resultater.xml");
$objXmlDocument = simplexml_load_file("resultater/Resultater.xml");
//xml to json
if ($objXmlDocument === FALSE) {

4
xmlToJson.php Normal file → Executable file
View File

@ -1,6 +1,6 @@
<?php
libxml_use_internal_errors(TRUE);
$objXmlDocument = simplexml_load_file("ttime-res/Resultater.xml");
$objXmlDocument = simplexml_load_file("resultater/Resultater.xml");
if ($objXmlDocument === FALSE) {
foreach(libxml_get_errors() as $error) {
@ -12,4 +12,4 @@ $objJsonDocument = json_encode($objXmlDocument);
$arrOutput = json_decode($objJsonDocument, TRUE);
echo $objJsonDocument;
?>
?>