Add web interface for scanning and checking
This commit is contained in:
parent
f9cac04003
commit
baa602ad90
66
app.py
66
app.py
|
@ -1,11 +1,21 @@
|
|||
from flask import Flask, request, jsonify, make_response
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
from sqlite3 import connect, OperationalError
|
||||
import bcrypt
|
||||
|
||||
app = Flask(__name__)
|
||||
import bcrypt
|
||||
from datetime import datetime
|
||||
from flask import Flask, request, jsonify, make_response, render_template
|
||||
from flask_httpauth import HTTPBasicAuth
|
||||
import flask_excel as excel
|
||||
from dateutil import tz
|
||||
|
||||
|
||||
def utc_to_local(utc_dt):
|
||||
return utc_dt.replace(tzinfo=tz.tzutc()).astimezone(tz.gettz("Europe/Amsterdam"))
|
||||
|
||||
|
||||
app = Flask(__name__, static_url_path='')
|
||||
auth = HTTPBasicAuth()
|
||||
db = connect("database.db", check_same_thread=False)
|
||||
excel.init_excel(app)
|
||||
|
||||
try:
|
||||
cursor = db.cursor()
|
||||
|
@ -23,6 +33,9 @@ except OperationalError:
|
|||
|
||||
@auth.verify_password
|
||||
def verpass(username, password):
|
||||
print(username)
|
||||
if username in (None, '') or password in (None, ''):
|
||||
return False
|
||||
# return True
|
||||
cur = db.cursor()
|
||||
ret = cur.execute('''select password from users where username = ?''', (username,)).fetchone()
|
||||
|
@ -58,6 +71,7 @@ def checknum(username, number, checked=0):
|
|||
@app.route("/ticket", methods=["POST"])
|
||||
@auth.login_required
|
||||
def addticket():
|
||||
print(request.json)
|
||||
if not request.json or "number" not in request.json or "function" not in request.json:
|
||||
return make_response(jsonify({"msg": "missing/faulty request body?"}), 400)
|
||||
fun = request.json["function"]
|
||||
|
@ -119,8 +133,52 @@ def control():
|
|||
return make_response(jsonify({"msg": "Removed!"}), 200)
|
||||
|
||||
|
||||
@app.route("/scan")
|
||||
@auth.login_required
|
||||
def scanlink():
|
||||
return render_template("scan.html", username=auth.username(), func="add", mode="Toevoegen")
|
||||
|
||||
|
||||
@app.route("/check")
|
||||
@auth.login_required
|
||||
def checklink():
|
||||
return render_template("scan.html", username=auth.username(), func="check", mode="Controleren")
|
||||
|
||||
|
||||
# @app.route("/list")
|
||||
# @auth.login_required
|
||||
# def tes():
|
||||
# cur = db.cursor()
|
||||
# tickets = cur.execute('''select * from tickets where username = ?;''', (auth.username(),)).fetchall()
|
||||
# cur.close()
|
||||
# print(tickets)
|
||||
# lst = list()
|
||||
# for (ln, num, dt, inside) in tickets:
|
||||
# lst.append(
|
||||
# {"number": num,
|
||||
# "date": datetime.strptime(dt, "%Y-%m-%d %H:%M:%S").astimezone(tz.gettz("Europe/Amsterdam")).strftime(
|
||||
# "%H:%M:%S %d-%m-%Y"), "inside": inside == 1})
|
||||
# return jsonify(lst)
|
||||
|
||||
|
||||
@app.route("/excel")
|
||||
@auth.login_required
|
||||
def exc():
|
||||
cur = db.cursor()
|
||||
tickets = cur.execute('''select * from tickets where username = ?;''', (auth.username(),)).fetchall()
|
||||
cur.close()
|
||||
print(tickets)
|
||||
lst = list()
|
||||
for (ln, num, dt, inside) in tickets:
|
||||
lst.append({"number": num, "date": datetime.strptime(dt, "%Y-%m-%d %H:%M:%S").astimezone(
|
||||
tz.gettz("Europe/Amsterdam")).strftime(
|
||||
"%H:%M:%S %d-%m-%Y"), "inside": inside == 1})
|
||||
|
||||
return excel.make_response_from_records(lst, 'xlsx', file_name="tickets - " + auth.username())
|
||||
|
||||
|
||||
@app.route("/list")
|
||||
@auth.login_required
|
||||
def check():
|
||||
cur = db.cursor()
|
||||
num1 = cur.execute('''select * from tickets where username = ?;''', (auth.username(),)).fetchall()
|
||||
|
|
29
static/css/style.css
Normal file
29
static/css/style.css
Normal file
|
@ -0,0 +1,29 @@
|
|||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
background-color: dimgrey;
|
||||
}
|
||||
|
||||
#centerdiv {
|
||||
padding: 10px 10px 10px 10px;
|
||||
margin: 5px auto;
|
||||
width: 600px;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
#centerdiv #derk {
|
||||
margin: 0 auto;
|
||||
width: 300px;
|
||||
text-align: left;
|
||||
|
||||
}
|
||||
|
||||
.drawingBuffer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mobileCanvas {
|
||||
padding: 10px 10px 10px 10px;
|
||||
|
||||
}
|
11581
static/libs/quagga.js
Normal file
11581
static/libs/quagga.js
Normal file
File diff suppressed because one or more lines are too long
1
static/libs/quagga.min.js
vendored
Normal file
1
static/libs/quagga.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
172
templates/scan.html
Normal file
172
templates/scan.html
Normal file
|
@ -0,0 +1,172 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=720, initial-scale=1">
|
||||
<title>Ticket Scanner 2.0</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||
<script>
|
||||
var siteWidth = 720;
|
||||
var scale = screen.width / siteWidth;
|
||||
|
||||
document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + siteWidth + ', initial-scale=' + scale + '');
|
||||
|
||||
function postData(url, data, method) {
|
||||
// Default options are marked with *
|
||||
return fetch(url, {
|
||||
body: JSON.stringify(data), // must match 'Content-Type' header
|
||||
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
||||
credentials: 'same-origin', // include, same-origin, *omit
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
|
||||
},
|
||||
method: method || 'POST', // *GET, POST, PUT, DELETE, etc.
|
||||
mode: 'cors', // no-cors, cors, *same-origin
|
||||
redirect: 'follow', // manual, *follow, error
|
||||
referrer: 'no-referrer', // *client, no-referrer
|
||||
})// parses response to JSON
|
||||
}
|
||||
|
||||
function users() {
|
||||
return fetch("/list", {
|
||||
{# body: JSON.stringify(data), // must match 'Content-Type' header#}
|
||||
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
|
||||
credentials: 'same-origin', // include, same-origin, *omit
|
||||
{#headers: {
|
||||
'content-type': 'application/json',
|
||||
|
||||
},#}
|
||||
method: 'GET', // *GET, POST, PUT, DELETE, etc.
|
||||
mode: 'cors', // no-cors, cors, *same-origin
|
||||
redirect: 'follow', // manual, *follow, error
|
||||
referrer: 'no-referrer', // *client, no-referrer
|
||||
}).then(resp => {
|
||||
return resp.text()
|
||||
}).then(data => {
|
||||
console.log(data);
|
||||
return data;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function addUser(username) {
|
||||
document.getElementById("result").innerText = username;
|
||||
postData("/ticket", {number: username, function: "{{ func }}"})
|
||||
.then(function (response) {
|
||||
if (response.ok) {
|
||||
document.getElementById("centerdiv").style.backgroundColor = "#00D41D";
|
||||
setTimeout(function () {
|
||||
document.getElementById("centerdiv").style.backgroundColor = "";
|
||||
}, 2500)
|
||||
} else {
|
||||
document.getElementById("centerdiv").style.backgroundColor = "#D40000";
|
||||
setTimeout(function () {
|
||||
document.getElementById("centerdiv").style.backgroundColor = "";
|
||||
}, 2500)
|
||||
}
|
||||
r = response.json();
|
||||
return r;
|
||||
})
|
||||
.then(function (data) {
|
||||
console.log(data);
|
||||
document.getElementById("msg").innerText = data.msg;
|
||||
|
||||
})
|
||||
|
||||
.catch(function (error) {
|
||||
console.error(error);
|
||||
document.getElementById("centerdiv").backgroundColor = "#D40000";
|
||||
setTimeout(function () {
|
||||
document.getElementById("centerdiv").style.backgroundColor = "#FFFFFF";
|
||||
}, 5000)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setInterval(function () {
|
||||
users().then(data => {
|
||||
document.getElementById("vb").innerHTML = data
|
||||
})
|
||||
}, 1000);
|
||||
|
||||
function addLlnr() {
|
||||
var x = document.getElementById("inputbox").value;
|
||||
if (x.toString().length !== 6) {
|
||||
alert("Een leerlingnummer heeft 6 getallen!");
|
||||
return
|
||||
}
|
||||
if (confirm("Wil je " + x.toString() + " Toevoegen?")) {
|
||||
addUser(x.toString());
|
||||
}
|
||||
document.getElementById("inputbox").value="";
|
||||
}
|
||||
|
||||
function checkval(evt) {
|
||||
if((evt.keyCode === 13) || evt.which === 13 || evt.key === 13){
|
||||
addLlnr();
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="centerdiv">
|
||||
<h1>TicketScanner 2.0: {{ username }}</h1>
|
||||
<h2>{{ mode }}</h2>
|
||||
<div id="derk">
|
||||
<p>Binnen/verkocht: <span id="vb"></span></p>
|
||||
<p>Leerlingnummer: <span id="result"></span></p>
|
||||
<p>Resultaat: <span id="msg"></span></p>
|
||||
<p>Voeg handmatig toe: <input type="text" id="inputbox" title="leerlingnummer" placeholder="######" autofocus="autofocus" {#onclick="addLlnr()"#} onkeydown="return checkval(event)">
|
||||
<button id="addBtn" onclick="addLlnr()">Voeg Toe</button>
|
||||
</p>
|
||||
<p><a href="/excel">Download xlsx bestand</a></p>
|
||||
</div>
|
||||
<div>
|
||||
<div id="mobileCanvas"{#style="display: none; float: bottom;"#}></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="/libs/quagga.min.js"></script>
|
||||
<script>
|
||||
Quagga.init(
|
||||
{
|
||||
inputStream: {
|
||||
name: "Live",
|
||||
locate: true,
|
||||
frequency: 5,
|
||||
type: "LiveStream",
|
||||
target: document.querySelector('#mobileCanvas'), // Or '#yourElement' (optional)
|
||||
constraints: {
|
||||
width: 640,
|
||||
height: 480,
|
||||
facingMode: "environment"
|
||||
},
|
||||
},
|
||||
decoder: {
|
||||
readers: ["codabar_reader"]
|
||||
}
|
||||
},
|
||||
function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return
|
||||
}
|
||||
console.log("Initialization finished. Ready to start");
|
||||
let last = "";
|
||||
Quagga.onDetected(function (data) {
|
||||
let code = data.codeResult.code;
|
||||
code = code.slice(1, -1);
|
||||
if (last !== code) {
|
||||
last = code;
|
||||
addUser(code)
|
||||
}
|
||||
});
|
||||
|
||||
Quagga.start();
|
||||
});
|
||||
</script>
|
||||
</html>
|
Loading…
Reference in a new issue