duzo zmian i funkcji

This commit is contained in:
Mateusz Gruszczyński
2025-07-02 23:51:19 +02:00
parent 36cdcf175a
commit b02bd27aa1
10 changed files with 285 additions and 125 deletions

72
app.py
View File

@ -1,7 +1,8 @@
import os
import secrets
import time
from datetime import datetime, timedelta
from flask import Flask, render_template, redirect, url_for, request, flash
from flask import Flask, render_template, redirect, url_for, request, flash, Blueprint, send_from_directory
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_socketio import SocketIO, emit, join_room
@ -19,6 +20,21 @@ socketio = SocketIO(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
static_bp = Blueprint('static_bp', __name__)
@static_bp.route('/static/js/live.js')
def serve_live_js():
response = send_from_directory('static/js', 'live.js')
response.cache_control.no_cache = True
response.cache_control.no_store = True
response.cache_control.must_revalidate = True
response.expires = 0
response.pragma = 'no-cache'
return response
app.register_blueprint(static_bp)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
@ -33,6 +49,7 @@ class ShoppingList(db.Model):
is_temporary = db.Column(db.Boolean, default=False)
share_token = db.Column(db.String(64), unique=True, nullable=True)
expires_at = db.Column(db.DateTime, nullable=True)
owner = db.relationship('User', backref='lists', lazy=True)
class Item(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -43,10 +60,18 @@ class Item(db.Model):
purchased = db.Column(db.Boolean, default=False)
purchased_at = db.Column(db.DateTime, nullable=True)
class SuggestedProduct(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(150), unique=True, nullable=False)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.context_processor
def inject_time():
return dict(time=time)
@app.before_request
def require_system_password():
if 'authorized' not in request.cookies \
@ -83,6 +108,10 @@ def system_auth():
@app.route('/')
def index_guest():
lists = ShoppingList.query.all()
for l in lists:
items = Item.query.filter_by(list_id=l.id).all()
l.total_count = len(items)
l.purchased_count = len([i for i in items if i.purchased])
return render_template('index.html', lists=lists)
@app.errorhandler(404)
@ -95,21 +124,16 @@ def login():
user = User.query.filter_by(username=request.form['username']).first()
if user and check_password_hash(user.password_hash, request.form['password']):
login_user(user)
flash('Zalogowano pomyślnie')
return redirect(url_for('dashboard'))
flash('Nieprawidłowy login lub hasło')
flash('Zalogowano pomyślnie', 'success')
return redirect(url_for('index_guest'))
flash('Nieprawidłowy login lub hasło', 'danger')
return render_template('login.html')
@app.route('/dashboard')
@login_required
def dashboard():
lists = ShoppingList.query.filter_by(owner_id=current_user.id).all()
return render_template('dashboard.html', lists=lists)
@app.route('/logout')
@login_required
def logout():
logout_user()
flash('Wylogowano pomyślnie', 'success')
return redirect(url_for('login'))
@app.route('/create', methods=['POST'])
@ -122,6 +146,7 @@ def create_list():
new_list = ShoppingList(title=title, owner_id=current_user.id, is_temporary=is_temporary, share_token=token, expires_at=expires_at)
db.session.add(new_list)
db.session.commit()
flash('Utworzono nową listę', 'success')
return redirect(url_for('view_list', list_id=new_list.id))
@app.route('/list/<int:list_id>')
@ -156,8 +181,17 @@ def copy_list(list_id):
copy_item = Item(list_id=new_list.id, name=item.name)
db.session.add(copy_item)
db.session.commit()
flash('Skopiowano listę', 'success')
return redirect(url_for('view_list', list_id=new_list.id))
@app.route('/suggest_products')
def suggest_products():
query = request.args.get('q', '')
suggestions = []
if query:
suggestions = SuggestedProduct.query.filter(SuggestedProduct.name.ilike(f'%{query}%')).limit(5).all()
return {'suggestions': [s.name for s in suggestions]}
@app.route('/admin')
@login_required
def admin_panel():
@ -166,7 +200,7 @@ def admin_panel():
user_count = User.query.count()
list_count = ShoppingList.query.count()
item_count = Item.query.count()
all_lists = ShoppingList.query.all()
all_lists = ShoppingList.query.options(db.joinedload(ShoppingList.owner)).all()
return render_template('admin/admin_panel.html', user_count=user_count, list_count=list_count, item_count=item_count, all_lists=all_lists)
@app.route('/admin/delete_list/<int:list_id>')
@ -175,11 +209,10 @@ def delete_list(list_id):
if not current_user.is_admin:
return redirect(url_for('index_guest'))
list_to_delete = ShoppingList.query.get_or_404(list_id)
# Usuń wszystkie powiązane produkty
Item.query.filter_by(list_id=list_to_delete.id).delete()
db.session.delete(list_to_delete)
db.session.commit()
flash(f'Usunięto listę: {list_to_delete.title}')
flash(f'Usunięto listę: {list_to_delete.title}', 'success')
return redirect(url_for('admin_panel'))
@app.route('/admin/delete_all_lists')
@ -190,7 +223,7 @@ def delete_all_lists():
Item.query.delete()
ShoppingList.query.delete()
db.session.commit()
flash('Usunięto wszystkie listy')
flash('Usunięto wszystkie listy', 'success')
return redirect(url_for('admin_panel'))
@app.route('/admin/add_user', methods=['GET', 'POST'])
@ -204,7 +237,7 @@ def add_user():
new_user = User(username=username, password_hash=password)
db.session.add(new_user)
db.session.commit()
flash('Dodano nowego użytkownika')
flash('Dodano nowego użytkownika', 'success')
return redirect(url_for('admin_panel'))
return render_template('admin/add_user.html')
@ -230,7 +263,7 @@ def reset_password(user_id):
new_password = generate_password_hash(request.form['password'])
user.password_hash = new_password
db.session.commit()
flash('Hasło zresetowane')
flash('Hasło zresetowane', 'success')
return redirect(url_for('list_users'))
return render_template('admin/reset_password.html', user=user)
@ -242,7 +275,7 @@ def delete_user(user_id):
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
flash('Użytkownik usunięty')
flash('Użytkownik usunięty', 'success')
return redirect(url_for('list_users'))
@socketio.on('delete_item')
@ -280,6 +313,11 @@ def handle_add_item(data):
added_by=current_user.id if current_user.is_authenticated else None
)
db.session.add(new_item)
if not SuggestedProduct.query.filter_by(name=name).first():
new_suggestion = SuggestedProduct(name=name)
db.session.add(new_suggestion)
db.session.commit()
emit('item_added', {
'id': new_item.id,