Compare commits

...
Sign in to create a new pull request.

3 commits

11 changed files with 181 additions and 47 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.venv
db.sqlite
**/__pycache__/

View file

@ -27,6 +27,10 @@ Execute in Terminal "python3 -m venv .venv", for the virtual enviroment activate
Note:
This are early stages of this project listed are missing and planed.
### DB Delete
To delete db simple add first_startup = True in Options.ini and remove db.sqlite
# To Does
---
Must have features / fixes

View file

@ -12,9 +12,13 @@ config.read('Options.ini')
class compare:
def is_user_pass_valid(username, password):
session_username = session.query(User).filter(User.username == username).one()
session.commit()
try: #check if username in db
session_username = session.query(User).filter(User.username == username).one()
session.commit()
except:
return False
print(session_username.hashed_password)
if bcrypt.hashpw(password.encode('utf-8'), session_username.salt) == session_username.hashed_password.encode('utf-8'):
return True
@ -39,17 +43,21 @@ class compare:
OUT: True, False if succeded adding to db
'''
if compare.verifie_order(ordered_list):
#products = Product()
order = Order(desk)
session.add(order)
session.commit()
order = Order(desk)
if compare.verifie_order(ordered_list):
is_emtpy = True #check if nothing in prouduct if True dont commit.
for product in ordered_list:
if int(product[0]) > 0: #dont add not ordered to list
if is_emtpy: #first time enter in loop
session.add(order)
session.commit()
productDB = Product(quantity=int(product[0]),name=product[1],order_id = order.id)
session.add(productDB)
session.add(productDB)
is_emtpy = False
if is_emtpy:
return False
session.commit()
logger.success("Order at desk "+ str(desk) +" resived")
# add a new ordered_list to the database
@ -126,11 +134,10 @@ class get:
def all_orders():
# All unfinished orders (finished is False or string "False")
result = []
desk = 1
orders = session.query(Order).filter(Order.finished == 0).all()
session.commit()
for order in orders:
products = session.query(Product).filter(Product.order_id == order.id , Order.desk_number == desk).all()
products = session.query(Product).filter(Product.order_id == order.id).all()
session.commit()
list_products = []
for p in products:

View file

@ -69,8 +69,7 @@ def login():
form = LoginForm()
if form.validate_on_submit():
user = user_loader(form.username.data)
#TODO if username not in User:
#TODO return if username or pass wrong a red textbox in ui...
if user and compare.is_user_pass_valid(form.username.data, form.password.data):
login_user(user) # store user id in session
@ -82,8 +81,9 @@ def login():
#next = request.args.get('next') is written in documentaion FLASK
#return redirect(next, url_for('orders')) # redirect to orders page
return redirect(url_for('orders')) # redirect to orders page
#return wrong_user_pass.html a indexer for wrong pass or username
return render_template('partials/_wrong_user_pass.html', form=form)
return render_template('login.html', form=form)
@app.route("/logout") #TODO make a button
@login_required
def logout():
@ -95,23 +95,27 @@ def logout():
def orders(): #TODO on new orderGet refresh orders list
if request.method == 'POST':
order_id = request.form.get('order_id')
action = request.form.get('action') # 'finish' or 'undo'
action = request.form.get('action') # 'refresh', 'finish' or 'undo'
order = session.get(Order, int(order_id))
if order: #SQL error handeling just in case
if action == 'finish':
order.finished = True
elif action == 'undo':
order.finished = False
if action == 'finish':
order = session.get(Order, int(order_id))
order.finished = True
session.commit()
return jsonify(success=True)
elif action == 'undo':
order = session.get(Order, int(order_id))
order.finished = False
session.commit()
return jsonify(success=True)
elif action == 'refresh':
html = render_template('partials/_order_rows.html', orders=get.all_orders())
return jsonify(success=True, html=html)
return jsonify(success=False)
return render_template('orders.html', orders=get.all_orders())
@app.route("/order_get", methods=['GET','POST'])
def order_get():
desk= 1
global config
#POST order
if request.method == 'POST' and config['SETTINGS']['lockqrcode_whit_secret'] == 'True':
@ -127,8 +131,11 @@ def order_get():
# Adding order to DB
if compare.process_main(ordered_list, desk):
return '<h1>your order got ressived!</h1>'
else:
#TODO IF nothing ordered send back to main and say something in a txt box
return '<h1>You have selected nothing try again</h1>'
return '<h1>your order coudnt be ressived try again Error:SQL </h1>'
# Veriefie if auth or not from GET
elif request.method == 'GET':
desk = int(request.args['desk'])
@ -137,11 +144,9 @@ def order_get():
return render_template('index.html', desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']), orderableItems = get.valid_products(get_json_=True))
elif config['SETTINGS']['lockqrcode_whit_secret'] == 'False':
return render_template('index.html', desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']),orderableItems = get.valid_products(get_json_=True))
else:
return '<h1>Somethign went wrong try again.</h1>' #TODO Make the HTML prettier for all
return '<h1>404 wrong Secret?</h1>' #TODO Make the HTML prettier for all
elif config['SETTINGS']['lockqrcode_whit_secret'] == 'True':
return '<h1>your LOCKQRCODE is invalid.</h1>'
elif config['SETTINGS']['lockqrcode_whit_secret'] == 'True':
return '<h1>your LOCKQRCODE is invalid.</h1>'
return '<h1>Something went wrong went wrong, Try again.</h1>' #TODO Make the HTML prettier for all
else:
return render_template('index.html',desk=desk, MAX_DESKS=int(config['DEFAULT']['max_desks']),orderableItems = get.valid_products(get_json_=True))

View file

@ -7,7 +7,7 @@
<title>Document</title>
</head>
<body>
<form name="order" onsubmit="return validateForm()" action="{{ url_for('order_get') }}" method="POST" class="flex-container">
<form name="order" onsubmit="return validateForm() && refresh()" action="{{ url_for('order_get') }}" method="POST" class="flex-container">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<li class="box desk-nr">Tisch Nummer
<div>

View file

@ -20,4 +20,4 @@
</form>
</body>
</html>
</html>

View file

@ -35,26 +35,31 @@
<th>Action</th>
<th>Order-Nr</th>
</tr>
<div id="refresh-timer" style="font-size: 0.9em; color: gray; margin-bottom: 10px;">
Last refreshed: 0s ago
</div>
<tbody id="orders-container">
{% for order in orders%}
<tr id="order-{{ order[2] }}">
<td>{{ order[0] }}</td>
<td>
<ul>
{% for product in order[1] %}
<li>{{ product }}</li>
{% endfor %}
</ul>
</td>
<td>
<button class="finish-btn" onclick="markFinished({{ order[2] }})" id="btn-{{ order[2] }}">
Finished
</button>
</td>
<td>order {{ order[2] }} </td>
</tr>
<tr id="order-{{ order[2] }}">
<td>{{ order[0] }}</td>
<td>
<ul>
{% for product in order[1] %}
<li>{{ product }}</li>
{% endfor %}
</ul>
</td>
<td>
<button class="finish-btn" onclick="markFinished({{ order[2] }})" id="btn-{{ order[2] }}">
Finished
</button>
</td>
<td>order {{ order[2] }} </td>
</tr>
{% else %}
<tr><td colspan="3">No open orders.</td></tr>
{% endfor %}
</tbody>
</table>
<script>
var csrfToken = "{{ csrf_token() }}";
@ -120,6 +125,42 @@
}
});
}
let secondsSinceRefresh = 0;
setInterval(() => refreshInfo({ preventDefault: () => {} }), 1000);
function refreshInfo(e) {
secondsSinceRefresh++
e.preventDefault();
document.getElementById('refresh-timer').textContent = `Last refreshed: ${secondsSinceRefresh}s ago`;
// Prevent refresh if any undo countdowns are active
if (Object.keys(window.activeTimers).length > 0) {
console.log('Refresh blocked: undo countdown in progress.');
document.getElementsById('#output').text('Please wait for undo countdown to finish.').show();
return
}
fetch('/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' ,
'X-CSRFToken': csrfToken },
body: `order_id=0&action=refresh`
})
.then(response => response.json())
.then(data => {
if (data.success) {
document.getElementById('orders-container').innerHTML = data.html;
secondsSinceRefresh = 0;
document.getElementById('refresh-timer').textContent = `Last refreshed: 0s ago`
} else {
console.error('Failed to load orders');
}
})
.catch(error => {
console.error('Error fetching and rendering:', error);
});
}
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
{% for order in orders%}
<tr id="order-{{ order[2] }}">
<td>{{ order[0] }}</td>
<td>
<ul>
{% for product in order[1] %}
<li>{{ product }}</li>
{% endfor %}
</ul>
</td>
<td>
<button class="finish-btn" onclick="markFinished({{ order[2] }})" id="btn-{{ order[2] }}">
Finished
</button>
</td>
<td>order {{ order[2] }} </td>
</tr>
{% else %}
<tr><td colspan="3">No open orders.</td></tr>
{% endfor %}
</html>

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<style>
/* Grundstil der Textbox */
div {
border: 2px solid gray;
width: 17vw;
margin-top: 5px;
height: 30px;
text-align: center;
font-size: 1rem;
outline: none;
transition: border-color 0.3s ease;
}
/* Schüttel-Animation definieren */
@keyframes shake {
0% { transform: translateX(0); }
25% { transform: translateX(5px); }
50% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
100% { transform: translateX(0); }
}
/* Animation bei ungültigem Zustand oder wenn Klasse "shake" gesetzt wird */
div.shake {
border-color: red;
animation: shake 0.3s ease-in-out 0s 3;
}
</style>
<body>
<h1>Login Page</h1>
<div type="text" class="shake" placeholder="Invalid">Invalid User or Password</div>
<form method="POST" action="{{ url_for('login') }}">
{{ form.csrf_token }}
{{ form.username.label }}
{{ form.username }}
<br>
<br>
{{ form.password.label }}
{{ form.password }}
<br>
<p>{{ form.remember_me }} {{ form.remember_me.label }}</p>
<br>
{{ form.submit }}
</form>
</body>
</html>

Binary file not shown.

2
app.py
View file

@ -20,7 +20,7 @@ you want async logging.
def run(): #TODO: sys.stderr back to a file log??
logger.add(sys.stderr, format="{time} {level} {message}", filter="startup", level="INFO")
logger.add(sys.stderr, backtrace=True, diagnose=config['OTHER']['log_diagnose'])
app.run(debug=False)
app.run(debug=False, host="0.0.0.0")
if __name__ == "__main__":
#First startup is handled in DB/handler