feat(logs): Add various log pages for tracking user activities and system events

This commit is contained in:
web
2025-08-26 11:29:12 -07:00
parent 4f7cc807af
commit d85af491aa
28 changed files with 876 additions and 252 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ interface IpLinkProps {
}
export function IpLink({ ip, children, className = '', target = '_blank' }: IpLinkProps) {
const url = `https://ip.sb/ip/${ip}`;
const url = `https://ipinfo.io/${ip}`;
return (
<a
+30 -4
View File
@@ -56,13 +56,37 @@ export function SidebarLeft({ ...props }: React.ComponentProps<typeof Sidebar>)
});
};
const isActiveUrl = (url: string) =>
url === '/dashboard' ? pathname === url : pathname.startsWith(url);
const normalize = (p: string) => (p.endsWith('/') && p !== '/' ? p.replace(/\/+$/, '') : p);
const isActiveUrl = (url: string) => {
const path = normalize(pathname);
const target = normalize(url);
if (target === '/dashboard') return path === target;
if (path === target) return true;
// Only treat as active if next char is a path boundary '/'
return path.startsWith(target + '/');
};
const isGroupActive = (nav: Nav) =>
(hasChildren(nav) && nav.items.some((i: any) => isActiveUrl(i.url))) ||
('url' in nav && nav.url ? isActiveUrl(nav.url as string) : false);
// Auto-open the group containing the active route whenever pathname changes
React.useEffect(() => {
setOpenGroups((prev) => {
const next: Record<string, boolean> = {};
(navs as typeof navs).forEach((nav) => {
if (hasChildren(nav)) next[nav.title] = isGroupActive(nav);
});
// If no active group detected, keep previously opened or default to first
if (!Object.values(next).some(Boolean)) {
(navs as typeof navs).forEach((nav) => {
if (hasChildren(nav)) next[nav.title] = prev[nav.title] ?? nav.title === firstGroupTitle;
});
}
return next;
});
}, [pathname]);
const renderCollapsedFlyout = (nav: Nav) => {
const ParentButton = (
<SidebarMenuButton
@@ -170,17 +194,19 @@ export function SidebarLeft({ ...props }: React.ComponentProps<typeof Sidebar>)
: (navs as typeof navs).map((nav) => {
if (hasChildren(nav)) {
const isOpen = openGroups[nav.title] ?? false;
const groupActive = isGroupActive(nav);
return (
<SidebarGroup key={nav.title} className={cn('py-1')}>
<SidebarMenuButton
size='sm'
className={cn('mb-2 flex h-8 w-full items-center justify-between', {
'bg-accent': isOpen,
'bg-accent text-accent-foreground': isOpen || groupActive,
'hover:bg-accent/60': !isOpen && !groupActive,
})}
onClick={() => handleToggleGroup(nav.title)}
tabIndex={0}
style={{ fontWeight: 500 }}
// isActive={isGroupActive(nav)}
isActive={groupActive}
>
<span className='flex min-w-0 items-center gap-2'>
{'icon' in nav && (nav as any).icon ? (