diff --git a/backend/db/models/assignment.js b/backend/db/models/assignment.js index c11a01e7d..55798067d 100644 --- a/backend/db/models/assignment.js +++ b/backend/db/models/assignment.js @@ -32,16 +32,16 @@ module.exports = (sequelize, DataTypes) => { label: "Maximum Revisions:", type: "slider", class: "custom-slider-class", - min: 1, + min: 0, max: 20, step: 1, unit: "revision(s)", unlimitedAtMax: true, unlimitedLabel: "unlimited", - unlimitedStoredValue: 0, + unlimitedStoredValue: -1, required: true, default: 1, - help: "Maximum number of allowed revision copies for this assignment. Move to the end for unlimited.", + help: "Maximum number of allowed resubmissions after the original submission (e.g. 1 revision = original + 1 resubmission = 2 submissions total). Move to the end for unlimited.", }, { key: "start", diff --git a/backend/webserver/sockets/document.js b/backend/webserver/sockets/document.js index cfa4538f1..9138c6d07 100644 --- a/backend/webserver/sockets/document.js +++ b/backend/webserver/sockets/document.js @@ -897,8 +897,8 @@ class DocumentSocket extends Socket { transaction, }); - // Check revision limit (0 = unlimited) - if (assignment && assignment.maxRevisions > 0 && assignmentSubmissions.length >= assignment.maxRevisions) { + // Check revision limit (-1 = unlimited) + if (assignment && assignment.maxRevisions !== -1 && assignmentSubmissions.length >= assignment.maxRevisions + 1) { throw new Error(`Revision limit reached: user ${submission.userId} already has ${assignmentSubmissions.length} submission(s) for this assignment (max: ${assignment.maxRevisions}).`); } @@ -1197,7 +1197,7 @@ class DocumentSocket extends Socket { previousSubmissionId = chainTails.sort((a, b) => b - a)[0]; } - if (assignment.maxRevisions !== null && assignment.maxRevisions !== undefined && previousSubmissionId) { + if (assignment.maxRevisions !== null && assignment.maxRevisions !== undefined && assignment.maxRevisions !== -1 && previousSubmissionId) { let chainDepth = 0; let currentId = previousSubmissionId; const visited = new Set(); @@ -1210,7 +1210,7 @@ class DocumentSocket extends Socket { if (chainDepth >= assignment.maxRevisions) { throw new Error( - `Maximum revisions reached for this assignment (${chainDepth}/${assignment.maxRevisions})` + `Maximum revisions reached for this assignment submission` ); } } diff --git a/frontend/src/components/dashboard/Assignments.vue b/frontend/src/components/dashboard/Assignments.vue index a0a48dfb1..1298c443e 100644 --- a/frontend/src/components/dashboard/Assignments.vue +++ b/frontend/src/components/dashboard/Assignments.vue @@ -292,7 +292,7 @@ export default { canCloseAssignment: (this.isAssignmentOwner(assignment) || this.canEditAssignments) && !assignment.closed, submissionStatus: this.getSubmissionStatus(assignment), assignedRoles, - maxRevisions: assignment.maxRevisions ?? 1, + maxRevisions: assignment.maxRevisions === -1 ? "∞" : (assignment.maxRevisions ?? 1), disable: assignment.disable, start: assignment.start ? new Date(assignment.start).toLocaleString() : "-", end: assignment.end ? new Date(assignment.end).toLocaleString() : "-", diff --git a/frontend/src/components/dashboard/Submissions.vue b/frontend/src/components/dashboard/Submissions.vue index 53f9495c3..01f6d4fe7 100644 --- a/frontend/src/components/dashboard/Submissions.vue +++ b/frontend/src/components/dashboard/Submissions.vue @@ -20,23 +20,33 @@ collapsed > -
@@ -61,15 +71,24 @@ collapsable collapsed > -