Skip to content

Commit

Permalink
feat: add submission status interaction with submissions API
Browse files Browse the repository at this point in the history
  • Loading branch information
mariajgrimaldi committed Sep 21, 2023
1 parent 95def34 commit 1c06c78
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 106 deletions.
11 changes: 11 additions & 0 deletions mindmap/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,16 @@ class MindMapConfig(AppConfig):
"test": {"relative_path": "settings.test"},
"production": {"relative_path": "settings.production"},
},
},
"signals_config": {
"lms.djangoapp": {
"relative_path": "receivers",
"receivers": [
{
"receiver_func_name": "update_student_submission_status",
"signal_path": "submissions.models.score_reset",
},
]
},
}
}
149 changes: 51 additions & 98 deletions mindmap/mindmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@
from xblock.fields import Boolean, DateTime, Dict, Float, Integer, Scope, String
from xblockutils.resources import ResourceLoader

try:
from lms.djangoapps.courseware.models import StudentModule
except ImportError:
StudentModule = None

from mindmap.edxapp_wrapper.student import user_by_anonymous_id
from mindmap.edxapp_wrapper.xmodule import get_extended_due_date
from mindmap.utils import _, utcnow
Expand Down Expand Up @@ -118,13 +113,6 @@ class MindMapXBlock(XBlock):
scope=Scope.settings,
)

submission_status = String(
display_name=_("Submission status"),
help=_("The submission status of the assignment."),
default=SubmissionStatus.NOT_ATTEMPTED.value,
scope=Scope.user_state,
)

@property
def block_id(self):
"""
Expand Down Expand Up @@ -191,17 +179,6 @@ def render_template(self, template_path, context=None) -> str:
template_path, context, i18n_service=self.runtime.service(self, 'i18n')
)

def set_submission_status(self) -> None:
"""Update the submission status for the current user."""
student_id = self.get_current_user().opt_attrs.get(ATTR_KEY_ANONYMOUS_USER_ID)
submission = self.get_submission(student_id)

if submission:
submission_status = submission["answer"].get(
"submission_status", SubmissionStatus.NOT_ATTEMPTED.value
)
self.submission_status = submission_status

def get_context(self, user):
"""
Return the context for the student view.
Expand All @@ -218,6 +195,14 @@ def get_context(self, user):
else:
editable = in_student_view

submission = self.get_submission()
submission_status = SubmissionStatus.NOT_ATTEMPTED.value
if submission:
submission_status = submission.get("answer", {}).get(
"submission_status",
SubmissionStatus.NOT_ATTEMPTED.value,
)

return {
"display_name": self.display_name,
"in_student_view": in_student_view,
Expand All @@ -228,7 +213,7 @@ def get_context(self, user):
"can_submit_assignment": self.submit_allowed(),
"score": self.score,
"max_score": self.max_score(),
"submission_status": self.submission_status,
"submission_status": submission_status,
}

def get_js_context(self, user, context):
Expand Down Expand Up @@ -259,7 +244,6 @@ def student_view(self, _context=None) -> Fragment:
Returns:
Fragment: The fragment to render
"""
self.set_submission_status()
user = self.get_current_user()
context = self.get_context(user)
js_context = self.get_js_context(user, context)
Expand Down Expand Up @@ -421,38 +405,10 @@ def submit_assignment(self, data, _suffix="") -> dict:
student_item_dict = self.get_student_item_dict()
create_submission(student_item_dict, answer)

self.submission_status = SubmissionStatus.SUBMITTED.value

return {
"success": True,
}

# def get_or_create_student_module(self, user):
# """
# Gets or creates a StudentModule for the given user for this block

# Returns:
# StudentModule: A StudentModule object
# """
# # pylint: disable=no-member
# student_module, created = StudentModule.objects.get_or_create(
# course_id=self.course_id,
# module_state_key=self.location,
# student=user,
# defaults={
# "state": "{}",
# "module_type": self.category,
# },
# )
# if created:
# log.info(
# "Created student module %s [course: %s] [student: %s]",
# student_module.module_state_key,
# student_module.course_id,
# student_module.student.username,
# )
# return student_module

@XBlock.json_handler
def get_instructor_grading_data(self, _, _suffix="") -> dict:
"""Return student assignment information for display on the grading screen.
Expand Down Expand Up @@ -482,11 +438,14 @@ def get_student_data() -> dict:
for student in students:

submission = self.get_submission(student.student_id)

if not submission:
continue
answer = submission.get("answer", {})

if (
not submission or
answer.get("submission_status") ==
answer.get("submission_status", SubmissionStatus.NOT_ATTEMPTED.value) ==
SubmissionStatus.NOT_ATTEMPTED.value
):
continue
Expand Down Expand Up @@ -514,18 +473,6 @@ def get_student_data() -> dict:
"display_name": self.display_name,
}

# def get_student_module(self, module_id):
# """
# Returns a StudentModule that matches the given id

# Args:
# module_id (int): The module id

# Returns:
# StudentModule: A StudentModule object
# """
# return StudentModule.objects.get(pk=module_id)

