atmosphere explorer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

show log validation status

Juliet 4a9e7d36 7e4a846c

+36 -4
+36 -4
src/views/logs.tsx
··· 2 2 CompatibleOperationOrTombstone, 3 3 defs, 4 4 IndexedEntry, 5 + IndexedEntryLog, 5 6 processIndexedEntryLog, 6 7 } from "@atcute/did-plc"; 7 - import { createResource, createSignal, For, Show } from "solid-js"; 8 + import { createEffect, createResource, createSignal, For, Show } from "solid-js"; 8 9 import { localDateFromTimestamp } from "../utils/date.js"; 9 10 import { createOperationHistory, DiffEntry, groupBy } from "../utils/plc-logs.js"; 10 11 ··· 12 13 13 14 export const PlcLogView = (props: { did: string }) => { 14 15 const [activePlcEvent, setActivePlcEvent] = createSignal<PlcEvent | undefined>(); 16 + const [validLog, setValidLog] = createSignal<boolean | undefined>(undefined); 17 + const [rawLogs, setRawLogs] = createSignal<IndexedEntryLog | undefined>(undefined); 15 18 16 19 const shouldShowDiff = (diff: DiffEntry) => 17 20 !activePlcEvent() || diff.type.startsWith(activePlcEvent()!); ··· 25 28 ); 26 29 const json = await res.json(); 27 30 const logs = defs.indexedEntryLog.parse(json); 31 + setRawLogs(logs); 32 + const opHistory = createOperationHistory(logs).reverse(); 33 + return Array.from(groupBy(opHistory, (item) => item.orig)); 34 + }; 35 + 36 + const validateLog = async (logs: IndexedEntryLog) => { 28 37 try { 29 38 await processIndexedEntryLog(props.did as any, logs); 39 + setValidLog(true); 30 40 } catch (e) { 31 41 console.error(e); 42 + setValidLog(false); 32 43 } 33 - const opHistory = createOperationHistory(logs).reverse(); 34 - return Array.from(groupBy(opHistory, (item) => item.orig)); 35 44 }; 36 45 37 46 const [plcOps] = 38 47 createResource<[IndexedEntry<CompatibleOperationOrTombstone>, DiffEntry[]][]>(fetchPlcLogs); 48 + 49 + createEffect(() => { 50 + const logs = rawLogs(); 51 + if (logs) { 52 + setValidLog(undefined); 53 + // Defer validation to next tick to avoid blocking rendering 54 + setTimeout(() => validateLog(logs), 0); 55 + } 56 + }); 39 57 40 58 const FilterButton = (props: { icon: string; event: PlcEvent; label: string }) => { 41 59 const isActive = () => activePlcEvent() === props.event; ··· 231 249 }; 232 250 233 251 return ( 234 - <div class="flex w-full flex-col gap-4 wrap-anywhere"> 252 + <div class="flex w-full flex-col gap-3 wrap-anywhere"> 235 253 <div class="flex flex-col gap-2"> 236 254 <div class="flex items-center gap-1.5 text-sm"> 237 255 <div class="iconify lucide--filter" /> ··· 251 269 label="Verification" 252 270 /> 253 271 </div> 272 + </div> 273 + <div class="flex items-center gap-1.5 text-sm font-medium"> 274 + <Show when={validLog() === true}> 275 + <span class="iconify lucide--check-circle-2 text-green-500 dark:text-green-400"></span> 276 + <span>Valid log</span> 277 + </Show> 278 + <Show when={validLog() === false}> 279 + <span class="iconify lucide--x-circle text-red-500 dark:text-red-400"></span> 280 + <span>Log validation failed</span> 281 + </Show> 282 + <Show when={validLog() === undefined}> 283 + <span class="iconify lucide--loader-circle animate-spin"></span> 284 + <span>Validating log...</span> 285 + </Show> 254 286 </div> 255 287 <div class="flex flex-col gap-3"> 256 288 <For each={plcOps()}>