From c0a3c048b732b4768ed7a18ca91df5a64e711f6a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:00:01 +0000 Subject: [PATCH 1/3] Initial plan From 4d9fc3186ba9ac9925469ec02b0ca21779e34ab8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 30 Aug 2025 15:08:44 +0000 Subject: [PATCH 2/3] Add reset start date functionality for students Co-authored-by: acbart <897227+acbart@users.noreply.github.com> --- controllers/endpoints/courses.py | 32 ++++++++++++++++++++++++++++ models/enums/logs.py | 3 ++- templates/courses/manage_time.html | 34 ++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/controllers/endpoints/courses.py b/controllers/endpoints/courses.py index 1e42bf39..b9e4b66b 100644 --- a/controllers/endpoints/courses.py +++ b/controllers/endpoints/courses.py @@ -1077,6 +1077,38 @@ def modify_time(): new_limits.append({"assignment": assignment.encode_json(), "time_limit": shown_amount}) return ajax_success({'new_limits': new_limits}) +@courses.route('/reset_start_date', methods=['POST']) +@courses.route('/reset_start_date/', methods=['POST']) +@login_required +def reset_start_date(): + course_id = get_course_id(False) + user, user_id = get_user() + student_id = maybe_int(request.values.get("student_id", "")) + assignment_ids = request.values.get("assignment_ids", "") + # Check permissions + require_course_instructor(g.user, course_id) + # Load Resources + course = Course.by_id(course_id) + student = User.by_id(student_id) + check_resource_exists(student, "User", student_id) + check_resource_exists(course, "Course", course_id) + # Reset the date_started for the assignments of this user + reset_assignments = [] + for assignment_id in assignment_ids.split(","): + assignment_id = maybe_int(assignment_id) + if assignment_id is None: + continue + assignment = Assignment.by_id(assignment_id) + submission = assignment.load_or_new_submission(student_id, course_id) + # Reset the start date + old_date = submission.date_started + submission.edit(dict(date_started=None)) + make_log_entry(submission.id, submission.version, assignment_id, assignment.version, + course_id, student_id, SubmissionLogEvent.RESET_START_DATE, + message=f"User {user_id} reset start date from `{old_date}`") + reset_assignments.append({"assignment": assignment.encode_json(), "old_date": str(old_date) if old_date else None}) + return ajax_success({'reset_assignments': reset_assignments}) + @courses.route('/manage_time', methods=['GET', 'POST']) @courses.route('/manage_time/', methods=['GET', 'POST']) @login_required diff --git a/models/enums/logs.py b/models/enums/logs.py index 9ef254e9..822727c0 100644 --- a/models/enums/logs.py +++ b/models/enums/logs.py @@ -48,4 +48,5 @@ class SubmissionLogEvent(StrEnum): TRANSFER = "transfer" CANVAS = "canvas" EXTEND_TIME = "extend_time" - START_TIMER = "start_timer" \ No newline at end of file + START_TIMER = "start_timer" + RESET_START_DATE = "reset_start_date" \ No newline at end of file diff --git a/templates/courses/manage_time.html b/templates/courses/manage_time.html index c24c28d9..43af503b 100644 --- a/templates/courses/manage_time.html +++ b/templates/courses/manage_time.html @@ -43,6 +43,35 @@ ); } +function resetStartDate(studentId, resultTarget) { + var selected = $("#assignment-select").val().join(","); + if (selected === null || selected.length === 0) { + alert("Please select at least one assignment to update."); + return; + } + if (!confirm("Are you sure you want to reset the start date for this student? This will allow them to restart the exam timer.")) { + return; + } + $.post( + {{ url_for('courses.reset_start_date')|tojson}}, + { + assignment_ids: selected, + student_id: studentId, + course_id: {{ course_id }} + }, + function(data) { + if (data.success) { + const message = data.reset_assignments.map( + update => `${update.assignment.name}: Start date reset` + ).join(", "); + $("#"+resultTarget).html(message + "
Student can now restart the timer."); + } else { + alert("Error: " + data.message); + } + }, + ); +} + function MainModel() { var self = this; } @@ -154,6 +183,11 @@

Manage Exam Time for Users

onclick="modifyTimeLimit({{ user.id }},'', 'time-limit-report-{{ user.id }}')"> Unset (use default time) +

+ {# #} {# #} {#