8.7 KiB
P44 OCR Viewer — Pass 1 Flag System Redesign Scope: p44-ocr-viewer.js, p44-ocr-viewer.css, p44-ocr-viewer.html. Make all three changes in sequence. Do not touch PDF rendering, zoom, sync scroll, Pass 2 logic, or the corrections storage model.
PART 1 — HTML (p44-ocr-viewer.html) In the right panel header, replace the five buttons: html<button id="btn-flag-verified" ...>✓ Verified <button id="btn-flag-review" ...>⚑ Review <button id="btn-flag-error" ...>✗ Error <button id="btn-flag-clear" ...>Clear <button id="btn-edit" ...>Edit With these three buttons: html✓ Done ⚠ Problem Edit Add a new read-only banner element inside #text-panel-body, immediately before #pass2-revert-bar: html
PART 2 — CSS (p44-ocr-viewer.css) Remove the CSS rules for #btn-flag-verified, #btn-flag-review, #btn-flag-error if any exist by those IDs. The .flag-btn and .flag-btn.active rules stay — they apply to the new buttons too. Add these new rules at the end of the file: css/* ── Done-page read-only banner (Pass 1) ─────────────────────── */ #done-banner { display: none; align-items: center; gap: 8px; padding: 7px 16px; background: #0f2a0f; border-bottom: 1px solid #2e6e2e; font-size: 10px; color: #5cb85c; letter-spacing: 0.05em; flex-shrink: 0; }
/* ── Problem flag indicator on page nav input ─────────────────── */ #page-input.problem { border-color: #c08020; }
/* ── Greyed-out done state on the OCR text panel ─────────────── */ #text-output.done-readonly { opacity: 0.55; pointer-events: none; user-select: none; }
PART 3 — JS (p44-ocr-viewer.js) Make the following changes in order. Each change is isolated — do not touch any other function. 3a — DOM refs Replace: javascriptconst btnFlagVerified = document.getElementById('btn-flag-verified'); const btnFlagReview = document.getElementById('btn-flag-review'); const btnFlagError = document.getElementById('btn-flag-error'); const btnFlagClear = document.getElementById('btn-flag-clear'); With: javascriptconst btnFlagDone = document.getElementById('btn-flag-done'); const btnFlagProblem = document.getElementById('btn-flag-problem'); 3b — Flag label constants Replace the PASS2_BTN_LABELS and PASS1_BTN_LABELS constants with: javascriptconst PASS2_BTN_LABELS = { done: '✓ Pass 2 approved', problem: '⚠ Needs work' }; const PASS1_BTN_LABELS = { done: '✓ Done', problem: '⚠ Problem' }; 3c — updateFlagButtons(pageNum) Replace the entire function body with: javascriptfunction updateFlagButtons(pageNum) { const flagSrc = currentRole === 'pass2' ? pass2Flags : state.flags; const flag = flagSrc[pageNum] || null; btnFlagDone.classList.toggle('active', flag === 'done'); btnFlagProblem.classList.toggle('active', flag === 'problem');
// Done pages are read-only in Pass 1 — disable both flag buttons and Edit const isDone = currentRole === 'pass1' && flag === 'done'; btnFlagDone.disabled = isDone; btnFlagProblem.disabled = isDone; btnEdit.disabled = isDone; btnEdit.style.opacity = isDone ? '0.35' : ''; } 3d — setFlag(type) Replace the entire function body with: javascriptfunction setFlag(type) { const p = state.currentPage;
if (currentRole === 'pass2') { if (type === null) { delete pass2Flags[p]; } else { pass2Flags[p] = type; } updateFlagButtons(p); savePass2Flags(); return; }
// Pass 1 — Done is one-way: once set it cannot be cleared by the volunteer if (state.flags[p] === 'done') return;
// Problem is toggleable — clicking it again removes it if (type === 'problem' && state.flags[p] === 'problem') { delete state.flags[p]; } else if (type === null) { delete state.flags[p]; } else { state.flags[p] = type; }
updateFlagButtons(p); updateFlagsSummary(); saveFlags(); } 3e — showOCRPage(pageNum) At the end of showOCRPage(), after the existing block that calls updateFlagButtons() and updateCorrectionIndicator(), add the following. Do not change any existing lines in showOCRPage() — only add this block at the end (before the closing brace), replacing the existing Pass 2 auto-edit-mode call: javascript // Pass 1 done-page read-only state const doneBanner = document.getElementById('done-banner'); const isDonePage = currentRole === 'pass1' && state.flags[pageNum] === 'done';
if (isDonePage) { // Show the final corrected text (same display logic as normal, already rendered above) // Lock the panel visually textOutput.classList.add('done-readonly'); doneBanner.innerHTML = '✓ Done — submitted to Pass 2 queue. This page is locked.'; doneBanner.style.display = 'flex'; // Ensure editor is closed and stays closed if (state.editMode) exitEditMode(); } else { textOutput.classList.remove('done-readonly'); doneBanner.style.display = 'none'; }
- // Pass 2 auto-edit mode (unchanged behaviour)
- if (currentRole === 'pass2') {
- if (!state.editMode) enterEditMode();
- updatePass2NavButtons();
- }
- Note: this block replaces the existing two lines at the bottom of showOCRPage() that read:
- javascript if (currentRole === 'pass2') {
- if (!state.editMode) enterEditMode();
- updatePass2NavButtons();
- }
- 3f — applyRole()
- In applyRole(), replace the two label-setting lines for pass2 branch:
- javascript btnFlagVerified.textContent = PASS2_BTN_LABELS.verified;
- btnFlagReview.textContent = PASS2_BTN_LABELS.review;
- btnFlagError.textContent = PASS2_BTN_LABELS.error;
- With:
- javascript btnFlagDone.textContent = PASS2_BTN_LABELS.done;
- btnFlagProblem.textContent = PASS2_BTN_LABELS.problem;
- And replace the three label-setting lines for the pass1 branch:
- javascript btnFlagVerified.textContent = PASS1_BTN_LABELS.verified;
- btnFlagReview.textContent = PASS1_BTN_LABELS.review;
- btnFlagError.textContent = PASS1_BTN_LABELS.error;
- With:
- javascript btnFlagDone.textContent = PASS1_BTN_LABELS.done;
- btnFlagProblem.textContent = PASS1_BTN_LABELS.problem;
- 3g — Event listeners
- Replace:
- javascriptbtnFlagVerified.addEventListener('click', () => setFlag('verified'));
- btnFlagReview.addEventListener('click', () => setFlag('review'));
- btnFlagError.addEventListener('click', () => setFlag('error'));
- btnFlagClear.addEventListener('click', () => setFlag(null));
- With:
- javascriptbtnFlagDone.addEventListener('click', () => setFlag('done'));
- btnFlagProblem.addEventListener('click', () => setFlag('problem'));
- 3h — updateFlagsSummary()
- Replace the counting logic inside updateFlagsSummary():
- javascript Object.values(state.flags).forEach(f => {
- if (f === 'verified') v++;
- else if (f === 'review') r++;
- else if (f === 'error') er++;
- });
- flagsSummary.textContent = v || r || er
- ? '✓ ' + v + ' ⚑ ' + r + ' ✗ ' + er
- ''; With: javascript let done = 0, problem = 0; Object.values(state.flags).forEach(f => { if (f === 'done') done++; else if (f === 'problem') problem++; }); flagsSummary.textContent = done || problem ? '✓ ' + done + (problem ? ' ⚠ ' + problem : '')
- ''; 3i — Keyboard shortcut In the keydown handler, replace: javascript case 'v': setFlag('verified'); break; case 'r': setFlag('review'); break; case 'e': setFlag('error'); break; With: javascript case 'v': setFlag('done'); break; case 'p': setFlag('problem'); break; Update the footer kbd hint in p44-ocr-viewer.html from: html← → navigate v/r/e flag esc close To: html← → navigate v done p problem esc close 3j — getVerifiedPages() Replace: javascript .filter(k => state.flags[k] === 'verified') With: javascript .filter(k => state.flags[k] === 'done')
VERIFICATION CHECKLIST — confirm each before closing the prompt:
Clicking ✓ Done on an unreviewed page: button highlights gold, page text goes grey, green Done banner appears, Edit button is disabled, cannot click Done or Problem again Clicking ⚠ Problem on an unreviewed page: button highlights gold, page remains editable Clicking ⚠ Problem again on a problem page: flag clears, button returns to inactive Navigating to a Done page while in Pass 1 role: banner shows, editor locked, text visible as final corrected version Switching to Pass 2 role: Done banner hidden, flag buttons show Pass 2 labels, auto-edit mode activates as before Footer summary shows correct counts using ✓ and ⚠ symbols Keyboard v sets Done, p sets/toggles Problem, no reference to old r or e keys anywhere