Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ORA staff grader mfe endpoints upgraded (not for review yet) #33596

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lms/djangoapps/ora_staff_grader/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Query params
PARAM_ORA_LOCATION = "oraLocation"
PARAM_SUBMISSION_ID = "submissionUUID"
PARAM_ASSESSMENT_FILTER = "assessmentFilter"

# Error codes
ERR_UNKNOWN = "ERR_UNKNOWN"
Expand Down
18 changes: 17 additions & 1 deletion lms/djangoapps/ora_staff_grader/ora_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
These are checked (usually by checking for a {"success":false} response) and raise errors, possibly with extra context.
"""
import json
from http import HTTPStatus
from lms.djangoapps.ora_staff_grader.errors import (
LockContestedError,
XBlockInternalError,
Expand All @@ -33,6 +34,21 @@ def get_submissions(request, usage_id):
return json.loads(response.content)


def get_assessments(request, usage_id, submission_uuid, assessment_filter):
"""
Get a list of assessments from the ORA's 'list_assessments_grades' XBlock.json_handler
"""
handler_name = "list_assessments"
body = {"item_id": usage_id, "submission_uuid": submission_uuid, "assessment_filter": assessment_filter}

response = call_xblock_json_handler(request, usage_id, handler_name, body)

if response.status_code != 200:
raise XBlockInternalError(context={"handler": handler_name})

return json.loads(response.content)


def get_submission_info(request, usage_id, submission_uuid):
"""
Get submission content from ORA 'get_submission_info' XBlock.json_handler
Expand Down Expand Up @@ -168,5 +184,5 @@ def batch_delete_submission_locks(request, usage_id, submission_uuids):
response = call_xblock_json_handler(request, usage_id, handler_name, body)

# Errors should raise a blanket exception. Otherwise body is empty, 200 is implicit success
if response.status_code != 200:
if response.status_code != HTTPStatus.OK:
raise XBlockInternalError(context={"handler": handler_name})
61 changes: 60 additions & 1 deletion lms/djangoapps/ora_staff_grader/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,13 @@ class ScoreSerializer(serializers.Serializer):

class SubmissionMetadataSerializer(serializers.Serializer):
"""
Submission metadata for displaying submissions table in ESG
Submission metadata for displaying submissions table in Enhanced Staff Grader (ESG)
"""

submissionUUID = serializers.CharField(source="submissionUuid")
username = serializers.CharField(allow_null=True)
email = serializers.CharField(allow_null=True)
fullname = serializers.CharField(allow_null=True)
teamName = serializers.CharField(allow_null=True)
dateSubmitted = serializers.DateTimeField()
dateGraded = serializers.DateTimeField(allow_null=True)
Expand All @@ -157,10 +159,57 @@ class Meta:
"gradeStatus",
"lockStatus",
"score",
"email",
"fullname",
]
read_only_fields = fields


class AssessmentScoresSerializer(serializers.Serializer):
"""
Score information associated with a specific assessment.

This serializer was intended for displaying assessment information in the Enhanced Staff Grader (ESG).
"""
criterion_name = serializers.CharField()
score_earned = serializers.IntegerField()
score_type = serializers.CharField()

class Meta:
fields = [
"criterion_name",
"score_earned",
"score_type",
]
read_only_fields = fields


class AssessmentSerializer(serializers.Serializer):
"""
Data for displaying Assessment objects in a table in Enhanced Staff Grader (ESG)
"""
assessment_id = serializers.CharField()
scorer_name = serializers.CharField(allow_null=True)
scorer_username = serializers.CharField(allow_null=True)
scorer_email = serializers.CharField(allow_null=True)
assesment_date = serializers.DateTimeField()
assesment_scores = serializers.ListField(child=AssessmentScoresSerializer())
problem_step = serializers.CharField(allow_null=True)
feedback = serializers.CharField(allow_null=True)

class Meta:
fields = [
"assessment_id",
"scorer_name",
"scorer_username",
"scorer_email",
"assesment_date",
"assesment_scores",
"problem_step",
"feedback",
]
read_only_fields = fields

class InitializeSerializer(serializers.Serializer):
"""
Serialize info for the initialize call. Packages ORA, course, submission, and rubric data.
Expand All @@ -187,6 +236,16 @@ def get_isEnabled(self, obj):
"""
return obj['isEnabled'] and not obj['oraMetadata'].teams_enabled

class AssessmentFeedbackSerializer(serializers.Serializer):
"""
Serialize info for every assessment for a table in Enhanced Staff Grader (ESG)
"""

assessments = serializers.ListField(child=AssessmentSerializer())

class Meta:
fields = ["assessments",]
read_only_fields = fields

