Pooof - Ampel appears
This commit is contained in:
commit
e3139e671e
6 changed files with 267 additions and 0 deletions
89
ampel.py
Executable file
89
ampel.py
Executable file
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import bottle
|
||||||
|
import json
|
||||||
|
from bottle import route, post, run, template, static_file, request, response, redirect
|
||||||
|
import sqlite3
|
||||||
|
import pdb
|
||||||
|
|
||||||
|
@route("/")
|
||||||
|
def index():
|
||||||
|
return template("display")
|
||||||
|
|
||||||
|
@route("/login")
|
||||||
|
def login():
|
||||||
|
global employees
|
||||||
|
if request.get_cookie("employeeId") is None:
|
||||||
|
return template("login", employees=sorted(employees.items(), key=lambda entry: entry[0]))
|
||||||
|
else:
|
||||||
|
redirect("/manage")
|
||||||
|
|
||||||
|
@post("/login")
|
||||||
|
def loginUser():
|
||||||
|
global employees
|
||||||
|
employeeId = request.forms.get("employeeId")
|
||||||
|
employee = employees[employeeId]
|
||||||
|
response.set_cookie("employeeId", employeeId, max_age=60*60*24*365*10)
|
||||||
|
redirect("/manage")
|
||||||
|
|
||||||
|
@post("/logout")
|
||||||
|
def logout():
|
||||||
|
response.set_cookie("employeeId", "") #clear cookie
|
||||||
|
redirect("/login")
|
||||||
|
|
||||||
|
@route("/manage")
|
||||||
|
def manage():
|
||||||
|
global employees
|
||||||
|
if request.get_cookie("employeeId") is None:
|
||||||
|
redirect("/login")
|
||||||
|
else:
|
||||||
|
return template("manage", employeeData=employees[request.get_cookie("employeeId")])
|
||||||
|
|
||||||
|
@post("/setStatus")
|
||||||
|
def setStatus():
|
||||||
|
if request.get_cookie("employeeId") is None:
|
||||||
|
redirect("/login")
|
||||||
|
else:
|
||||||
|
global employees
|
||||||
|
employeeId = request.get_cookie("employeeId")
|
||||||
|
newStatus = list(employees[employeeId])
|
||||||
|
newStatus[2] = not newStatus[2] #toggle availability
|
||||||
|
employees[employeeId] = newStatus
|
||||||
|
|
||||||
|
redirect("/manage")
|
||||||
|
|
||||||
|
@post("/getStatus")
|
||||||
|
def getStatus():
|
||||||
|
response.content_type = 'application/json'
|
||||||
|
global employees
|
||||||
|
employeeId = request.get_cookie("employeeId")
|
||||||
|
resp = json.dumps(employees)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
@route("/assets/static/<filename>")
|
||||||
|
def staticContent(filename):
|
||||||
|
return static_file(filename, root="./assets/static")
|
||||||
|
|
||||||
|
@route("/assets/js/<filename>")
|
||||||
|
def staticContent(filename):
|
||||||
|
return static_file(filename, root="./assets/js")
|
||||||
|
|
||||||
|
@route("/assets/css/<filename>")
|
||||||
|
def staticContent(filename):
|
||||||
|
return static_file(filename, root="./assets/css")
|
||||||
|
|
||||||
|
def initTool():
|
||||||
|
global employees
|
||||||
|
employees = {}
|
||||||
|
with open("bearbeiter.txt", "r") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
name, room = line.strip().split("|")
|
||||||
|
status = False
|
||||||
|
employeeId = name.strip().replace(" ", "_")
|
||||||
|
employees[employeeId] = (name, room, status)
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bottle.TEMPLATE_PATH += ["./assets/templates/"]
|
||||||
|
initTool()
|
||||||
|
run(host='localhost', port=8080, debug=True)
|
112
assets/js/mainDisplay.js
Normal file
112
assets/js/mainDisplay.js
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
window.onload = function() {
|
||||||
|
setInterval(updateDashboard, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDashboard() {
|
||||||
|
//document.body.innerHTML = ""
|
||||||
|
currentStatus = getEmployeeStatus()
|
||||||
|
currentStatus.then(function(data) {
|
||||||
|
jsonData = data
|
||||||
|
for (var employee in jsonData) {
|
||||||
|
if (!jsonData.hasOwnProperty(employee)) continue;
|
||||||
|
|
||||||
|
name = jsonData[employee][0]
|
||||||
|
room = jsonData[employee][1]
|
||||||
|
available = jsonData[employee][2]
|
||||||
|
//document.body.innerHTML += jsonData[employee][0] + " is available: " + jsonData[employee][2] + "<br />"
|
||||||
|
drawLight(available, name.replace(" ", "_"), name)
|
||||||
|
}
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.log("err")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEmployeeStatus() {
|
||||||
|
return fetch('getStatus', {
|
||||||
|
method: 'post'
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.json()
|
||||||
|
}).catch(function(err) {
|
||||||
|
console.log(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createOrGetLight(id, label) {
|
||||||
|
light = document.querySelectorAll(".trafficLight." + id)
|
||||||
|
if (light.length > 0) {
|
||||||
|
return light[0]
|
||||||
|
} else {
|
||||||
|
light = createLight(id, label)
|
||||||
|
document.body.appendChild(light)
|
||||||
|
return light
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLight(id, labelText) {
|
||||||
|
trafficLight = document.createElement("div")
|
||||||
|
trafficLight.classList.add("trafficLight")
|
||||||
|
trafficLight.classList.add(id)
|
||||||
|
label = document.createElement("div")
|
||||||
|
label.classList.add("label")
|
||||||
|
label.innerHTML = labelText
|
||||||
|
trafficLight.appendChild(label)
|
||||||
|
canvas = document.createElement("canvas")
|
||||||
|
canvas.classList.add("lights")
|
||||||
|
trafficLight.appendChild(canvas)
|
||||||
|
|
||||||
|
return trafficLight
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLight(available, id, label) {
|
||||||
|
container = createOrGetLight(id, label)
|
||||||
|
//clearCanvas()
|
||||||
|
//container = document.querySelectorAll(".trafficLight." + id)[0]
|
||||||
|
canvas = container.children[1]
|
||||||
|
//canvas = document.querySelectorAll(".trafficLight." + id + ">canvas")[0];
|
||||||
|
canvas.width = container.getBoundingClientRect().width
|
||||||
|
canvas.height = container.getBoundingClientRect().height - 80
|
||||||
|
cxt = canvas.getContext("2d");
|
||||||
|
cHeight = canvas.getBoundingClientRect().height
|
||||||
|
cWidth = canvas.getBoundingClientRect().width
|
||||||
|
centerX = cWidth / 2;
|
||||||
|
centerRedY = cHeight / 4;
|
||||||
|
centerGreenY = (cHeight / 4) * 3;
|
||||||
|
halfHeight = cHeight / 2
|
||||||
|
if (halfHeight < cWidth) {
|
||||||
|
radius = halfHeight / 2
|
||||||
|
} else {
|
||||||
|
radius = cWidth / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
radius -= 20 //margin
|
||||||
|
|
||||||
|
if (available == true) {
|
||||||
|
green = "#00f300" //turned on
|
||||||
|
red = "#570000" //turned off
|
||||||
|
} else {
|
||||||
|
green = "#003000"
|
||||||
|
red = "#cc0000"
|
||||||
|
}
|
||||||
|
cxt.strikeStyle = "#999999";
|
||||||
|
cxt.lineWidth = 3;
|
||||||
|
|
||||||
|
// Draw green light
|
||||||
|
cxt.beginPath()
|
||||||
|
cxt.arc(centerX, centerGreenY, radius, 0, 2 * Math.PI);
|
||||||
|
cxt.fillStyle = green;
|
||||||
|
cxt.fill();
|
||||||
|
cxt.stroke();
|
||||||
|
|
||||||
|
// Draw red light
|
||||||
|
cxt.beginPath()
|
||||||
|
cxt.arc(centerX, centerRedY, radius, 0, 2 * Math.PI);
|
||||||
|
cxt.fillStyle = red;
|
||||||
|
cxt.fill();
|
||||||
|
cxt.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCanvas() {
|
||||||
|
canvas = document.getElementsByClassName("lights")[0];
|
||||||
|
cxt = canvas.getContext("2d");
|
||||||
|
cxt.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
33
assets/templates/display.tpl
Normal file
33
assets/templates/display.tpl
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Anzeige</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.trafficLight {
|
||||||
|
display: inline-block;
|
||||||
|
height: 765px;
|
||||||
|
width: 415px;
|
||||||
|
background-color: black;
|
||||||
|
margin-right: 100px;
|
||||||
|
margin-left: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.label {
|
||||||
|
height: 60px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
font-size: 4em;
|
||||||
|
font-weight: "bold";
|
||||||
|
background-color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="assets/js/mainDisplay.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
16
assets/templates/login.tpl
Normal file
16
assets/templates/login.tpl
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Mitarbeiterlogin</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>Login für Mitarbeiter</div>
|
||||||
|
<form method="post">
|
||||||
|
<select name="employeeId">
|
||||||
|
% for employee in employees:
|
||||||
|
<option value="{{employee[0]}}">{{employee[1][0]}}</option>
|
||||||
|
% end
|
||||||
|
</select>
|
||||||
|
<button type="submit">Einloggen</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
14
assets/templates/manage.tpl
Normal file
14
assets/templates/manage.tpl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Ampelmanagement für Benutzer {{employeeData[0]}}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>Hello {{employeeData}}</div>
|
||||||
|
<form method="post" action="logout">
|
||||||
|
<button type="submit">Logout</button>
|
||||||
|
</form>
|
||||||
|
<form method="post" action="setStatus">
|
||||||
|
<button type="submit">Ampel ändern</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
bearbeiter.txt
Executable file
3
bearbeiter.txt
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
Hans Maier|251
|
||||||
|
Ypsilon|252
|
||||||
|
Xanthippe|253
|
Loading…
Reference in a new issue