data-line
portal: catalog page of repository commit 62473f64f8f2
638568b
Raw History Blame Contribute Delete
4.39 kB
// The first screen, drawn before the index is read: the pictograms, and the hero from first.json (written by the deploy
// step from the index commit of the day) when that commit is the one the page reads. app.js draws the hero from the
// index itself when it has read it (data.js totals; portal.py first_screen counts alike).
import { fmtBytes, fmtCompact, fmtDate, fmtInt } from './charts.js';
import { loadRevision } from './commit.js';
import { onLanguage, t } from './i18n.js';
import { icon } from './icons.js';
const reduced = () => matchMedia('(prefers-reduced-motion: reduce)').matches;
const FACTS = { ready_sources: fmtInt, answers: fmtInt, raw_rows: fmtCompact, sources: fmtInt };
const shown = new Map();
/** Pictograms for every [data-icon] element, once. */
export function decorate(root = document) {
for (const n of root.querySelectorAll('[data-icon]:not([data-drawn])')) {
n.dataset.drawn = '1';
const inBar = n.closest('.progress');
n.prepend(icon(n.dataset.icon, { size: Number(n.dataset.size || (inBar ? 14 : 20)) }));
}
}
/** Write value into node. The first value is written as it is (no count from 0: the first screen shows the true
* numbers at once). A later, different value (main has moved past the commit first.json names, or the page reads
* preview data) is written and briefly highlighted as an update. */
export function setNumber(node, key, value, fmt) {
if (!node) return;
const was = shown.get(key);
shown.set(key, value);
node.textContent = fmt(value);
node.dataset.v = String(value);
if (was == null || was === value || reduced()) return;
node.classList.remove('updated');
void node.offsetWidth;
node.classList.add('updated');
node.addEventListener('animationend', () => node.classList.remove('updated'), { once: true });
}
/** The size line (#364): distinct content and the rows without a size, not in it; the words of docs/sources.md of the
* index. */
function drawSize(v) {
const node = document.getElementById('hero-size');
if (!node || !('distinct_bytes' in v)) return;
if (v.distinct_bytes == null) { node.replaceChildren(t('hero.sizeUnknown')); return; }
const big = document.createElement('b');
const unsized = v.unsized_rows ? ` · ${t('hero.unsized', { count: v.unsized_rows, n: fmtInt(v.unsized_rows) })}` : '';
node.replaceChildren(big, ` ${t('hero.distinct')}${unsized}`);
setNumber(big, 'distinct_bytes', v.distinct_bytes, fmtBytes);
}
let last = null;
/** v: {ready_units, ready_sources, answers, raw_rows, sources, distinct_bytes, unsized_rows, index, date}. */
export function drawHero(v) {
if (!v) return;
last = v;
setNumber(document.getElementById('hero-big'), 'ready_units', v.ready_units, fmtInt);
setNumber(document.getElementById('material-n'), 'material_units', v.ready_units, fmtInt);
drawSize(v);
for (const li of document.querySelectorAll('#hero-facts .fact-tile')) {
const k = li.dataset.k;
if (v[k] != null) setNumber(li.querySelector('.fact-num'), k, v[k], FACTS[k]);
}
const pin = document.getElementById('pin-link');
if (v.index && pin) {
pin.textContent = fmtDate(v.date);
pin.href = `https://huggingface.co/datasets/Battam/agentic-env-index/tree/${v.index}`;
pin.title = t('hero.commit', { sha: v.index });
}
const foot = document.getElementById('foot-pin');
if (v.index && foot) foot.textContent = t('foot.index', { sha: v.index.slice(0, 7), date: fmtDate(v.date) });
}
decorate();
// the hero in the new language: the same numbers, written again
onLanguage(() => drawHero(last));
let drawnFromIndex = false;
export const markFromIndex = () => { drawnFromIndex = true; };
// first.json was computed at deploy from one commit of the index; it is drawn only when that is the commit the page reads
// (?rev= or main as it is now), else the hero waits for the page's own count. With ?catalog= or ?vocabulary= the page
// shows other data at the same commit, so the hero waits too (the file is still read: the page preloads it).
const params = new URLSearchParams(location.search);
const override = params.has('catalog') || params.has('vocabulary');
Promise.all([
fetch('first.json', { cache: 'no-cache' }).then((r) => (r.ok ? r.json() : null)),
loadRevision(params.get('rev')),
])
.then(([j, rev]) => { if (j && !override && !drawnFromIndex && rev.sha && j.index === rev.sha) drawHero(j); })
.catch(() => {});