fix(5.11): tabel trimiteri stabil — bug status=None, pills in bara de filtre, nudge "Date noi" in loc de poll 15s, logo ROMFAST marit
- Fix bug: campul hidden de filtru randa literal "None" (status_filtru None +
Jinja default('')) -> poll-ul trimitea status=None -> tabel gol. status or "".
- Pills de stare mutate din bara de status in bara de filtre (filtreazaStare scrie
campul hidden + re-trimite form-ul; filtrul persista la reincarcari). Re-randate
OOB cu contoare proaspete la fiecare reincarcare a tabelului.
- Polling redesign: tabelul nu se mai reincarca singur (fara every 15s). Poller usor
JSON (/_fragments/trimiteri-versiune) detecteaza schimbari -> nudge "Date noi —
Reincarca". Reincarcarea (nudge / actiune) pastreaza filtrul+pagina. Scroll/selectia
nu se mai pierd. Poll-guard eliminat (nu mai exista poll periodic de pauzat).
- Logo ROMFAST 32px -> 60px (ca pe romfast.ro), header min-height 92px, 44px pe mobil.
Regresie: 896 passed, 1 deselected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@ from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, File, Form, HTTPException, Request, UploadFile
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.responses import HTMLResponse, JSONResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
from .. import __version__
|
||||
@@ -113,6 +113,18 @@ def _status_counts(conn, account_id: int) -> dict[str, int]:
|
||||
return {r["status"]: int(r["n"]) for r in rows}
|
||||
|
||||
|
||||
def _trimiteri_versiune(conn, account_id: int) -> str:
|
||||
"""Semnatura ieftina a starii trimiterilor contului: numar randuri + cel mai recent
|
||||
updated_at. Se schimba la orice insert/update/delete -> nudge-ul "Date noi" o compara
|
||||
fara a re-randa tabelul."""
|
||||
row = conn.execute(
|
||||
"SELECT COUNT(*) AS n, COALESCE(MAX(updated_at), '') AS m FROM submissions "
|
||||
"WHERE (account_id = ? OR (? = 1 AND account_id IS NULL))",
|
||||
(account_id, account_id),
|
||||
).fetchone()
|
||||
return f"{row['n']}:{row['m']}"
|
||||
|
||||
|
||||
def _account_active(conn, account_id: int) -> bool:
|
||||
"""True daca contul e activ (sau legacy cu NULL/absent active)."""
|
||||
row = conn.execute("SELECT active FROM accounts WHERE id=?", (account_id,)).fetchone()
|
||||
@@ -196,6 +208,10 @@ def _get_acasa_context(request: Request, conn, account_id: int) -> dict:
|
||||
"are_trimiteri": are_trimiteri,
|
||||
"are_cheie_folosita": are_cheie_folosita,
|
||||
"blocate_total": blocate_total,
|
||||
# Pill-uri de filtrare a starii, randate in bara de filtre (nu in bara de status).
|
||||
"pills_categorii": _pills_categorii(counts),
|
||||
# Semnatura datelor: nudge-ul "Date noi" o compara la fiecare poll usor.
|
||||
"versiune_trimiteri": _trimiteri_versiune(conn, account_id),
|
||||
# US-002: Acasa include caseta de upload -> are nevoie de csrf_token
|
||||
"csrf_token": get_csrf_token(request),
|
||||
}
|
||||
@@ -212,7 +228,9 @@ def _render_panel_acasa(request: Request, conn=None, account_id: int = 1, status
|
||||
{"request": request, "csrf_token": get_csrf_token(request)}
|
||||
)
|
||||
ctx = _get_acasa_context(request, conn, account_id)
|
||||
ctx["status_filtru"] = status
|
||||
# `status or ""`: campul hidden de filtru ar randa literal "None" cu un None Python
|
||||
# (Jinja `default('')` inlocuieste doar undefined), trimitand status=None la poll.
|
||||
ctx["status_filtru"] = status or ""
|
||||
return templates.get_template("_acasa.html").render(ctx)
|
||||
|
||||
|
||||
@@ -621,6 +639,19 @@ def fragment_status(request: Request) -> HTMLResponse:
|
||||
conn.close()
|
||||
|
||||
|
||||
@router.get("/_fragments/trimiteri-versiune", response_class=JSONResponse)
|
||||
def fragment_trimiteri_versiune(request: Request) -> JSONResponse:
|
||||
"""Semnatura curenta a trimiterilor contului (JSON usor). Pollerul "Date noi" o
|
||||
compara cu versiunea cu care s-a randat tabelul; daca difera, arata nudge-ul de
|
||||
reincarcare — tabelul nu se mai schimba singur."""
|
||||
account_id = require_login(request)
|
||||
conn = get_connection()
|
||||
try:
|
||||
return JSONResponse({"v": _trimiteri_versiune(conn, account_id)})
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def _iso_date_prefix(value: object) -> str | None:
|
||||
"""Intoarce primele 10 caractere (YYYY-MM-DD) daca incep cu o data ISO valida, altfel None.
|
||||
|
||||
@@ -795,6 +826,10 @@ def fragment_submissions(
|
||||
"f_vehicul": vehicul_q or "",
|
||||
"f_data_de": data_de or "",
|
||||
"f_data_pana": data_pana or "",
|
||||
# Pill-uri (OOB) + stare activa + versiune pentru nudge-ul "Date noi".
|
||||
"pills_categorii": _pills_categorii(_status_counts(conn, account_id)),
|
||||
"status_filtru": status or "",
|
||||
"versiune_trimiteri": _trimiteri_versiune(conn, account_id),
|
||||
})
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -823,6 +858,9 @@ def _render_submissions(request: Request, conn, account_id: int) -> HTMLResponse
|
||||
"rows": view,
|
||||
"filtru_activ": False,
|
||||
"csrf_token": get_csrf_token(request),
|
||||
"pills_categorii": _pills_categorii(_status_counts(conn, account_id)),
|
||||
"status_filtru": "",
|
||||
"versiune_trimiteri": _trimiteri_versiune(conn, account_id),
|
||||
})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user