feat(viewer): interactive HTML viewer for JSON reports (#50) - #56
Closed
NikolaosSokos wants to merge 26 commits into
Closed
feat(viewer): interactive HTML viewer for JSON reports (#50)#56NikolaosSokos wants to merge 26 commits into
NikolaosSokos wants to merge 26 commits into
Conversation
Replace the colored-bar timeline with the ASCII glyph timeline (█ both / · neither / ▲ dataselect-only / ▼ availability-only / | gap boundary) to match the CLI/Markdown output. Refresh the CSS (sticky toolbar, monospace timeline, card detail, row hover/selection, styled request buttons/links). Swap the misleading hand-made fixture for a real 30-epoch NOA report (7 inconsistent rows, full coverage+mismatch).
…rowser - Summary: SVG score gauge (color by threshold) + direction breakdown bars alongside the consistent/inconsistent/skipped chips. - Results table: click-to-sort column headers (toggle asc/desc), a gap-count badge, and a Max-gap column; sort dropdown removed. - Detail: per-gap duration, copy-to-clipboard for every request URL, and a clearer full-window vs per-gap grouping. - Report browser: landing page renders an index.json manifest of available reports; a URL box loads any report (e.g. an Oculus report.json) without hand-editing the query string. Demo manifest lists NOA + RESIF samples. 31 node:test cases pass (added fmtDuration, gapStats, renderIndex, table badge/sort-header, per-gap duration + copy).
The landing must list every available report, not a hand-picked pair. Add make-index.mjs: scans a report directory and writes index.json with one entry per report (name, url, node, score, timestamp, inconsistent), newest first. The manifest and the reports symlink are generated/local artifacts, so untrack the curated index.json + the redundant resif copy and gitignore them; deployments (Oculus) regenerate the manifest over their own report tree.
Keep the landing a manifest-driven slot: if an index.json is present (e.g. published by Oculus alongside its latest report JSONs) the list is shown; otherwise the loader stands alone. No scraping or hardcoded report lists. Loading now works three ways — paste a report .json URL, choose a local file, or drop a file onto the page — with validation that the file is an EIDA consistency report before rendering.
Add a two-lane SVG coverage chart (Availability lane + Dataselect lane, mismatch regions highlighted, hover tooltips with exact times) shown above the ASCII line when a record has coverage. For older reports without coverage (e.g. those currently on Oculus) fall back to a single-track 'request window with gaps' chart so every inconsistency still gets a graph. Scales to container width; colours via CSS vars for dark mode.
Add make-oculus-index.mjs: crawls the public Oculus consistency tree, picks the latest report per node, reads each summary, and writes index.json with absolute year-level JSON URLs (Oculus serves these with open CORS, so the browser loads any entry cross-origin). The landing renders the manifest as a one-row-per-node dashboard with node, score (colour-coded), timestamp, and inconsistent count; the URL/file loader stays available beneath it. index.json is a generated artifact (gitignored) — re-run the crawler to refresh, or point the viewer at an Oculus-published manifest.
Older reports (e.g. those currently on Oculus) store only the availability url. Derive the dataselect URL from it — swap the service path and the start/end param names, narrow location/channel to the record's stream — so the detail view offers Run/open/copy for dataselect too, both full-window and per-gap. Stored dataselect_url still wins when present.
runRequest now returns hasData (availability spans > 0, or dataselect 200 with bytes). The detail view shows a colour-coded pill next to each Run button — green HAS DATA, red NO DATA, grey FAILED — with the HTTP/size summary beside it. Re-running a request replaces its previous result instead of stacking.
Clicking a row now smooth-scrolls the detail section into view so the timeline and Requests are immediately visible. Add viewer/README.md documenting the architecture, data flow, every module/function, the timeline renderers, request replay, loaders, security, manifest generators, and how Oculus integrates.
The design write-up was meant as personal documentation, not a product artifact served by the viewer. Remove the in-page 'How this viewer works' link and move the doc out of the served viewer/ folder.
The table showed a bare ▲/▼ glyph for direction and the dataselect HTTP
status (often 'OK') for an inconsistent row, so what the inconsistency was
never read in plain language.
- Results table: 'Dir' -> 'Disagreement' column now shows a labelled pill
('▲ Data only' / '▼ Avail only', full phrasing on hover); 'Status' -> 'Result'
column shows the verdict in words (Inconsistent / Consistent / Skipped)
instead of the raw dataselect status.
- Detail view now leads with a plain sentence, e.g. 'Inconsistency: for 10m
(…), dataselect returned data but availability reported none.'
- New core helpers recordVerdict() and explainRecord() (+5 tests, 47 total).
Every row's max gap equals the fixed 10-minute request window, so the column (and sorting by it) carried no information. Remove it; the 'Gaps' column now sorts by gap count.
Filter options now read 'all ▲▼ / ▲ Data only / ▼ Avail only', matching the column pills. Behaviour unchanged (still filters by gap direction).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #50.
A dependency-free static viewer that renders EIDA consistency JSON reports as an interactive HTML page — no framework, no build step.
What's included (
viewer/)viewer.core.js) + 42node:testcases (viewer.core.test.mjs), DOM glue (viewer.js), and shell (viewer.html).dataselect_url.?report=<url>(opaque), file picker, drag-and-drop.index.jsonmanifest → one row per node. Generatorsmake-index.mjs(local dir) andmake-oculus-index.mjs(crawl Oculus, latest per node). Manifest is git-ignored/generated.🔍 Interactive viewlink (report.py), with tests.Validation
node --testpass.sample-report.jsonthrough the core (summary + table + detail) with no errors.main, 23 commits ahead — clean merge.Deployment note (follow-up, not in this PR)
The markdown link uses
VIEWER_BASE = "../../viewer.html"(relative). The Oculus hosting path / whether Oculus publishesindex.jsonis deferred — overrideVIEWER_BASEwhen the serving location is decided.