zmiany w css oraz poprawki w ux
This commit is contained in:
24
app.py
24
app.py
@@ -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>')
|
||||
|
@@ -2,6 +2,7 @@ Flask
|
||||
Flask-SQLAlchemy
|
||||
Flask-Login
|
||||
Flask-SocketIO
|
||||
Flask-Compress
|
||||
eventlet
|
||||
Werkzeug
|
||||
Pillow
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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 %}
|
||||
|
@@ -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 %}
|
||||
|
@@ -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 %}
|
||||
|
Reference in New Issue
Block a user