Skip to content

Commit 806cc0f

Browse files
committed
Using pagination for manage submissions page
1 parent f0a5d37 commit 806cc0f

File tree

3 files changed

+224
-211
lines changed

3 files changed

+224
-211
lines changed

app/assets/javascripts/manage_submissions.js

Lines changed: 103 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ const buttonIDs = ['#regrade-selected', '#delete-selected', '#download-selected'
1111
let tweaks = [];
1212
let currentPage = 0;
1313
$(document).ready(function() {
14-
var submission_info = {}
14+
var submission_info = {};
15+
var selectedStudentCids = [];
16+
var selectedSubmissions = [];
17+
var submissions_to_cud = {}; // Build dynamically from server data
1518
const EditTweakButton = (totalSum) => {
1619
if (totalSum == null) {
1720
return `
@@ -70,7 +73,7 @@ $(document).ready(function() {
7073
$(document).ready(function () {
7174
$('.modal').modal();
7275

73-
$('.score-details').on('click', function () {
76+
$(document).on('click', '.score-details', function () {
7477
// Get the email
7578
const course_user_datum_id = $(this).data('cuid');
7679
const email = $(this).data('email');
@@ -105,9 +108,9 @@ $(document).ready(function() {
105108
tweaks = [];
106109

107110
const submissions_body = data.submissions.map((submission) => {
108-
const Tweak = new AutolabComponent(`tweak-value-${submission.id}`, { amount: null });
111+
const Tweak = new AutolabComponent(`tweak-value-${submission.id}`, {amount: null});
109112
Tweak.template = function () {
110-
return EditTweakButton( this.state.amount );
113+
return EditTweakButton(this.state.amount);
111114
}
112115
tweaks.push({tweak: Tweak, submission_id: submission.id, submission});
113116

@@ -118,21 +121,21 @@ $(document).ready(function() {
118121

119122
// Convert to human readable date with timezone
120123
const human_readable_created_at =
121-
moment(submission.created_at).format('MMM Do YY, h:mma z UTC Z');
124+
moment(submission.created_at).format('MMM Do YY, h:mma z UTC Z');
122125

123126
const view_button = submission.filename ?
124-
`<div class="submissions-center-icons">
127+
`<div class="submissions-center-icons">
125128
<a href="submissions/${submission.id}/view"
126129
title="View the file for this submission"
127130
class="btn small">
128131
<i class='material-icons'>zoom_in</i>
129132
</a>
130133
<p>View Source</p>
131134
</div>`
132-
: "None";
135+
: "None";
133136

134137
const download_button =
135-
/text/.test(submission.detected_mime_type) ?
138+
/text/.test(submission.detected_mime_type) ?
136139
`<div class="submissions-center-icons">
137140
<a href="submissions/${submission.id}/download?forceMime=text/plain"
138141
title="Download as text/plain"
@@ -160,16 +163,15 @@ $(document).ready(function() {
160163
<td class="submissions-td">
161164
${submission.total}
162165
</td>
163-
${submission.problems.
164-
map((problem) =>
165-
`<td class="submissions-td">
166+
${submission.problems.map((problem) =>
167+
`<td class="submissions-td">
166168
${data.scores[submission.id]?.[problem.id]?.['score'] !== undefined
167-
? `<a href="viewFeedback?submission_id=${submission.id}&feedback=${problem.id}">
169+
? `<a href="viewFeedback?submission_id=${submission.id}&feedback=${problem.id}">
168170
${data.scores[submission.id][problem.id]['score'].toFixed(1)}
169171
</a>`
170-
: "-"}
172+
: "-"}
171173
</td>`
172-
).join('')}
174+
).join('')}
173175
<td class="submissions-td">
174176
${submission.late_penalty}
175177
</td>
@@ -185,7 +187,7 @@ $(document).ready(function() {
185187
}).join('');
186188

187189
const submissions_table =
188-
` <p>Click on non-autograded problem scores to edit or leave a comment. </p>
190+
` <p>Click on non-autograded problem scores to edit or leave a comment. </p>
189191
<table class="prettyBorder" id="score-details-table">
190192
<thead>
191193
<tr>
@@ -211,10 +213,10 @@ $(document).ready(function() {
211213
"order": [[0, "desc"]],
212214
"paging": false,
213215
"info": false,
214-
"searching": false,});
216+
"searching": false,
217+
});
215218

216219
return data.submissions;
217-
218220
}).then((submissions) => {
219221
$('.tweak-button').on('click', selectTweak(submissions));
220222
}).catch((err) => {
@@ -229,48 +231,94 @@ $(document).ready(function() {
229231
});
230232
});
231233

232-
var selectedStudentCids = [];
233-
var selectedSubmissions = [];
234-
234+
// Initialize DataTable with server-side processing
235235
var table = $('#submissions').DataTable({
236-
'dom': 'f<"selected-buttons">rtip', // show buttons, search, table
237-
'paging': true,
238-
'createdRow': completeRow,
239-
'sPaginationType': 'full_numbers',
240-
'pageLength': 100,
241-
'info': true,
242-
'deferRender': true,
236+
dom: 'f<"selected-buttons">rtip',
237+
processing: true,
238+
serverSide: true,
239+
ajax: {
240+
url: window.location.pathname + '.json',
241+
type: 'GET',
242+
dataSrc: function (json) {
243+
json.data.forEach(row => {
244+
submissions_to_cud[row[7]] = row[8];
245+
});
246+
return json.data;
247+
},
248+
error: function (xhr, error, code) {
249+
console.error('DataTables error:', error, code);
250+
}
251+
},
252+
columns: [
253+
{
254+
data: null, orderable: false, className: 'submissions-td submissions-checkbox',
255+
render: function (data, type, row, meta) {
256+
return `<div><label class="submissions-cbox-label"><input class="cbox" type="checkbox" id="cbox-${row[7]}"><span></span></label></div>`;
257+
}
258+
},
259+
{
260+
data: 1, className: 'submissions-td',
261+
render: function (data, type, row, meta) {
262+
var excusedLabel = data.excused ? '<a class="submissions-excused-label" title="Click to unexcuse this student">EXCUSED</a>' : '';
263+
return `<div class="submissions-name">${data.name || ''}${excusedLabel}</div>${data.email}`;
264+
}
265+
},
266+
{data: 2, className: 'submissions-td'},
267+
{
268+
data: 3, className: 'submissions-td',
269+
render: function (data, type, row, meta) {
270+
var score = data.score != null ? data.score : '-';
271+
return `<div class="submissions-score-align"><div class="score-num">${score}</div><div class="score-icon"><a class="modal-trigger score-details" data-email="${data.email}" data-cuid="${data.cud_id}"><i class="material-icons submissions-score-icon">zoom_in</i></a></div></div>`;
272+
}
273+
},
274+
{data: 4, className: 'submissions-td', render: d => `<span class="moment-date-time">${d}</span>`},
275+
{
276+
data: 5,
277+
orderable: false,
278+
className: 'submissions-td',
279+
render: d => d.has_file ? `<div class="submissions-center-icons"><a href="submissions/${d.submission_id}/view" title="View the file for this submission" class="btn small"><i class='material-icons'>zoom_in</i></a><p>View File</p></div>` : 'None'
280+
},
281+
{
282+
data: 6, orderable: false, className: 'submissions-td exclude-click', render: function (data, row) {
283+
var regradeBtn = data.is_autograded ? `<div class="submissions-center-icons"><a href="regradeBatch?submission_ids[]=${data.submission_id}" data-method="post" title="Regrade this submission" class="btn small"><i class='material-icons'>autorenew</i></a><p>Regrade</p></div>` : '';
284+
return `${regradeBtn}<div class="submissions-center-icons"><a href="submissions/${data.submission_id}/destroyConfirm" title="Destroy this submission forever" class="btn small"><i class='material-icons'>delete_outline</i></a><p>Delete</p></div>`;
285+
}
286+
},
287+
{data: 7, visible: false},
288+
{data: 8, visible: false}
289+
],
290+
pageLength: 100,
291+
lengthMenu: [[25, 50, 100, 200], [25, 50, 100, 200]],
292+
order: [[4, 'desc']],
293+
createdRow: function (row, data) {
294+
var submissionId = data[7];
295+
$(row).attr('id', 'row-' + submissionId).attr('data-submission-id', submissionId).addClass('submission-row');
296+
},
297+
drawCallback: function () {
298+
$('#submissions tbody .cbox').each(function () {
299+
var submissionId = parseInt($(this).attr('id').replace('cbox-', ''), 10);
300+
$(this).prop('checked', selectedSubmissions.includes(submissionId));
301+
if (selectedSubmissions.includes(submissionId)) $(this).closest('tr').addClass('selected');
302+
});
303+
updateSelectAllCheckbox();
304+
}
243305
});
244306

245-
// Check if the table is empty
246-
if (table.data().count() === 0) {
247-
$('#submissions').closest('.dataTables_wrapper').hide(); // Hide the table and its controls
248-
$('#no-data-message').show(); // Optionally show a custom message
249-
} else {
250-
$('#no-data-message').hide(); // Hide custom message when there is data
251-
}
252-
253-
function completeRow(row, data, index) {
254-
var submission = additional_data[index];
255-
$(row).attr('data-submission-id', submission['submission-id']);
256-
}
257-
258-
$('thead').on('click', function(e) {
259-
if (currentPage < 0) {
260-
currentPage = 0
261-
}
262-
if (currentPage > table.page.info().pages) {
263-
currentPage = table.page.info().pages - 1
264-
}
265-
table.page(currentPage).draw(false);
266-
})
267307

268308
// Listen for select-all checkbox click
269309
$('#cbox-select-all').on('click', async function(e) {
270310
var selectAll = $(this).is(':checked');
271311
await toggleAllRows(selectAll);
272312
});
273313

314+
function updateSelectAllCheckbox() {
315+
var allChecked = true, anyChecked = false;
316+
$('#submissions tbody .cbox').each(function () {
317+
if ($(this).prop('checked')) anyChecked = true; else allChecked = false;
318+
});
319+
$('#cbox-select-all').prop('checked', allChecked && anyChecked);
320+
}
321+
274322
// Function to toggle all checkboxes
275323
function toggleAllRows(selectAll) {
276324
$('#submissions tbody .cbox').each(function() {
@@ -297,21 +345,17 @@ $(document).ready(function() {
297345
var downloadHTML = $('#download-batch-html').html();
298346
var excuseHTML = $('#excuse-batch-html').html();
299347
$('div.selected-buttons').html(`<div id='selected-buttons'>${regradeHTML}${deleteHTML}${downloadHTML}${excuseHTML}</div>`);
300-
301-
// add ids to each selected button
302348
$('#selected-buttons > a').each(function () {
303349
let idText = this.title.split(' ')[0].toLowerCase() + '-selected';
304350
this.setAttribute('id', idText);
305351
});
306-
307352
if (!is_autograded) {
308353
$('#regrade-selected').hide();
309354
$('#regrade-all-html').hide();
310355
}
311356

312-
// base URLs for selected buttons
313357
var baseURLs = {};
314-
buttonIDs.forEach(function(id) {
358+
buttonIDs.forEach(function (id) {
315359
baseURLs[id] = $(id).prop('href');
316360
});
317361

@@ -374,7 +418,6 @@ $(document).ready(function() {
374418
}
375419
});
376420
});
377-
378421
function changeButtonStates(state) {
379422
buttonIDs.forEach((id) => {
380423
const button = $(id);
@@ -396,14 +439,13 @@ $(document).ready(function() {
396439
return;
397440
}
398441
$(document).off("click", id).on("click", id, function (event) {
399-
console.log(`${id} button clicked`);
400442
event.preventDefault();
401443
if (selectedSubmissions.length === 0) {
402444
alert("No submissions selected.");
403445
return;
404446
}
405447
const endpoint = manage_submissions_endpoints[id.replace("#", "")];
406-
const requestData = { submission_ids: selectedSubmissions };
448+
const requestData = {submission_ids: selectedSubmissions};
407449
if (id === "#delete-selected") {
408450
if (!confirm("Deleting will delete all checked submissions and cannot be undone. Are you sure you want to delete these submissions?")) {
409451
return;
@@ -457,6 +499,8 @@ $(document).ready(function() {
457499

458500
// SELECTING STUDENT CHECKBOXES
459501
function toggleRow(submissionId, forceSelect = null) {
502+
console.log('toggleRow called:', submissionId, 'forceSelect:', forceSelect);
503+
console.log('selectedSubmissions before:', [...selectedSubmissions]);
460504
var selectedCid = submissions_to_cud[submissionId];
461505
const isSelected = selectedSubmissions.includes(submissionId);
462506
const shouldSelect = forceSelect !== null ? forceSelect : !isSelected;
@@ -489,6 +533,8 @@ $(document).ready(function() {
489533
$('#cbox-select-all').prop('checked', numericSelectedSubmissions.length === $('#submissions tbody .cbox').length);
490534
updateSelectedCount(numericSelectedSubmissions);
491535
changeButtonStates(disableButtons);
536+
console.log('selectedSubmissions after:', [...selectedSubmissions]);
537+
console.log('Checkbox state:', $('#cbox-' + submissionId).prop('checked'));
492538
}
493539

494540
$('#submissions').on('click', '.exclude-click i', function (e) {

0 commit comments

Comments
 (0)