class UploadedFileSerializer(serializers.Serializer):
"""Serializer for a file uploaded as a part of a response"""
Expand Down
10 changes: 10 additions & 0 deletions lms/djangoapps/ora_staff_grader/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ class TestSubmissionMetadataSerializer(TestCase):
"submissionUuid": "a",
"username": "foo",
"teamName": "",
'email': "[email protected]",
'fullname': "",
"dateSubmitted": "1969-07-16 13:32:00",
"dateGraded": "None",
"gradedBy": "",
Expand All @@ -249,6 +251,8 @@ class TestSubmissionMetadataSerializer(TestCase):
"b": {
"submissionUuid": "b",
"username": "",
'email': "[email protected]",
'fullname': "Jhon Does",
"teamName": "bar",
"dateSubmitted": "1969-07-20 20:17:40",
"dateGraded": "None",
Expand All @@ -260,6 +264,8 @@ class TestSubmissionMetadataSerializer(TestCase):
"c": {
"submissionUuid": "c",
"username": "baz",
'email': "[email protected]",
'fullname': "Jhon Does",
"teamName": "",
"dateSubmitted": "1969-07-21 21:35:00",
"dateGraded": "1969-07-24 16:44:00",
Expand Down Expand Up @@ -291,6 +297,8 @@ def test_empty_score(self):
submission = {
"submissionUuid": "empty-score",
"username": "WOPR",
'email': "[email protected]",
'fullname': "",
"dateSubmitted": "1983-06-03 00:00:00",
"dateGraded": None,
"gradedBy": None,
Expand All @@ -302,6 +310,8 @@ def test_empty_score(self):
expected_output = {
"submissionUUID": "empty-score",
"username": "WOPR",
'email': "[email protected]",
'fullname': "",
"teamName": None,
"dateSubmitted": "1983-06-03 00:00:00",
"dateGraded": None,
Expand Down
2 changes: 2 additions & 0 deletions lms/djangoapps/ora_staff_grader/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
SubmissionLockView,
SubmissionStatusFetchView,
UpdateGradeView,
AssessmentFeedbackView,
)


Expand All @@ -22,6 +23,7 @@
urlpatterns += [
path("mock/", include("lms.djangoapps.ora_staff_grader.mock.urls")),
path("initialize", InitializeView.as_view(), name="initialize"),
path("assessments/feedback", AssessmentFeedbackView.as_view(), name="assessment-feedback"),
path("submission/batch/unlock", SubmissionBatchUnlockView.as_view(), name="batch-unlock"),
path("submission/files", SubmissionFilesFetchView.as_view(), name="fetch-files"),
path(
Expand Down
45 changes: 45 additions & 0 deletions lms/djangoapps/ora_staff_grader/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from lms.djangoapps.ora_staff_grader.constants import (
PARAM_ORA_LOCATION,
PARAM_SUBMISSION_ID,
PARAM_ASSESSMENT_FILTER,
)
from lms.djangoapps.ora_staff_grader.errors import (
BadOraLocationResponse,
Expand All @@ -43,11 +44,13 @@
get_assessment_info,
get_submission_info,
get_submissions,
get_assessments,
submit_grade,
)
from lms.djangoapps.ora_staff_grader.serializers import (
FileListSerializer,
InitializeSerializer,
AssessmentFeedbackSerializer,
LockStatusSerializer,
StaffAssessSerializer,
SubmissionFetchSerializer,
Expand Down Expand Up @@ -147,6 +150,48 @@ def get(self, request, ora_location, *args, **kwargs):
return UnknownErrorResponse()


class AssessmentFeedbackView(StaffGraderBaseView):
"""
GET data about Assessments by submission_uuid and ora_location

Response: {
assessments
}

Errors:
- MissingParamResponse (HTTP 400) for missing params
- BadOraLocationResponse (HTTP 400) for bad ORA location
- XBlockInternalError (HTTP 500) for an issue with ORA
- UnknownError (HTTP 500) for other errors
"""

@require_params([PARAM_ORA_LOCATION, PARAM_SUBMISSION_ID, PARAM_ASSESSMENT_FILTER])
def get(self, request, ora_location, submission_uuid, assessment_filter=None, *args, **kwargs):

try:
assessments_data = {}

assessments_data["assessments"] = get_assessments(request, ora_location, submission_uuid, assessment_filter)

response_data = AssessmentFeedbackSerializer(assessments_data).data
return Response(response_data)

# Catch bad ORA location
except (InvalidKeyError, ItemNotFoundError):
log.error(f"Bad ORA location provided: {ora_location}")
return BadOraLocationResponse()

# Issues with the XBlock handlers
except XBlockInternalError as ex:
log.error(ex)
return InternalErrorResponse(context=ex.context)

# Blanket exception handling in case something blows up
except Exception as ex:
log.exception(ex)
return UnknownErrorResponse()


class SubmissionFetchView(StaffGraderBaseView):
"""
GET submission contents and assessment info, if any
Expand Down