Spaces:
Sleeping
Sleeping
Commit ·
65d2d3e
1
Parent(s): 2f3e9c6
Add pagination to regions table in result modal (10 rows per page)
Browse files- static/css/style.css +43 -0
- static/js/app.js +61 -5
- templates/index.html +2 -1
static/css/style.css
CHANGED
|
@@ -768,6 +768,49 @@ input:focus, select:focus, textarea:focus {
|
|
| 768 |
.regions-table tr:hover td { background: rgba(46, 51, 197, 0.04); }
|
| 769 |
.regions-table tr.region-hover td { background: rgba(255, 255, 0, 0.12); }
|
| 770 |
.regions-table td:nth-child(2) { color: var(--text); font-weight: 500; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 771 |
.severity-badge {
|
| 772 |
display: inline-block;
|
| 773 |
padding: 0.15rem 0.5rem;
|
|
|
|
| 768 |
.regions-table tr:hover td { background: rgba(46, 51, 197, 0.04); }
|
| 769 |
.regions-table tr.region-hover td { background: rgba(255, 255, 0, 0.12); }
|
| 770 |
.regions-table td:nth-child(2) { color: var(--text); font-weight: 500; }
|
| 771 |
+
|
| 772 |
+
/* ---- Pagination ---- */
|
| 773 |
+
.pagination {
|
| 774 |
+
display: flex;
|
| 775 |
+
align-items: center;
|
| 776 |
+
justify-content: center;
|
| 777 |
+
gap: 0.35rem;
|
| 778 |
+
padding: 0.75rem 0 0.25rem;
|
| 779 |
+
flex-wrap: wrap;
|
| 780 |
+
}
|
| 781 |
+
.pagination button {
|
| 782 |
+
min-width: 2rem;
|
| 783 |
+
height: 2rem;
|
| 784 |
+
padding: 0 0.5rem;
|
| 785 |
+
border: 1px solid var(--border);
|
| 786 |
+
border-radius: 6px;
|
| 787 |
+
background: var(--bg-card);
|
| 788 |
+
color: var(--text-muted);
|
| 789 |
+
font-size: 0.8rem;
|
| 790 |
+
cursor: pointer;
|
| 791 |
+
transition: all 0.15s;
|
| 792 |
+
}
|
| 793 |
+
.pagination button:hover:not(:disabled) {
|
| 794 |
+
background: rgba(46, 51, 197, 0.08);
|
| 795 |
+
border-color: rgba(46, 51, 197, 0.3);
|
| 796 |
+
color: var(--text);
|
| 797 |
+
}
|
| 798 |
+
.pagination button.active {
|
| 799 |
+
background: linear-gradient(135deg, #2e33c5, #cf2040);
|
| 800 |
+
color: #fff;
|
| 801 |
+
border-color: transparent;
|
| 802 |
+
font-weight: 600;
|
| 803 |
+
}
|
| 804 |
+
.pagination button:disabled {
|
| 805 |
+
opacity: 0.4;
|
| 806 |
+
cursor: default;
|
| 807 |
+
}
|
| 808 |
+
.pagination .page-info {
|
| 809 |
+
font-size: 0.75rem;
|
| 810 |
+
color: var(--text-dim);
|
| 811 |
+
margin: 0 0.5rem;
|
| 812 |
+
}
|
| 813 |
+
|
| 814 |
.severity-badge {
|
| 815 |
display: inline-block;
|
| 816 |
padding: 0.15rem 0.5rem;
|
static/js/app.js
CHANGED
|
@@ -374,6 +374,10 @@ function formatCompact(n) {
|
|
| 374 |
|
| 375 |
// Store current result for zoom and region hover (bbox in % for overlay)
|
| 376 |
let currentResultData = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 377 |
|
| 378 |
function showResult(data) {
|
| 379 |
const modal = document.getElementById('result-modal');
|
|
@@ -428,9 +432,9 @@ function showResult(data) {
|
|
| 428 |
beforeImg.onload = onReady;
|
| 429 |
setTimeout(() => { resetCompareSlider(); resetZoom(); }, 500);
|
| 430 |
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
regions.
|
| 434 |
const tr = document.createElement('tr');
|
| 435 |
tr.dataset.regionId = r.id;
|
| 436 |
const subType = r.subType || '—';
|
|
@@ -451,13 +455,65 @@ function showResult(data) {
|
|
| 451 |
<td>${height}</td>
|
| 452 |
<td>${stage}</td>
|
| 453 |
`;
|
| 454 |
-
|
| 455 |
});
|
| 456 |
|
| 457 |
-
|
|
|
|
| 458 |
openResultModal();
|
| 459 |
}
|
| 460 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
function openResultModal() {
|
| 462 |
const modal = document.getElementById('result-modal');
|
| 463 |
if (!modal) return;
|
|
|
|
| 374 |
|
| 375 |
// Store current result for zoom and region hover (bbox in % for overlay)
|
| 376 |
let currentResultData = null;
|
| 377 |
+
let _regionRows = []; // all region <tr> elements for pagination
|
| 378 |
+
let _regionList = []; // matching data objects
|
| 379 |
+
const REGIONS_PER_PAGE = 10;
|
| 380 |
+
let _regionPage = 0;
|
| 381 |
|
| 382 |
function showResult(data) {
|
| 383 |
const modal = document.getElementById('result-modal');
|
|
|
|
| 432 |
beforeImg.onload = onReady;
|
| 433 |
setTimeout(() => { resetCompareSlider(); resetZoom(); }, 500);
|
| 434 |
|
| 435 |
+
const regions = (data.regions || []).slice(0, 60);
|
| 436 |
+
_regionList = regions;
|
| 437 |
+
_regionRows = regions.map((r) => {
|
| 438 |
const tr = document.createElement('tr');
|
| 439 |
tr.dataset.regionId = r.id;
|
| 440 |
const subType = r.subType || '—';
|
|
|
|
| 455 |
<td>${height}</td>
|
| 456 |
<td>${stage}</td>
|
| 457 |
`;
|
| 458 |
+
return tr;
|
| 459 |
});
|
| 460 |
|
| 461 |
+
_regionPage = 0;
|
| 462 |
+
renderRegionPage();
|
| 463 |
openResultModal();
|
| 464 |
}
|
| 465 |
|
| 466 |
+
function renderRegionPage() {
|
| 467 |
+
const tbody = document.getElementById('regions-tbody');
|
| 468 |
+
const pag = document.getElementById('regions-pagination');
|
| 469 |
+
if (!tbody) return;
|
| 470 |
+
|
| 471 |
+
const totalPages = Math.max(1, Math.ceil(_regionRows.length / REGIONS_PER_PAGE));
|
| 472 |
+
_regionPage = Math.max(0, Math.min(_regionPage, totalPages - 1));
|
| 473 |
+
const start = _regionPage * REGIONS_PER_PAGE;
|
| 474 |
+
const pageRows = _regionRows.slice(start, start + REGIONS_PER_PAGE);
|
| 475 |
+
const pageData = _regionList.slice(start, start + REGIONS_PER_PAGE);
|
| 476 |
+
|
| 477 |
+
tbody.innerHTML = '';
|
| 478 |
+
pageRows.forEach((tr) => tbody.appendChild(tr));
|
| 479 |
+
setupRegionHover(tbody, pageData);
|
| 480 |
+
|
| 481 |
+
if (pag) {
|
| 482 |
+
pag.innerHTML = '';
|
| 483 |
+
if (totalPages <= 1) return;
|
| 484 |
+
|
| 485 |
+
const prev = document.createElement('button');
|
| 486 |
+
prev.textContent = '‹';
|
| 487 |
+
prev.disabled = _regionPage === 0;
|
| 488 |
+
prev.addEventListener('click', () => { _regionPage--; renderRegionPage(); });
|
| 489 |
+
pag.appendChild(prev);
|
| 490 |
+
|
| 491 |
+
const maxButtons = 7;
|
| 492 |
+
let rangeStart = Math.max(0, _regionPage - Math.floor(maxButtons / 2));
|
| 493 |
+
let rangeEnd = Math.min(totalPages, rangeStart + maxButtons);
|
| 494 |
+
if (rangeEnd - rangeStart < maxButtons) rangeStart = Math.max(0, rangeEnd - maxButtons);
|
| 495 |
+
|
| 496 |
+
for (let i = rangeStart; i < rangeEnd; i++) {
|
| 497 |
+
const btn = document.createElement('button');
|
| 498 |
+
btn.textContent = i + 1;
|
| 499 |
+
if (i === _regionPage) btn.classList.add('active');
|
| 500 |
+
btn.addEventListener('click', () => { _regionPage = i; renderRegionPage(); });
|
| 501 |
+
pag.appendChild(btn);
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
const next = document.createElement('button');
|
| 505 |
+
next.textContent = '›';
|
| 506 |
+
next.disabled = _regionPage >= totalPages - 1;
|
| 507 |
+
next.addEventListener('click', () => { _regionPage++; renderRegionPage(); });
|
| 508 |
+
pag.appendChild(next);
|
| 509 |
+
|
| 510 |
+
const info = document.createElement('span');
|
| 511 |
+
info.className = 'page-info';
|
| 512 |
+
info.textContent = `${start + 1}–${Math.min(start + REGIONS_PER_PAGE, _regionRows.length)} of ${_regionRows.length}`;
|
| 513 |
+
pag.appendChild(info);
|
| 514 |
+
}
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
function openResultModal() {
|
| 518 |
const modal = document.getElementById('result-modal');
|
| 519 |
if (!modal) return;
|
templates/index.html
CHANGED
|
@@ -329,6 +329,7 @@
|
|
| 329 |
</thead>
|
| 330 |
<tbody id="regions-tbody"></tbody>
|
| 331 |
</table>
|
|
|
|
| 332 |
</div>
|
| 333 |
</div>
|
| 334 |
</div>
|
|
@@ -345,6 +346,6 @@
|
|
| 345 |
</div>
|
| 346 |
</div>
|
| 347 |
|
| 348 |
-
<script src="/static/js/app.js?v=
|
| 349 |
</body>
|
| 350 |
</html>
|
|
|
|
| 329 |
</thead>
|
| 330 |
<tbody id="regions-tbody"></tbody>
|
| 331 |
</table>
|
| 332 |
+
<div class="pagination" id="regions-pagination"></div>
|
| 333 |
</div>
|
| 334 |
</div>
|
| 335 |
</div>
|
|
|
|
| 346 |
</div>
|
| 347 |
</div>
|
| 348 |
|
| 349 |
+
<script src="/static/js/app.js?v=22"></script>
|
| 350 |
</body>
|
| 351 |
</html>
|