Document OCR review UI and docs
Document OCR review UI and docs
Line 2,175: Line 2,175:
$('<strong>').text('Confirm changes, then Apply'),
$('<strong>').text('Confirm changes, then Apply'),
document.createTextNode(' — nothing is saved until you click Apply.')
document.createTextNode(' — nothing is saved until you click Apply.')
));
}
if (job.source_kind === 'facebook_seed') {
$panel.append($('<div>', { 'class': 'ocr-seed-banner' }).append(
$('<strong>').text('Facebook OCR seed'),
document.createTextNode(
' — review #' + (job.source_ref || '?') +
'. Text is from a prior gallery OCR; verify against the File on the soldier page before Apply.'
)
));
));
}
}
Line 2,416: Line 2,425:
var $actions = $('<div>', { 'class': 'ocr-review-actions' });
var $actions = $('<div>', { 'class': 'ocr-review-actions' });
var $discard = $('<button>', { type: 'button', text: 'Discard' });
var $discard = $('<button>', { type: 'button', text: 'Discard' });
var $dry = $('<button>', { type: 'button', text: 'Preview Apply' });
var $apply = $('<button>', {
var $apply = $('<button>', {
type: 'button',
type: 'button',
'class': 'ocr-apply-btn',
'class': 'ocr-apply-btn',
text: isMultiPersonJob(job) ? 'Apply selected' : 'Apply selected'
text: 'Apply selected'
});
});
var $status = $('<p>', { 'class': 'ocr-review-status' });
var $status = $('<p>', { 'class': 'ocr-review-status' });
if (!cfg.canApply) {
if (!cfg.canApply) {
$apply.prop('disabled', true);
$apply.prop('disabled', true);
$dry.prop('disabled', true);
$status.text('Apply requires the ocr-reviewer group (or admin). Your upload stays in the review queue.');
$status.text('Apply requires the ocr-reviewer group (or admin). Your upload stays in the review queue.');
}
}
$actions.append($discard, $apply, $status);
$actions.append($discard, $dry, $apply, $status);
$panel.append($actions);
$panel.append($actions);
$host.append($panel);
$host.append($panel);
Line 2,539: Line 2,550:
ocrPost({ op: 'discard', job_id: job.id }).then(function () {
ocrPost({ op: 'discard', job_id: job.id }).then(function () {
$host.empty().append($('<p>').text('Discarded.'));
$host.empty().append($('<p>').text('Discarded.'));
});
});
$dry.on('click', function () {
$status.text('Building Apply preview…');
$dry.prop('disabled', true);
ocrPost({
op: 'dryrun',
job_id: job.id,
payload: JSON.stringify(payload())
}).then(function (resp) {
$dry.prop('disabled', false);
var plan = resp.plan || {};
var pages = plan.pages || [];
var $box = $('<div>', { 'class': 'ocr-dry-run' });
$box.append($('<strong>').text(
'Apply preview — would edit ' + (plan.will_edit || 0) +
' of ' + (plan.page_count || 0) + ' page(s)'
));
var $ul = $('<ul>');
pages.forEach(function (pg) {
var $li = $('<li>');
$li.append($('<a>', {
href: mw.util.getUrl(pg.title),
text: pg.title,
target: '_blank'
}));
$li.append(document.createTextNode(' — ' + (pg.status || 'planned')));
if (pg.changes && pg.changes.length) {
var $sub = $('<ul>');
pg.changes.forEach(function (c) {
$sub.append($('<li>').text(c));
});
$li.append($sub);
}
$ul.append($li);
});
$box.append($ul);
$status.empty().append($box);
}).catch(function (err) {
$dry.prop('disabled', false);
$status.text(String(err && err.error && err.error.info || err));
});
});
});
});
Line 2,817: Line 2,870:
: (job.bound_title ? job.bound_title : 'single document');
: (job.bound_title ? job.bound_title : 'single document');
var mineBit = (job.uploader || '') === me ? ' · you' : '';
var mineBit = (job.uploader || '') === me ? ' · you' : '';
var kindBit = job.source_kind === 'facebook_seed'
? ' · FB seed' + (job.source_ref ? (' #' + job.source_ref) : '')
: '';
$meta.append($('<div>').append(
$meta.append($('<div>').append(
$('<strong>').text(job.filename || job.id),
$('<strong>').text(job.filename || job.id),
document.createTextNode(' · ' + (job.doc_type_label || job.doc_type || 'document'))
document.createTextNode(
' · ' + (job.doc_type_label || job.doc_type || 'document') + kindBit
)
));
));
$meta.append($('<div>', { 'class': 'ocr-fact-meta' }).text(
$meta.append($('<div>', { 'class': 'ocr-fact-meta' }).text(