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;
|
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: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 .arrow{ font-size:10px; opacity:.6; }
|
||||||
.dropdown-btn[aria-expanded="true"]{ border-color:var(--accent); background:var(--accent-wash); color:var(--ink); }
|
.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; }
|
.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;
|
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: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; }
|
.dropdown-list{ max-height:260px; overflow-y:auto; display:flex; flex-direction:column; gap:1px; }
|
||||||
.type-row{
|
.type-row{
|
||||||
display:flex; align-items:center; gap:8px; padding:5px 4px; border-radius:6px; cursor:pointer; font-size:12.5px;
|
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);
|
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;
|
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); }
|
.role-chip[aria-pressed="true"]{ background:var(--accent-wash); border-color:var(--accent); color:var(--ink); }
|
||||||
.type-row .role-badge{
|
.type-row .role-badge{
|
||||||
flex:none; font-size:10px; color:var(--ink-3); background:var(--page);
|
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{ display:flex; border:1px solid var(--border); border-radius:8px; overflow:hidden; }
|
||||||
.segmented button{
|
.segmented button{
|
||||||
border:0; background:var(--surface); color:var(--ink-2); font:inherit; font-size:12.5px;
|
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 + 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"]{ background:var(--accent); color:#fff; }
|
||||||
|
.segmented button[aria-pressed="true"]:hover{ background:var(--accent); }
|
||||||
|
|
||||||
.presets{ display:flex; gap:6px; }
|
.presets{ display:flex; gap:6px; }
|
||||||
.presets button{
|
.presets button{
|
||||||
@@ -196,6 +203,7 @@
|
|||||||
font:inherit; font-size:12.5px; padding:6px 10px; border-radius:7px; cursor:pointer;
|
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: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); }
|
.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; }
|
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;
|
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-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-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{ display:flex; flex-wrap:wrap; gap:5px; }
|
||||||
.resumo-people span{
|
.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-file{ font-size:10.5px; color:var(--ink-3); line-height:1.5; overflow-wrap:anywhere; }
|
||||||
|
|
||||||
.resumo-processo-btn{
|
.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;
|
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); }
|
.resumo-processo-btn:hover{ border-color:var(--accent); }
|
||||||
#resumoProcessoNum{ display:block; text-align:center; margin-top:2px; }
|
|
||||||
.resumo-processo-content{
|
.resumo-processo-content{
|
||||||
margin-top:10px; max-height:46vh; overflow-y:auto; overflow-wrap:anywhere; font-size:12px;
|
margin-top:14px; max-height:60vh; overflow-y:auto; overflow-wrap:anywhere;
|
||||||
line-height:1.55; color:var(--ink-2);
|
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{
|
.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;
|
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); }
|
.selection-ring{ border:2px solid var(--accent); box-shadow:0 0 0 3px var(--accent-wash); }
|
||||||
#tooltip{
|
#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;
|
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;
|
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;
|
color:var(--ink-2); line-height:1.5; display:none;
|
||||||
@@ -332,7 +342,11 @@
|
|||||||
td.type{ white-space:nowrap; color:var(--ink-2); }
|
td.type{ white-space:nowrap; color:var(--ink-2); }
|
||||||
td.people{ color:var(--ink-2); max-width:220px; }
|
td.people{ color:var(--ink-2); max-width:220px; }
|
||||||
td.text{ color:var(--ink); max-width:520px; }
|
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{ display:flex; align-items:center; justify-content:center; gap:12px; padding:14px; }
|
||||||
.table-foot button{
|
.table-foot button{
|
||||||
border:1px solid var(--border); background:var(--page); color:var(--ink);
|
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
|
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
|
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
|
<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>
|
Compliance Zero — e os demais inquéritos e petições apartadas, reunidos em <span class="mono">resumos/parte1/</span>
|
||||||
e <span class="mono">parte2/</span>). Clique em qualquer ponto da linha do tempo para abrir o resumo do
|
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.
|
documento e, dali, o resumo completo do processo a que ele pertence.
|
||||||
</p>
|
</p>
|
||||||
<div class="stats" id="stats"></div>
|
<div class="stats" id="stats"></div>
|
||||||
@@ -471,22 +485,22 @@
|
|||||||
<div class="resumo-id mono" id="resumoId"></div>
|
<div class="resumo-id mono" id="resumoId"></div>
|
||||||
<div class="resumo-type" id="resumoType"></div>
|
<div class="resumo-type" id="resumoType"></div>
|
||||||
<p class="resumo-text" id="resumoText"></p>
|
<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-label">Pessoas mencionadas</div>
|
||||||
<div class="resumo-people" id="resumoPeople"></div>
|
<div class="resumo-people" id="resumoPeople"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="resumo-block">
|
<div>
|
||||||
<div class="resumo-label">Arquivo-fonte</div>
|
<div class="resumo-label">Arquivo-fonte</div>
|
||||||
<div class="resumo-file mono" id="resumoFile"></div>
|
<div class="resumo-file mono" id="resumoFile"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="resumo-block">
|
<div>
|
||||||
<button type="button" class="resumo-processo-btn" id="resumoProcessoBtn" aria-expanded="false">
|
<button type="button" class="resumo-processo-btn" id="resumoProcessoBtn" aria-expanded="false">
|
||||||
Ver resumo do processo <span class="mono" id="resumoProcessoNum"></span>
|
Ver resumo do processo <span class="mono" id="resumoProcessoNum"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="resumo-processo-content" id="resumoProcessoContent" hidden></div>
|
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="resumo-processo-content" id="resumoProcessoContent" hidden></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="tableView" hidden>
|
<section id="tableView" hidden>
|
||||||
@@ -514,8 +528,7 @@
|
|||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<p>
|
<p>
|
||||||
Linha do tempo: <span class="mono">TIMELINE.md</span> e <span class="mono">gitgraph.md</span> (atribuição de
|
Da leva original de 615 documentos sem data de juntada identificada, 366 tiveram
|
||||||
instituição por documento). 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
|
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
|
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
|
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>
|
||||||
<p>
|
<p>
|
||||||
Resumo dos processos: ao abrir o resumo de um documento, o botão "Ver resumo do processo" busca o arquivo
|
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.
|
vinculados à Pet16704, lidos e resumidos a partir dos autos originais.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -1223,10 +1236,17 @@
|
|||||||
var textEl = document.createElement("div"); textEl.className = "text"; textEl.textContent = p.text;
|
var textEl = document.createElement("div"); textEl.className = "text"; textEl.textContent = p.text;
|
||||||
tt.appendChild(row1); tt.appendChild(idEl); tt.appendChild(textEl);
|
tt.appendChild(row1); tt.appendChild(idEl); tt.appendChild(textEl);
|
||||||
|
|
||||||
var left = x+16, top = y-10;
|
// tt is position:fixed, so convert the canvas-local x/y into viewport
|
||||||
if (left + 330 > dtWidth) left = x-330-8;
|
// 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.left = left+"px";
|
||||||
tt.style.top = Math.max(0,top)+"px";
|
tt.style.top = Math.max(8,top)+"px";
|
||||||
}
|
}
|
||||||
function clearHover(){
|
function clearHover(){
|
||||||
state.hover = null;
|
state.hover = null;
|
||||||
@@ -1281,6 +1301,7 @@
|
|||||||
function closeResumo(){
|
function closeResumo(){
|
||||||
state.selected = null;
|
state.selected = null;
|
||||||
document.getElementById("resumoPanel").hidden = true;
|
document.getElementById("resumoPanel").hidden = true;
|
||||||
|
document.getElementById("resumoProcessoContent").hidden = true;
|
||||||
document.getElementById("selectionRing").style.display = "none";
|
document.getElementById("selectionRing").style.display = "none";
|
||||||
resizeAll();
|
resizeAll();
|
||||||
}
|
}
|
||||||
@@ -1302,7 +1323,7 @@
|
|||||||
if (e.key==="Escape" && !document.getElementById("resumoPanel").hidden) closeResumo();
|
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){
|
function escapeHtml(s){
|
||||||
return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||||
@@ -1316,7 +1337,7 @@
|
|||||||
s = s.replace(/`([^`]+)`/g, "<code>$1</code>");
|
s = s.replace(/`([^`]+)`/g, "<code>$1</code>");
|
||||||
return s;
|
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
|
// files (headers, bold, inline code, links, "- " lists, paragraphs) — not
|
||||||
// a general CommonMark renderer, just enough for these fairly plain files.
|
// a general CommonMark renderer, just enough for these fairly plain files.
|
||||||
function mdToHtml(md){
|
function mdToHtml(md){
|
||||||
@@ -1349,14 +1370,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var processoCache = {}; // process number -> rendered HTML, or null if not found
|
var processoCache = {}; // process number -> rendered HTML, or null if not found
|
||||||
// parte1/ and parte2/ live one level above web/ in the intended (repo-root)
|
// resumos/parte1/ and resumos/parte2/ live one level above web/ in the
|
||||||
// deployment, but a local server started from inside web/ (as the README's
|
// intended (repo-root) deployment, but a local server started from inside
|
||||||
// own quickstart does) has no parent directory to serve — so try both
|
// web/ (as the README's own quickstart does) has no parent directory to
|
||||||
// "../parteN/" and "parteN/" for each folder and use whichever resolves.
|
// serve — so try both "../resumos/parteN/" and "resumos/parteN/" for each
|
||||||
|
// folder and use whichever resolves.
|
||||||
function fetchProcessoMd(num){
|
function fetchProcessoMd(num){
|
||||||
var candidates = [
|
var candidates = [
|
||||||
"../parte2/"+num+".md", "../parte1/"+num+".md",
|
"../resumos/parte2/"+num+".md", "../resumos/parte1/"+num+".md",
|
||||||
"parte2/"+num+".md", "parte1/"+num+".md"
|
"resumos/parte2/"+num+".md", "resumos/parte1/"+num+".md"
|
||||||
];
|
];
|
||||||
function tryNext(i){
|
function tryNext(i){
|
||||||
if (i >= candidates.length) return null;
|
if (i >= candidates.length) return null;
|
||||||
@@ -1632,6 +1654,11 @@
|
|||||||
tr.appendChild(tdPeople);
|
tr.appendChild(tdPeople);
|
||||||
|
|
||||||
var tdFile = document.createElement("td"); tdFile.className="file"; tdFile.textContent = r.file;
|
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);
|
tr.appendChild(tdFile);
|
||||||
|
|
||||||
frag.appendChild(tr);
|
frag.appendChild(tr);
|
||||||
|
|||||||
Reference in New Issue
Block a user