From 730ea271156f1ed792e1c64d67f48e14dd46b863 Mon Sep 17 00:00:00 2001 From: Rick Staa Date: Fri, 7 Nov 2025 10:22:40 +0100 Subject: [PATCH] fix: hide performance regions with no data Previously all data returned by the testers was displayed. This commmit changes the behavoir to only display data of regions and pipelines for which the tester did have data. --- components/PerformanceList/index.tsx | 35 +++++++++++------------ pages/leaderboard.tsx | 42 ++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/components/PerformanceList/index.tsx b/components/PerformanceList/index.tsx index 6ba1c98a..8f1a87fc 100644 --- a/components/PerformanceList/index.tsx +++ b/components/PerformanceList/index.tsx @@ -6,31 +6,35 @@ import { ExplorerTooltip } from "@components/ExplorerTooltip"; import Link from "next/link"; import { useMemo } from "react"; import QRCode from "qrcode.react"; -import { useAllScoreData, useEnsData } from "hooks"; +import { useEnsData } from "hooks"; import { OrchestratorsQueryResult } from "apollo"; import numeral from "numeral"; import { Pipeline } from "@lib/api/types/get-available-pipelines"; import { Region } from "@lib/api/types/get-regions"; +import { AllPerformanceMetrics } from "@lib/api/types/get-performance"; const EmptyData = () => ; const PerformanceList = ({ - data, + orchestratorIds, pageSize = 20, region, pipeline, model, + performanceMetrics = null, + isLoadingMetrics = false, }: { pageSize: number; region: Region["id"]; pipeline: Pipeline["id"] | null; model: string | null; - data: Pick< + performanceMetrics?: AllPerformanceMetrics | null; + isLoadingMetrics?: boolean; + orchestratorIds: Pick< NonNullable["transcoders"][number], "id" >[]; }) => { - const {isValidating, data: allScores} = useAllScoreData(pipeline, model); const isAIData = pipeline !== null && model !== null; const scoreAccessor = `scores.${region}`;//total score const successRateAccessor = `successRates.${region}`;//success rate @@ -53,8 +57,8 @@ const PerformanceList = ({ }; const mergedData = useMemo( - () => data.map((o) => ({ ...o, ...allScores?.[o?.id] })), - [allScores, data] + () => orchestratorIds.map((o) => ({ ...o, ...performanceMetrics?.[o?.id] })), + [performanceMetrics, orchestratorIds] ); //tanstack v7's numberic sorting function incorrectly treats 0, null, and undefined as 0 (the same value). @@ -215,11 +219,8 @@ const PerformanceList = ({ defaultCanSort: true, sortType: sortTypeFn, Cell: ({ value }) => { - if ( - isValidating - ) { - return ; - } + if (isLoadingMetrics) return ; + return ( {typeof value === "undefined" || value === null ? @@ -251,9 +252,8 @@ const PerformanceList = ({ accessor: `${successRateAccessor}`, sortType: sortTypeFn, Cell: ({ value }) => { - if (isValidating) { - return ; - } + if (isLoadingMetrics) return ; + return ( {typeof value === "undefined" || value === null ? @@ -286,9 +286,8 @@ const PerformanceList = ({ accessor: `${roundTripScoreAccessor}`, sortType: sortTypeFn, Cell: ({ value }) => { - if (isValidating) { - return ; - } + if (isLoadingMetrics) return ; + return ( {typeof value === "undefined" || value === null ? @@ -302,7 +301,7 @@ const PerformanceList = ({ }, }, ], - [region, isValidating] + [region, isLoadingMetrics] ); return ( diff --git a/pages/leaderboard.tsx b/pages/leaderboard.tsx index 4985563f..e5c4edd6 100644 --- a/pages/leaderboard.tsx +++ b/pages/leaderboard.tsx @@ -6,10 +6,10 @@ import { EnsIdentity } from "@lib/api/types/get-ens"; import { Box, Container, Flex, Heading } from "@livepeer/design-system"; import { ChevronDownIcon } from "@modulz/radix-icons"; import Head from "next/head"; -import { useState } from "react"; +import { useState, useMemo } from "react"; import { getApollo, OrchestratorsQueryResult } from "../apollo"; import { Pipeline } from "@lib/api/types/get-available-pipelines"; -import { useRegionsData } from "hooks/useSwr"; +import { useRegionsData, useAllScoreData } from "hooks/useSwr"; import { Region } from "@lib/api/types/get-regions"; type PageProps = { @@ -25,6 +25,36 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => { const [selectedModel, setSelectedModel] = useState(null); const knownRegions = useRegionsData(); const [region, setRegion] = useState("GLOBAL"); + const { data: allScores, isValidating } = useAllScoreData(selectedPipeline, selectedModel); + + // Filter regions to only show those with data. + const availableRegions = useMemo(() => { + if (!knownRegions?.regions) return []; + + const pipelineType = selectedPipeline ? "ai" : "transcoding"; + + // If no scores loaded yet, just filter by pipeline type. + if (!allScores) { + return knownRegions.regions.filter((r) => r.type === pipelineType); + } + + // Collect regions that have score data. + const regionsWithData = new Set(); + Object.values(allScores).forEach((orchestratorData) => { + if (orchestratorData?.scores) { + Object.entries(orchestratorData.scores).forEach(([regionKey, value]) => { + if (value != null) { + regionsWithData.add(regionKey); + } + }); + } + }); + + // Filter regions based on pipeline type and data availability. + return knownRegions.regions.filter( + (r) => r.type === pipelineType && regionsWithData.has(r.id) + ); + }, [knownRegions?.regions, allScores, selectedPipeline]); return ( <> @@ -99,9 +129,7 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => { appearance: "none", }} > - {knownRegions?.regions - .filter((r) => r.type === (selectedPipeline?"ai":"transcoding")) - .map((region) => { + {availableRegions.map((region) => { return ( {region.name} ) @@ -137,11 +165,13 @@ const LeaderboardPage = ({ orchestratorIds }: PageProps) => {