instance sort

Changed files
+14 -7
src
+3
bun.lock
··· 6 "dependencies": { 7 "@tailwindcss/vite": "^4.1.16", 8 "date-fns": "^4.1.0", 9 "numeral": "^2.0.6", 10 "tailwindcss": "^4.1.16", 11 }, ··· 330 "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], 331 332 "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], 333 334 "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], 335
··· 6 "dependencies": { 7 "@tailwindcss/vite": "^4.1.16", 8 "date-fns": "^4.1.0", 9 + "lodash": "^4.17.21", 10 "numeral": "^2.0.6", 11 "tailwindcss": "^4.1.16", 12 }, ··· 331 "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], 332 333 "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], 334 + 335 + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], 336 337 "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], 338
+1
package.json
··· 24 "dependencies": { 25 "@tailwindcss/vite": "^4.1.16", 26 "date-fns": "^4.1.0", 27 "numeral": "^2.0.6", 28 "tailwindcss": "^4.1.16" 29 }
··· 24 "dependencies": { 25 "@tailwindcss/vite": "^4.1.16", 26 "date-fns": "^4.1.0", 27 + "lodash": "^4.17.21", 28 "numeral": "^2.0.6", 29 "tailwindcss": "^4.1.16" 30 }
+10 -7
src/App.svelte
··· 2 import { onMount } from 'svelte'; 3 import { formatDistanceToNow, addSeconds, formatDate, formatISO9075 } from 'date-fns'; 4 import { Progress, Switch } from '@skeletonlabs/skeleton-svelte'; 5 import instancesData from './instances.json'; 6 import numeral from 'numeral'; 7 ··· 26 let canRefresh = $state(true) 27 let lastUpdated = $state(new Date()) 28 let autoRefreshEnabled = $state(true) 29 - let instances = $state(instancesData) 30 - let instancesSorted = $derived(instances.sort((a, b) => a.status?.responseTime > b.status?.responseTime ? 1 : -1)) 31 32 function formatNumber(n: number) { 33 return numeral(n).format() ··· 56 } 57 } 58 if (statusResp) { 59 - statusResp.responseTime = performance.now() - start; 60 } 61 return statusResp 62 } ··· 71 await Promise.all(instances.map(async (instance) => { 72 const status = await getStatus(instance) 73 74 - if (status?.bundles?.last_bundle > lastKnownBundle.number) { 75 lastKnownBundle.number = status?.bundles?.last_bundle 76 lastKnownBundle.hash = status?.bundles?.head_hash 77 lastKnownBundle.time = status?.bundles?.end_time ··· 82 lastKnownBundle.etaNext = addSeconds(new Date(), status?.mempool?.eta_next_bundle_seconds) 83 } 84 } 85 - instance.status = status 86 lastUpdated = new Date() 87 })) 88 isUpdating = false ··· 173 </tr> 174 </thead> 175 <tbody> 176 - {#each instances as instance} 177 <tr> 178 <td><a href={instance.url} target="_blank" class="font-semibold">{instance.url.replace("https://", "")}</a></td> 179 <td>{#if instance.status?.bundles?.last_bundle === lastKnownBundle.number}✅{:else if instance.status}🔄{:else}⌛{/if}</td> ··· 182 <td><span class="font-mono text-xs">{#if instance.status?.bundles?.head_hash}{instance.status?.bundles?.head_hash.slice(0, 7)}{/if}</span></td> 183 <td><span class="font-mono text-xs">{#if instance.status?.bundles?.root_hash}{instance.status?.bundles?.root_hash.slice(0, 7)}{/if}</span></td> 184 <td>{#if instance.status?.server?.version}{instance.status?.server?.version}{/if}</td> 185 - <td class="opacity-50">{#if instance.status?.responseTime}{Math.round(instance.status?.responseTime)}ms{/if}</td> 186 </tr> 187 {/each} 188 </tbody>
··· 2 import { onMount } from 'svelte'; 3 import { formatDistanceToNow, addSeconds, formatDate, formatISO9075 } from 'date-fns'; 4 import { Progress, Switch } from '@skeletonlabs/skeleton-svelte'; 5 + import orderBy from "lodash/orderBy"; 6 import instancesData from './instances.json'; 7 import numeral from 'numeral'; 8 ··· 27 let canRefresh = $state(true) 28 let lastUpdated = $state(new Date()) 29 let autoRefreshEnabled = $state(true) 30 + let instances = $state(instancesData.sort(() => Math.random() - 0.5)) 31 + 32 + const instanceOrderBy = [['status.head', 'status.latency'], ['desc', 'asc']] 33 34 function formatNumber(n: number) { 35 return numeral(n).format() ··· 58 } 59 } 60 if (statusResp) { 61 + statusResp.latency = performance.now() - start; 62 } 63 return statusResp 64 } ··· 73 await Promise.all(instances.map(async (instance) => { 74 const status = await getStatus(instance) 75 76 + instance.status = status 77 + instance.status.head = status?.bundles?.last_bundle > lastKnownBundle.number 78 + if (instance.status.head) { 79 lastKnownBundle.number = status?.bundles?.last_bundle 80 lastKnownBundle.hash = status?.bundles?.head_hash 81 lastKnownBundle.time = status?.bundles?.end_time ··· 86 lastKnownBundle.etaNext = addSeconds(new Date(), status?.mempool?.eta_next_bundle_seconds) 87 } 88 } 89 lastUpdated = new Date() 90 })) 91 isUpdating = false ··· 176 </tr> 177 </thead> 178 <tbody> 179 + {#each orderBy(instances, ...instanceOrderBy) as instance} 180 <tr> 181 <td><a href={instance.url} target="_blank" class="font-semibold">{instance.url.replace("https://", "")}</a></td> 182 <td>{#if instance.status?.bundles?.last_bundle === lastKnownBundle.number}✅{:else if instance.status}🔄{:else}⌛{/if}</td> ··· 185 <td><span class="font-mono text-xs">{#if instance.status?.bundles?.head_hash}{instance.status?.bundles?.head_hash.slice(0, 7)}{/if}</span></td> 186 <td><span class="font-mono text-xs">{#if instance.status?.bundles?.root_hash}{instance.status?.bundles?.root_hash.slice(0, 7)}{/if}</span></td> 187 <td>{#if instance.status?.server?.version}{instance.status?.server?.version}{/if}</td> 188 + <td class="opacity-50">{#if instance.status?.latency}{Math.round(instance.status?.latency)}ms{/if}</td> 189 </tr> 190 {/each} 191 </tbody>