Skip to content

Commit c794bb2

Browse files
authored
Review Later, catch and fix corrupt bulkLoad, close other modals on error modal
2 parents 5d3bd4a + f89d50b commit c794bb2

File tree

5 files changed

+114
-12
lines changed

5 files changed

+114
-12
lines changed

src/checker/checker.js

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,8 @@ try {
886886
button.id = r.id;
887887
button.classList = (r.status === "Incorrect") ? 'incorrect' : (r.status === "Correct") ? 'correct' : '';
888888
if (r.flagged) button.classList.add('flagged');
889-
var response = `<b>Status:</b> ${r.status.includes('Unknown') ? r.status.split('Unknown, ')[1] : r.status} at ${unixToString(r.timestamp)}${(r.reason) ? `</p>\n<p><b>Response:</b> ${r.reason}<br>` : ''}</p><button data-flag-response><i class="bi bi-flag-fill"></i> ${r.flagged ? 'Unflag Response' : 'Flag for Review'}</button>`;
889+
if (r.review_later) button.classList.add('reviewLater');
890+
var response = `<b>Status:</b> ${r.status.includes('Unknown') ? r.status.split('Unknown, ')[1] : r.status} at ${unixToString(r.timestamp)}${(r.reason) ? `</p>\n<p><b>Response:</b> ${r.reason}<br>` : ''}</p><div data-modal-actions style="margin-top: -0.25rem;"><button data-flag-response><i class="bi bi-flag-fill"></i> ${r.flagged ? 'Unflag Response' : 'Flag for Review'}</button><button data-review-later-response><i class="bi ${r.review_later ? 'bi-bookmark-check-fill' : 'bi-bookmark-plus-fill'}"></i> ${r.review_later ? 'Mark Reviewed' : 'Review Later'}</button></div>`;
890891
switch (r.mode) {
891892
case 'latex':
892893
button.innerHTML = `${convertLatexToMarkup(r.response)}\n<p class="hint">(Equation may not display properly)</p>\n<p>${response}`;
@@ -906,6 +907,7 @@ try {
906907
// Resubmit check
907908
button.addEventListener("click", async (event) => {
908909
if (event.target.hasAttribute('data-flag-response')) return r.flagged ? unflagResponse(event, true) : flagResponse(event, true);
910+
if (event.target.hasAttribute('data-review-later-response')) return r.review_later ? unReviewLaterResponse(event, true) : reviewLaterResponse(event, true);
909911
await resubmitCheck(r);
910912
window.scrollTo(0, document.body.scrollHeight);
911913
});
@@ -1131,7 +1133,8 @@ try {
11311133
button.id = r.id;
11321134
button.classList = (r.status === "Incorrect") ? 'incorrect' : (r.status === "Correct") ? 'correct' : '';
11331135
if (r.flagged) button.classList.add('flagged');
1134-
var response = `<b>Status:</b> ${r.status.includes('Unknown') ? r.status.split('Unknown, ')[1] : r.status}${(r.reason) ? `</p>\n<p><b>Response:</b> ${r.reason}<br>` : ''}</p><button data-flag-response><i class="bi bi-flag-fill"></i> ${r.flagged ? 'Unflag Response' : 'Flag for Review'}</button>`;
1136+
if (r.review_later) button.classList.add('reviewLater');
1137+
var response = `<b>Status:</b> ${r.status.includes('Unknown') ? r.status.split('Unknown, ')[1] : r.status}${(r.reason) ? `</p>\n<p><b>Response:</b> ${r.reason}<br>` : ''}</p><div data-modal-actions style="margin-top: -0.25rem;"><button data-flag-response><i class="bi bi-flag-fill"></i> ${r.flagged ? 'Unflag Response' : 'Flag for Review'}</button><button data-review-later-response><i class="bi ${r.review_later ? 'bi-bookmark-check-fill' : 'bi-bookmark-plus-fill'}"></i> ${r.review_later ? 'Mark Reviewed' : 'Review Later'}</button></div>`;
11351138
var segmentNumber = segmentsArray.find(s => (String(s.id) === String(r.segment)) && (courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))) ? (String(s.course) === String(courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))).id)) : true)) ? (segmentsArray.find(s => (String(s.id) === String(r.segment)) && (courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))) ? (String(s.course) === String(courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))).id)) : true)).number || r.segment) : (segmentsArray.find(s => (courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))) ? (String(s.course) === String(courses.find(c => JSON.parse(c.periods).includes(Number(String(r.seatCode).slice(0, 1)))).id)) : false) && JSON.parse(s.question_ids || [])?.find(q => String(q.id) === String(r.question_id)))?.number || null);
11361139
var questionNumber = JSON.parse(segmentsArray.find(s => String(s.id) === String(r.segment))?.question_ids || '[]').find(q => String(q.id) === String(r.question_id))?.name || questionsArray.find(question => String(question.id) === String(r.question_id)).number;
11371140
switch (r.mode) {
@@ -1153,6 +1156,7 @@ try {
11531156
// Resubmit check
11541157
button.addEventListener("click", async (event) => {
11551158
if (event.target.hasAttribute('data-flag-response')) return r.flagged ? unflagResponse(event) : flagResponse(event);
1159+
if (event.target.hasAttribute('data-review-later-response')) return r.review_later ? unReviewLaterResponse(event) : reviewLaterResponse(event);
11561160
ui.view("");
11571161
await resubmitCheck(r);
11581162
window.scrollTo(0, document.body.scrollHeight);
@@ -1266,13 +1270,17 @@ try {
12661270
body: JSON.stringify({
12671271
usr: storage.get("code"),
12681272
pwd: storage.get("password"),
1269-
question_id: event.srcElement.parentElement.id,
1273+
question_id: event.srcElement.parentElement.parentElement.id,
12701274
}),
12711275
})
12721276
.then(q => q.json())
1273-
.then(() => {
1277+
.then(async () => {
12741278
ui.setUnsavedChanges(false);
12751279
ui.toast("Flagged response for review.", 3000, "success", "bi bi-flag-fill");
1280+
await auth.bulkLoad(["courses", "segments", "questions", "responses"], storage.get("code"), storage.get("password"));
1281+
await storage.idbReady;
1282+
const _cache = (await storage.idbGet('cache')) || storage.get('cache') || {};
1283+
history = (_cache).responses || [];
12761284
isInQuestion ? updateQuestion() : updateHistory();
12771285
})
12781286
.catch((e) => {
@@ -1292,13 +1300,77 @@ try {
12921300
body: JSON.stringify({
12931301
usr: storage.get("code"),
12941302
pwd: storage.get("password"),
1295-
question_id: event.srcElement.parentElement.id,
1303+
question_id: event.srcElement.parentElement.parentElement.id,
12961304
}),
12971305
})
12981306
.then(q => q.json())
1299-
.then(() => {
1307+
.then(async () => {
13001308
ui.setUnsavedChanges(false);
13011309
ui.toast("Unflagged response.", 3000, "success", "bi bi-flag-fill");
1310+
await auth.bulkLoad(["courses", "segments", "questions", "responses"], storage.get("code"), storage.get("password"));
1311+
await storage.idbReady;
1312+
const _cache = (await storage.idbGet('cache')) || storage.get('cache') || {};
1313+
history = (_cache).responses || [];
1314+
isInQuestion ? updateQuestion() : updateHistory();
1315+
})
1316+
.catch((e) => {
1317+
console.error(e);
1318+
ui.view("api-fail");
1319+
});
1320+
}
1321+
1322+
function reviewLaterResponse(event, isInQuestion = false) {
1323+
event.srcElement.disabled = true;
1324+
ui.setUnsavedChanges(true);
1325+
fetch(domain + '/reviewLater', {
1326+
method: "POST",
1327+
headers: {
1328+
"Content-Type": "application/json",
1329+
},
1330+
body: JSON.stringify({
1331+
usr: storage.get("code"),
1332+
pwd: storage.get("password"),
1333+
question_id: event.srcElement.parentElement.parentElement.id,
1334+
}),
1335+
})
1336+
.then(q => q.json())
1337+
.then(async () => {
1338+
ui.setUnsavedChanges(false);
1339+
ui.toast("Marked response to review later.", 3000, "success", "bi bi-bookmark-plus-fill");
1340+
await auth.bulkLoad(["courses", "segments", "questions", "responses"], storage.get("code"), storage.get("password"));
1341+
await storage.idbReady;
1342+
const _cache = (await storage.idbGet('cache')) || storage.get('cache') || {};
1343+
history = (_cache).responses || [];
1344+
isInQuestion ? updateQuestion() : updateHistory();
1345+
})
1346+
.catch((e) => {
1347+
console.error(e);
1348+
ui.view("api-fail");
1349+
});
1350+
}
1351+
1352+
function unReviewLaterResponse(event, isInQuestion = false) {
1353+
event.srcElement.disabled = true;
1354+
ui.setUnsavedChanges(true);
1355+
fetch(domain + '/unReviewLater', {
1356+
method: "POST",
1357+
headers: {
1358+
"Content-Type": "application/json",
1359+
},
1360+
body: JSON.stringify({
1361+
usr: storage.get("code"),
1362+
pwd: storage.get("password"),
1363+
question_id: event.srcElement.parentElement.parentElement.id,
1364+
}),
1365+
})
1366+
.then(q => q.json())
1367+
.then(async () => {
1368+
ui.setUnsavedChanges(false);
1369+
ui.toast("Marked response as reviewed.", 3000, "success", "bi bi-bookmark-check-fill");
1370+
await auth.bulkLoad(["courses", "segments", "questions", "responses"], storage.get("code"), storage.get("password"));
1371+
await storage.idbReady;
1372+
const _cache = (await storage.idbGet('cache')) || storage.get('cache') || {};
1373+
history = (_cache).responses || [];
13021374
isInQuestion ? updateQuestion() : updateHistory();
13031375
})
13041376
.catch((e) => {

src/design.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,10 +1233,15 @@ hidden,
12331233
opacity: 0.75;
12341234
}
12351235

1236-
.history-feed button button i {
1236+
.history-feed button button .bi-flag-fill {
12371237
font-size: 12px;
12381238
}
12391239

1240+
.history-feed button button .bi-bookmark-check-fill,
1241+
.history-feed button button .bi-bookmark-plus-fill {
1242+
font-size: 14px;
1243+
}
1244+
12401245
#checker:not(.timestamps) [data-time-taken] {
12411246
display: none;
12421247
}

src/layout.css

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ div.spacer {
101101
justify-content: center;
102102
width: min(100%, 900px);
103103
gap: 12.5px;
104-
transition: 0.25s width, 0.25s align-self;
104+
transition:
105+
0.25s width,
106+
0.25s align-self;
105107
}
106108

107109
#checker:has(.responses) {
@@ -110,7 +112,9 @@ div.spacer {
110112

111113
body:has(.island.visible) #checker {
112114
align-self: flex-end;
113-
transition: 0.25s width, 0.25s align-self;
115+
transition:
116+
0.25s width,
117+
0.25s align-self;
114118
}
115119

116120
#checker .column {
@@ -345,11 +349,13 @@ body:has(.island.visible) #checker {
345349
display: none;
346350
}
347351

348-
.history-feed > button.flagged {
352+
.history-feed > button.flagged,
353+
.history-feed > button.reviewLater {
349354
position: relative;
350355
}
351356

352-
.history-feed > button.flagged::after {
357+
.history-feed > button.flagged::after,
358+
.history-feed > button.reviewLater:not(.flagged)::after {
353359
display: inline-block;
354360
font-family: bootstrap-icons !important;
355361
font-style: normal;
@@ -367,6 +373,14 @@ body:has(.island.visible) #checker {
367373
right: 15px;
368374
}
369375

376+
.history-feed > button.flagged::after {
377+
content: "\f3cb";
378+
}
379+
380+
.history-feed > button.reviewLater:not(.flagged)::after {
381+
content: "\F19F";
382+
}
383+
370384
.history-feed > .flagged-response-alert {
371385
height: fit-content;
372386
padding: 0.375em 0.75em;

src/modules/auth.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,6 @@ export async function bulkLoad(fields = [], usr = null, pwd = null, isAdmin = fa
752752
const cacheIds = {};
753753
const cache = (await storage.idbGet((isAdmin || isTA) ? "adminCache" : "cache")) ||
754754
storage.get((isAdmin || isTA) ? "adminCache" : "cache") || {};
755-
756755
for (const table in cache) {
757756
if (Array.isArray(cache[table] || []))
758757
cacheIds[table] = (cache[table] || []).map(data =>
@@ -789,6 +788,17 @@ export async function bulkLoad(fields = [], usr = null, pwd = null, isAdmin = fa
789788
ui.view("maintenance-mode");
790789
return false;
791790
}
791+
if (!((await storage.idbGet((isAdmin || isTA) ? "adminCache" : "cache")) ||
792+
storage.get((isAdmin || isTA) ? "adminCache" : "cache") || {})?.['courses']?.length && !fetchedBulkLoad?.courses?.length) {
793+
console.log('🔴 Bulk load out of sync, reloading');
794+
await storage.idbReady;
795+
storage.idbDelete("cache").catch((e) => console.error('IDB delete failed', e));
796+
storage.delete("lastBulkLoad");
797+
storage.idbDelete("adminCache").catch((e) => console.error('IDB delete failed', e));
798+
storage.delete("lastAdminBulkLoad");
799+
location.reload();
800+
return false;
801+
}
792802
var updatedBulkLoad = {};
793803
for (const table in fetchedBulkLoad) {
794804
if (table === 'asOf' || table === 'syncDeleted') continue;

src/modules/ui.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ export function view(path = "") {
429429
});
430430
}
431431
show(document.querySelector(`[data-modal-page="${pages[0]}"]`), title, buttons);
432+
if ((path === 'api-fail') || (path === 'no-course') || (path === 'maintenance-mode')) view();
432433
if ((path === 'api-fail') || (path === 'no-course') || (path === 'maintenance-mode')) startLoader();
433434
const event = new Event("view");
434435
target.dispatchEvent(event);

0 commit comments

Comments
 (0)