From 5c84a53d1123cff05a0e3eab5640137d968ccef9 Mon Sep 17 00:00:00 2001 From: Vasili Pascal Date: Mon, 2 Nov 2026 13:58:19 +0200 Subject: [PATCH] fix(web): keep pagination inside the card and make the logo visible The alert list rendered one pagination button per page. At 27k alerts that is 2711 buttons in one unwrapped row, spilling across the whole viewport. Window the pages: first, last, current +/-1, ellipses. Also reset to page 1 when the filter changes, so a filtered list cannot show an empty table behind page buttons from the previous total. The sidebar logo was loaded from a remote URL, blank whenever that host is unreachable, and the artwork is a black silhouette on a dark sidebar either way. Bundle it as web/src/assets/logo.png with the webpack asset rule and TypeScript declarations, and draw it inverted (white) via CSS. cargo test is unaffected; web jest suite 54/54 and the production webpack build pass. --- web/src/assets/logo.png | Bin 0 -> 46814 bytes web/src/components/AlertPanel.tsx | 54 +++++++++++++++++++++++++----- web/src/components/Sidebar.css | 3 ++ web/src/components/Sidebar.tsx | 5 ++- web/src/types/assets.d.ts | 14 ++++++++ web/webpack.config.js | 4 +++ 6 files changed, 68 insertions(+), 12 deletions(-) create mode 100644 web/src/assets/logo.png create mode 100644 web/src/types/assets.d.ts diff --git a/web/src/assets/logo.png b/web/src/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..85bf85ff3fc1d9c410ad903e01fb58252297e2cc GIT binary patch literal 46814 zcmeGEWl$Vpw*?9h0|a*q1O|5v1h>J0OM(r-2^u`O4{iyrL4zi^YjAf94#8c6J74F1 z=RN2Cz5m~;fvO&g>3*Kxz4zK{tv%stDzaGUWauCe2uog0`aK8)hX4CPeF40KIWj;C z0#SkFr6n}n4GuF*5^3awqOw3(azZUuhsje2m^>jN zh$6^%mr!XuiNCl?KSG(}-X&1s(_17hKeibzt~^CLy4G8`N`|^!?OB*xG&L9bYA#=1 zX&d?^8vm66(?S39!es%IerI9FQ2fsuz+a5sfvWIgKxqH-g7%}TfkH|;b@cG55dP4$y+WfRK&)S<-vx|8p5s2J4JL$B7dsFq|L9-I*f{>P0U$IrP!-mHH{`z? z^8XLl|3=7vADRE=kpCvt|5lm*K?DCSyZ^-@{{?3MMXLXwp}T(tUca<|bwy&SX0cZA zi&r=mOa0*G*dDc8>xx3 zR&6RjPS!?ZIw_Z6S(Ept=T?)Pn#HSEWV;7oelv9HV3 z!N$FE*|=cRku?7D24E#24HH=zSy?OC_Y}UTs~u$SoT17{#xGjy$K_KfqBBPiOH5kK zP4-|WcoKGF2ixhvF0JObkK+v{rLXwS6nX_C@iXksG&EYI3E;uuHLyjsn#bjIDbm5N zgj<#fTSpq9xDM(g^4ZUuQW|1qkAb)$_n)1dt~Z2MP~J5VU&HOs&(6d+bn6b!Y!~Zn zJLRtXMflsXHU2gAm+tb}aQ;`2w zxLkWKa30YQuZOh;&@{>oTFx>>y)xUmR4JF{s<*y;&UIsk|8ljR+g3QLQBn+%V&QJ% z-qalLNHud6^D6bGFL%iNPKShT#Ti9aRk|6h&$%ttV?Ra|3j5viyVciXKiOKU9LK+a zhL{p(^`3;<@}%41FUe*k5?HZak;KY~y4q-u8ork9>HwnrI$BcctaZjxB&Ddz@lkb} z(3Ry=ZidX2dhr)m2aX>5!_;*=e=4dY8NSNhy-WNNGNzSOTZNwNtc7G|kn)hwU@iHx zTThErNWd+Pe>*NH09(aIe+Jqf=#;(-+G&Dx!3t2M~oyS>DYjUGRRD>-n zxBD%K+P1m$*`$2F+rL9V!M$y#%E1<^CN9ebOISuQ)JpalXI(yCWYhz=%XO%4+Hyf`nI0)u@YBjgxnOjnlEFk)%Cl7?G0R=tq8j?3_f@zCJ;af| zX9#Z&cqNe_?TAy#`pvFBR-Hj;ZK;yL5<&l#Xp~AldSy22Z zOQnrJL`>p;_Oj{Q7wT1~4WWfxl%HENLi>>%P5orTt|h@#Gr($vUpw``!YrXzOoCZt zxFpqjT_1xnva#3RA$itRsi(6~<*z2`+Es>NlA1))JpQrajN`4m83^oqW&g`q-)V&R z>UkmQVgK{m4fl2jzEGJ|D7IgQh{xF|p*CVXt$zZ*qbQMnVn{Fn(|`)04>gL8P4cQL zLZ+le!uN;OrGGd2bgMkWZ>)%}@D)cogE4Fo!gMC;#Iv!pO(o)YGGy<2wM*BybXgH%r zl3F4#X|?g$F2GKm*iNTeG(g*uAdWj_&>*)P%hSW0L}&#?VNJgf5*zq*fH6yiPD7#Q zi`=VkT)qJ=J&D?cBCxzSU1%!9c<@_y%Wr7>aR#Rd3DXicH2%0A3D5V@NS`Z>Q;tR}*O!xJ06XfhoN}7SD^$1q< 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 { return match ? decodeURIComponent(match[1]) : null; }; +/** Page numbers around `current`, plus first, last and ellipses. Rendering + * every page button overflowed the card once alert counts reached five + * digits; this keeps the row short whatever the total. */ +export const pageItems = (current: number, total: number): (number | 'ellipsis')[] => { + if (total <= 9) { + return Array.from({ length: total }, (_, index) => index + 1); + } + const wanted = new Set([1, total, current - 1, current, current + 1]); + if (current <= 4) { + [2, 3, 4, 5].forEach((page) => wanted.add(page)); + } + if (current >= total - 3) { + [total - 1, total - 2, total - 3, total - 4].forEach((page) => wanted.add(page)); + } + const items: (number | 'ellipsis')[] = []; + let previous = 0; + for (const page of [...wanted] + .filter((page) => page >= 1 && page <= total) + .sort((a, b) => a - b)) { + if (previous && page - previous > 1) { + items.push('ellipsis'); + } + items.push(page); + previous = page; + } + return items; +}; + const AlertPanel: React.FC = () => { const [alerts, setAlerts] = useState([]); const [stats, setStats] = useState(null); @@ -25,6 +53,10 @@ const AlertPanel: React.FC = () => { const [error, setError] = useState(null); useEffect(() => { + // A new filter shrinks the list; staying on page 500 of what used to be + // 2700 pages shows an empty table behind a pagination row that no longer + // matches. Start over. + setCurrentPage(1); loadAlerts(); loadStats(); setupWebSocket(); @@ -345,15 +377,19 @@ const AlertPanel: React.FC = () => { onClick={() => setCurrentPage(p => Math.max(1, p - 1))} disabled={currentPage === 1} /> - {[...Array(totalPages)].map((_, i) => ( - setCurrentPage(i + 1)} - > - {i + 1} - - ))} + {pageItems(currentPage, totalPages).map((item, index) => + item === 'ellipsis' ? ( + + ) : ( + setCurrentPage(item)} + > + {item} + + ) + )} setCurrentPage(p => Math.min(totalPages, p + 1))} disabled={currentPage === totalPages} diff --git a/web/src/components/Sidebar.css b/web/src/components/Sidebar.css index 0bd26a3..18e6382 100644 --- a/web/src/components/Sidebar.css +++ b/web/src/components/Sidebar.css @@ -21,6 +21,9 @@ width: 39px; height: 39px; object-fit: contain; + flex-shrink: 0; + /* The artwork is a black silhouette; the sidebar is dark, so draw it white. */ + filter: brightness(0) invert(1); } .sidebar-nav { diff --git a/web/src/components/Sidebar.tsx b/web/src/components/Sidebar.tsx index c1be24b..e81a03d 100644 --- a/web/src/components/Sidebar.tsx +++ b/web/src/components/Sidebar.tsx @@ -1,14 +1,13 @@ import React from 'react'; +import logoUrl from '../assets/logo.png'; import './Sidebar.css'; -const DASHBOARD_LOGO_URL = 'https://github.com/user-attachments/assets/0c8a9216-8315-4ef7-9b73-d96c40521ed1'; - const Sidebar: React.FC = () => { return (