zmiany w css oraz poprawki w ux

This commit is contained in:
Mateusz Gruszczyński
2025-07-07 15:23:34 +02:00
parent c9573ad41a
commit 78e5e274be
6 changed files with 54 additions and 30 deletions

24
app.py
View File

@@ -2,11 +2,17 @@ import os
import secrets
import time
import mimetypes
import sys
import platform
import psutil
from datetime import datetime, timedelta
from flask import Flask, render_template, redirect, url_for, request, flash, Blueprint, send_from_directory, request, abort, session, jsonify, make_response
from markupsafe import Markup
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_compress import Compress
from flask_socketio import SocketIO, emit, join_room
from werkzeug.security import generate_password_hash, check_password_hash
from config import Config
@@ -16,11 +22,11 @@ from werkzeug.middleware.proxy_fix import ProxyFix
from sqlalchemy import func, extract
from collections import defaultdict, deque
app = Flask(__name__)
app.config.from_object(Config)
app.config['COMPRESS_ALGORITHM'] = ['zstd', 'br', 'gzip', 'deflate']
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1)
SYSTEM_PASSWORD = app.config.get('SYSTEM_PASSWORD', 'changeme')
DEFAULT_ADMIN_USERNAME = app.config.get('DEFAULT_ADMIN_USERNAME', 'admin')
DEFAULT_ADMIN_PASSWORD = app.config.get('DEFAULT_ADMIN_PASSWORD', 'admin123')
@@ -39,10 +45,15 @@ socketio = SocketIO(app, async_mode="eventlet")
login_manager = LoginManager(app)
login_manager.login_view = 'login'
# flask-compress
compress = Compress()
compress.init_app(app)
static_bp = Blueprint('static_bp', __name__)
# dla live
active_users = {}
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
@@ -142,7 +153,6 @@ def serve_css_lib(filename):
response.headers.pop('Etag', None)
return response
app.register_blueprint(static_bp)
def allowed_file(filename):
@@ -618,6 +628,9 @@ def admin_panel():
.scalar() or 0
)
process = psutil.Process(os.getpid())
app_mem = process.memory_info().rss // (1024 * 1024) # w MB
return render_template(
'admin/admin_panel.html',
user_count=user_count,
@@ -629,7 +642,10 @@ def admin_panel():
total_expense_sum=total_expense_sum,
year_expense_sum=year_expense_sum,
month_expense_sum=month_expense_sum,
now=now
now=now,
python_version=sys.version,
system_info=platform.platform(),
app_memory=f"{app_mem} MB",
)
@app.route('/admin/delete_list/<int:list_id>')

View File

@@ -2,6 +2,7 @@ Flask
Flask-SQLAlchemy
Flask-Login
Flask-SocketIO
Flask-Compress
eventlet
Werkzeug
Pillow

View File

@@ -16,6 +16,7 @@
background-color: #2c2f33 !important;
color: white !important;
}
/* --- Styl przycisku wyboru pliku --- */
input[type="file"]::file-selector-button {
background-color: #225d36;
@@ -52,39 +53,40 @@ input[type="file"]::file-selector-button {
/* Badge - kolory pasujące do ciemnych alertów */
.badge.bg-success, .badge.text-bg-success {
background-color: #225d36 !important; /* jak alert-success */
color: #eaffea !important;
background-color: #225d36 !important;
color: #eaffea !important;
}
.badge.bg-danger, .badge.text-bg-danger {
background-color: #7a1f23 !important; /* jak alert-danger */
color: #ffeaea !important;
background-color: #7a1f23 !important;
color: #ffeaea !important;
}
.badge.bg-info, .badge.text-bg-info {
background-color: #1d3a4d !important; /* jak alert-info */
color: #eaf6ff !important;
background-color: #1d3a4d !important;
color: #eaf6ff !important;
}
.badge.bg-warning, .badge.text-bg-warning {
background-color: #665c1e !important; /* jak alert-warning */
color: #fffbe5 !important;
background-color: #665c1e !important;
color: #fffbe5 !important;
}
.badge.bg-secondary, .badge.text-bg-secondary {
background-color: #343a40 !important; /* ciemny szary */
color: #e2e3e5 !important;
background-color: #343a40 !important;
color: #e2e3e5 !important;
}
.badge.bg-primary, .badge.text-bg-primary {
background-color: #184076 !important; /* ciemny niebieski */
color: #e6f0ff !important;
background-color: #184076 !important;
color: #e6f0ff !important;
}
.badge.bg-light, .badge.text-bg-light {
background-color: #444950 !important; /* ciemniejszy jasny */
color: #f8f9fa !important;
background-color: #444950 !important;
color: #f8f9fa !important;
}
.badge.bg-dark, .badge.text-bg-dark {
background-color: #181a1b !important; /* bardzo ciemny */
color: #f8f9fa !important;
background-color: #181a1b !important;
color: #f8f9fa !important;
}
input[type="checkbox"] {
/* --- Styl dla własnych checkboxów --- */
input[type="checkbox"].large-checkbox {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
@@ -99,9 +101,9 @@ input[type="checkbox"] {
vertical-align: middle;
}
input[type="checkbox"]::before {
input[type="checkbox"].large-checkbox::before {
content: '✗';
color: #dc3545; /* Bootstrap danger */
color: #dc3545;
font-size: 1.5em;
font-weight: bold;
position: absolute;
@@ -112,16 +114,16 @@ input[type="checkbox"]::before {
transition: color 0.2s;
}
input[type="checkbox"]:checked::before {
input[type="checkbox"].large-checkbox:checked::before {
content: '✓';
color: #ffc107; /* Bootstrap warning */
color: #ffc107;
}
input[type="checkbox"]:disabled::before {
input[type="checkbox"].large-checkbox:disabled::before {
opacity: 0.5;
cursor: not-allowed;
}
input[type="checkbox"]:disabled {
input[type="checkbox"].large-checkbox:disabled {
cursor: not-allowed;
}
@@ -133,4 +135,4 @@ input[type="checkbox"]:disabled {
input.form-control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}

View File

@@ -202,4 +202,9 @@ document.getElementById('select-all').addEventListener('click', function(){
<script src="{{ url_for('static_bp.serve_js', filename='expenses.js') }}"></script>
{% endblock %}
<div class="position-fixed bottom-0 end-0 m-2 p-2 small"
style="background: rgba(255,255,255,0.1); color: #f8f9fa; border-radius: 8px; text-align: right; margin-bottom: 140px; width: auto; max-width: 100%;">
Python: {{ python_version.split()[0] }} | {{ system_info }} | RAM app: {{ app_memory }}
</div>
{% endblock %}

View File

@@ -76,7 +76,7 @@ Lista: <strong>{{ list.title }}</strong>
{% for item in items %}
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap {% if item.purchased %}bg-success text-white{% else %}item-not-checked{% endif %}" id="item-{{ item.id }}">
<div class="d-flex align-items-center flex-wrap gap-2 flex-grow-1">
<input type="checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<input class="large-checkbox" type="checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">
{{ item.name }}
{% if item.quantity and item.quantity > 1 %}

View File

@@ -21,7 +21,7 @@
<ul id="items" class="list-group mb-3">
{% for item in items %}
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap clickable-item {% if item.purchased %}bg-success text-white{% else %}item-not-checked{% endif %}" id="item-{{ item.id }}"> <div class="d-flex align-items-center gap-3 flex-grow-1">
<input type="checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<input class="large-checkbox" type="checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">
{{ item.name }}
{% if item.quantity and item.quantity > 1 %}