zapamietanie akcji
This commit is contained in:
+2
-2
@@ -96,11 +96,11 @@ def create_app(test_config=None):
|
|||||||
filename = request.view_args.get("filename", "") if request.view_args else ""
|
filename = request.view_args.get("filename", "") if request.view_args else ""
|
||||||
|
|
||||||
if filename.endswith((".css", ".js")):
|
if filename.endswith((".css", ".js")):
|
||||||
response.headers["Cache-Control"] = "public, max-age=3600, immutable"
|
response.headers["Cache-Control"] = "public, max-age=2592000, immutable"
|
||||||
response.headers.pop("Content-Disposition", None)
|
response.headers.pop("Content-Disposition", None)
|
||||||
|
|
||||||
elif response.mimetype == "text/html":
|
elif response.mimetype == "text/html":
|
||||||
response.headers["Cache-Control"] = "private, no-store"
|
response.headers["Cache-Control"] = "no-store, private, must-revalidate"
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -308,7 +308,17 @@ def fuel():
|
|||||||
p = fetch_orlen_price(request.form["fuel_type"], fueled_at.date(), price_region); wholesale=p["price_per_liter"]; source=p["source"]
|
p = fetch_orlen_price(request.form["fuel_type"], fueled_at.date(), price_region); wholesale=p["price_per_liter"]; source=p["source"]
|
||||||
except Exception: pass
|
except Exception: pass
|
||||||
station_label = station_company.company_name if station_company else request.form.get("station")
|
station_label = station_company.company_name if station_company else request.form.get("station")
|
||||||
e = FuelEntry(vehicle=vehicle, user_id=current_user.id, fueled_at=fueled_at, liters=Decimal(request.form["liters"]), price_per_liter=Decimal(request.form["price_per_liter"]), fuel_type=request.form["fuel_type"], odometer=odometer, station=station_label, station_company_id=station_company.id if station_company else None, invoice_number=request.form.get("invoice_number"), used_fuel_card="used_fuel_card" in request.form, wholesale_price=wholesale, wholesale_source=source)
|
requested_card_id = request.form.get("fuel_card_id", type=int)
|
||||||
|
default_card_id = vehicle.fuel_card_id or current_user.fuel_card_id
|
||||||
|
fuel_card = db.session.get(FuelCard, requested_card_id or default_card_id) if (requested_card_id or default_card_id) else None
|
||||||
|
used_fuel_card = "used_fuel_card" in request.form and fuel_card is not None
|
||||||
|
if fuel_card and fuel_card.company_id and fuel_card.company_id != (vehicle.company_id or vehicle.owner.company_id):
|
||||||
|
response = error_response("Wybrana karta nie należy do firmy pojazdu"); return response or redirect(url_for("main.fuel"))
|
||||||
|
if used_fuel_card and station_company:
|
||||||
|
card_rule = FuelCardStationRule.query.filter_by(fuel_card_id=fuel_card.id, station_company_id=station_company.id).first()
|
||||||
|
if card_rule and not card_rule.allowed:
|
||||||
|
response = error_response("Ta stacja jest zablokowana dla wybranej karty paliwowej", 403); return response or redirect(url_for("main.fuel"))
|
||||||
|
e = FuelEntry(vehicle=vehicle, user_id=current_user.id, fueled_at=fueled_at, liters=Decimal(request.form["liters"]), price_per_liter=Decimal(request.form["price_per_liter"]), fuel_type=request.form["fuel_type"], odometer=odometer, station=station_label, station_company_id=station_company.id if station_company else None, fuel_card_id=fuel_card.id if used_fuel_card else None, invoice_number=request.form.get("invoice_number"), used_fuel_card=used_fuel_card, wholesale_price=wholesale, wholesale_source=source)
|
||||||
freeze_vat_action(e, settings.vat_rate)
|
freeze_vat_action(e, settings.vat_rate)
|
||||||
freeze_settlement(e, settings, source="Automatycznie przy dodaniu")
|
freeze_settlement(e, settings, source="Automatycznie przy dodaniu")
|
||||||
vehicle.current_odometer = odometer; db.session.add(e); db.session.commit(); response = ok_response("Zapisano tankowanie", redirect=url_for("main.dashboard")); return response or redirect(url_for("main.dashboard"))
|
vehicle.current_odometer = odometer; db.session.add(e); db.session.commit(); response = ok_response("Zapisano tankowanie", redirect=url_for("main.dashboard")); return response or redirect(url_for("main.dashboard"))
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ html,body{min-height:100%}body{min-height:100vh;min-height:100dvh;display:flex;f
|
|||||||
.app-navbar .nav-link{border-radius:.6rem;padding:.55rem .75rem;font-weight:550;color:var(--bs-secondary-color)}.app-navbar .nav-link:hover{color:var(--bs-emphasis-color);background:var(--bs-tertiary-bg)}.app-navbar .nav-link.active{color:var(--bs-primary);background:color-mix(in srgb,var(--bs-primary) 10%,transparent)}.navbar-divider{height:1.5rem;border-left:1px solid var(--bs-border-color);margin-left:.35rem}
|
.app-navbar .nav-link{border-radius:.6rem;padding:.55rem .75rem;font-weight:550;color:var(--bs-secondary-color)}.app-navbar .nav-link:hover{color:var(--bs-emphasis-color);background:var(--bs-tertiary-bg)}.app-navbar .nav-link.active{color:var(--bs-primary);background:color-mix(in srgb,var(--bs-primary) 10%,transparent)}.navbar-divider{height:1.5rem;border-left:1px solid var(--bs-border-color);margin-left:.35rem}
|
||||||
.app-main{flex:1;padding-top:2rem;padding-bottom:3rem}.app-footer{padding:1.25rem 0;border-top:1px solid var(--bs-border-color-translucent);background:var(--bs-body-bg);color:var(--bs-secondary-color)}.app-footer a{color:inherit}
|
.app-main{flex:1;padding-top:2rem;padding-bottom:3rem}.app-footer{padding:1.25rem 0;border-top:1px solid var(--bs-border-color-translucent);background:var(--bs-body-bg);color:var(--bs-secondary-color)}.app-footer a{color:inherit}
|
||||||
.page-header{display:flex;justify-content:space-between;align-items:flex-end;gap:1rem;margin-bottom:1.5rem}.page-header h1{letter-spacing:-.035em}.page-kicker{font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700;color:var(--bs-primary);margin-bottom:.3rem}
|
.page-header{display:flex;justify-content:space-between;align-items:flex-end;gap:1rem;margin-bottom:1.5rem}.page-header h1{letter-spacing:-.035em}.page-kicker{font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;font-weight:700;color:var(--bs-primary);margin-bottom:.3rem}
|
||||||
#live-alerts{max-width:min(420px,calc(100vw - 2rem))}.app-alert{box-shadow:var(--app-shadow);border:0}
|
#live-alerts,.app-alert-host{position:fixed;top:max(1rem,env(safe-area-inset-top));right:max(1rem,env(safe-area-inset-right));z-index:1080;width:min(420px,calc(100vw - 2rem));pointer-events:none}.app-alert-host .alert,#live-alerts .alert{pointer-events:auto}.app-alert{box-shadow:var(--app-shadow);border:0}
|
||||||
.auth-page{background:radial-gradient(circle at 20% 10%,color-mix(in srgb,var(--bs-primary) 14%,transparent),transparent 34%),radial-gradient(circle at 85% 85%,color-mix(in srgb,var(--bs-warning) 10%,transparent),transparent 30%),var(--bs-tertiary-bg)}.auth-main{display:grid;place-items:center;width:100%;padding-top:2rem;padding-bottom:2rem}.auth-shell{width:min(100%,28rem)}.auth-brand{display:block;width:max-content;margin:0 auto 1.25rem;font-size:1.8rem;font-weight:850;letter-spacing:-.055em}.auth-card{border-color:color-mix(in srgb,var(--bs-primary) 18%,var(--bs-border-color));box-shadow:none}
|
.auth-page{background:var(--bs-tertiary-bg)}.auth-main{display:grid;place-items:center;width:100%;padding-top:2rem;padding-bottom:2rem}.auth-shell{width:min(100%,28rem)}.auth-brand{display:block;width:max-content;margin:0 auto 1.25rem;font-size:1.8rem;font-weight:850;letter-spacing:-.055em}.auth-card{border-color:color-mix(in srgb,var(--bs-primary) 18%,var(--bs-border-color));box-shadow:none}
|
||||||
|
|
||||||
/* Geometria interfejsu jest wspólna dla wszystkich motywów. Motyw zmienia wyłącznie kolory. */
|
/* Geometria interfejsu jest wspólna dla wszystkich motywów. Motyw zmienia wyłącznie kolory. */
|
||||||
.app-navbar{min-height:4.25rem}
|
.app-navbar{min-height:4.25rem}
|
||||||
@@ -22,8 +22,10 @@ html,body{min-height:100%}body{min-height:100vh;min-height:100dvh;display:flex;f
|
|||||||
[data-bs-theme="dark"] .app-navbar{background:rgba(24,26,29,.94);border-bottom-color:#34383d;box-shadow:0 .1rem .45rem rgba(0,0,0,.18)}
|
[data-bs-theme="dark"] .app-navbar{background:rgba(24,26,29,.94);border-bottom-color:#34383d;box-shadow:0 .1rem .45rem rgba(0,0,0,.18)}
|
||||||
[data-bs-theme="dark"] .app-footer{background:#1b1d20;border-top-color:#34383d}
|
[data-bs-theme="dark"] .app-footer{background:#1b1d20;border-top-color:#34383d}
|
||||||
[data-bs-theme="dark"] .brand-fuel{color:#f8f9fa}
|
[data-bs-theme="dark"] .brand-fuel{color:#f8f9fa}
|
||||||
[data-bs-theme="dark"] .auth-page{background:radial-gradient(circle at 20% 10%,rgba(55,139,230,.16),transparent 36%),radial-gradient(circle at 85% 85%,rgba(255,193,7,.08),transparent 32%),#141619}
|
[data-bs-theme="dark"] .auth-page{background:#141619}
|
||||||
@media(max-width:991.98px){.app-main{padding-top:1.35rem}.app-navbar .navbar-collapse{border-top:1px solid var(--bs-border-color-translucent);margin-top:.75rem}.app-navbar .nav-link{padding:.7rem .8rem}.page-header{align-items:stretch;flex-direction:column}}
|
@media(max-width:991.98px){.app-main{padding-top:1.35rem}.app-navbar .navbar-collapse{border-top:1px solid var(--bs-border-color-translucent);margin-top:.75rem}.app-navbar .nav-link{padding:.7rem .8rem}.page-header{align-items:stretch;flex-direction:column}}
|
||||||
@media(max-width:575.98px){.app-main{padding-left:1rem;padding-right:1rem}.page-header h1{font-size:1.65rem}.auth-main{padding-top:1.25rem;padding-bottom:1.25rem}}
|
@media(max-width:575.98px){.app-main{padding-left:1rem;padding-right:1rem}.page-header h1{font-size:1.65rem}.auth-main{padding-top:1.25rem;padding-bottom:1.25rem}}
|
||||||
|
|
||||||
@supports(padding:max(0px)){.app-navbar{padding-top:max(.5rem,env(safe-area-inset-top))}.app-footer{padding-bottom:max(1.25rem,env(safe-area-inset-bottom))}}
|
@supports(padding:max(0px)){.app-navbar{padding-top:max(.5rem,env(safe-area-inset-top))}.app-footer{padding-bottom:max(1.25rem,env(safe-area-inset-bottom))}}
|
||||||
|
|
||||||
|
.auth-page .app-alert{box-shadow:none}
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ window.FuelTrack=window.FuelTrack||{};
|
|||||||
FuelTrack.charts={};
|
FuelTrack.charts={};
|
||||||
FuelTrack.qs=(s,r=document)=>r.querySelector(s);
|
FuelTrack.qs=(s,r=document)=>r.querySelector(s);
|
||||||
FuelTrack.qsa=(s,r=document)=>[...r.querySelectorAll(s)];
|
FuelTrack.qsa=(s,r=document)=>[...r.querySelectorAll(s)];
|
||||||
FuelTrack.notify=(message,type='success')=>{let host=FuelTrack.qs('#live-alerts');if(!host){host=document.createElement('div');host.id='live-alerts';host.className='position-fixed top-0 end-0 p-3';host.style.zIndex='1080';document.body.append(host)}const el=document.createElement('div');el.className=`alert alert-${type} shadow`;el.textContent=message;host.append(el);setTimeout(()=>el.remove(),3500)};
|
FuelTrack.notify=(message,type='success')=>{let host=FuelTrack.qs('#live-alerts');if(!host){host=document.createElement('div');host.id='live-alerts';host.className='app-alert-host';document.body.append(host)}const el=document.createElement('div');el.className=`alert alert-${type} alert-dismissible fade show app-alert`;el.textContent=message;host.append(el);setTimeout(()=>el.remove(),3500)};
|
||||||
FuelTrack.debounce=(fn,delay=300)=>{let timer;return(...args)=>{clearTimeout(timer);timer=setTimeout(()=>fn(...args),delay)}};
|
FuelTrack.debounce=(fn,delay=300)=>{let timer;return(...args)=>{clearTimeout(timer);timer=setTimeout(()=>fn(...args),delay)}};
|
||||||
|
|||||||
@@ -41,10 +41,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<main class="container app-main {% if not current_user.is_authenticated %}auth-main{% endif %}">
|
|
||||||
{% with msgs=get_flashed_messages(with_categories=true) %}
|
{% with msgs=get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if msgs %}
|
||||||
|
<div id="server-alerts" class="app-alert-host" aria-live="polite" aria-atomic="true">
|
||||||
{% for cat,msg in msgs %}<div class="alert alert-{{cat}} alert-dismissible fade show app-alert" role="alert">{{msg}}<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Zamknij"></button></div>{% endfor %}
|
{% for cat,msg in msgs %}<div class="alert alert-{{cat}} alert-dismissible fade show app-alert" role="alert">{{msg}}<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Zamknij"></button></div>{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
<main class="container app-main {% if not current_user.is_authenticated %}auth-main{% endif %}">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
{% if current_user.is_authenticated %}<footer class="app-footer"><div class="container d-flex justify-content-between align-items-center small"><span>@linuxiarz.pl</span><a href="/docs" target="_blank" rel="noopener">Dokumentacja API</a></div></footer>{% endif %}
|
{% if current_user.is_authenticated %}<footer class="app-footer"><div class="container d-flex justify-content-between align-items-center small"><span>@linuxiarz.pl</span><a href="/docs" target="_blank" rel="noopener">Dokumentacja API</a></div></footer>{% endif %}
|
||||||
|
|||||||
Reference in New Issue
Block a user