data-experiments / app /static /index.html
okosti's picture
deploy dc86eb14
44453a0 verified
Raw History Blame Contribute Delete
13.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Data Experiments</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap">
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.2/marked.min.js" integrity="sha384-/TQbtLCAerC3jgaim+N78RZSDYV7ryeoBCVqTuzRrFec2akfBkHS7ACQ3PQhvMVi" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js" integrity="sha384-+VfUPEb0PdtChMwmBcBmykRMDd+v6D/oFmB3rZM/puCMDYcIvF968OimRh4KQY9a" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<style>
/* Layout: a status strip, a filter bar, then one section per status with a grid of project cards; access guides open in a side reader. */
:root {
--bg: #f3f5f8; --panel: #ffffff; --ink: #16202c; --muted: #5d6a7b; --rule: #dde2ea; --accent: #2a5bd7;
--bld: #8a5a00; --bld-bg: #fff2d1; --plt: #6a3fc4; --plt-bg: #f0e9fd; --run: #1d64d8; --run-bg: #e3edff;
--don: #18794b; --don-bg: #e2f5ea; --code-bg: #eef1f5; --pau: #8b4a3c; --pau-bg: #fbe9e4;
--sft: #0b6e74; --sft-bg: #ddf3f2;
--sans: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
--mono: "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
--bg: #0f141b; --panel: #161d27; --ink: #e4e9f1; --muted: #98a4b6; --rule: #283241; --accent: #7ea6ff;
--bld: #f0c35a; --bld-bg: #2d2412; --plt: #b99cf7; --plt-bg: #241b38; --run: #7fb0ff; --run-bg: #14233d;
--don: #6fd39d; --don-bg: #11281d; --code-bg: #1d2633; --pau: #f0a08c; --pau-bg: #2e1a15;
--sft: #5fd4d0; --sft-bg: #0f2a2a; color-scheme: dark } }
:root[data-theme="dark"] {
--bg: #0f141b; --panel: #161d27; --ink: #e4e9f1; --muted: #98a4b6; --rule: #283241; --accent: #7ea6ff;
--bld: #f0c35a; --bld-bg: #2d2412; --plt: #b99cf7; --plt-bg: #241b38; --run: #7fb0ff; --run-bg: #14233d;
--don: #6fd39d; --don-bg: #11281d; --code-bg: #1d2633; --pau: #f0a08c; --pau-bg: #2e1a15;
--sft: #5fd4d0; --sft-bg: #0f2a2a; color-scheme: dark }
body { background: var(--bg); color: var(--ink); font: 15px/1.5 var(--sans);
padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); padding-block: 26px 56px; }
main { max-width: 1180px; margin: 0 auto; display: flex; flex-direction: column; gap: 26px; }
h1, h2, h3 { margin: 0; text-wrap: balance; font-weight: 600; }
h1 { font-size: 1.85rem; line-height: 1.15; letter-spacing: -0.01em; }
h2 { font-size: 1.05rem; display: flex; align-items: center; gap: 10px; }
h3 { font-size: 1.02rem; line-height: 1.3; }
p { margin: 0; max-width: 72ch; }
.lede { color: var(--muted); }
.strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 170px), 1fr)); gap: 10px; }
.stat { background: var(--panel); border: 1px solid var(--rule); border-radius: 10px; padding: 12px 14px; display: flex; flex-direction: column; gap: 2px;
cursor: pointer; text-align: left; font: inherit; color: inherit; }
.stat b { font: 600 1.6rem/1.1 var(--mono); font-variant-numeric: tabular-nums; }
.stat span { font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.stat small { font-size: .78rem; line-height: 1.35; color: var(--muted); margin-top: 4px; }
.stat[aria-pressed="true"] { outline: 2px solid var(--accent); outline-offset: -1px; }
.stat.building b { color: var(--bld); } .stat.pilot_ready b { color: var(--plt); } .stat.prod_running b { color: var(--run); } .stat.prod_done b { color: var(--don); }
.stat.prod_paused b { color: var(--pau); } .stat.sft b { color: var(--sft); }
.bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.bar input { font: inherit; color: var(--ink); background: var(--panel); border: 1px solid var(--rule); border-radius: 8px; padding: 7px 10px; min-width: 0; flex: 1 1 220px; max-width: 360px; }
.bar .note { color: var(--muted); font-size: .85rem; }
button:focus-visible, input:focus-visible, a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
section { display: flex; flex-direction: column; gap: 12px; }
.count { font: 500 .8rem var(--mono); color: var(--muted); }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); gap: 14px; }
.card { background: var(--panel); border: 1px solid var(--rule); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.top { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.pill { flex: none; font: 600 .72rem var(--sans); text-transform: uppercase; letter-spacing: .06em; padding: 3px 9px; border-radius: 999px; white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; }
.pill.building { background: var(--bld-bg); color: var(--bld); } .pill.pilot_ready { background: var(--plt-bg); color: var(--plt); }
.pill.prod_running { background: var(--run-bg); color: var(--run); } .pill.prod_done { background: var(--don-bg); color: var(--don); }
.pill.prod_paused { background: var(--pau-bg); color: var(--pau); }
.sftrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: .84rem; }
.sftbadge { font: 600 .74rem var(--sans); text-transform: uppercase; letter-spacing: .06em; padding: 3px 9px; border-radius: 999px; background: var(--sft-bg); color: var(--sft); }
.sftrow .who { color: var(--muted); }
.sftrow .sftnote { flex-basis: 100%; color: var(--ink); overflow-wrap: anywhere; }
.sftrow button { font: 500 .8rem var(--sans); color: var(--sft); background: transparent; border: 1px solid var(--rule); border-radius: 999px; padding: 3px 10px; cursor: pointer; }
.sftrow button:hover { border-color: var(--sft); }
.sftrow input { font: inherit; font-size: .85rem; color: var(--ink); background: var(--bg); border: 1px solid var(--rule); border-radius: 8px; padding: 5px 8px; flex: 1 1 200px; min-width: 0; }
.sftrow .err { flex-basis: 100%; color: var(--pau); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pill.prod_running .dot { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .pill.prod_running .dot { animation: none; } }
.desc { font-size: .95rem; line-height: 1.45; }
.type { color: var(--muted); font-size: .86rem; }
.size { font: 500 .9rem var(--mono); font-variant-numeric: tabular-nums; }
.prog { display: flex; flex-direction: column; gap: 4px; }
.track { height: 8px; background: var(--code-bg); border-radius: 999px; overflow: hidden; }
.fill { height: 100%; background: var(--run); border-radius: 999px; }
.prog .lbl { font: .8rem var(--mono); color: var(--muted); font-variant-numeric: tabular-nums; }
.links { display: flex; flex-wrap: wrap; gap: 8px; }
.links a, .links button { font: 500 .82rem var(--sans); color: var(--accent); background: transparent; border: 1px solid var(--rule); border-radius: 999px; padding: 4px 11px; text-decoration: none; cursor: pointer; }
.links a:hover, .links button:hover { border-color: var(--accent); }
.loc { display: flex; gap: 8px; align-items: center; min-width: 0; }
.loc code { font: .78rem var(--mono); background: var(--code-bg); padding: 3px 7px; border-radius: 6px; overflow-wrap: anywhere; min-width: 0; }
.loc button { flex: none; font: .75rem var(--sans); color: var(--muted); background: transparent; border: 1px solid var(--rule); border-radius: 6px; padding: 2px 8px; cursor: pointer; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; font-size: .86rem; }
.kv dt { color: var(--muted); } .kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.foot { font-size: .78rem; color: var(--muted); border-top: 1px solid var(--rule); padding-top: 8px; }
.empty { background: var(--panel); border: 1px dashed var(--rule); border-radius: 12px; padding: 22px; color: var(--muted); }
.howto { background: var(--panel); border: 1px solid var(--rule); border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 8px; }
.howto code { font: .82rem var(--mono); background: var(--code-bg); padding: 1px 5px; border-radius: 4px; }
.reader { position: fixed; inset: 0; background: color-mix(in srgb, var(--ink) 35%, transparent); display: flex; justify-content: flex-end; z-index: 20; }
.reader[hidden] { display: none !important; }
.sheet { background: var(--panel); width: min(860px, 100%); height: 100%; display: flex; flex-direction: column; border-left: 1px solid var(--rule);
padding-top: env(safe-area-inset-top, 0px); padding-bottom: env(safe-area-inset-bottom, 0px); padding-right: env(safe-area-inset-right, 0px); }
.sheet header { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 14px 18px; border-bottom: 1px solid var(--rule); }
.sheet header .path { font: .78rem var(--mono); color: var(--muted); overflow-wrap: anywhere; }
.sheet header button { font: 500 .85rem var(--sans); color: var(--ink); background: var(--bg); border: 1px solid var(--rule); border-radius: 8px; padding: 6px 12px; cursor: pointer; flex: none; }
.md { overflow: auto; padding: 18px 22px 40px; line-height: 1.6; }
.md h1 { font-size: 1.4rem; margin: .2em 0 .6em; } .md h2 { font-size: 1.15rem; margin: 1.3em 0 .5em; display: block; } .md h3 { font-size: 1rem; margin: 1.1em 0 .4em; }
.md p, .md ul, .md ol { margin: .5em 0; max-width: 78ch; }
.md table { border-collapse: collapse; font-size: .88rem; display: block; overflow-x: auto; max-width: 100%; margin: .7em 0; }
.md th, .md td { border: 1px solid var(--rule); padding: 5px 9px; text-align: left; vertical-align: top; }
.md th { background: var(--code-bg); font-weight: 600; }
.md code { font: .85em var(--mono); background: var(--code-bg); padding: 1px 5px; border-radius: 4px; }
.md pre { background: var(--code-bg); padding: 12px 14px; border-radius: 8px; overflow-x: auto; }
.md pre code { background: none; padding: 0; }
.md a { color: var(--accent); }
.md blockquote { border-left: 3px solid var(--rule); margin: .6em 0; padding: .1em 0 .1em 12px; color: var(--muted); }
.who-am-i { color: var(--muted); font-size: .82rem; }
.who-am-i a { color: var(--accent); margin-left: 6px; }
.gate { border: 1px solid var(--rule); border-radius: 12px; background: var(--panel); padding: 20px 22px; display: flex; flex-direction: column; gap: 8px; max-width: 640px; }
.gate h2 { margin: 0; font-size: 1.15rem; }
.gate p { margin: 0; }
.gate a.signin { display: inline-block; font-weight: 600; color: var(--panel); background: var(--accent); text-decoration: none; padding: 8px 14px; border-radius: 9px; }
.build { font: .72rem var(--mono); color: var(--muted); }
</style>
</head>
<body>
<main>
<header style="display:flex;flex-direction:column;gap:8px">
<h1>Data Experiments</h1>
<p class="lede">Every data type we are building, piloting or producing: what it is, where it stands, the pilot to listen to, and how to get the production data. Sessions keep their own rows up to date.</p>
<span class="who-am-i"><span id="me"></span> <a id="signout" href="/logout" hidden>Sign out</a></span>
</header>
<div class="gate" id="gate" hidden>
<h2 id="gtitle">Sign in to see the projects</h2>
<p id="gtext">This dashboard is for the Extrian team and invited collaborators. Sign in with your Hugging Face account; a free one works.</p>
<p><a class="signin" id="signin" href="/login">Sign in with Hugging Face</a></p>
<p class="note" id="gnote">No access after signing in? Ask the dashboard owner to add your email or Hugging Face username.</p>
</div>
<div class="strip" id="strip"></div>
<div class="bar">
<input id="q" type="search" placeholder="Search titles, data types, locations" aria-label="Search projects">
<span class="note" id="status">Loading projects…</span>
</div>
<div id="sections" style="display:flex;flex-direction:column;gap:26px">
<div class="empty" id="empty">Projects will appear here as each session adds its row. Nothing has loaded yet.</div>
</div>
<div class="howto">
<h2>Add or update a project</h2>
<p>Each project is one JSON record under <code>projects/&lt;slug&gt;</code>, with access guides under <code>docs/&lt;id&gt;</code>. A session updates its own record with <code>python dataops/experiments_db.py</code>, and this page picks it up within a minute. Full instructions, fields and examples are in <code>DATA_EXPERIMENTS_DASHBOARD.md</code> at the root of the data-processing-tts repo.</p>
<p>Trained on a dataset? Press <b>Mark SFT done</b> on its card and add a note (the run name or result). Anyone signed in can mark or undo it; everyone sees who marked it and when.</p>
<span class="build">build dc86eb14</span>
</div>
</main>
<div class="reader" id="reader" hidden>
<div class="sheet" role="dialog" aria-modal="true" aria-labelledby="rtitle">
<header>
<div style="display:flex;flex-direction:column;gap:2px;min-width:0"><b id="rtitle"></b><span class="path" id="rpath"></span></div>
<button type="button" id="rclose">Close</button>
</header>
<div class="md" id="rbody"></div>
</div>
</div>
<script src="/app.js"></script>
</body>
</html>