diff --git a/Changelog.md b/Changelog.md
index ff0ad39f09..5a1d1089e1 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -7,6 +7,7 @@
### 🚨 Breaking changes
### ✨ New features and improvements
+- Added CSV upload support for criterion marks in the assignment Grades tab (#8008)
- Added a confirm dialog when a student tries to submit work after the deadline has passed (#8003)
- Added a confirm dialog to the Upload Scans form that appears when no template divisions are assigned to the selected exam template (#7993)
- Migrated `MarkingSchemesTable` component to React Table V8 (#7985)
diff --git a/app/controllers/assignments_controller.rb b/app/controllers/assignments_controller.rb
index 9029566850..4297311054 100644
--- a/app/controllers/assignments_controller.rb
+++ b/app/controllers/assignments_controller.rb
@@ -268,6 +268,19 @@ def summary
end
end
+ def upload_grades
+ @assignment = record
+ begin
+ data = process_file_upload(['.csv'])
+ rescue StandardError => e
+ flash_message(:error, e.message)
+ else
+ result = @assignment.import_marks_from_csv(data[:contents], params[:overwrite], current_role)
+ flash_csv_result(result)
+ end
+ redirect_to action: 'summary', id: @assignment.id
+ end
+
def download_test_results
@assignment = record
respond_to do |format|
diff --git a/app/javascript/Components/Modals/assignment_grades_upload_modal.jsx b/app/javascript/Components/Modals/assignment_grades_upload_modal.jsx
new file mode 100644
index 0000000000..1fbfa01d1c
--- /dev/null
+++ b/app/javascript/Components/Modals/assignment_grades_upload_modal.jsx
@@ -0,0 +1,69 @@
+import React from "react";
+import Modal from "react-modal";
+
+class AssignmentGradesUploadModal extends React.Component {
+ componentDidMount() {
+ Modal.setAppElement("body");
+ }
+
+ authenticityToken() {
+ return document.querySelector("meta[name='csrf-token']")?.content || "";
+ }
+
+ render() {
+ return (
+
+