mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
feat(admin): track and display per-user download egress for Bunny version downloads
This commit is contained in:
@@ -18,7 +18,7 @@ export default async function AdminLayout({
|
||||
return (
|
||||
<div className="relative flex min-h-screen flex-col">
|
||||
<Header user={session.user} />
|
||||
<div className="container mx-auto px-4 md:px-8 flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
|
||||
<div className="w-full px-4 md:px-8 flex-1 items-start md:grid md:grid-cols-[220px_minmax(0,1fr)] md:gap-6 lg:grid-cols-[240px_minmax(0,1fr)] lg:gap-10">
|
||||
{/* Mobile Nav */}
|
||||
<div className="md:hidden py-4 border-b mb-4">
|
||||
<nav className="flex items-center gap-4 overflow-x-auto">
|
||||
|
||||
@@ -5,6 +5,7 @@ import { redirect } from 'next/navigation';
|
||||
import {
|
||||
getCachedBunnyStorageStats,
|
||||
getCachedUserBunnyStorage,
|
||||
getCachedUserDownloadEgress,
|
||||
getCachedUserMediaStorage
|
||||
} from '@/lib/admin-stats';
|
||||
import { Film, HardDrive } from 'lucide-react';
|
||||
@@ -33,6 +34,7 @@ type SortBy =
|
||||
| 'projectsOwned'
|
||||
| 'totalComments'
|
||||
| 'bunnyUpload'
|
||||
| 'downloadEgress'
|
||||
| 'mediaStorage';
|
||||
|
||||
type SortDirection = 'asc' | 'desc';
|
||||
@@ -45,6 +47,7 @@ const SORTABLE_COLUMNS: SortBy[] = [
|
||||
'projectsOwned',
|
||||
'totalComments',
|
||||
'bunnyUpload',
|
||||
'downloadEgress',
|
||||
'mediaStorage',
|
||||
];
|
||||
|
||||
@@ -90,7 +93,7 @@ export default async function AdminUsersPage({
|
||||
? resolvedSearchParams.sortDirection
|
||||
: getDefaultSortDirection(sortBy);
|
||||
|
||||
const [users, userStorage, userBunnyStorage, bunnyStorageStats] = await Promise.all([
|
||||
const [users, userStorage, userBunnyStorage, userDownloadEgress, bunnyStorageStats] = await Promise.all([
|
||||
db.user.findMany({
|
||||
orderBy: { createdAt: 'desc' },
|
||||
select: {
|
||||
@@ -118,6 +121,7 @@ export default async function AdminUsersPage({
|
||||
}),
|
||||
getCachedUserMediaStorage(),
|
||||
getCachedUserBunnyStorage(),
|
||||
getCachedUserDownloadEgress(),
|
||||
getCachedBunnyStorageStats(),
|
||||
]);
|
||||
|
||||
@@ -128,6 +132,7 @@ export default async function AdminUsersPage({
|
||||
0
|
||||
),
|
||||
bunnyUploadBytes: userBunnyStorage[user.id] || 0,
|
||||
downloadEgressBytes: userDownloadEgress[user.id] || 0,
|
||||
mediaStorageBytes: userStorage[user.id]?.total || 0,
|
||||
}));
|
||||
|
||||
@@ -150,6 +155,8 @@ export default async function AdminUsersPage({
|
||||
comparison = a._count.comments - b._count.comments;
|
||||
} else if (sortBy === 'bunnyUpload') {
|
||||
comparison = a.bunnyUploadBytes - b.bunnyUploadBytes;
|
||||
} else if (sortBy === 'downloadEgress') {
|
||||
comparison = a.downloadEgressBytes - b.downloadEgressBytes;
|
||||
} else if (sortBy === 'mediaStorage') {
|
||||
comparison = a.mediaStorageBytes - b.mediaStorageBytes;
|
||||
}
|
||||
@@ -193,7 +200,7 @@ export default async function AdminUsersPage({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex-1 space-y-4 px-4 md:px-8">
|
||||
<div className="flex-1 space-y-4">
|
||||
<div className="flex items-center justify-between space-y-2">
|
||||
<h2 className="text-3xl font-bold tracking-tight">Users</h2>
|
||||
</div>
|
||||
@@ -275,6 +282,12 @@ export default async function AdminUsersPage({
|
||||
<span className="text-xs">{getSortIndicator('bunnyUpload', sortBy, sortDirection)}</span>
|
||||
</Link>
|
||||
</TableHead>
|
||||
<TableHead className="text-right">
|
||||
<Link href={buildSortHref('downloadEgress')} className="inline-flex items-center justify-end gap-1 hover:underline">
|
||||
Download Egress (Est.)
|
||||
<span className="text-xs">{getSortIndicator('downloadEgress', sortBy, sortDirection)}</span>
|
||||
</Link>
|
||||
</TableHead>
|
||||
<TableHead className="text-right">
|
||||
<Link href={buildSortHref('mediaStorage')} className="inline-flex items-center justify-end gap-1 hover:underline">
|
||||
Media Storage
|
||||
@@ -286,7 +299,7 @@ export default async function AdminUsersPage({
|
||||
<TableBody>
|
||||
{paginatedUsers.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={8} className="h-24 text-center">
|
||||
<TableCell colSpan={9} className="h-24 text-center">
|
||||
No users found.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -309,6 +322,9 @@ export default async function AdminUsersPage({
|
||||
<TableCell className="text-right text-sm font-medium">
|
||||
{formatBytes(user.bunnyUploadBytes)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right text-sm font-medium">
|
||||
{formatBytes(user.downloadEgressBytes)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right text-sm">
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="font-medium text-foreground">{formatBytes(user.mediaStorageBytes)}</span>
|
||||
|
||||
Reference in New Issue
Block a user