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