rafmacalaba commited on
Commit
df3d8a0
·
verified ·
1 Parent(s): 5721d11

review.html: push-all button, no legacy

Browse files
Files changed (1) hide show
  1. review.html +49 -0
review.html CHANGED
@@ -72,6 +72,7 @@ footer .sp { flex: 1; }
72
  <span class="sp"></span><span id="count"></span>
73
  <input id="hubtok" type="password" placeholder="HF token" title="write token for data-use-annotations; only needed on static hosting without the bundled server"
74
  style="font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:8px 10px;max-width:130px">
 
75
  <button id="hubBtn" onclick="exp()">export</button>
76
  </footer>
77
  <script>
@@ -81,6 +82,7 @@ const DS = { sample: './queue_annotate_sample.json', gold: './queue_review473.js
81
  const USERS = ['paddy', 'aj', 'aivin', 'rafael'];
82
  const LS = 'review_rulings';
83
  let R = JSON.parse(localStorage.getItem(LS) || '{}');
 
84
  const $ = id => document.getElementById(id);
85
  const esc = s => String(s).replace(/[&<>]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));
86
  const QD = document.documentElement;
@@ -242,7 +244,9 @@ async function rule(v) {
242
  if (needName()) return;
243
  const k = span().key;
244
  R[k] = v;
 
245
  localStorage.setItem(LS, JSON.stringify(R));
 
246
  paintGate();
247
  const entry = {key: k, ruling: v, queue: $('ds').value, annotator: who()};
248
  let saved = 'this browser only';
@@ -287,6 +291,50 @@ async function hubCommit(entry) {
287
  return 'Hub';
288
  } catch (e) { return 'this browser only (Hub sync failed)'; }
289
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  document.addEventListener('keydown', e => {
291
  if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return;
292
  if (e.key === 'ArrowRight') smove(1);
@@ -294,6 +342,7 @@ document.addEventListener('keydown', e => {
294
  else if (e.key === '[') { wc = Math.max(0, (wc ?? 0) - WSIZES[wi] / 2); render(); }
295
  else if (e.key === ']') { wc = (wc ?? 0) + WSIZES[wi] / 2; render(); }
296
  else if (e.key === '-' || e.key === '_') { wi = Math.max(0, wi - 1); render(); }
 
297
  else if (e.key === 'k' || e.key === 'K') rule('DATA_MENTION');
298
  else if (e.key === 'd' || e.key === 'D') rule('NON_MENTION');
299
  else if (e.key === ' ') { e.preventDefault(); skip(); }
 
72
  <span class="sp"></span><span id="count"></span>
73
  <input id="hubtok" type="password" placeholder="HF token" title="write token for data-use-annotations; only needed on static hosting without the bundled server"
74
  style="font:inherit;color:var(--fg);background:var(--bg);border:1px solid var(--line);border-radius:8px;padding:8px 10px;max-width:130px">
75
+ <button id="pushBtn" onclick="pushAll()">push annotations</button>
76
  <button id="hubBtn" onclick="exp()">export</button>
77
  </footer>
78
  <script>
 
82
  const USERS = ['paddy', 'aj', 'aivin', 'rafael'];
83
  const LS = 'review_rulings';
84
  let R = JSON.parse(localStorage.getItem(LS) || '{}');
85
+ let RQ = JSON.parse(localStorage.getItem('review_queues') || '{}');
86
  const $ = id => document.getElementById(id);
87
  const esc = s => String(s).replace(/[&<>]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;'}[c]));
88
  const QD = document.documentElement;
 
244
  if (needName()) return;
245
  const k = span().key;
246
  R[k] = v;
247
+ RQ[k] = $('ds').value;
248
  localStorage.setItem(LS, JSON.stringify(R));
249
+ localStorage.setItem('review_queues', JSON.stringify(RQ));
250
  paintGate();
251
  const entry = {key: k, ruling: v, queue: $('ds').value, annotator: who()};
252
  let saved = 'this browser only';
 
291
  return 'Hub';
292
  } catch (e) { return 'this browser only (Hub sync failed)'; }
293
  }
294
+ async function pushAll() {
295
+ // one read, merge every local ruling, one commit to your own file.
296
+ // use after pasting your token, or to retry anything saved locally only.
297
+ if (needName()) return;
298
+ const tok = ($('hubtok').value || '').trim();
299
+ if (!tok) { $('mine').textContent = 'paste your HF write token first (footer field)'; $('hubtok').focus(); return; }
300
+ const btn = $('pushBtn');
301
+ btn.disabled = true;
302
+ try {
303
+ const repo = 'rafmacalaba/data-use-annotations';
304
+ const who = who().replace(/[^a-zA-Z0-9-_]/g, '_');
305
+ const path = `rulings/${who}.jsonl`;
306
+ let rows = [];
307
+ try {
308
+ const r = await fetch(`https://huggingface.co/datasets/${repo}/resolve/main/${path}`);
309
+ if (r.ok) rows = (await r.text()).split('\n').filter(Boolean).map(JSON.parse);
310
+ } catch (e) {}
311
+ const seen = new Set(rows.map(x => x.queue + '|' + x.key));
312
+ let added = 0;
313
+ for (const [key, ruling] of Object.entries(R)) {
314
+ const q = RQ[key] || $('ds').value;
315
+ if (seen.has(q + '|' + key)) continue;
316
+ rows.push({key, ruling, queue: q, annotator: who(),
317
+ ts: new Date().toISOString().replace(/\.\d+Z$/, '+00:00')});
318
+ added++;
319
+ }
320
+ if (!added) { lastSaved = 'Hub (already in sync)'; lightMeta(); btn.disabled = false; return; }
321
+ const content = btoa(unescape(encodeURIComponent(rows.map(x => JSON.stringify(x)).join('\n') + '\n')));
322
+ const nd = [{key: 'header', value: {summary: `push ${added} rulings (${who}, web)`, description: ''}},
323
+ {key: 'file', value: {content, path, encoding: 'base64'}}].map(o => JSON.stringify(o)).join('\n');
324
+ const res = await fetch(`https://huggingface.co/api/datasets/${repo}/commit/main`, {
325
+ method: 'POST', headers: {Authorization: `Bearer ${tok}`, 'Content-Type': 'application/x-ndjson'}, body: nd});
326
+ if (!res.ok) throw new Error('hub ' + res.status);
327
+ lastSaved = `Hub (${added} pushed)`;
328
+ } catch (e) { lastSaved = 'push failed — still stored in this browser'; }
329
+ btn.disabled = false;
330
+ lightMeta();
331
+ }
332
+ function exp() {
333
+ const rows = Object.entries(R).map(([key, ruling]) => ({key, ruling, queue: RQ[key] || $('ds').value, annotator: who()}));
334
+ const a = document.createElement('a');
335
+ a.href = URL.createObjectURL(new Blob([rows.map(r => JSON.stringify(r)).join('\n')], {type: 'application/json'}));
336
+ a.download = 'review-rulings.jsonl'; a.click();
337
+ }
338
  document.addEventListener('keydown', e => {
339
  if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT') return;
340
  if (e.key === 'ArrowRight') smove(1);
 
342
  else if (e.key === '[') { wc = Math.max(0, (wc ?? 0) - WSIZES[wi] / 2); render(); }
343
  else if (e.key === ']') { wc = (wc ?? 0) + WSIZES[wi] / 2; render(); }
344
  else if (e.key === '-' || e.key === '_') { wi = Math.max(0, wi - 1); render(); }
345
+ else if (e.key === '=' || e.key === '+') { wi = Math.min(WSIZES.length - 1, wi + 1); render(); }
346
  else if (e.key === 'k' || e.key === 'K') rule('DATA_MENTION');
347
  else if (e.key === 'd' || e.key === 'D') rule('NON_MENTION');
348
  else if (e.key === ' ') { e.preventDefault(); skip(); }