feat: redesign process-résumé panel, fix hover tooltip scrollbars, open résumé from table view
This commit is contained in:
+56
-29
@@ -138,6 +138,7 @@
|
||||
font:inherit; font-size:12.5px; padding:7px 12px; border-radius:8px; cursor:pointer;
|
||||
}
|
||||
.dropdown-btn:hover{ border-color:var(--accent); color:var(--ink); }
|
||||
.dropdown-btn:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
|
||||
.dropdown-btn .arrow{ font-size:10px; opacity:.6; }
|
||||
.dropdown-btn[aria-expanded="true"]{ border-color:var(--accent); background:var(--accent-wash); color:var(--ink); }
|
||||
.dropdown-btn .tag{ background:var(--accent); color:#fff; border-radius:999px; font-size:10.5px; padding:1px 6px; }
|
||||
@@ -156,6 +157,7 @@
|
||||
border:0; background:none; color:var(--accent); font:inherit; font-size:12px; cursor:pointer; padding:0;
|
||||
}
|
||||
.dropdown-actions button:hover{ text-decoration:underline; }
|
||||
.dropdown-actions button:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; border-radius:3px; }
|
||||
.dropdown-list{ max-height:260px; overflow-y:auto; display:flex; flex-direction:column; gap:1px; }
|
||||
.type-row{
|
||||
display:flex; align-items:center; gap:8px; padding:5px 4px; border-radius:6px; cursor:pointer; font-size:12.5px;
|
||||
@@ -173,6 +175,8 @@
|
||||
border:1px solid var(--border); background:var(--page); color:var(--ink-2);
|
||||
font:inherit; font-size:11px; padding:3px 8px; border-radius:999px; cursor:pointer;
|
||||
}
|
||||
.role-chip:hover{ border-color:var(--accent); color:var(--ink); }
|
||||
.role-chip:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
|
||||
.role-chip[aria-pressed="true"]{ background:var(--accent-wash); border-color:var(--accent); color:var(--ink); }
|
||||
.type-row .role-badge{
|
||||
flex:none; font-size:10px; color:var(--ink-3); background:var(--page);
|
||||
@@ -185,10 +189,13 @@
|
||||
.segmented{ display:flex; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
|
||||
.segmented button{
|
||||
border:0; background:var(--surface); color:var(--ink-2); font:inherit; font-size:12.5px;
|
||||
padding:7px 12px; cursor:pointer;
|
||||
padding:7px 12px; cursor:pointer; transition:background .15s ease, color .15s ease;
|
||||
}
|
||||
.segmented button + button{ border-left:1px solid var(--border); }
|
||||
.segmented button:hover{ background:var(--accent-wash); color:var(--ink); }
|
||||
.segmented button:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }
|
||||
.segmented button[aria-pressed="true"]{ background:var(--accent); color:#fff; }
|
||||
.segmented button[aria-pressed="true"]:hover{ background:var(--accent); }
|
||||
|
||||
.presets{ display:flex; gap:6px; }
|
||||
.presets button{
|
||||
@@ -196,6 +203,7 @@
|
||||
font:inherit; font-size:12.5px; padding:6px 10px; border-radius:7px; cursor:pointer;
|
||||
}
|
||||
.presets button:hover{ border-color:var(--accent); color:var(--ink); }
|
||||
.presets button:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
|
||||
.presets button[aria-pressed="true"]{ background:var(--accent-wash); border-color:var(--accent); color:var(--ink); }
|
||||
|
||||
label.check{ display:flex; align-items:center; gap:6px; font-size:12.5px; color:var(--ink-2); cursor:pointer; }
|
||||
@@ -229,7 +237,6 @@
|
||||
border-radius:999px; padding:2px 9px; margin-bottom:10px;
|
||||
}
|
||||
.resumo-text{ font-size:13.5px; line-height:1.6; color:var(--ink); margin:0 0 14px; }
|
||||
.resumo-block{ margin-top:12px; padding-top:12px; border-top:1px solid var(--grid); }
|
||||
.resumo-label{ font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-3); margin-bottom:6px; }
|
||||
.resumo-people{ display:flex; flex-wrap:wrap; gap:5px; }
|
||||
.resumo-people span{
|
||||
@@ -239,15 +246,15 @@
|
||||
.resumo-file{ font-size:10.5px; color:var(--ink-3); line-height:1.5; overflow-wrap:anywhere; }
|
||||
|
||||
.resumo-processo-btn{
|
||||
width:100%; text-align:left; font:inherit; font-size:12.5px; font-weight:600; color:var(--accent);
|
||||
width:100%; text-align:center; font:inherit; font-size:12.5px; font-weight:600; color:var(--accent);
|
||||
background:var(--accent-wash); border:1px solid var(--border); border-radius:8px; padding:8px 10px;
|
||||
cursor:pointer;
|
||||
cursor:pointer; margin-top:12px;
|
||||
}
|
||||
.resumo-processo-btn:hover{ border-color:var(--accent); }
|
||||
#resumoProcessoNum{ display:block; text-align:center; margin-top:2px; }
|
||||
.resumo-processo-content{
|
||||
margin-top:10px; max-height:46vh; overflow-y:auto; overflow-wrap:anywhere; font-size:12px;
|
||||
line-height:1.55; color:var(--ink-2);
|
||||
margin-top:14px; max-height:60vh; overflow-y:auto; overflow-wrap:anywhere;
|
||||
font-size:14px; line-height:1.65; color:var(--ink-2);
|
||||
background:var(--surface); border:1px solid var(--border); border-radius:12px; padding:16px 18px;
|
||||
}
|
||||
.resumo-processo-content h1, .resumo-processo-content h2, .resumo-processo-content h3{
|
||||
font-family:"Source Serif 4",serif; color:var(--ink); margin:12px 0 4px; line-height:1.3;
|
||||
@@ -298,7 +305,10 @@
|
||||
}
|
||||
.selection-ring{ border:2px solid var(--accent); box-shadow:0 0 0 3px var(--accent-wash); }
|
||||
#tooltip{
|
||||
position:absolute; pointer-events:none; max-width:320px; z-index:5;
|
||||
/* fixed (not absolute-in-wrap) so a tall/near-edge tooltip overlays the
|
||||
page instead of expanding .detail-card's scrollable box and popping a
|
||||
scrollbar */
|
||||
position:fixed; pointer-events:none; max-width:320px; z-index:5;
|
||||
background:var(--surface); border:1px solid var(--border); border-radius:9px;
|
||||
box-shadow:0 6px 20px rgba(0,0,0,.16); padding:10px 12px; font-size:12.5px;
|
||||
color:var(--ink-2); line-height:1.5; display:none;
|
||||
@@ -332,7 +342,11 @@
|
||||
td.type{ white-space:nowrap; color:var(--ink-2); }
|
||||
td.people{ color:var(--ink-2); max-width:220px; }
|
||||
td.text{ color:var(--ink); max-width:520px; }
|
||||
td.file{ font-family:"IBM Plex Mono",monospace; font-size:10.5px; color:var(--ink-3); max-width:220px; overflow-wrap:anywhere; }
|
||||
td.file{
|
||||
font-family:"IBM Plex Mono",monospace; font-size:10.5px; color:var(--ink-3); max-width:220px;
|
||||
overflow-wrap:anywhere; cursor:pointer;
|
||||
}
|
||||
td.file:hover{ color:var(--accent); text-decoration:underline; }
|
||||
.table-foot{ display:flex; align-items:center; justify-content:center; gap:12px; padding:14px; }
|
||||
.table-foot button{
|
||||
border:1px solid var(--border); background:var(--page); color:var(--ink);
|
||||
@@ -384,8 +398,8 @@
|
||||
Linha do tempo interativa da <span class="mono">Pet16704</span> (STF) — um ponto por documento, agrupado
|
||||
pela instituição de origem e posicionado pela data real de juntada — cruzada com o resumo de cada um dos
|
||||
<strong>53 processos conexos</strong> (o inquérito-mãe <span class="mono">Inq 5026</span> — Operação
|
||||
Compliance Zero — e os demais inquéritos e petições apartadas, reunidos em <span class="mono">parte1/</span>
|
||||
e <span class="mono">parte2/</span>). Clique em qualquer ponto da linha do tempo para abrir o resumo do
|
||||
Compliance Zero — e os demais inquéritos e petições apartadas, reunidos em <span class="mono">resumos/parte1/</span>
|
||||
e <span class="mono">resumos/parte2/</span>). Clique em qualquer ponto da linha do tempo para abrir o resumo do
|
||||
documento e, dali, o resumo completo do processo a que ele pertence.
|
||||
</p>
|
||||
<div class="stats" id="stats"></div>
|
||||
@@ -471,22 +485,22 @@
|
||||
<div class="resumo-id mono" id="resumoId"></div>
|
||||
<div class="resumo-type" id="resumoType"></div>
|
||||
<p class="resumo-text" id="resumoText"></p>
|
||||
<div class="resumo-block" id="resumoPeopleBlock" hidden>
|
||||
<div id="resumoPeopleBlock" hidden>
|
||||
<div class="resumo-label">Pessoas mencionadas</div>
|
||||
<div class="resumo-people" id="resumoPeople"></div>
|
||||
</div>
|
||||
<div class="resumo-block">
|
||||
<div>
|
||||
<div class="resumo-label">Arquivo-fonte</div>
|
||||
<div class="resumo-file mono" id="resumoFile"></div>
|
||||
</div>
|
||||
<div class="resumo-block">
|
||||
<div>
|
||||
<button type="button" class="resumo-processo-btn" id="resumoProcessoBtn" aria-expanded="false">
|
||||
Ver resumo do processo <span class="mono" id="resumoProcessoNum"></span>
|
||||
</button>
|
||||
<div class="resumo-processo-content" id="resumoProcessoContent" hidden></div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
<div class="resumo-processo-content" id="resumoProcessoContent" hidden></div>
|
||||
</section>
|
||||
|
||||
<section id="tableView" hidden>
|
||||
@@ -514,8 +528,7 @@
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
Linha do tempo: <span class="mono">TIMELINE.md</span> e <span class="mono">gitgraph.md</span> (atribuição de
|
||||
instituição por documento). Da leva original de 615 documentos sem data de juntada identificada, 366 tiveram
|
||||
Da leva original de 615 documentos sem data de juntada identificada, 366 tiveram
|
||||
uma data recuperada a partir do próprio texto do documento (data de assinatura/expedição, ex. "Brasília, 10 de
|
||||
abril de 2026") — marcados no resumo do documento como "data lida no texto", já que não é necessariamente a
|
||||
data de juntada nos autos. Os 249 restantes ficam de fora do gráfico e aparecem só na tabela. As 292 pessoas do
|
||||
@@ -526,7 +539,7 @@
|
||||
</p>
|
||||
<p>
|
||||
Resumo dos processos: ao abrir o resumo de um documento, o botão "Ver resumo do processo" busca o arquivo
|
||||
correspondente em <span class="mono">parte1/</span> ou <span class="mono">parte2/</span> — 53 processos
|
||||
correspondente em <span class="mono">resumos/parte1/</span> ou <span class="mono">resumos/parte2/</span> — 53 processos
|
||||
vinculados à Pet16704, lidos e resumidos a partir dos autos originais.
|
||||
</p>
|
||||
<p>
|
||||
@@ -1223,10 +1236,17 @@
|
||||
var textEl = document.createElement("div"); textEl.className = "text"; textEl.textContent = p.text;
|
||||
tt.appendChild(row1); tt.appendChild(idEl); tt.appendChild(textEl);
|
||||
|
||||
var left = x+16, top = y-10;
|
||||
if (left + 330 > dtWidth) left = x-330-8;
|
||||
// tt is position:fixed, so convert the canvas-local x/y into viewport
|
||||
// coordinates via the canvas's own rect, then clamp to the viewport
|
||||
// (not the scrollable card) so it never grows .detail-card's overflow.
|
||||
var rect = dtCanvas.getBoundingClientRect();
|
||||
var vx = rect.left+x, vy = rect.top+y;
|
||||
var left = vx+16, top = vy-10;
|
||||
if (left + 330 > window.innerWidth) left = vx-330-8;
|
||||
var ttH = tt.offsetHeight;
|
||||
if (top + ttH > window.innerHeight) top = window.innerHeight-ttH-8;
|
||||
tt.style.left = left+"px";
|
||||
tt.style.top = Math.max(0,top)+"px";
|
||||
tt.style.top = Math.max(8,top)+"px";
|
||||
}
|
||||
function clearHover(){
|
||||
state.hover = null;
|
||||
@@ -1281,6 +1301,7 @@
|
||||
function closeResumo(){
|
||||
state.selected = null;
|
||||
document.getElementById("resumoPanel").hidden = true;
|
||||
document.getElementById("resumoProcessoContent").hidden = true;
|
||||
document.getElementById("selectionRing").style.display = "none";
|
||||
resizeAll();
|
||||
}
|
||||
@@ -1302,7 +1323,7 @@
|
||||
if (e.key==="Escape" && !document.getElementById("resumoPanel").hidden) closeResumo();
|
||||
});
|
||||
|
||||
/* ---------------- per-process résumé (parte1/parte2 .md, fetched on demand) ---------------- */
|
||||
/* ---------------- per-process résumé (resumos/parte1,parte2 .md, fetched on demand) ---------------- */
|
||||
|
||||
function escapeHtml(s){
|
||||
return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
@@ -1316,7 +1337,7 @@
|
||||
s = s.replace(/`([^`]+)`/g, "<code>$1</code>");
|
||||
return s;
|
||||
}
|
||||
// small, purpose-built markdown→HTML pass for the parte1/parte2 résumé
|
||||
// small, purpose-built markdown→HTML pass for the resumos/parte1,parte2 résumé
|
||||
// files (headers, bold, inline code, links, "- " lists, paragraphs) — not
|
||||
// a general CommonMark renderer, just enough for these fairly plain files.
|
||||
function mdToHtml(md){
|
||||
@@ -1349,14 +1370,15 @@
|
||||
}
|
||||
|
||||
var processoCache = {}; // process number -> rendered HTML, or null if not found
|
||||
// parte1/ and parte2/ live one level above web/ in the intended (repo-root)
|
||||
// deployment, but a local server started from inside web/ (as the README's
|
||||
// own quickstart does) has no parent directory to serve — so try both
|
||||
// "../parteN/" and "parteN/" for each folder and use whichever resolves.
|
||||
// resumos/parte1/ and resumos/parte2/ live one level above web/ in the
|
||||
// intended (repo-root) deployment, but a local server started from inside
|
||||
// web/ (as the README's own quickstart does) has no parent directory to
|
||||
// serve — so try both "../resumos/parteN/" and "resumos/parteN/" for each
|
||||
// folder and use whichever resolves.
|
||||
function fetchProcessoMd(num){
|
||||
var candidates = [
|
||||
"../parte2/"+num+".md", "../parte1/"+num+".md",
|
||||
"parte2/"+num+".md", "parte1/"+num+".md"
|
||||
"../resumos/parte2/"+num+".md", "../resumos/parte1/"+num+".md",
|
||||
"resumos/parte2/"+num+".md", "resumos/parte1/"+num+".md"
|
||||
];
|
||||
function tryNext(i){
|
||||
if (i >= candidates.length) return null;
|
||||
@@ -1632,6 +1654,11 @@
|
||||
tr.appendChild(tdPeople);
|
||||
|
||||
var tdFile = document.createElement("td"); tdFile.className="file"; tdFile.textContent = r.file;
|
||||
tdFile.title = "Ver resumo deste documento";
|
||||
tdFile.addEventListener("click", function(){
|
||||
setView("chart");
|
||||
openResumo(r, laneIndex[r.lane]);
|
||||
});
|
||||
tr.appendChild(tdFile);
|
||||
|
||||
frag.appendChild(tr);
|
||||
|
||||
Reference in New Issue
Block a user