Spaces:
Running
Running
review.html: import-to-resume + instructions
Browse files- review.html +31 -0
review.html
CHANGED
|
@@ -102,6 +102,8 @@ footer { position: fixed; bottom: 0; left: 0; right: 0; background: var(--card);
|
|
| 102 |
<span><kbd>←</kbd><kbd>→</kbd> prev/next mention · <kbd>k</kbd> keep · <kbd>d</kbd> drop · <kbd>space</kbd> skip · <kbd>[</kbd><kbd>]</kbd> slide · <kbd>-</kbd><kbd>+</kbd> size · <kbd>e</kbd> export</span>
|
| 103 |
<span class="sp"></span><span id="count"></span>
|
| 104 |
<button id="hubBtn" onclick="exp()">export</button>
|
|
|
|
|
|
|
| 105 |
</footer>
|
| 106 |
<script>
|
| 107 |
let SINK = null, HFFUSER = null, SHAREDTOK = null;
|
|
@@ -436,6 +438,35 @@ function exp() {
|
|
| 436 |
a.href = URL.createObjectURL(new Blob([rows.map(r => JSON.stringify(r)).join('\n')], {type: 'application/json'}));
|
| 437 |
a.download = `rulings-${who() || 'anon'}-${$('ds').value}.jsonl`; a.click();
|
| 438 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
document.addEventListener('keydown', e => {
|
| 440 |
if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return;
|
| 441 |
if (e.key === 'ArrowRight') smove(1);
|
|
|
|
| 102 |
<span><kbd>←</kbd><kbd>→</kbd> prev/next mention · <kbd>k</kbd> keep · <kbd>d</kbd> drop · <kbd>space</kbd> skip · <kbd>[</kbd><kbd>]</kbd> slide · <kbd>-</kbd><kbd>+</kbd> size · <kbd>e</kbd> export</span>
|
| 103 |
<span class="sp"></span><span id="count"></span>
|
| 104 |
<button id="hubBtn" onclick="exp()">export</button>
|
| 105 |
+
<button onclick="$('impFile').click()" title="load a previous export to resume">import</button>
|
| 106 |
+
<input id="impFile" type="file" accept=".jsonl,.json" style="display:none">
|
| 107 |
</footer>
|
| 108 |
<script>
|
| 109 |
let SINK = null, HFFUSER = null, SHAREDTOK = null;
|
|
|
|
| 438 |
a.href = URL.createObjectURL(new Blob([rows.map(r => JSON.stringify(r)).join('\n')], {type: 'application/json'}));
|
| 439 |
a.download = `rulings-${who() || 'anon'}-${$('ds').value}.jsonl`; a.click();
|
| 440 |
}
|
| 441 |
+
document.getElementById('impFile').addEventListener('change', async e => {
|
| 442 |
+
const f = e.target.files[0];
|
| 443 |
+
if (!f) return;
|
| 444 |
+
try {
|
| 445 |
+
const lines = (await f.text()).split('\n').filter(Boolean);
|
| 446 |
+
let n = 0;
|
| 447 |
+
for (const line of lines) {
|
| 448 |
+
let r;
|
| 449 |
+
try { r = JSON.parse(line); } catch { continue; }
|
| 450 |
+
const items = r.items && Array.isArray(r.items) ? r.items : [r];
|
| 451 |
+
for (const it of items) {
|
| 452 |
+
if (!it.key || !['DATA_MENTION', 'NON_MENTION'].includes(it.ruling)) continue;
|
| 453 |
+
R[it.key] = it.ruling;
|
| 454 |
+
if (it.queue) RQ[it.key] = it.queue;
|
| 455 |
+
n++;
|
| 456 |
+
}
|
| 457 |
+
}
|
| 458 |
+
localStorage.setItem(LS, JSON.stringify(R));
|
| 459 |
+
localStorage.setItem('review_queues', JSON.stringify(RQ));
|
| 460 |
+
// jump to first unruled span
|
| 461 |
+
let done = false;
|
| 462 |
+
for (let ni = 0; ni < ITEMS.length && !done; ni++)
|
| 463 |
+
for (let ns = 0; ns < ITEMS[ni].spans.length; ns++)
|
| 464 |
+
if (!R[ITEMS[ni].spans[ns].key]) { i = ni; needCenter = true; show(ni, ns); done = true; break; }
|
| 465 |
+
if (!done) render();
|
| 466 |
+
$('mine').textContent = `imported ${n} rulings — resuming at first unreviewed mention`;
|
| 467 |
+
} catch (err) { $('mine').textContent = 'could not read that file'; }
|
| 468 |
+
e.target.value = '';
|
| 469 |
+
});
|
| 470 |
document.addEventListener('keydown', e => {
|
| 471 |
if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return;
|
| 472 |
if (e.key === 'ArrowRight') smove(1);
|