generate website

This commit is contained in:
2025-08-24 22:32:24 +02:00
parent 10df613dd7
commit ddef1be220
11 changed files with 937 additions and 260 deletions

BIN
static/images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

199
static/styles.css Normal file
View File

@@ -0,0 +1,199 @@
/* .header-box {
display: flex;
justify-content: space-between; /* pushes items to opposite sides
align-items: top; /* vertically center them
width: 100%;
height: 12%;
font-size: 120%;
}
.header-box h1 {
margin: 0 2.5% 2.5% 2.5%;
} */
html, body {
/* margin: 0; */
padding: 0;
height: 100%;
overflow: hidden; /* no scrollbars */
font-size: 150%;
font-family: "Rubik", sans-serif;
font-optical-sizing: auto;
font-weight: 500;
font-style: normal;
background: #282a35;
color: #899194;
}
.header-table-container {
width: 95%;
margin: 0 2.5% 1% 2.5%;
height: 12%;
display: flex;
flex-direction: column;
justify-content: center;
}
.header-table {
width: 100%;
height: 100%;
border-collapse: collapse;
table-layout: fixed;
font-size: 120%;
}
.header-station {
width: 79%;
}
/* .header-clock {
width: 15%;
} */
.line {
width: 6%;
/* text-align: left; */
/* padding: 0 0 0 0; */
vertical-align: 25%;
}
.destination{
padding: 100em;
}
.departure_time {
width: 12%;
text-align: center;
}
.departure_delay {
width: 10%;
text-align: left;
font-size: 50%;
color: #646a6c
}
.until_departure {
width: 16%;
text-align: right;
}
.departure-table-container {
width: 95%;
margin: 0 2.5% 2.5% 2.5%;
height: 83%;
display: flex;
flex-direction: column;
justify-content: center;
}
.departure-table {
width: 100%;
height: 100%;
border-collapse: collapse;
table-layout: fixed;
font-size: 200%;
}
.departure-table th,
.departure-table td {
padding: 0 0.25em 0 0;
/* vertical-align: middle; */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* border: 1px solid #8de8fa; */
/* height: 12.5%; */
}
.departure-table td:last-child,
.departure-table th:last-child {
padding-right: 0;
}
.line-pill {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.2em 0.5em; /* relative padding */
font-weight: bold;
font-size: 0.75em;
border-radius: 9999px; /* pill shape adjusts automatically */
height: 100%; /* takes most of cell height */
max-height: 100%; /* dont overflow cell */
width: 100%;
max-width: 100%; /* stay within cell */
aspect-ratio: 2 / 1;
box-sizing: border-box;
white-space: nowrap; /* prevent text wrapping */
overflow: hidden; /* hide overflow if text is too long */
text-overflow: ellipsis; /* show "..." if necessary */
}
/* Colors for different lines */
.line-S1 {
background-color: #14bae7;
color: #b5b5b5;
}
.line-S2 {
background-color: #75b728;
color: #b5b5b5;
}
.line-S3 {
background-color: #951781;
color: #b5b5b5;
}
.line-S4 {
background-color: #e30b1b;
color: #b5b5b5;
}
.line-S5 {
background-color: #00517f;
color: #b5b5b5;
}
.line-S6 {
background-color: #008c58;
color: #b5b5b5;
}
.line-S7 {
background-color: #882d22;
color: #b5b5b5;
}
.line-S8 {
background-color: #000000;
color: #f0a901;
}
.line-S20 {
background-color: #ea516c;
color: #b5b5b5;
}
.line-default {
background-color: #bdc3c7;
color: #1f2831;
}
.delay-high {
color: #dc4d21;
}
.delay-neg {
color: #5bc812
}
.until-low {
color: #dc4d21
}
.until-medium {
color: #dc9e21
}

171
static/update_time.js Normal file
View File

