feat(5.8): reguli mapare pe text (substring/cont) + UX tabel trimiteri (detaliu inline, fara scroll, cod RAR)
Reguli text per cont (operation_text_rules), resolve_prestatii cu param aditiv text_rules + precedenta stricta, threadat pe toate cele 6 callsite-uri + valid_codes + seam classify_prezentare. UI Mapari: sectiune reguli + preview pre-salvare + overlap + telemetrie text_rule_hit. UX tabel: cod_rar sub operatie, pill eticheta scurta, fara scroll orizontal (scopat .tabel-trimiteri + carduri <768px), detaliu inline expandabil (a11y + pauza poll). code-review: reparat regula auto_send=0 care trimitea automat la RAR in loc sa tina randul pentru review. 814 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -162,6 +162,52 @@
|
||||
.dt-pager button { background:transparent; color:var(--ink); border:1px solid var(--line);
|
||||
padding:5px 12px; min-height:32px; }
|
||||
.dt-pager button:disabled { opacity:.45; cursor:default; }
|
||||
/* === Tabel trimiteri (PRD 5.8 US-007): fara scroll orizontal. SCOPAT prin
|
||||
.tabel-trimiteri ca sa NU strice celelalte tabele (.tablewrap e partajat de
|
||||
Mapari/Formate). Permitem wrap controlat pe coloanele text + latimi rezonabile. === */
|
||||
.tabel-trimiteri table { table-layout:fixed; }
|
||||
.tabel-trimiteri th, .tabel-trimiteri td { white-space:normal; word-break:break-word; vertical-align:top; }
|
||||
.tabel-trimiteri .col-chk { width:30px; }
|
||||
.tabel-trimiteri .col-id { width:48px; }
|
||||
.tabel-trimiteri .col-stare { width:104px; }
|
||||
.tabel-trimiteri .col-data { width:104px; }
|
||||
.tabel-trimiteri .col-rar { width:96px; }
|
||||
.tabel-trimiteri .col-actualizat { width:128px; }
|
||||
.tabel-trimiteri .col-operatie > div { line-height:1.35; }
|
||||
/* secundarul muted („cod RAR" / „nemapat") — >=12px, contrast pe var(--muted) >=4.5:1 */
|
||||
.tabel-trimiteri .cod-rar-sub { font-size:12px; margin-top:2px; }
|
||||
/* === Detaliu inline (PRD 5.8 US-008): rand-sibling expandabil sub randul selectat. === */
|
||||
/* Chevron de stare (▸ inchis / ▾ deschis), rotit prin schimbarea glifei in JS. */
|
||||
.tabel-trimiteri .chevron { display:inline-block; color:var(--muted); font-size:11px;
|
||||
width:1.1em; text-align:center; margin-right:2px; }
|
||||
/* Randul deschis: fundal evidentiat (nu doar culoare de text -> a11y). */
|
||||
.tabel-trimiteri tr.rand-deschis > td { background:#1d212b; }
|
||||
[data-theme="light"] .tabel-trimiteri tr.rand-deschis > td { background:#eef1f6; }
|
||||
/* Conectorul detaliului = fundal subtil + border-top (NU border-left accent / slop). */
|
||||
.tabel-trimiteri tr.detaliu-rand > td { padding:0; border-top:2px solid var(--accent);
|
||||
background:color-mix(in srgb, var(--accent) 6%, var(--card)); }
|
||||
.tabel-trimiteri tr.detaliu-rand .card { margin:10px; }
|
||||
/* `hidden` trebuie sa invinga `display:block` din banda <768 (specificitate). */
|
||||
.tabel-trimiteri tr.detaliu-rand[hidden] { display:none; }
|
||||
/* 768-1024px: ascunde Actualizat (e in detaliu) -> 7 coloane, fara scroll */
|
||||
@media (max-width:1024px) {
|
||||
.tabel-trimiteri .col-actualizat { display:none; }
|
||||
}
|
||||
/* Tinta de atins >=44px pe touch (chevron-ul e ancora de toggle). */
|
||||
@media (pointer:coarse) {
|
||||
.tabel-trimiteri .chevron { min-width:44px; min-height:44px; line-height:44px; }
|
||||
}
|
||||
/* <768px: card per rand (eticheta:valoare stivuit), nu tabel -> fara scroll orizontal */
|
||||
@media (max-width:767px) {
|
||||
.tabel-trimiteri table { table-layout:auto; }
|
||||
.tabel-trimiteri thead { display:none; }
|
||||
.tabel-trimiteri table, .tabel-trimiteri tbody, .tabel-trimiteri tr, .tabel-trimiteri td { display:block; width:auto; }
|
||||
.tabel-trimiteri tr { border:1px solid var(--line); border-radius:8px; padding:8px 12px; margin-bottom:10px; }
|
||||
.tabel-trimiteri td { border-bottom:none; padding:4px 0; display:flex; gap:10px; align-items:baseline; }
|
||||
.tabel-trimiteri td::before { content:attr(data-eticheta); color:var(--muted); font-size:12px;
|
||||
flex:0 0 auto; min-width:120px; }
|
||||
.tabel-trimiteri td.col-chk { display:none; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -371,5 +417,94 @@
|
||||
document.body.addEventListener('htmx:afterSettle', function(e) { enhance(e.target); });
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
// Detaliu trimitere INLINE (PRD 5.8 US-008): randul de detaliu (#detaliu-{id}) e
|
||||
// un <tr class="detaliu-rand"> sibling, ascuns pana la deschidere. La click pe rand:
|
||||
// - se inchid celelalte detalii (un singur rand deschis o data);
|
||||
// - se arata randul-sibling (placeholder „Se incarca…" prin hx-indicator);
|
||||
// - chevron ▸/▾ + fundal evidentiat + aria-expanded sincronizate.
|
||||
// Re-click pe acelasi rand inchide fara re-fetch. Cat un detaliu e deschis, poll-ul
|
||||
// de 15s (#submissions-wrap) e pus pe pauza (D-eng-2) ca lista sa nu se miste sub
|
||||
// operator. Delegare pe document.body -> supravietuieste swap-urilor HTMX ale listei.
|
||||
(function() {
|
||||
function chevron(row, on) {
|
||||
var c = row.querySelector('.chevron');
|
||||
if (c) c.innerHTML = on ? '▾' : '▸'; // ▾ / ▸
|
||||
}
|
||||
function setExpanded(row, on) {
|
||||
row.setAttribute('aria-expanded', on ? 'true' : 'false');
|
||||
if (on) row.classList.add('rand-deschis'); else row.classList.remove('rand-deschis');
|
||||
chevron(row, on);
|
||||
}
|
||||
function detRowFor(id) {
|
||||
var cont = document.getElementById('detaliu-' + id);
|
||||
return cont ? cont.closest('tr.detaliu-rand') : null;
|
||||
}
|
||||
function closeOne(row) {
|
||||
var id = row.getAttribute('data-detaliu-id');
|
||||
var cont = document.getElementById('detaliu-' + id);
|
||||
if (cont) cont.innerHTML = '';
|
||||
var dr = detRowFor(id);
|
||||
if (dr) dr.hidden = true;
|
||||
setExpanded(row, false);
|
||||
}
|
||||
function closeAllDetalii(except) {
|
||||
document.querySelectorAll('tr.trimitere-row[aria-expanded="true"]').forEach(function(r) {
|
||||
if (r !== except) closeOne(r);
|
||||
});
|
||||
}
|
||||
// Expus pentru butonul „Inchide" din _trimitere_detaliu.html: goleste containerul
|
||||
// randului CURENT si readuce focusul pe randul declansator.
|
||||
window.inchideDetaliu = function(id) {
|
||||
var row = document.getElementById('trimitere-row-' + id);
|
||||
if (row) { closeOne(row); row.focus(); }
|
||||
else {
|
||||
var cont = document.getElementById('detaliu-' + id);
|
||||
if (cont) cont.innerHTML = '';
|
||||
var dr = detRowFor(id);
|
||||
if (dr) dr.hidden = true;
|
||||
}
|
||||
};
|
||||
// Expus pentru scriptul fragmentului: marcheaza randul ca deschis dupa un re-swap
|
||||
// (corectie/mapare inline), inchizand orice alt detaliu ramas deschis.
|
||||
window.marcheazaDetaliuDeschis = function(row) {
|
||||
closeAllDetalii(row);
|
||||
setExpanded(row, true);
|
||||
};
|
||||
// htmx:beforeRequest — single point: pauza poll + toggle deschidere/inchidere.
|
||||
document.body.addEventListener('htmx:beforeRequest', function(evt) {
|
||||
var elt = evt.detail && evt.detail.elt;
|
||||
if (!elt) return;
|
||||
// Pauza poll periodic cat un detaliu e deschis (cererea vine chiar de pe wrap).
|
||||
if (elt.id === 'submissions-wrap' &&
|
||||
document.querySelector('tr.detaliu-rand:not([hidden])')) {
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
if (!(elt.classList && elt.classList.contains('trimitere-row'))) return;
|
||||
var id = elt.getAttribute('data-detaliu-id');
|
||||
if (elt.getAttribute('aria-expanded') === 'true') {
|
||||
// Re-click pe randul deschis -> inchide, fara re-fetch.
|
||||
evt.preventDefault();
|
||||
window.inchideDetaliu(id);
|
||||
return;
|
||||
}
|
||||
// Deschidere: inchide celelalte, arata randul-sibling (placeholder loading).
|
||||
closeAllDetalii(elt);
|
||||
var dr = detRowFor(id);
|
||||
if (dr) dr.hidden = false;
|
||||
setExpanded(elt, true);
|
||||
});
|
||||
// Tastatura (role=button): Enter/Space deschid/inchid randul focusat.
|
||||
document.body.addEventListener('keydown', function(evt) {
|
||||
var t = evt.target;
|
||||
if (!(t && t.classList && t.classList.contains('trimitere-row'))) return;
|
||||
if (evt.key === 'Enter' || evt.key === ' ' || evt.key === 'Spacebar') {
|
||||
evt.preventDefault();
|
||||
t.click();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user