From 25a9a000efac7446bd69c5d88cadacd611bac0af Mon Sep 17 00:00:00 2001 From: Kumaraguru <19eucs071@skcet.ac.in> Date: Mon, 13 Jan 2025 18:13:52 +0000 Subject: [PATCH] ui enhancements and changes in db tracking everyday active nodes --- pages/index.js | 222 +++++++++++++++++++++++++++++++++--------------- public/logo.png | Bin 0 -> 50876 bytes 2 files changed, 154 insertions(+), 68 deletions(-) create mode 100644 public/logo.png diff --git a/pages/index.js b/pages/index.js index 3b65802..f745608 100644 --- a/pages/index.js +++ b/pages/index.js @@ -67,7 +67,7 @@ export default function Dashboard() { versions: true, peers: true, }); - + // Pagination and Search states const [versionPage, setVersionPage] = useState(1); const [peerPage, setPeerPage] = useState(1); @@ -83,8 +83,8 @@ export default function Dashboard() { useEffect(() => { if (searchQuery.trim()) { setIsSearching(true); - const results = activePeerIds.filter(peerId => - peerId.toLowerCase().includes(searchQuery.toLowerCase()) + const results = activeNodeIds.filter(nodeId => + nodeId.toLowerCase().includes(searchQuery.toLowerCase()) ); setSearchResults(results); setPeerPage(1); @@ -105,12 +105,24 @@ export default function Dashboard() { }); try { + // Calculate date range based on timeframe + const now = new Date(); + const startDate = new Date(); + if (timeframe === "7d") { + startDate.setDate(now.getDate() - 7); + } else if (timeframe === "30d") { + startDate.setDate(now.getDate() - 30); + } else if (timeframe === "1y") { + startDate.setDate(now.getDate() - 365); + } + // Fetch metrics const { data: metricsData, error: metricsError } = await supabase .from("metrics") .select("*") - .order("date", { ascending: true }) - .limit(timeframe === "7d" ? 7 : timeframe === "30d" ? 30 : 365); + .gte('date', startDate.toISOString().split('T')[0]) + .lte('date', now.toISOString().split('T')[0]) + .order("date", { ascending: true }); if (metricsError) throw metricsError; setMetrics(metricsData || []); @@ -188,7 +200,7 @@ export default function Dashboard() { const date = new Date(timestamp); const time = format(date, "HH:mm"); let dateText; - + if (isToday(date)) { dateText = "Today"; } else if (isYesterday(date)) { @@ -196,17 +208,26 @@ export default function Dashboard() { } else { dateText = format(date, "dd.MM.yyyy"); } - + return { time, dateText }; }; // Calculate statistics - const currentActiveNodes = activeNodes.length; + const totalUniqueNodes = [...new Set(activeNodes.map(node => node.node_id))].length; const averagePeerCount = activeNodes.length ? (activeNodes.reduce((acc, node) => acc + node.peer_count, 0) / activeNodes.length).toFixed(1) : 0; const activePeerIds = [...new Set(activeNodes.map((node) => node.peer_id))]; - const totalNodes = metrics.reduce((acc, day) => acc + day.new_records_count, 0); + + // Calculate today's active nodes + const todayStart = new Date(); + todayStart.setHours(0, 0, 0, 0); + const todayActiveNodes = [...new Set( + activeNodes + .filter(node => new Date(node.timestamp) >= todayStart) + .map(node => node.node_id) + )].length; + const versionDistribution = activeNodes.reduce((acc, node) => { acc[node.version] = (acc[node.version] || 0) + 1; return acc; @@ -223,12 +244,46 @@ export default function Dashboard() { const totalVersionPages = getPageCount(versionEntries.length); const totalPeerPages = getPageCount(displayPeerIds.length); + // Prepare chart data + const chartData = metrics.map((day) => ({ + date: new Date(day.date), + "Active Nodes": day.active_nodes_count + })); + + // Get unique node IDs and their latest records + const nodeRecords = activeNodes.reduce((acc, node) => { + if (!acc[node.node_id] || new Date(acc[node.node_id].timestamp) < new Date(node.timestamp)) { + acc[node.node_id] = node; + } + return acc; + }, {}); + + const activeNodeIds = Object.keys(nodeRecords); + const displayNodeIds = searchQuery ? searchResults : activeNodeIds; + const paginatedNodeIds = getPaginatedData(displayNodeIds, peerPage); + const totalNodePages = getPageCount(displayNodeIds.length); + + // Node details dialog state + const [selectedNode, setSelectedNode] = useState(null); + + // Format timestamp for node details + const formatNodeTimestamp = (timestamp) => { + if (!timestamp) return "N/A"; + const date = new Date(timestamp); + if (isToday(date)) { + return `Today at ${format(date, "HH:mm")}`; + } else if (isYesterday(date)) { + return `Yesterday at ${format(date, "HH:mm")}`; + } + return format(date, "MMM d, yyyy 'at' HH:mm"); + }; + return ( <>
The data displayed in this dashboard is collected from Codex nodes that use the{' '} - @@ -323,19 +378,19 @@ export default function Dashboard() { {' '}for running a Codex alturistic node in the testnet.
- Users agree to a privacy disclaimer before using the Codex CLI and the data collected will be used to - understand the testnet statistics and help troubleshooting users who face + Users agree to a privacy disclaimer before using the Codex CLI and the data collected will be used to + understand the testnet statistics and help troubleshooting users who face difficulty in getting onboarded to Codex.
You can still run a Codex node without providing any data. To do this, please follow the steps mentioned in the{' '}
-
@@ -356,7 +411,7 @@ export default function Dashboard() {
The best way to get in touch with us is to join the{' '}
@@ -384,8 +439,8 @@ export default function Dashboard() {
No active peers available No matching peer IDs found
+ {searchQuery ? "No matching node IDs found" : "No active node IDs"}
+ U6*rm{98_pBFnV>Lfk?30i!H-Db$B}XEd9B+MzSZJmObjVBp6O
z*rP-XWd)qP?fGY0 i!KR+Kl+1_}*fZi3^Ubuf!P@
z#9TkoMS=BQZ4KE{kEU7WfpIm&@Reh`(Ho~B{8B*=_{@Hs!%e9Qds4%$0L^MHK{cZZ
ziH4+|f(TRjFrrKASenP_7d>}hDy~1Wmv0jOkml3FP26L8!TXmXLEhbZj;| Izw3-Rt!dhM`
zEMHfhRws2Dw%PxR9f-hx^+*c()CnG>>7|aUaD42P(L%GsoK;Q72@3LpT a75y>|6GOO20jB<5Hc{56oU
zeJF09KM(qv!=pSB!^$|$A8Sx?)uC)@uM_Ml6ch}JS`ua}ut-dr2G1YSsK&ursS7p1
zmi>S9zQ9947k0!S@UQ1+oPj&X4P_i>D^y(r%i|Zmv|a;{0JG*Bb+p63gPRg^v%q1u
z;79s=hOU%{dwNV6cSFyhwSB%wZ*T0~f9{!LO|i5)@LEbY8J{gBmXY9Sd)L=nTS4%R
zlK9#|+K@EB(R=NUO9D|xJ^<5&8|N?vMh=0kIYEUVc<}!JZB47QTkK?5hHSY<9^ftL
zcP^e#=yRINmKP?IR^R2Z@ga@1HHh+o%zhuk3~U58EQYo=^J&uTh)X8%4MDPjDUk(f
zb=1c;?_eij(}g(mmU2$GAD37xkNZqH3VMOom8FE)G)!k})&G%mtcmg8BQ)-R$I
zqY@>f3){-I{fK4TylK-;zovC&8;jl{gT4Tb%y@KqRHKS4Ap4xe$uehq
-
+
e2G@#Dj*5y%>!Ir=kd$BBxQpTHlz~Um+LAXXCw**?{kW{o9)}9~~xB
z;U0q0LQEcarv9PkTyDd%jKJybcH&w;^+tz+sGkiet+ce^H*S3siKilKU2V;=TwiH4
zul~<26tcadxMlh+$*=pblm?0_()=nn9rU8<9e}lgM0)VH0<(+70@7c`VE