Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added web/src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 45 additions & 9 deletions web/src/components/AlertPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,34 @@ export const alertIdFromHash = (hash: string): string | null => {
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<Alert[]>([]);
const [stats, setStats] = useState<AlertStats | null>(null);
Expand All @@ -25,6 +53,10 @@ const AlertPanel: React.FC = () => {
const [error, setError] = useState<string | null>(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();
Expand Down Expand Up @@ -345,15 +377,19 @@ const AlertPanel: React.FC = () => {
onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
disabled={currentPage === 1}
/>
{[...Array(totalPages)].map((_, i) => (
<Pagination.Item
key={i + 1}
active={i + 1 === currentPage}
onClick={() => setCurrentPage(i + 1)}
>
{i + 1}
</Pagination.Item>
))}
{pageItems(currentPage, totalPages).map((item, index) =>
item === 'ellipsis' ? (
<Pagination.Ellipsis key={`gap-${index}`} disabled />
) : (
<Pagination.Item
key={item}
active={item === currentPage}
onClick={() => setCurrentPage(item)}
>
{item}
</Pagination.Item>
)
)}
<Pagination.Next
onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
disabled={currentPage === totalPages}
Expand Down
3 changes: 3 additions & 0 deletions web/src/components/Sidebar.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 2 additions & 3 deletions web/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<aside className="sidebar">
<div className="sidebar-brand">
<img
src={DASHBOARD_LOGO_URL}
src={logoUrl}
alt="Stackdog logo"
className="sidebar-logo"
width={39}
Expand Down
14 changes: 14 additions & 0 deletions web/src/types/assets.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
declare module '*.png' {
const src: string;
export default src;
}

declare module '*.svg' {
const src: string;
export default src;
}

declare module '*.jpg' {
const src: string;
export default src;
}
4 changes: 4 additions & 0 deletions web/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ module.exports = {
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|jpe?g|gif|webp|svg|ico)$/i,
type: 'asset',
},
],
},
plugins: [
Expand Down
Loading