@XBlock.json_handler
def enter_grade(self, data, _suffix="") -> dict:
"""
Expand All @@ -551,27 +498,34 @@ def enter_grade(self, data, _suffix="") -> dict:
if score > self.max_score():
raise JsonHandlerError(400, "Score cannot be greater than max score")

# Create a new submission
self.mindmap_student_body = data.get("mind_map")
answer = {
"mindmap_student_body": json.dumps(self.mindmap_student_body),
"submission_status": SubmissionStatus.COMPLETED.value,
}
student_item_dict = self.get_student_item_dict()
submission = create_submission(student_item_dict, answer)
set_score(submission["uuid"], score, self.max_score())
breakpoint()

# module = self.get_student_module(data.get("module_id"))
# state = json.loads(module.state)
# state["submission_status"] = SubmissionStatus.COMPLETED.value
# module.state = json.dumps(state)
# module.save()
latest_submission = self.update_student_submission_status(
data.get("student_id"), SubmissionStatus.COMPLETED.value,
)
set_score(latest_submission["uuid"], score, self.max_score())

return {
"success": True,
}

def update_student_submission_status(self, student_id, submission_status):
"""
Update the submission status for a student.
Args:
submission_id (str): The submission id.
student_id (str): The student id.
submission_status (str): The submission status.
"""
from submissions.api import create_submission
student_submission = self.get_submission(student_id)
mindmap_student_body = student_submission.get("mindmap_student_body", {})
answer = {
"mindmap_student_body": mindmap_student_body,
"submission_status": submission_status,
}
student_item_dict = self.get_student_item_dict(student_id)
return create_submission(student_item_dict, answer)

@XBlock.json_handler
def remove_grade(self, data, _suffix="") -> dict:
"""
Expand All @@ -593,22 +547,11 @@ def remove_grade(self, data, _suffix="") -> dict:
if not student_id:
raise JsonHandlerError(400, "Missing required parameters")

# Create a new submission
self.mindmap_student_body = data.get("mind_map")
answer = {
"mindmap_student_body": json.dumps(self.mindmap_student_body),
"submission_status": SubmissionStatus.SUBMITTED.value,
}
student_item_dict = self.get_student_item_dict()
submission = create_submission(student_item_dict, answer)

reset_score(submission["uuid"], self.block_course_id, self.block_id)
latest_submission = self.update_student_submission_status(
data.get("student_id"), SubmissionStatus.SUBMITTED.value,
)

# module = self.get_student_module(data.get("module_id"))
# state = json.loads(module.state)
# state["submission_status"] = SubmissionStatus.SUBMITTED.value
# module.state = json.dumps(state)
# module.save()
reset_score(latest_submission["uuid"], self.block_course_id, self.block_id)

return {
"success": True,
Expand Down Expand Up @@ -652,10 +595,20 @@ def submit_allowed(self) -> bool:
Returns:
bool: True if student is allowed to submit an assignment.
"""
student_submission = self.get_submission()
if not student_submission:
return (
not self.past_due()
and self.score is None
)
submission_status = student_submission.get("answer", {}).get(
"submission_status",
SubmissionStatus.NOT_ATTEMPTED.value,
)
return (
not self.past_due()
and self.score is None
and self.submission_status == SubmissionStatus.NOT_ATTEMPTED.value
and submission_status == SubmissionStatus.NOT_ATTEMPTED.value
)

def get_score(self, student_id=None) -> int:
Expand Down
10 changes: 2 additions & 8 deletions mindmap/public/js/src/mindmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function MindMapXBlock(runtime, element, context) {
e.preventDefault();
const typeAction = $(this).attr("data-type");
const grade = $("#grade_value").val();
const { submission_id, student_id, module_id } = submissionData;
const { student_id } = submissionData;
const invalidGradeMessage = gettext("Invalid grade must be a number");
const maxGradeMessage = gettext("Please enter a lower grade, maximum grade allowed is:");
const gradeParsed = parseInt(grade, 10);
Expand All @@ -253,16 +253,14 @@ function MindMapXBlock(runtime, element, context) {
apiUrl = enterGradeURL;
data = {
grade: grade,
submission_id: submission_id,
module_id: module_id,
student_id: student_id,
};
}

if (typeAction === "remove_grade") {
apiUrl = removeGradeURL;
data = {
student_id: student_id,
module_id: module_id,
};
}

Expand Down Expand Up @@ -298,11 +296,9 @@ function MindMapXBlock(runtime, element, context) {
.click(function () {
const grade = $(element).find(`#grade-input_${context.xblock_id}`).val();
const submission_id = $(element).find(`#submission-id-input_${context.xblock_id}`).val();
const module_id = $(element).find(`#module-id-input_${context.xblock_id}`).val();
const data = {
grade: grade,
submission_id: submission_id,
module_id: module_id,
};
console.log(data);
$.post(enterGradeURL, JSON.stringify(data))
Expand All @@ -318,10 +314,8 @@ function MindMapXBlock(runtime, element, context) {
.find(`#remove-grade-button_${context.xblock_id}`)
.click(function () {
const student_id = $(element).find(`#student-id-input_${context.xblock_id}`).val();
const module_id = $(element).find(`#module-id-input_${context.xblock_id}`).val();
const data = {
student_id: student_id,
module_id: module_id,
};
console.log(data);
$.post(removeGradeURL, JSON.stringify(data))
Expand Down
23 changes: 23 additions & 0 deletions mindmap/receivers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from mindmap.mindmap import SubmissionStatus


def update_student_submission_status(*args, **kwargs):
"""Update the submission status for a student after resetting their score."""
from submissions.api import get_submissions # pylint: disable=import-outside-toplevel
from submissions.api import create_submission

student_item_dict = {
"student_id": kwargs.get("anonymous_user_id"),
"item_id": kwargs.get("item_id"),
"item_type": "mindmap",
"course_id": kwargs.get("course_id"),
}
submissions = get_submissions(student_item_dict)
if not submissions:
return

student_submission = submissions[0]
new_answer = student_submission.get("answer")
new_answer["submission_status"] = SubmissionStatus.NOT_ATTEMPTED.value

create_submission(student_item_dict, new_answer)

0 comments on commit 1c06c78

Please sign in to comment.