| Line 1... |
Line 1... |
| 1 |
$(function () {
|
1 |
$(function () {
|
| 2 |
|
2 |
|
| 3 |
// The screen is an AJAX fragment injected into #main-content, so every handler
|
3 |
// The screen is an AJAX fragment injected into #main-content, so every handler
|
| 4 |
// is delegated from document and state is re-initialised on each load.
|
4 |
// is delegated from document and state is re-initialised on each load.
|
| 5 |
var state = { page: 1, rows: [], total: 0, pages: 1, pageSize: 50, brandsLoaded: false,
|
5 |
var state = { page: 1, rows: [], total: 0, pages: 1, pageSize: 50, brandsLoaded: false,
|
| 6 |
decisions: [], huntTimer: null };
|
6 |
decisions: [], huntTimer: null, documents: [], pollTimer: null };
|
| 7 |
|
7 |
|
| 8 |
function ctx() {
|
8 |
function ctx() {
|
| 9 |
return (typeof context !== 'undefined' && context) ? context : (window.ocContext || '');
|
9 |
return (typeof context !== 'undefined' && context) ? context : (window.ocContext || '');
|
| 10 |
}
|
10 |
}
|
| 11 |
|
11 |
|
| Line 365... |
Line 365... |
| 365 |
state.total = payload.total || 0;
|
365 |
state.total = payload.total || 0;
|
| 366 |
state.pages = payload.pages || 1;
|
366 |
state.pages = payload.pages || 1;
|
| 367 |
state.page = payload.page || 1;
|
367 |
state.page = payload.page || 1;
|
| 368 |
state.pageSize = payload.pageSize || 50;
|
368 |
state.pageSize = payload.pageSize || 50;
|
| 369 |
|
369 |
|
| - |
|
370 |
state.documents = payload.documents || state.documents || [];
|
| 370 |
if (payload.documents) {
|
371 |
if (payload.documents) {
|
| 371 |
var docSel = root().find('[data-oc-doc]');
|
372 |
var docSel = root().find('[data-oc-doc]');
|
| 372 |
if (docSel.find('option').filter(function () { return this.value !== ''; }).length === 0) {
|
373 |
if (docSel.find('option').filter(function () { return this.value !== ''; }).length === 0) {
|
| 373 |
docSel.empty();
|
374 |
docSel.empty();
|
| 374 |
payload.documents.forEach(function (doc) {
|
375 |
payload.documents.forEach(function (doc) {
|
| Line 394... |
Line 395... |
| 394 |
select.val(current);
|
395 |
select.val(current);
|
| 395 |
root().find('[data-oc-stat="brands"]').text(payload.brands.filter(Boolean).length);
|
396 |
root().find('[data-oc-stat="brands"]').text(payload.brands.filter(Boolean).length);
|
| 396 |
state.brandsLoaded = true;
|
397 |
state.brandsLoaded = true;
|
| 397 |
}
|
398 |
}
|
| 398 |
render();
|
399 |
render();
|
| - |
|
400 |
renderIngestState();
|
| - |
|
401 |
schedulePoll();
|
| 399 |
// an empty result while circulars exist is nearly always a filter
|
402 |
// an empty result while circulars exist is nearly always a filter
|
| 400 |
// mismatch, so name the months that actually hold rows
|
403 |
// mismatch, so name the months that actually hold rows
|
| 401 |
if (state.total === 0 && payload.documents && payload.documents.length > 0) {
|
404 |
if (state.total === 0 && payload.documents && payload.documents.length > 0) {
|
| 402 |
root().find('[data-oc-summary]').text(
|
405 |
root().find('[data-oc-summary]').text(
|
| 403 |
'No rows matched these filters. Loaded circulars: ' +
|
406 |
'No rows matched these filters. Loaded circulars: ' +
|
| Line 417... |
Line 420... |
| 417 |
// sidebar entry / any trigger loads the fragment then initialises it
|
420 |
// sidebar entry / any trigger loads the fragment then initialises it
|
| 418 |
function openOfferCircularReview(domId) {
|
421 |
function openOfferCircularReview(domId) {
|
| 419 |
ocGet(ctx() + '/offerCircularReview', function (response) {
|
422 |
ocGet(ctx() + '/offerCircularReview', function (response) {
|
| 420 |
$('#' + (domId || 'main-content')).html(response);
|
423 |
$('#' + (domId || 'main-content')).html(response);
|
| 421 |
state = { page: 1, rows: [], total: 0, pages: 1, pageSize: 50, brandsLoaded: false,
|
424 |
state = { page: 1, rows: [], total: 0, pages: 1, pageSize: 50, brandsLoaded: false,
|
| 422 |
decisions: [], huntTimer: null };
|
425 |
decisions: [], huntTimer: null, documents: [], pollTimer: null };
|
| 423 |
loadRows();
|
426 |
loadRows();
|
| 424 |
});
|
427 |
});
|
| 425 |
}
|
428 |
}
|
| 426 |
window.openOfferCircularReview = openOfferCircularReview;
|
429 |
window.openOfferCircularReview = openOfferCircularReview;
|
| 427 |
|
430 |
|
| Line 891... |
Line 894... |
| 891 |
btn.prop('disabled', false).text('Re-ingest to apply');
|
894 |
btn.prop('disabled', false).text('Re-ingest to apply');
|
| 892 |
resolveMsg('Could not queue re-ingest: ' + failMessage(xhr));
|
895 |
resolveMsg('Could not queue re-ingest: ' + failMessage(xhr));
|
| 893 |
});
|
896 |
});
|
| 894 |
});
|
897 |
});
|
| 895 |
|
898 |
|
| - |
|
899 |
// ------------------------------------------------------- ingest status polling
|
| - |
|
900 |
//
|
| - |
|
901 |
// Upload and parsing run in different processes: the portal stores the PDF as
|
| - |
|
902 |
// DRAFT, and the cron job claims and parses it on its own schedule. Without this
|
| - |
|
903 |
// the screen looks identical before and after a successful ingest, so a reviewer
|
| - |
|
904 |
// has no way to tell "not parsed yet" from "parsed and produced nothing".
|
| - |
|
905 |
|
| - |
|
906 |
var PENDING_STATES = { DRAFT: 'queued for parsing', PROCESSING: 'parsing now' };
|
| - |
|
907 |
|
| - |
|
908 |
function selectedDoc() {
|
| - |
|
909 |
var id = currentDocumentId();
|
| - |
|
910 |
if (!id) { return null; }
|
| - |
|
911 |
for (var i = 0; i < (state.documents || []).length; i++) {
|
| - |
|
912 |
if (String(state.documents[i].documentId) === String(id)) {
|
| - |
|
913 |
return state.documents[i];
|
| - |
|
914 |
}
|
| - |
|
915 |
}
|
| - |
|
916 |
return null;
|
| - |
|
917 |
}
|
| - |
|
918 |
|
| - |
|
919 |
function renderIngestState() {
|
| - |
|
920 |
var box = root().find('[data-oc-ingest-state]');
|
| - |
|
921 |
var doc = selectedDoc();
|
| - |
|
922 |
if (!doc) { box.empty(); return; }
|
| - |
|
923 |
|
| - |
|
924 |
if (PENDING_STATES[doc.status]) {
|
| - |
|
925 |
box.html('<span class="oc-pill oc-pill-warn">' + esc(PENDING_STATES[doc.status])
|
| - |
|
926 |
+ '</span> <span class="oc-num">the ingest job runs every 5 minutes; '
|
| - |
|
927 |
+ 'this refreshes itself</span>');
|
| - |
|
928 |
} else if (doc.status === 'FAILED') {
|
| - |
|
929 |
box.html('<span class="oc-pill oc-pill-danger">ingest failed</span> '
|
| - |
|
930 |
+ '<span class="oc-num">' + esc(doc.ingestError || 'no reason recorded')
|
| - |
|
931 |
+ '</span>');
|
| - |
|
932 |
} else if (doc.status === 'PUBLISHED') {
|
| - |
|
933 |
box.html('<span class="oc-pill oc-pill-ok">parsed</span> '
|
| - |
|
934 |
+ '<span class="oc-num">' + esc(doc.ingestSummary || '') + '</span>');
|
| - |
|
935 |
} else {
|
| - |
|
936 |
box.html('<span class="oc-pill oc-pill-muted">' + esc(doc.status) + '</span>');
|
| - |
|
937 |
}
|
| - |
|
938 |
}
|
| - |
|
939 |
|
| - |
|
940 |
function schedulePoll() {
|
| - |
|
941 |
clearTimeout(state.pollTimer);
|
| - |
|
942 |
var doc = selectedDoc();
|
| - |
|
943 |
if (!doc || !PENDING_STATES[doc.status]) {
|
| - |
|
944 |
return; // settled - stop polling, do not spin forever
|
| - |
|
945 |
}
|
| - |
|
946 |
state.pollTimer = setTimeout(function () {
|
| - |
|
947 |
ocGet(ctx() + '/offerCircular/documents', function (response) {
|
| - |
|
948 |
var docs;
|
| - |
|
949 |
try { docs = typeof response === 'string' ? JSON.parse(response) : response; }
|
| - |
|
950 |
catch (e) { return; }
|
| - |
|
951 |
var was = selectedDoc();
|
| - |
|
952 |
state.documents = docs || [];
|
| - |
|
953 |
var now = selectedDoc();
|
| - |
|
954 |
renderIngestState();
|
| - |
|
955 |
// it just finished: pull in the rows the parse produced
|
| - |
|
956 |
if (was && now && was.status !== now.status && !PENDING_STATES[now.status]) {
|
| - |
|
957 |
loadRows();
|
| - |
|
958 |
return;
|
| - |
|
959 |
}
|
| - |
|
960 |
schedulePoll();
|
| - |
|
961 |
}, function () { schedulePoll(); }); // transient failure - keep waiting
|
| - |
|
962 |
}, 15000);
|
| - |
|
963 |
}
|
| - |
|
964 |
|
| 896 |
// direct navigation: the fragment is already on the page
|
965 |
// direct navigation: the fragment is already on the page
|
| 897 |
if (root().length > 0) {
|
966 |
if (root().length > 0) {
|
| 898 |
loadRows();
|
967 |
loadRows();
|
| 899 |
}
|
968 |
}
|
| 900 |
});
|
969 |
});
|