Attach completion data to `Assignment` in GraphQL schema
This commit is contained in:
parent
4bc1ca636c
commit
21174d17db
|
|
@ -99,6 +99,7 @@ export type AssignmentObjectType = CoursePageInterface & {
|
||||||
__typename?: 'AssignmentObjectType';
|
__typename?: 'AssignmentObjectType';
|
||||||
assignment_type: AssignmentAssignmentAssignmentTypeChoices;
|
assignment_type: AssignmentAssignmentAssignmentTypeChoices;
|
||||||
circle?: Maybe<CircleObjectType>;
|
circle?: Maybe<CircleObjectType>;
|
||||||
|
completion?: Maybe<AssignmentCompletionObjectType>;
|
||||||
content_type?: Maybe<Scalars['String']['output']>;
|
content_type?: Maybe<Scalars['String']['output']>;
|
||||||
course?: Maybe<CourseObjectType>;
|
course?: Maybe<CourseObjectType>;
|
||||||
/** Zeitaufwand als Text */
|
/** Zeitaufwand als Text */
|
||||||
|
|
@ -122,6 +123,13 @@ export type AssignmentObjectType = CoursePageInterface & {
|
||||||
translation_key?: Maybe<Scalars['String']['output']>;
|
translation_key?: Maybe<Scalars['String']['output']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type AssignmentObjectTypeCompletionArgs = {
|
||||||
|
assignment_user_id?: InputMaybe<Scalars['UUID']['input']>;
|
||||||
|
course_session_id: Scalars['ID']['input'];
|
||||||
|
learning_content_page_id?: InputMaybe<Scalars['ID']['input']>;
|
||||||
|
};
|
||||||
|
|
||||||
export type AttendanceCourseUserMutation = {
|
export type AttendanceCourseUserMutation = {
|
||||||
__typename?: 'AttendanceCourseUserMutation';
|
__typename?: 'AttendanceCourseUserMutation';
|
||||||
course_session_attendance_course?: Maybe<CourseSessionAttendanceCourseType>;
|
course_session_attendance_course?: Maybe<CourseSessionAttendanceCourseType>;
|
||||||
|
|
@ -566,7 +574,6 @@ export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
assignment?: Maybe<AssignmentObjectType>;
|
assignment?: Maybe<AssignmentObjectType>;
|
||||||
assignment_completion?: Maybe<AssignmentCompletionObjectType>;
|
assignment_completion?: Maybe<AssignmentCompletionObjectType>;
|
||||||
assignment_completions?: Maybe<Array<Maybe<AssignmentCompletionObjectType>>>;
|
|
||||||
circle?: Maybe<CircleObjectType>;
|
circle?: Maybe<CircleObjectType>;
|
||||||
competence_certificate?: Maybe<CompetenceCertificateObjectType>;
|
competence_certificate?: Maybe<CompetenceCertificateObjectType>;
|
||||||
competence_certificate_list?: Maybe<CompetenceCertificateListObjectType>;
|
competence_certificate_list?: Maybe<CompetenceCertificateListObjectType>;
|
||||||
|
|
@ -600,13 +607,6 @@ export type QueryAssignmentCompletionArgs = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryAssignmentCompletionsArgs = {
|
|
||||||
assignment_ids: Array<InputMaybe<Scalars['ID']['input']>>;
|
|
||||||
assignment_user_id?: InputMaybe<Scalars['UUID']['input']>;
|
|
||||||
course_session_id: Scalars['ID']['input'];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export type QueryCircleArgs = {
|
export type QueryCircleArgs = {
|
||||||
id?: InputMaybe<Scalars['ID']['input']>;
|
id?: InputMaybe<Scalars['ID']['input']>;
|
||||||
slug?: InputMaybe<Scalars['String']['input']>;
|
slug?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ type Query {
|
||||||
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String): CompetenceCertificateListObjectType
|
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String): CompetenceCertificateListObjectType
|
||||||
assignment(id: ID, slug: String): AssignmentObjectType
|
assignment(id: ID, slug: String): AssignmentObjectType
|
||||||
assignment_completion(assignment_id: ID!, course_session_id: ID!, learning_content_page_id: ID, assignment_user_id: UUID): AssignmentCompletionObjectType
|
assignment_completion(assignment_id: ID!, course_session_id: ID!, learning_content_page_id: ID, assignment_user_id: UUID): AssignmentCompletionObjectType
|
||||||
assignment_completions(assignment_ids: [ID]!, course_session_id: ID!, assignment_user_id: UUID): [AssignmentCompletionObjectType]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningPathObjectType implements CoursePageInterface {
|
type LearningPathObjectType implements CoursePageInterface {
|
||||||
|
|
@ -253,6 +252,7 @@ type AssignmentObjectType implements CoursePageInterface {
|
||||||
performance_objectives: JSONStreamField
|
performance_objectives: JSONStreamField
|
||||||
max_points: Int
|
max_points: Int
|
||||||
learning_content: LearningContentInterface
|
learning_content: LearningContentInterface
|
||||||
|
completion(course_session_id: ID!, learning_content_page_id: ID, assignment_user_id: UUID): AssignmentCompletionObjectType
|
||||||
}
|
}
|
||||||
|
|
||||||
"""An enumeration."""
|
"""An enumeration."""
|
||||||
|
|
@ -275,6 +275,53 @@ enum AssignmentAssignmentAssignmentTypeChoices {
|
||||||
|
|
||||||
scalar JSONStreamField
|
scalar JSONStreamField
|
||||||
|
|
||||||
|
type AssignmentCompletionObjectType {
|
||||||
|
id: UUID!
|
||||||
|
created_at: DateTime!
|
||||||
|
updated_at: DateTime!
|
||||||
|
submitted_at: DateTime
|
||||||
|
evaluation_submitted_at: DateTime
|
||||||
|
evaluation_user: UserType
|
||||||
|
evaluation_grade: Float
|
||||||
|
evaluation_points: Float
|
||||||
|
assignment_user: UserType!
|
||||||
|
assignment: AssignmentObjectType!
|
||||||
|
completion_status: AssignmentAssignmentCompletionCompletionStatusChoices!
|
||||||
|
completion_data: GenericScalar
|
||||||
|
additional_json_data: JSONString!
|
||||||
|
learning_content_page_id: ID
|
||||||
|
}
|
||||||
|
|
||||||
|
"""An enumeration."""
|
||||||
|
enum AssignmentAssignmentCompletionCompletionStatusChoices {
|
||||||
|
"""IN_PROGRESS"""
|
||||||
|
IN_PROGRESS
|
||||||
|
|
||||||
|
"""SUBMITTED"""
|
||||||
|
SUBMITTED
|
||||||
|
|
||||||
|
"""EVALUATION_IN_PROGRESS"""
|
||||||
|
EVALUATION_IN_PROGRESS
|
||||||
|
|
||||||
|
"""EVALUATION_SUBMITTED"""
|
||||||
|
EVALUATION_SUBMITTED
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
The `GenericScalar` scalar type represents a generic
|
||||||
|
GraphQL scalar value that could be:
|
||||||
|
String, Boolean, Int, Float, List or Object.
|
||||||
|
"""
|
||||||
|
scalar GenericScalar
|
||||||
|
|
||||||
|
"""
|
||||||
|
Allows use of a JSON String for input / output from the GraphQL schema.
|
||||||
|
|
||||||
|
Use of this type is *not recommended* as you lose the benefits of having a defined, static
|
||||||
|
schema (one of the key benefits of GraphQL).
|
||||||
|
"""
|
||||||
|
scalar JSONString
|
||||||
|
|
||||||
"""An enumeration."""
|
"""An enumeration."""
|
||||||
enum LearnpathLearningContentAssignmentAssignmentTypeChoices {
|
enum LearnpathLearningContentAssignmentAssignmentTypeChoices {
|
||||||
"""CASEWORK"""
|
"""CASEWORK"""
|
||||||
|
|
@ -497,53 +544,6 @@ type CompetenceCertificateListObjectType implements CoursePageInterface {
|
||||||
competence_certificates: [CompetenceCertificateObjectType]
|
competence_certificates: [CompetenceCertificateObjectType]
|
||||||
}
|
}
|
||||||
|
|
||||||
type AssignmentCompletionObjectType {
|
|
||||||
id: UUID!
|
|
||||||
created_at: DateTime!
|
|
||||||
updated_at: DateTime!
|
|
||||||
submitted_at: DateTime
|
|
||||||
evaluation_submitted_at: DateTime
|
|
||||||
evaluation_user: UserType
|
|
||||||
evaluation_grade: Float
|
|
||||||
evaluation_points: Float
|
|
||||||
assignment_user: UserType!
|
|
||||||
assignment: AssignmentObjectType!
|
|
||||||
completion_status: AssignmentAssignmentCompletionCompletionStatusChoices!
|
|
||||||
completion_data: GenericScalar
|
|
||||||
additional_json_data: JSONString!
|
|
||||||
learning_content_page_id: ID
|
|
||||||
}
|
|
||||||
|
|
||||||
"""An enumeration."""
|
|
||||||
enum AssignmentAssignmentCompletionCompletionStatusChoices {
|
|
||||||
"""IN_PROGRESS"""
|
|
||||||
IN_PROGRESS
|
|
||||||
|
|
||||||
"""SUBMITTED"""
|
|
||||||
SUBMITTED
|
|
||||||
|
|
||||||
"""EVALUATION_IN_PROGRESS"""
|
|
||||||
EVALUATION_IN_PROGRESS
|
|
||||||
|
|
||||||
"""EVALUATION_SUBMITTED"""
|
|
||||||
EVALUATION_SUBMITTED
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
The `GenericScalar` scalar type represents a generic
|
|
||||||
GraphQL scalar value that could be:
|
|
||||||
String, Boolean, Int, Float, List or Object.
|
|
||||||
"""
|
|
||||||
scalar GenericScalar
|
|
||||||
|
|
||||||
"""
|
|
||||||
Allows use of a JSON String for input / output from the GraphQL schema.
|
|
||||||
|
|
||||||
Use of this type is *not recommended* as you lose the benefits of having a defined, static
|
|
||||||
schema (one of the key benefits of GraphQL).
|
|
||||||
"""
|
|
||||||
scalar JSONString
|
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
send_feedback(input: SendFeedbackInput!): SendFeedbackPayload
|
send_feedback(input: SendFeedbackInput!): SendFeedbackPayload
|
||||||
update_course_session_attendance_course_users(attendance_user_list: [AttendanceUserInputType]!, id: ID!): AttendanceCourseUserMutation
|
update_course_session_attendance_course_users(attendance_user_list: [AttendanceUserInputType]!, id: ID!): AttendanceCourseUserMutation
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import graphene
|
import graphene
|
||||||
from rest_framework.exceptions import PermissionDenied
|
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.graphql.types import (
|
from vbv_lernwelt.assignment.graphql.types import (
|
||||||
AssignmentCompletionObjectType,
|
AssignmentCompletionObjectType,
|
||||||
AssignmentObjectType,
|
AssignmentObjectType, resolve_assignment_completion,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
from vbv_lernwelt.assignment.models import Assignment
|
||||||
from vbv_lernwelt.course.graphql.types import resolve_course_page
|
from vbv_lernwelt.course.graphql.types import resolve_course_page
|
||||||
from vbv_lernwelt.course.models import CourseSession
|
|
||||||
from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert
|
|
||||||
|
|
||||||
|
|
||||||
class AssignmentQuery(object):
|
class AssignmentQuery(object):
|
||||||
|
|
@ -36,55 +33,7 @@ class AssignmentQuery(object):
|
||||||
assignment_user_id=None,
|
assignment_user_id=None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
if assignment_user_id is None:
|
return resolve_assignment_completion(
|
||||||
assignment_user_id = info.context.user.id
|
info, assignment_id, course_session_id, learning_content_page_id,
|
||||||
|
assignment_user_id,
|
||||||
if str(assignment_user_id) == str(
|
)
|
||||||
info.context.user.id
|
|
||||||
) or is_course_session_expert(info.context.user, course_session_id):
|
|
||||||
course_id = CourseSession.objects.get(id=course_session_id).course_id
|
|
||||||
if has_course_access(info.context.user, course_id):
|
|
||||||
if learning_content_page_id is None:
|
|
||||||
learning_content_page = Assignment.objects.get(
|
|
||||||
id=assignment_id
|
|
||||||
).learningcontentassignment_set.first()
|
|
||||||
if learning_content_page:
|
|
||||||
learning_content_page_id = learning_content_page.id
|
|
||||||
|
|
||||||
return AssignmentCompletion.objects.filter(
|
|
||||||
assignment_user_id=assignment_user_id,
|
|
||||||
assignment_id=assignment_id,
|
|
||||||
learning_content_page_id=learning_content_page_id,
|
|
||||||
course_session_id=course_session_id,
|
|
||||||
).first()
|
|
||||||
raise PermissionDenied()
|
|
||||||
|
|
||||||
assignment_completions = graphene.List(
|
|
||||||
AssignmentCompletionObjectType,
|
|
||||||
assignment_ids=graphene.List(graphene.ID, required=True),
|
|
||||||
course_session_id=graphene.ID(required=True),
|
|
||||||
assignment_user_id=graphene.UUID(required=False),
|
|
||||||
)
|
|
||||||
|
|
||||||
def resolve_assignment_completions(
|
|
||||||
root,
|
|
||||||
info,
|
|
||||||
assignment_ids,
|
|
||||||
course_session_id,
|
|
||||||
assignment_user_id=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
if assignment_user_id is None:
|
|
||||||
assignment_user_id = info.context.user.id
|
|
||||||
|
|
||||||
if str(assignment_user_id) == str(
|
|
||||||
info.context.user.id
|
|
||||||
) or is_course_session_expert(info.context.user, course_session_id):
|
|
||||||
course_id = CourseSession.objects.get(id=course_session_id).course_id
|
|
||||||
if has_course_access(info.context.user, course_id):
|
|
||||||
return AssignmentCompletion.objects.filter(
|
|
||||||
assignment_user_id=assignment_user_id,
|
|
||||||
assignment_id__in=assignment_ids,
|
|
||||||
course_session_id=course_session_id,
|
|
||||||
)
|
|
||||||
raise PermissionDenied()
|
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,16 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphene.types.generic import GenericScalar
|
from graphene.types.generic import GenericScalar
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
||||||
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
||||||
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||||
|
from vbv_lernwelt.course.models import CourseSession
|
||||||
|
from vbv_lernwelt.course.permissions import is_course_session_expert, has_course_access
|
||||||
from vbv_lernwelt.learnpath.graphql.types import LearningContentInterface
|
from vbv_lernwelt.learnpath.graphql.types import LearningContentInterface
|
||||||
|
|
||||||
|
|
||||||
class AssignmentObjectType(DjangoObjectType):
|
|
||||||
tasks = JSONStreamField()
|
|
||||||
evaluation_tasks = JSONStreamField()
|
|
||||||
performance_objectives = JSONStreamField()
|
|
||||||
max_points = graphene.Int()
|
|
||||||
learning_content = graphene.Field(LearningContentInterface)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Assignment
|
|
||||||
interfaces = (CoursePageInterface,)
|
|
||||||
fields = (
|
|
||||||
"assignment_type",
|
|
||||||
"intro_text",
|
|
||||||
"effort_required",
|
|
||||||
"evaluation_description",
|
|
||||||
"evaluation_document_url",
|
|
||||||
"learning_content",
|
|
||||||
)
|
|
||||||
|
|
||||||
def resolve_max_points(self, info):
|
|
||||||
return self.get_max_points()
|
|
||||||
|
|
||||||
def resolve_learning_content(self, info):
|
|
||||||
return self.find_attached_learning_content()
|
|
||||||
|
|
||||||
|
|
||||||
class AssignmentCompletionObjectType(DjangoObjectType):
|
class AssignmentCompletionObjectType(DjangoObjectType):
|
||||||
completion_data = GenericScalar()
|
completion_data = GenericScalar()
|
||||||
learning_content_page_id = graphene.ID(source="learning_content_page_id")
|
learning_content_page_id = graphene.ID(source="learning_content_page_id")
|
||||||
|
|
@ -57,3 +34,82 @@ class AssignmentCompletionObjectType(DjangoObjectType):
|
||||||
"evaluation_grade",
|
"evaluation_grade",
|
||||||
"evaluation_points",
|
"evaluation_points",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AssignmentObjectType(DjangoObjectType):
|
||||||
|
tasks = JSONStreamField()
|
||||||
|
evaluation_tasks = JSONStreamField()
|
||||||
|
performance_objectives = JSONStreamField()
|
||||||
|
max_points = graphene.Int()
|
||||||
|
learning_content = graphene.Field(LearningContentInterface)
|
||||||
|
completion = graphene.Field(
|
||||||
|
AssignmentCompletionObjectType,
|
||||||
|
course_session_id=graphene.ID(required=True),
|
||||||
|
learning_content_page_id=graphene.ID(required=False),
|
||||||
|
assignment_user_id=graphene.UUID(required=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Assignment
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = (
|
||||||
|
"assignment_type",
|
||||||
|
"intro_text",
|
||||||
|
"effort_required",
|
||||||
|
"evaluation_description",
|
||||||
|
"evaluation_document_url",
|
||||||
|
"learning_content",
|
||||||
|
)
|
||||||
|
|
||||||
|
def resolve_max_points(self, info):
|
||||||
|
return self.get_max_points()
|
||||||
|
|
||||||
|
def resolve_learning_content(self, info):
|
||||||
|
return self.find_attached_learning_content()
|
||||||
|
|
||||||
|
def resolve_completion(
|
||||||
|
self, info, course_session_id, learning_content_page_id=None,
|
||||||
|
assignment_user_id=None,
|
||||||
|
):
|
||||||
|
if learning_content_page_id is None:
|
||||||
|
lp = self.find_attached_learning_content()
|
||||||
|
if lp:
|
||||||
|
learning_content_page_id = lp.id
|
||||||
|
return resolve_assignment_completion(
|
||||||
|
info=info,
|
||||||
|
course_session_id=course_session_id,
|
||||||
|
learning_content_page_id=learning_content_page_id,
|
||||||
|
assignment_user_id=assignment_user_id,
|
||||||
|
assignment_id=self.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_assignment_completion(
|
||||||
|
info,
|
||||||
|
assignment_id,
|
||||||
|
course_session_id,
|
||||||
|
learning_content_page_id=None,
|
||||||
|
assignment_user_id=None,
|
||||||
|
):
|
||||||
|
if assignment_user_id is None:
|
||||||
|
assignment_user_id = info.context.user.id
|
||||||
|
|
||||||
|
if str(assignment_user_id) == str(
|
||||||
|
info.context.user.id
|
||||||
|
) or is_course_session_expert(info.context.user, course_session_id):
|
||||||
|
course_id = CourseSession.objects.get(id=course_session_id).course_id
|
||||||
|
if has_course_access(info.context.user, course_id):
|
||||||
|
if learning_content_page_id is None:
|
||||||
|
learning_content_page = Assignment.objects.get(
|
||||||
|
id=assignment_id
|
||||||
|
).learningcontentassignment_set.first()
|
||||||
|
if learning_content_page:
|
||||||
|
learning_content_page_id = learning_content_page.id
|
||||||
|
|
||||||
|
return AssignmentCompletion.objects.filter(
|
||||||
|
assignment_user_id=assignment_user_id,
|
||||||
|
assignment_id=assignment_id,
|
||||||
|
learning_content_page_id=learning_content_page_id,
|
||||||
|
course_session_id=course_session_id,
|
||||||
|
).first()
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,12 @@ class Assignment(CourseBasePage):
|
||||||
return page.specific
|
return page.specific
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def get_frontend_url(self):
|
||||||
|
lp = self.find_attached_learning_content()
|
||||||
|
if lp:
|
||||||
|
return lp.get_frontend_url()
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
class AssignmentCompletionStatus(Enum):
|
class AssignmentCompletionStatus(Enum):
|
||||||
IN_PROGRESS = "IN_PROGRESS"
|
IN_PROGRESS = "IN_PROGRESS"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue