Skip to content

Commit

Permalink
Merge pull request #30 from IonMich/develop-pdf
Browse files Browse the repository at this point in the history
Develop-pdf
  • Loading branch information
IonMich authored Oct 9, 2022
2 parents a9f9aeb + 8085a45 commit c2c86f2
Show file tree
Hide file tree
Showing 14 changed files with 498 additions and 117 deletions.
94 changes: 82 additions & 12 deletions assignments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
from submissions.utils import CommaSeparatedFloatField
from courses.utils import get_canvas_course
from django.urls import reverse
from django.conf import settings
import tempfile
import os
import shutil

# Create your models here.

Expand Down Expand Up @@ -166,13 +170,52 @@ def sync_labeled_submissions_from_canvas(self):
submission.save()


def upload_graded_submissions_to_canvas(self):
"""Uploads the graded submissions to canvas.
def upload_graded_submissions_to_canvas(self,
submission_sync_option,
comment_sync_option,
specific_submissions=None
):
"""Uploads the grades and comments of the submissions to canvas.
Options to in the SyncToForm:
A select form field to choose the set of submissions to sync:
- upload all locally graded submissions or,
- only graded locally submissions that are not graded on canvas.
- a specific selection of submissions. This would require a
multiple select form field.
A select form field to choose the comment syncing behavior:
- upload all locally saved comments as new comments on canvas, or
- upload all locally saved comments as new comments on canvas,
but delete all previously uploaded comments on the canvas
submission posted by the current user, or
- upload only comments that are not on canvas. This requires
a check for each comment if it is already on canvas which
means that we need to get the canvas_id of the comment when
we upload it to canvas. This is not implemented yet.
for these two form fields, we use as parameters here:
- submission_sync_option
- comment_sync_option
submission_sync_option = forms.ChoiceField(
choices=(
('all', 'Upload all locally graded submissions'),
('grade_not_on_canvas', 'Upload only locally graded submissions that are not graded on canvas'),
('specific', 'Upload a specific selection of submissions'),
),
)
# Now fot the submissions determined by submission_sync_option,
# we also specify the comment_sync_option:
comment_sync_option = forms.ChoiceField(
choices=(
('all', 'Upload all locally saved comments as new comments on canvas'),
('delete_previous', 'Upload all locally saved comments as new comments on canvas, but delete all previously uploaded comments on the canvas submission posted by the current user'),
('comment_not_on_canvas', 'Upload only comments that are not on canvas'),
),
)
"""
raise NotImplementedError(
"stopping here. I need to add a verification from "
"the user that they want to upload the graded "
"submissions to canvas.")
raise ValueError("This error is raised as a final safety measure to prevent accidental uploads of grades to canvas. Comment out this line from assignments.models.upload_graded_submissions_to_canvas to enable the upload.")
canvas_course = get_canvas_course(canvas_id=self.course.canvas_id)
canvas_assignment = canvas_course.get_assignment(
self.canvas_id)
Expand All @@ -192,6 +235,14 @@ def upload_graded_submissions_to_canvas(self):
if submission.grade is None:
print(f"Will not upload submission without grade for {canvas_submission.user['name']}")
continue
if submission_sync_option == "grade_not_on_canvas" and canvas_submission.score is not None:
print(f"Will not upload grade for {canvas_submission.user['name']} because it is already on canvas.")
continue
if submission_sync_option == "specific" and submission not in specific_submissions:
print(f"Will not upload grade for {canvas_submission.user['name']} because it is not in the specific selection.")
continue

# continue

for comment in submission.submissions_submissioncomment_related.all():
print(f'Comment: {comment.text}')
Expand All @@ -201,12 +252,22 @@ def upload_graded_submissions_to_canvas(self):
question_grades_comment += f"Question {idx+1} Grade: {question_grade}\n"
print(f'Student grade: {score}')
print(f'Question grades comment: {question_grades_comment}')
canvas_submission.edit(submission={
uploaded_canvas_submission = canvas_submission.edit(submission={
'posted_grade': score},
comment=
{"text_comment":question_grades_comment,
},
)
# TODO: use the following to use comment_sync_option
# print(uploaded_canvas_submission.__dict__)
# for comment in uploaded_canvas_submission.submission_comments:
# if (comment["comment"] == question_grades_comment.strip("\n")
# and comment["author_id"] == uploaded_canvas_submission.grader_id):
# print(f"Found comment in canvas submission: {comment['comment']}")
# print(f"Comment id: {comment['id']}")
# submission.canvas_comment_id = comment["id"]
# submission.save()
# break
print(f"Uploaded grade and grade comment for {canvas_submission.user['name']}")

for comment in submission.submissions_submissioncomment_related.all():
Expand All @@ -216,11 +277,20 @@ def upload_graded_submissions_to_canvas(self):
},
)
print(f'Submission comment file url: {submission.pdf}')
uploaded = canvas_submission.upload_comment(
file=submission.pdf,
)
if uploaded:
print(f"Uploaded file comment to canvas for {canvas_submission.user['name']}")

new_file_name = f"submission_{submission.student.first_name}_{submission.student.last_name}.pdf"
tmp_folder_path = os.path.join(settings.BASE_DIR, "tmp")
if not os.path.exists(tmp_folder_path):
os.makedirs(tmp_folder_path)
with tempfile.TemporaryDirectory(dir=tmp_folder_path) as tmp_dir:
tmp_file_path = os.path.join(tmp_dir, new_file_name)
shutil.copyfile(submission.pdf.path, tmp_file_path)

uploaded = canvas_submission.upload_comment(
file=tmp_file_path,
)
if uploaded:
print(f"Uploaded file comment to canvas for {canvas_submission.user['name']}")



Expand Down
20 changes: 20 additions & 0 deletions assignments/static/assignments/detail.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ if (btnFetch) {
btnFetch.addEventListener('click', syncSubsFromCanvas);
}

// in the Post to Canvas modal, when the user selects the option "specific" in the submission_sync_option
// show the select element to select the submission(s) to sync
function showSelectSubs(event) {
const selectSubs = document.getElementById('specific-submission-select-div');
console.log(event);
if (event.target.value === 'specific') {
selectSubs.classList.remove('d-none');
} else {
selectSubs.classList.add('d-none');
}
}

// add event listener to the specific-submission-select element of the Post to Canvas modal
// when the user selects the option "specific" in the submission_sync_option
// show the select element to select the submission(s) to sync
const selectSyncOption = document.getElementsByName('submission_sync_option');
if (selectSyncOption) {
selectSyncOption.forEach(el => el.addEventListener('change', showSelectSubs));
}

// on hover of a submission card, show delete button at top right
// on click of delete button, show confirmation modal
// the button has an attribute data-pk which is the primary key of the submission
Expand Down
Loading

0 comments on commit c2c86f2

Please sign in to comment.