@@ -0,0 +1,171 @@
(function () {
function updateClock ( clock ) {
clock.innerHTML = new Date().toLocaleTimeString();
}
function ensureTableSize(table, x, y) {
// Adjust number of rows
while (table.rows.length < x) {
table.insertRow();
}
while (table.rows.length > x) {
table.deleteRow(table.rows.length - 1);
}
// Ensure each row has y cells
for (let row of table.rows) {
while (row.cells.length < y) {
row.insertCell();
}
while (row.cells.length > y) {
row.deleteCell(row.cells.length - 1);
}
}
}
function formatWithSign(num) {
if (num > 0) {
return `+ ${num}`;
} else if (num < 0) {
return `- ${Math.abs(num)}`;
} else {
return "";
}
}
function cssClassExists(className) {
return Array.from(document.styleSheets).some(sheet => {
try {
return Array.from(sheet.cssRules).some(rule =>
rule.selectorText === `.${className}`
);
} catch (e) {
// Ignore CORS-restricted stylesheets
return false;
}
});
}
function redraw_table(data, table) {
// const res = JSON.parse(result)
const columns = {
"line": 0,
"destination": 1,
"departure_time": 2,
"departure_delay": 3,
"until_departure": 4
}
// console.log(data)
ensureTableSize(table, Math.min(data.length, 8), 5);
for (let i = 0; i < Math.min(data.length, 8); i++) {
const row = table.rows[i];
// row.classList.add("departure-table-row")
// row.style.height = `$10%`;
const train = Object.entries(data[i]);
for (let [key, value] of train) {
if (key in columns) {
const cell = row.cells[columns[key]]; // Get the cell once
cell.classList.add(key); // Add class based on column name
if (key == "line") {
// cell.textContent = String(value);
const lineClass = `line-${value}`;
const appliedClass = cssClassExists(lineClass) ? lineClass : "line-default";
cell.innerHTML = `<span class="line-pill ${appliedClass}">${value}</span>`;
const pill = document.querySelector('.line-pill');
const cellHeight = cell.clientHeight;
const cellWidth = cell.clientWidth;
// Set maximum sizes dynamically
pill.style.maxWidth = `${cellHeight * 2}px`;
pill.style.maxHeight = `${cellWidth * 0.5}px`;
}
if (key == "destination") {
dest = String(value);
dest = dest.replace(/\s*\(.*?\)\s*/g, "")
.replace(/^München\s*/i, "")
.replace(/^[\s-]+|[\s-]+$/g, "");
cell.textContent = dest;
}
if (key == "departure_time") {
if (train["canceled"]) {
cell.textContent = "Fällt aus :(";
cell.classList.add("train-canceled");
} else {
const date = new Date(value*1000);
cell.textContent = date.toLocaleTimeString("de-DE",
{
hour: "2-digit",
minute: "2-digit"
}
);
}
}
if (key == "departure_delay") {
if (train["canceled"]) {
cell.textContent = "";
} else {
cell.textContent = formatWithSign(value);
if (value >= 5) {
cell.classList.add("delay-high");
} else if (value < 0) {
cell.classList.add("delay-neg");
}
}
}
if (key == "until_departure") {
if (train["canceled"]) {
cell.textContent = "";
} else {
const minutes = Math.round(value/60);
cell.textContent = String(minutes) + " min";
if (minutes <= 6) {
cell.classList.add("until-low");
} else if (minutes <= 10) {
cell.classList.add("until-medium");
}
}
}
// cell.innerHTML.classList.add("scrolling-text")
}
}
}
// document.querySelector('.departure-table')
// .style.setProperty('--row-count', table.rows.length);
}
function updateTable( table ){
fetch('/update', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
// TODO: pass number of rows we want
})
.then(response => response.json())
.then(result => {
// console.log(result);
redraw_table(result.table_data, table);
// const res = JSON.parse(result);
// console.log(res.table_data);
// for (const elem of res.table_data) {
// console.log(elem);
// }
});
}
var clockElement = document.getElementById( "clock" );
var tableElement = document.getElementById( "departures" );
setInterval(function () {
updateClock( clockElement );
updateTable( tableElement);
}, 1000);
}());