Add provider filter and expiry sorting to quota dashboard (#769)

Co-authored-by: Delynn Assistant <zhen@dkzhen.org>
This commit is contained in:
Zhen
2026-04-28 10:05:28 +07:00
committed by GitHub
parent 54a67dbeb8
commit 296e21c8ad

View File

@@ -27,6 +27,8 @@ export default function ProviderLimits() {
const [showEditModal, setShowEditModal] = useState(false);
const [selectedConnection, setSelectedConnection] = useState(null);
const [proxyPools, setProxyPools] = useState([]);
const [providerFilter, setProviderFilter] = useState("all");
const [expiringFirst, setExpiringFirst] = useState(false);
const intervalRef = useRef(null);
const countdownRef = useRef(null);
@@ -362,14 +364,32 @@ export default function ProviderLimits() {
conn.authType === "oauth",
);
// Sort providers by USAGE_SUPPORTED_PROVIDERS order, then alphabetically
const sortedConnections = [...filteredConnections].sort((a, b) => {
const providerFilteredConnections = filteredConnections.filter(
(conn) => providerFilter === "all" || conn.provider === providerFilter,
);
const getEarliestResetTime = (conn) => {
const resetTimes = (quotaData[conn.id]?.quotas || [])
.map((quota) => quota.resetAt ? new Date(quota.resetAt).getTime() : Number.POSITIVE_INFINITY)
.filter((time) => Number.isFinite(time));
return resetTimes.length > 0 ? Math.min(...resetTimes) : Number.POSITIVE_INFINITY;
};
// Sort providers by USAGE_SUPPORTED_PROVIDERS order, then alphabetically.
// Optionally surface accounts with quotas expiring soonest first.
const sortedConnections = [...providerFilteredConnections].sort((a, b) => {
if (expiringFirst) {
const expiryDiff = getEarliestResetTime(a) - getEarliestResetTime(b);
if (expiryDiff !== 0) return expiryDiff;
}
const orderA = USAGE_SUPPORTED_PROVIDERS.indexOf(a.provider);
const orderB = USAGE_SUPPORTED_PROVIDERS.indexOf(b.provider);
if (orderA !== orderB) return orderA - orderB;
return a.provider.localeCompare(b.provider);
});
const providerOptions = Array.from(new Set(filteredConnections.map((conn) => conn.provider))).sort();
// Calculate summary stats
const totalProviders = sortedConnections.length;
const activeWithLimits = Object.values(quotaData).filter(
@@ -422,6 +442,26 @@ export default function ProviderLimits() {
</div>
<div className="flex items-center gap-2">
<select
value={providerFilter}
onChange={(event) => setProviderFilter(event.target.value)}
className="h-10 rounded-lg border border-black/10 bg-transparent px-3 text-sm text-text-primary dark:border-white/10"
aria-label="Filter quota providers"
>
<option value="all">All providers</option>
{providerOptions.map((provider) => (
<option key={provider} value={provider}>{provider}</option>
))}
</select>
<button
type="button"
onClick={() => setExpiringFirst((prev) => !prev)}
className={`flex items-center gap-2 rounded-lg border px-3 py-2 text-sm transition-colors ${expiringFirst ? "border-amber-500/40 bg-amber-500/10 text-amber-500" : "border-black/10 text-text-primary hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/5"}`}
title="Sort accounts by earliest quota reset time"
>
<span className="material-symbols-outlined text-[18px]">hourglass_top</span>
Expiring first
</button>
{/* Auto-refresh toggle */}
<button
onClick={() => setAutoRefresh((prev) => !prev)}