zmiany ux i kodowe
This commit is contained in:
114
app.py
114
app.py
@@ -1,3 +1,7 @@
|
|||||||
|
import markdown as md
|
||||||
|
import hashlib, os
|
||||||
|
import re
|
||||||
|
import socket
|
||||||
from flask import Flask, render_template, request, redirect, url_for, flash
|
from flask import Flask, render_template, request, redirect, url_for, flash
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_login import (
|
from flask_login import (
|
||||||
@@ -11,29 +15,42 @@ from flask_login import (
|
|||||||
from werkzeug.security import generate_password_hash, check_password_hash
|
from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from markupsafe import Markup
|
from markupsafe import Markup
|
||||||
from sqlalchemy import event, Numeric
|
from sqlalchemy import event, Numeric, select
|
||||||
from sqlalchemy.engine import Engine
|
from sqlalchemy.engine import Engine
|
||||||
from decimal import Decimal, InvalidOperation
|
from decimal import Decimal, InvalidOperation
|
||||||
import markdown as md
|
|
||||||
from flask import request, flash, abort
|
from flask import request, flash, abort
|
||||||
import os
|
try:
|
||||||
import re
|
from zoneinfo import ZoneInfo # Python 3.9+
|
||||||
import socket
|
except ImportError:
|
||||||
|
from backports.zoneinfo import ZoneInfo
|
||||||
|
|
||||||
|
|
||||||
|
def build_fingerprint(paths):
|
||||||
|
h = hashlib.sha256()
|
||||||
|
for base in paths:
|
||||||
|
if not os.path.exists(base):
|
||||||
|
continue
|
||||||
|
for root, _, files in os.walk(base):
|
||||||
|
for f in sorted(files):
|
||||||
|
p = os.path.join(root, f)
|
||||||
|
try:
|
||||||
|
with open(p, "rb") as fh:
|
||||||
|
h.update(fh.read())
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
return h.hexdigest()[:8]
|
||||||
|
|
||||||
|
APP_VERSION = f"{datetime.now():%Y.%m.%d}+{build_fingerprint(['templates','static','app.py'])}"
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
app.config['APP_VERSION'] = APP_VERSION
|
||||||
|
|
||||||
# Ładujemy konfigurację z pliku config.py
|
# Ładujemy konfigurację z pliku config.py
|
||||||
app.config.from_object("config.Config")
|
app.config.from_object("config.Config")
|
||||||
|
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
login_manager = LoginManager(app)
|
login_manager = LoginManager(app)
|
||||||
login_manager.login_view = "zaloguj"
|
login_manager.login_view = "zaloguj"
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
from zoneinfo import ZoneInfo # Python 3.9+
|
|
||||||
except ImportError:
|
|
||||||
from backports.zoneinfo import ZoneInfo
|
|
||||||
|
|
||||||
LOCAL_TZ = ZoneInfo("Europe/Warsaw")
|
LOCAL_TZ = ZoneInfo("Europe/Warsaw")
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +160,7 @@ class GlobalSettings(db.Model):
|
|||||||
|
|
||||||
@login_manager.user_loader
|
@login_manager.user_loader
|
||||||
def load_user(user_id):
|
def load_user(user_id):
|
||||||
return User.query.get(int(user_id))
|
return db.session.get(User, int(user_id))
|
||||||
|
|
||||||
|
|
||||||
@event.listens_for(Engine, "connect")
|
@event.listens_for(Engine, "connect")
|
||||||
@@ -235,6 +252,11 @@ def inject_globals():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def inject_version():
|
||||||
|
return {'APP_VERSION': app.config['APP_VERSION']}
|
||||||
|
|
||||||
|
|
||||||
# TRASY PUBLICZNE
|
# TRASY PUBLICZNE
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
@@ -255,7 +277,9 @@ def page_not_found(e):
|
|||||||
|
|
||||||
@app.route("/zbiorka/<int:zbiorka_id>")
|
@app.route("/zbiorka/<int:zbiorka_id>")
|
||||||
def zbiorka(zbiorka_id):
|
def zbiorka(zbiorka_id):
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
if zb.ukryta and (not current_user.is_authenticated or not current_user.is_admin):
|
if zb.ukryta and (not current_user.is_authenticated or not current_user.is_admin):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
@@ -364,7 +388,9 @@ def formularz_zbiorek(zbiorka_id=None):
|
|||||||
|
|
||||||
# Tryb
|
# Tryb
|
||||||
is_edit = zbiorka_id is not None
|
is_edit = zbiorka_id is not None
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id) if is_edit else None
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
global_settings = GlobalSettings.query.first()
|
global_settings = GlobalSettings.query.first()
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
@@ -498,7 +524,9 @@ def dodaj_wplate(zbiorka_id):
|
|||||||
flash("Brak uprawnień", "danger")
|
flash("Brak uprawnień", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id) if is_edit else None
|
||||||
|
if is_edit and not zb:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
try:
|
try:
|
||||||
@@ -527,7 +555,9 @@ def usun_zbiorka(zbiorka_id):
|
|||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger")
|
flash("Brak uprawnień", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
db.session.delete(zb)
|
db.session.delete(zb)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("Zbiórka została usunięta", "success")
|
flash("Zbiórka została usunięta", "success")
|
||||||
@@ -540,7 +570,9 @@ def edytuj_stan(zbiorka_id):
|
|||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger")
|
flash("Brak uprawnień", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
try:
|
try:
|
||||||
nowy_stan = Decimal(request.form.get("stan", "").replace(",", "."))
|
nowy_stan = Decimal(request.form.get("stan", "").replace(",", "."))
|
||||||
@@ -560,7 +592,9 @@ def zmien_widzialnosc(zbiorka_id):
|
|||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger")
|
flash("Brak uprawnień", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
zb.ukryta = not zb.ukryta
|
zb.ukryta = not zb.ukryta
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("Zbiórka została " + ("ukryta" if zb.ukryta else "przywrócona"), "success")
|
flash("Zbiórka została " + ("ukryta" if zb.ukryta else "przywrócona"), "success")
|
||||||
@@ -579,7 +613,6 @@ def create_admin_account():
|
|||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def apply_headers(response):
|
def apply_headers(response):
|
||||||
# --- STATIC: jak wcześniej ---
|
|
||||||
if request.path.startswith("/static/"):
|
if request.path.startswith("/static/"):
|
||||||
response.headers.pop("Content-Disposition", None)
|
response.headers.pop("Content-Disposition", None)
|
||||||
response.headers["Vary"] = "Accept-Encoding"
|
response.headers["Vary"] = "Accept-Encoding"
|
||||||
@@ -616,7 +649,7 @@ def apply_headers(response):
|
|||||||
response.headers.pop("Vary", None)
|
response.headers.pop("Vary", None)
|
||||||
else:
|
else:
|
||||||
response.headers["Vary"] = "Cookie, Accept-Encoding"
|
response.headers["Vary"] = "Cookie, Accept-Encoding"
|
||||||
default_cache = app.config.get("CACHE_CONTROL_HEADER") or "private, max-age=0"
|
default_cache = app.config.get("CACHE_CONTROL_HEADER") or "private, no-store"
|
||||||
response.headers["Cache-Control"] = default_cache
|
response.headers["Cache-Control"] = default_cache
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -694,7 +727,9 @@ def dodaj_wydatek(zbiorka_id):
|
|||||||
flash("Brak uprawnień", "danger")
|
flash("Brak uprawnień", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
try:
|
try:
|
||||||
@@ -734,7 +769,9 @@ def oznacz_zbiorka(zbiorka_id):
|
|||||||
flash("Brak uprawnień do wykonania tej operacji", "danger")
|
flash("Brak uprawnień do wykonania tej operacji", "danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("index"))
|
||||||
|
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
if "niezrealizowana" in request.path:
|
if "niezrealizowana" in request.path:
|
||||||
zb.zrealizowana = False
|
zb.zrealizowana = False
|
||||||
@@ -762,7 +799,9 @@ def robots():
|
|||||||
def transakcje_zbiorki(zbiorka_id):
|
def transakcje_zbiorki(zbiorka_id):
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
||||||
zb = Zbiorka.query.get_or_404(zbiorka_id)
|
zb = db.session.get(Zbiorka, zbiorka_id)
|
||||||
|
if zb is None:
|
||||||
|
abort(404)
|
||||||
aktywnosci = (
|
aktywnosci = (
|
||||||
[{"typ": "wpłata", "id": w.id, "kwota": w.kwota, "opis": w.opis, "data": w.data} for w in zb.wplaty] +
|
[{"typ": "wpłata", "id": w.id, "kwota": w.kwota, "opis": w.opis, "data": w.data} for w in zb.wplaty] +
|
||||||
[{"typ": "wydatek","id": x.id, "kwota": x.kwota,"opis": x.opis,"data": x.data} for x in zb.wydatki]
|
[{"typ": "wydatek","id": x.id, "kwota": x.kwota,"opis": x.opis,"data": x.data} for x in zb.wydatki]
|
||||||
@@ -776,7 +815,9 @@ def transakcje_zbiorki(zbiorka_id):
|
|||||||
def zapisz_wplate(wplata_id):
|
def zapisz_wplate(wplata_id):
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
||||||
w = Wplata.query.get_or_404(wplata_id)
|
w = db.session.get(Wplata, wplata_id)
|
||||||
|
if w is None:
|
||||||
|
abort(404)
|
||||||
zb = w.zbiorka
|
zb = w.zbiorka
|
||||||
try:
|
try:
|
||||||
nowa_kwota = Decimal(request.form.get("kwota", "").replace(",", "."))
|
nowa_kwota = Decimal(request.form.get("kwota", "").replace(",", "."))
|
||||||
@@ -800,7 +841,9 @@ def zapisz_wplate(wplata_id):
|
|||||||
def usun_wplate(wplata_id):
|
def usun_wplate(wplata_id):
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
||||||
w = Wplata.query.get_or_404(wplata_id)
|
w = db.session.get(Wplata, wplata_id)
|
||||||
|
if w is None:
|
||||||
|
abort(404)
|
||||||
zb = w.zbiorka
|
zb = w.zbiorka
|
||||||
zb.stan -= w.kwota
|
zb.stan -= w.kwota
|
||||||
db.session.delete(w)
|
db.session.delete(w)
|
||||||
@@ -814,7 +857,9 @@ def usun_wplate(wplata_id):
|
|||||||
def zapisz_wydatek(wydatek_id):
|
def zapisz_wydatek(wydatek_id):
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
||||||
x = Wydatek.query.get_or_404(wydatek_id)
|
x = db.session.get(Wydatek, wydatek_id)
|
||||||
|
if x is None:
|
||||||
|
abort(404)
|
||||||
zb = x.zbiorka
|
zb = x.zbiorka
|
||||||
try:
|
try:
|
||||||
nowa_kwota = Decimal(request.form.get("kwota", "").replace(",", "."))
|
nowa_kwota = Decimal(request.form.get("kwota", "").replace(",", "."))
|
||||||
@@ -839,7 +884,9 @@ def zapisz_wydatek(wydatek_id):
|
|||||||
def usun_wydatek(wydatek_id):
|
def usun_wydatek(wydatek_id):
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
flash("Brak uprawnień", "danger"); return redirect(url_for("index"))
|
||||||
x = Wydatek.query.get_or_404(wydatek_id)
|
x = db.session.get(Wydatek, wydatek_id)
|
||||||
|
if x is None:
|
||||||
|
abort(404)
|
||||||
zb = x.zbiorka
|
zb = x.zbiorka
|
||||||
zb.stan += x.kwota
|
zb.stan += x.kwota
|
||||||
db.session.delete(x)
|
db.session.delete(x)
|
||||||
@@ -867,9 +914,16 @@ if __name__ == "__main__":
|
|||||||
with app.app_context():
|
with app.app_context():
|
||||||
db.create_all()
|
db.create_all()
|
||||||
# Tworzenie konta głównego admina, jeśli nie istnieje
|
# Tworzenie konta głównego admina, jeśli nie istnieje
|
||||||
if not User.query.filter_by(is_admin=True).first():
|
stmt = select(User).filter_by(is_admin=True)
|
||||||
main_admin = User(username=app.config["MAIN_ADMIN_USERNAME"], is_admin=True)
|
admin = db.session.execute(stmt).scalars().first()
|
||||||
|
|
||||||
|
if not admin:
|
||||||
|
main_admin = User(
|
||||||
|
username=app.config["MAIN_ADMIN_USERNAME"],
|
||||||
|
is_admin=True
|
||||||
|
)
|
||||||
main_admin.set_password(app.config["MAIN_ADMIN_PASSWORD"])
|
main_admin.set_password(app.config["MAIN_ADMIN_PASSWORD"])
|
||||||
db.session.add(main_admin)
|
db.session.add(main_admin)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
app.run(debug=True)
|
app.run(debug=True)
|
||||||
|
@@ -14,11 +14,26 @@
|
|||||||
<h3 class="card-title mb-0">Dodaj wpłatę: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
<h3 class="card-title mb-0">Dodaj wpłatę: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
{% if zbiorka.cel %}
|
{% if zbiorka.cel %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Cel: {{ zbiorka.cel|round(2) }}
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
PLN</span>
|
Cel: {{ zbiorka.cel|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Stan: {{ zbiorka.stan|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{% if zbiorka.cel and zbiorka.cel > 0 %}
|
||||||
|
{% set delta = zbiorka.cel - zbiorka.stan %}
|
||||||
|
{% if delta > 0 %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Brakuje: {{ delta|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Nadwyżka: {{ (-delta)|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Stan: {{ zbiorka.stan|round(2) }}
|
|
||||||
PLN</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -82,5 +97,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/dodaj_wplate.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/dodaj_wplate.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -13,14 +13,30 @@
|
|||||||
<div
|
<div
|
||||||
class="card-header bg-secondary text-white d-flex flex-wrap align-items-center justify-content-between gap-2">
|
class="card-header bg-secondary text-white d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<h3 class="card-title mb-0">Dodaj wydatek: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
<h3 class="card-title mb-0">Dodaj wydatek: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||||
{% if zbiorka.cel %}
|
{% if has_cel %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Cel: {{ zbiorka.cel|round(2) }}
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
PLN</span>
|
Cel: {{ zbiorka.cel|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Obecnie: {{ zbiorka.stan|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{% if has_cel %}
|
||||||
|
{% set delta = zbiorka.cel - zbiorka.stan %}
|
||||||
|
{% if delta > 0 %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Brakuje: {{ delta|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Nadwyżka: {{ (-delta)|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Stan: {{ zbiorka.stan|round(2)
|
|
||||||
}} PLN</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -59,5 +75,5 @@
|
|||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/dodaj_wydatek.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/dodaj_wydatek.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -20,11 +20,26 @@
|
|||||||
<h3 class="card-title mb-0">Edytuj stan: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
<h3 class="card-title mb-0">Edytuj stan: <span class="fw-semibold">{{ zbiorka.nazwa }}</span></h3>
|
||||||
<div class="d-flex align-items-center flex-wrap gap-2">
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||||
{% if has_cel %}
|
{% if has_cel %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Cel: {{ zbiorka.cel|round(2) }}
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
PLN</span>
|
Cel: {{ zbiorka.cel|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Obecnie: {{ zbiorka.stan|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{% if has_cel %}
|
||||||
|
{% set delta = zbiorka.cel - zbiorka.stan %}
|
||||||
|
{% if delta > 0 %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Brakuje: {{ delta|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Nadwyżka: {{ (-delta)|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span class="badge bg-dark border" style="border-color: var(--border);">Obecnie: {{ zbiorka.stan|round(2) }}
|
|
||||||
PLN</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -124,5 +139,5 @@
|
|||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/edytuj_stan.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/edytuj_stan.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -37,15 +37,35 @@
|
|||||||
Cel: {{ zbiorka.cel|round(2) }} PLN
|
Cel: {{ zbiorka.cel|round(2) }} PLN
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if zbiorka.ukryj_kwote %}
|
|
||||||
<span class="badge bg-secondary">Kwoty ukryte</span>
|
{% if not zbiorka.ukryj_kwote %}
|
||||||
{% else %}
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
<span class="badge bg-success">Kwoty widoczne</span>
|
Stan: {{ zbiorka.stan|round(2) }} PLN
|
||||||
{% endif %}
|
</span>
|
||||||
|
|
||||||
|
{% if zbiorka.cel %}
|
||||||
|
{% set delta = zbiorka.cel - zbiorka.stan %}
|
||||||
|
{% if delta > 0 %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Brakuje: {{ delta|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% elif delta < 0 %} <span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Nadwyżka: {{ (-delta)|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if zbiorka.ukryj_kwote %}
|
||||||
|
<span class="badge bg-secondary">Kwoty niepubliczne</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-success">Kwoty widoczne</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<small class="opacity-75">Uzupełnij podstawowe dane i dane płatności</small>
|
<small class="opacity-75">Uzupełnij podstawowe dane i dane płatności</small>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@@ -82,10 +102,10 @@
|
|||||||
|
|
||||||
<!-- SEKCJA: Lista produktów -->
|
<!-- SEKCJA: Lista produktów -->
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h6 class="text-muted mb-2">Lista produktów</h6>
|
<h6 class="text-muted mb-2">Lista produktów / Pozycje / Cele</h6>
|
||||||
<p class="text-muted small mb-3">
|
<p class="text-muted small mb-3">
|
||||||
Wypunktuj dokładnie produkty do zakupu — podaj nazwę, opcjonalny link do sklepu i cenę.
|
Wypunktuj dokładnie produkty do zakupu — podaj nazwę, opcjonalny link do sklepu i cenę.
|
||||||
Status domyślnie <em>Do kupienia</em>; przełącz na <em>Kupione</em> po realizacji.
|
Status domyślnie <code>Do kupienia</code>; przełącz na <code>Kupione</code> po realizacji.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
@@ -221,7 +241,6 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h6 class="text-muted mb-2">Cel i widoczność</h6>
|
<h6 class="text-muted mb-2">Cel i widoczność</h6>
|
||||||
|
|
||||||
{# === BOX: zgodność sumy produktów z celem === #}
|
|
||||||
<div id="celSyncBox" class="alert d-none py-2 px-3 mb-3" role="alert">
|
<div id="celSyncBox" class="alert d-none py-2 px-3 mb-3" role="alert">
|
||||||
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<div id="celSyncMsg" class="small"></div>
|
<div id="celSyncMsg" class="small"></div>
|
||||||
@@ -268,8 +287,8 @@
|
|||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
|
||||||
<script src="{{ url_for('static', filename='js/mde_custom.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/mde_custom.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/formularz_zbiorek.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/formularz_zbiorek.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/produkty_formularz.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/produkty_formularz.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/kwoty_formularz.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/kwoty_formularz.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -139,5 +139,5 @@
|
|||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/transakcje.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/transakcje.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -162,5 +162,5 @@
|
|||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/ustawienia.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/ustawienia.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
<title>{% block title %}Aplikacja Zbiórek{% endblock %}</title>
|
<title>{% block title %}Aplikacja Zbiórek{% endblock %}</title>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.0/dist/darkly/bootstrap.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.0/dist/darkly/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}" />
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/custom.css') }}?v={{ APP_VERSION }}" />
|
||||||
{% block extra_head %}{% endblock %}
|
{% block extra_head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -80,10 +80,12 @@
|
|||||||
{{ global_settings.footer_text if global_settings and global_settings.footer_text else "© " ~ (now().year if now
|
{{ global_settings.footer_text if global_settings and global_settings.footer_text else "© " ~ (now().year if now
|
||||||
else '2025') ~ " linuxiarz.pl" }}
|
else '2025') ~ " linuxiarz.pl" }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<div class="small text-muted">v{{ APP_VERSION }}</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="{{ url_for('static', filename='js/progress.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/progress.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
|
|
||||||
{% block extra_scripts %}{% endblock %}
|
{% block extra_scripts %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
@@ -49,11 +49,24 @@ zbiórki{% endif %}{% endblock %}
|
|||||||
<span class="badge bg-dark border" style="border-color: var(--border);">
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
Stan: {{ z.stan|round(2) }} PLN
|
Stan: {{ z.stan|round(2) }} PLN
|
||||||
</span>
|
</span>
|
||||||
{% else %}
|
|
||||||
<span class="badge bg-secondary">Kwoty ukryte</span>
|
{% if z.cel > 0 %}
|
||||||
{% endif %}
|
{% set delta = z.cel - z.stan %}
|
||||||
|
{% if delta > 0 %}
|
||||||
|
<span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Brakuje: {{ delta|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% elif delta < 0 %} <span class="badge bg-dark border" style="border-color: var(--border);">
|
||||||
|
Nadwyżka: {{ (-delta)|round(2) }} PLN
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<span class="badge bg-secondary">Kwoty niepubliczne</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="mb-1">
|
<div class="mb-1">
|
||||||
<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100"
|
<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100"
|
||||||
aria-valuenow="{{ progress_clamped|round(2) if not z.ukryj_kwote else '' }}"
|
aria-valuenow="{{ progress_clamped|round(2) if not z.ukryj_kwote else '' }}"
|
||||||
|
@@ -51,5 +51,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
<script src="{{ url_for('static', filename='js/walidacja_logowanie.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/walidacja_logowanie.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -57,5 +57,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
<script src="{{ url_for('static', filename='js/walidacja_rejestracja.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/walidacja_rejestracja.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -18,7 +18,7 @@
|
|||||||
<span class="badge rounded-pill" style="background: var(--accent); color:#111;">Zrealizowana</span>
|
<span class="badge rounded-pill" style="background: var(--accent); color:#111;">Zrealizowana</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if zbiorka.ukryj_kwote %}
|
{% if zbiorka.ukryj_kwote %}
|
||||||
<span class="badge bg-secondary">Kwoty ukryte</span>
|
<span class="badge bg-secondary">Kwoty niepubliczne</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="badge bg-success">Kwoty widoczne</span>
|
<span class="badge bg-success">Kwoty widoczne</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -264,6 +264,6 @@
|
|||||||
|
|
||||||
{% block extra_scripts %}
|
{% block extra_scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ url_for('static', filename='js/zbiorka.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/zbiorka.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/progress.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/progress.js') }}?v={{ APP_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
Reference in New Issue
Block a user