Add CourseSessionAssignment to serializer

This commit is contained in:
Daniel Egger 2023-07-11 17:39:50 +02:00
parent 324725964b
commit 5890e908f2
13 changed files with 223 additions and 160 deletions

View File

@ -1,11 +1,13 @@
import type { ResultOf, TypedDocumentNode as DocumentNode, } from '@graphql-typed-document-node/core'; import type { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core';
import type { FragmentDefinitionNode } from 'graphql';
import type { Incremental } from './graphql';
export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocumentType extends DocumentNode< export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> = TDocumentType extends DocumentTypeDecoration<
infer TType, infer TType,
any any
> >
? TType extends { ' $fragmentName'?: infer TKey } ? [TType] extends [{ ' $fragmentName'?: infer TKey }]
? TKey extends string ? TKey extends string
? { ' $fragmentRefs'?: { [key in TKey]: TType } } ? { ' $fragmentRefs'?: { [key in TKey]: TType } }
: never : never
@ -14,35 +16,51 @@ export type FragmentType<TDocumentType extends DocumentNode<any, any>> = TDocume
// return non-nullable if `fragmentType` is non-nullable // return non-nullable if `fragmentType` is non-nullable
export function useFragment<TType>( export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>, _documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> fragmentType: FragmentType<DocumentTypeDecoration<TType, any>>
): TType; ): TType;
// return nullable if `fragmentType` is nullable // return nullable if `fragmentType` is nullable
export function useFragment<TType>( export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>, _documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | null | undefined fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined
): TType | null | undefined; ): TType | null | undefined;
// return array of non-nullable if `fragmentType` is array of non-nullable // return array of non-nullable if `fragmentType` is array of non-nullable
export function useFragment<TType>( export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>, _documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>>
): ReadonlyArray<TType>; ): ReadonlyArray<TType>;
// return array of nullable if `fragmentType` is array of nullable // return array of nullable if `fragmentType` is array of nullable
export function useFragment<TType>( export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>, _documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): ReadonlyArray<TType> | null | undefined; ): ReadonlyArray<TType> | null | undefined;
export function useFragment<TType>( export function useFragment<TType>(
_documentNode: DocumentNode<TType, any>, _documentNode: DocumentTypeDecoration<TType, any>,
fragmentType: FragmentType<DocumentNode<TType, any>> | ReadonlyArray<FragmentType<DocumentNode<TType, any>>> | null | undefined fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined
): TType | ReadonlyArray<TType> | null | undefined { ): TType | ReadonlyArray<TType> | null | undefined {
return fragmentType as any; return fragmentType as any;
} }
export function makeFragmentData< export function makeFragmentData<
F extends DocumentNode, F extends DocumentTypeDecoration<any, any>,
FT extends ResultOf<F> FT extends ResultOf<F>
>(data: FT, _fragment: F): FragmentType<F> { >(data: FT, _fragment: F): FragmentType<F> {
return data as FragmentType<F>; return data as FragmentType<F>;
} }
export function isFragmentReady<TQuery, TFrag>(
queryNode: DocumentTypeDecoration<TQuery, any>,
fragmentNode: TypedDocumentNode<TFrag>,
data: FragmentType<TypedDocumentNode<Incremental<TFrag>, any>> | null | undefined
): data is FragmentType<typeof fragmentNode> {
const deferredFields = (queryNode as { __meta__?: { deferredFields: Record<string, (keyof TFrag)[]> } }).__meta__
?.deferredFields;
if (!deferredFields) return true;
const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined;
const fragName = fragDef?.name?.value;
const fields = (fragName && deferredFields[fragName]) || [];
return fields.length > 0 && fields.every(field => data && field in data);
}

View File

@ -10,7 +10,7 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
* 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle.
* 3. It does not support dead code elimination, so it will add unused operations. * 3. It does not support dead code elimination, so it will add unused operations.
* *
* Therefore it is highly recommended to use the babel-plugin for production. * Therefore it is highly recommended to use the babel or swc plugin for production.
*/ */
const documents = { const documents = {
"\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n send_feedback(input: $input) {\n feedback_response {\n id\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument, "\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n send_feedback(input: $input) {\n feedback_response {\n id\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
@ -25,7 +25,7 @@ const documents = {
* *
* @example * @example
* ```ts * ```ts
* const query = gql(`query GetUser($id: ID!) { user(id: $id) { name } }`); * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`);
* ``` * ```
* *
* The query argument is unknown! * The query argument is unknown!

View File

@ -5,33 +5,35 @@ export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] }; export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> }; export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> }; export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
/** All built-in and custom scalars, mapped to their actual values */ /** All built-in and custom scalars, mapped to their actual values */
export type Scalars = { export type Scalars = {
ID: string; ID: { input: string; output: string; }
String: string; String: { input: string; output: string; }
Boolean: boolean; Boolean: { input: boolean; output: boolean; }
Int: number; Int: { input: number; output: number; }
Float: number; Float: { input: number; output: number; }
/** /**
* The `DateTime` scalar type represents a DateTime * The `DateTime` scalar type represents a DateTime
* value as specified by * value as specified by
* [iso8601](https://en.wikipedia.org/wiki/ISO_8601). * [iso8601](https://en.wikipedia.org/wiki/ISO_8601).
*/ */
DateTime: any; DateTime: { input: any; output: any; }
/** /**
* The `GenericScalar` scalar type represents a generic * The `GenericScalar` scalar type represents a generic
* GraphQL scalar value that could be: * GraphQL scalar value that could be:
* String, Boolean, Int, Float, List or Object. * String, Boolean, Int, Float, List or Object.
*/ */
GenericScalar: any; GenericScalar: { input: any; output: any; }
JSONStreamField: any; JSONStreamField: { input: any; output: any; }
/** /**
* Allows use of a JSON String for input / output from the GraphQL schema. * 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 * 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). * schema (one of the key benefits of GraphQL).
*/ */
JSONString: any; JSONString: { input: any; output: any; }
}; };
/** An enumeration. */ /** An enumeration. */
@ -61,19 +63,19 @@ export type AssignmentCompletionMutation = {
export type AssignmentCompletionObjectType = { export type AssignmentCompletionObjectType = {
__typename?: 'AssignmentCompletionObjectType'; __typename?: 'AssignmentCompletionObjectType';
additional_json_data: Scalars['JSONString']; additional_json_data: Scalars['JSONString']['output'];
assignment: AssignmentObjectType; assignment: AssignmentObjectType;
assignment_user: UserType; assignment_user: UserType;
completion_data?: Maybe<Scalars['GenericScalar']>; completion_data?: Maybe<Scalars['GenericScalar']['output']>;
completion_status: AssignmentAssignmentCompletionCompletionStatusChoices; completion_status: AssignmentAssignmentCompletionCompletionStatusChoices;
created_at: Scalars['DateTime']; created_at: Scalars['DateTime']['output'];
evaluation_grade?: Maybe<Scalars['Float']>; evaluation_grade?: Maybe<Scalars['Float']['output']>;
evaluation_points?: Maybe<Scalars['Float']>; evaluation_points?: Maybe<Scalars['Float']['output']>;
evaluation_submitted_at?: Maybe<Scalars['DateTime']>; evaluation_submitted_at?: Maybe<Scalars['DateTime']['output']>;
evaluation_user?: Maybe<UserType>; evaluation_user?: Maybe<UserType>;
id: Scalars['ID']; id: Scalars['ID']['output'];
submitted_at?: Maybe<Scalars['DateTime']>; submitted_at?: Maybe<Scalars['DateTime']['output']>;
updated_at: Scalars['DateTime']; updated_at: Scalars['DateTime']['output'];
}; };
/** An enumeration. */ /** An enumeration. */
@ -86,24 +88,24 @@ export type AssignmentCompletionStatus =
export type AssignmentObjectType = CoursePageInterface & { export type AssignmentObjectType = CoursePageInterface & {
__typename?: 'AssignmentObjectType'; __typename?: 'AssignmentObjectType';
assignment_type: AssignmentAssignmentAssignmentTypeChoices; assignment_type: AssignmentAssignmentAssignmentTypeChoices;
content_type?: Maybe<Scalars['String']>; content_type?: Maybe<Scalars['String']['output']>;
/** Zeitaufwand als Text */ /** Zeitaufwand als Text */
effort_required: Scalars['String']; effort_required: Scalars['String']['output'];
/** Beschreibung der Bewertung */ /** Beschreibung der Bewertung */
evaluation_description: Scalars['String']; evaluation_description: Scalars['String']['output'];
/** URL zum Beurteilungsinstrument */ /** URL zum Beurteilungsinstrument */
evaluation_document_url: Scalars['String']; evaluation_document_url: Scalars['String']['output'];
evaluation_tasks?: Maybe<Scalars['JSONStreamField']>; evaluation_tasks?: Maybe<Scalars['JSONStreamField']['output']>;
frontend_url?: Maybe<Scalars['String']>; frontend_url?: Maybe<Scalars['String']['output']>;
id?: Maybe<Scalars['ID']>; id?: Maybe<Scalars['ID']['output']>;
/** Erläuterung der Ausgangslage */ /** Erläuterung der Ausgangslage */
intro_text: Scalars['String']; intro_text: Scalars['String']['output'];
live?: Maybe<Scalars['Boolean']>; live?: Maybe<Scalars['Boolean']['output']>;
performance_objectives?: Maybe<Scalars['JSONStreamField']>; performance_objectives?: Maybe<Scalars['JSONStreamField']['output']>;
slug?: Maybe<Scalars['String']>; slug?: Maybe<Scalars['String']['output']>;
tasks?: Maybe<Scalars['JSONStreamField']>; tasks?: Maybe<Scalars['JSONStreamField']['output']>;
title?: Maybe<Scalars['String']>; title?: Maybe<Scalars['String']['output']>;
translation_key?: Maybe<Scalars['String']>; translation_key?: Maybe<Scalars['String']['output']>;
}; };
/** An enumeration. */ /** An enumeration. */
@ -116,69 +118,69 @@ export type CoreUserLanguageChoices =
| 'IT'; | 'IT';
export type CoursePageInterface = { export type CoursePageInterface = {
content_type?: Maybe<Scalars['String']>; content_type?: Maybe<Scalars['String']['output']>;
frontend_url?: Maybe<Scalars['String']>; frontend_url?: Maybe<Scalars['String']['output']>;
id?: Maybe<Scalars['ID']>; id?: Maybe<Scalars['ID']['output']>;
live?: Maybe<Scalars['Boolean']>; live?: Maybe<Scalars['Boolean']['output']>;
slug?: Maybe<Scalars['String']>; slug?: Maybe<Scalars['String']['output']>;
title?: Maybe<Scalars['String']>; title?: Maybe<Scalars['String']['output']>;
translation_key?: Maybe<Scalars['String']>; translation_key?: Maybe<Scalars['String']['output']>;
}; };
export type CourseType = { export type CourseType = {
__typename?: 'CourseType'; __typename?: 'CourseType';
category_name: Scalars['String']; category_name: Scalars['String']['output'];
id: Scalars['ID']; id: Scalars['ID']['output'];
learning_path?: Maybe<LearningPathType>; learning_path?: Maybe<LearningPathType>;
slug: Scalars['String']; slug: Scalars['String']['output'];
title: Scalars['String']; title: Scalars['String']['output'];
}; };
export type ErrorType = { export type ErrorType = {
__typename?: 'ErrorType'; __typename?: 'ErrorType';
field: Scalars['String']; field: Scalars['String']['output'];
messages: Array<Scalars['String']>; messages: Array<Scalars['String']['output']>;
}; };
export type FeedbackResponse = Node & { export type FeedbackResponse = Node & {
__typename?: 'FeedbackResponse'; __typename?: 'FeedbackResponse';
created_at: Scalars['DateTime']; created_at: Scalars['DateTime']['output'];
data?: Maybe<Scalars['GenericScalar']>; data?: Maybe<Scalars['GenericScalar']['output']>;
/** The ID of the object */ /** The ID of the object */
id: Scalars['ID']; id: Scalars['ID']['output'];
}; };
export type LearningPathType = CoursePageInterface & { export type LearningPathType = CoursePageInterface & {
__typename?: 'LearningPathType'; __typename?: 'LearningPathType';
content_type?: Maybe<Scalars['String']>; content_type?: Maybe<Scalars['String']['output']>;
depth: Scalars['Int']; depth: Scalars['Int']['output'];
draft_title: Scalars['String']; draft_title: Scalars['String']['output'];
expire_at?: Maybe<Scalars['DateTime']>; expire_at?: Maybe<Scalars['DateTime']['output']>;
expired: Scalars['Boolean']; expired: Scalars['Boolean']['output'];
first_published_at?: Maybe<Scalars['DateTime']>; first_published_at?: Maybe<Scalars['DateTime']['output']>;
frontend_url?: Maybe<Scalars['String']>; frontend_url?: Maybe<Scalars['String']['output']>;
go_live_at?: Maybe<Scalars['DateTime']>; go_live_at?: Maybe<Scalars['DateTime']['output']>;
has_unpublished_changes: Scalars['Boolean']; has_unpublished_changes: Scalars['Boolean']['output'];
id?: Maybe<Scalars['ID']>; id?: Maybe<Scalars['ID']['output']>;
last_published_at?: Maybe<Scalars['DateTime']>; last_published_at?: Maybe<Scalars['DateTime']['output']>;
latest_revision_created_at?: Maybe<Scalars['DateTime']>; latest_revision_created_at?: Maybe<Scalars['DateTime']['output']>;
live?: Maybe<Scalars['Boolean']>; live?: Maybe<Scalars['Boolean']['output']>;
locked: Scalars['Boolean']; locked: Scalars['Boolean']['output'];
locked_at?: Maybe<Scalars['DateTime']>; locked_at?: Maybe<Scalars['DateTime']['output']>;
locked_by?: Maybe<UserType>; locked_by?: Maybe<UserType>;
numchild: Scalars['Int']; numchild: Scalars['Int']['output'];
owner?: Maybe<UserType>; owner?: Maybe<UserType>;
path: Scalars['String']; path: Scalars['String']['output'];
/** Die informative Beschreibung, dargestellt in Suchmaschinen-Ergebnissen unter der Überschrift. */ /** Die informative Beschreibung, dargestellt in Suchmaschinen-Ergebnissen unter der Überschrift. */
search_description: Scalars['String']; search_description: Scalars['String']['output'];
/** Der Titel der Seite, dargestellt in Suchmaschinen-Ergebnissen als die verlinkte Überschrift. */ /** Der Titel der Seite, dargestellt in Suchmaschinen-Ergebnissen als die verlinkte Überschrift. */
seo_title: Scalars['String']; seo_title: Scalars['String']['output'];
/** Ob ein Link zu dieser Seite in automatisch generierten Menüs auftaucht. */ /** Ob ein Link zu dieser Seite in automatisch generierten Menüs auftaucht. */
show_in_menus: Scalars['Boolean']; show_in_menus: Scalars['Boolean']['output'];
slug?: Maybe<Scalars['String']>; slug?: Maybe<Scalars['String']['output']>;
title?: Maybe<Scalars['String']>; title?: Maybe<Scalars['String']['output']>;
translation_key?: Maybe<Scalars['String']>; translation_key?: Maybe<Scalars['String']['output']>;
url_path: Scalars['String']; url_path: Scalars['String']['output'];
}; };
export type Mutation = { export type Mutation = {
@ -194,19 +196,19 @@ export type MutationSendFeedbackArgs = {
export type MutationUpsertAssignmentCompletionArgs = { export type MutationUpsertAssignmentCompletionArgs = {
assignment_id: Scalars['ID']; assignment_id: Scalars['ID']['input'];
assignment_user_id?: InputMaybe<Scalars['ID']>; assignment_user_id?: InputMaybe<Scalars['ID']['input']>;
completion_data_string?: InputMaybe<Scalars['String']>; completion_data_string?: InputMaybe<Scalars['String']['input']>;
completion_status?: InputMaybe<AssignmentCompletionStatus>; completion_status?: InputMaybe<AssignmentCompletionStatus>;
course_session_id: Scalars['ID']; course_session_id: Scalars['ID']['input'];
evaluation_grade?: InputMaybe<Scalars['Float']>; evaluation_grade?: InputMaybe<Scalars['Float']['input']>;
evaluation_points?: InputMaybe<Scalars['Float']>; evaluation_points?: InputMaybe<Scalars['Float']['input']>;
}; };
/** An object with an ID */ /** An object with an ID */
export type Node = { export type Node = {
/** The ID of the object */ /** The ID of the object */
id: Scalars['ID']; id: Scalars['ID']['output'];
}; };
export type Query = { export type Query = {
@ -218,32 +220,32 @@ export type Query = {
export type QueryAssignmentArgs = { export type QueryAssignmentArgs = {
id?: InputMaybe<Scalars['ID']>; id?: InputMaybe<Scalars['ID']['input']>;
slug?: InputMaybe<Scalars['String']>; slug?: InputMaybe<Scalars['String']['input']>;
}; };
export type QueryAssignmentCompletionArgs = { export type QueryAssignmentCompletionArgs = {
assignment_id: Scalars['ID']; assignment_id: Scalars['ID']['input'];
assignment_user_id?: InputMaybe<Scalars['ID']>; assignment_user_id?: InputMaybe<Scalars['ID']['input']>;
course_session_id: Scalars['ID']; course_session_id: Scalars['ID']['input'];
}; };
export type QueryCourseArgs = { export type QueryCourseArgs = {
id?: InputMaybe<Scalars['Int']>; id?: InputMaybe<Scalars['Int']['input']>;
}; };
export type SendFeedbackInput = { export type SendFeedbackInput = {
clientMutationId?: InputMaybe<Scalars['String']>; clientMutationId?: InputMaybe<Scalars['String']['input']>;
course_session: Scalars['Int']; course_session: Scalars['Int']['input'];
data?: InputMaybe<Scalars['GenericScalar']>; data?: InputMaybe<Scalars['GenericScalar']['input']>;
page: Scalars['String']; page: Scalars['String']['input'];
}; };
export type SendFeedbackPayload = { export type SendFeedbackPayload = {
__typename?: 'SendFeedbackPayload'; __typename?: 'SendFeedbackPayload';
clientMutationId?: Maybe<Scalars['String']>; clientMutationId?: Maybe<Scalars['String']['output']>;
/** May contain more than one error for same field. */ /** May contain more than one error for same field. */
errors?: Maybe<Array<Maybe<ErrorType>>>; errors?: Maybe<Array<Maybe<ErrorType>>>;
feedback_response?: Maybe<FeedbackResponse>; feedback_response?: Maybe<FeedbackResponse>;
@ -251,14 +253,14 @@ export type SendFeedbackPayload = {
export type UserType = { export type UserType = {
__typename?: 'UserType'; __typename?: 'UserType';
avatar_url: Scalars['String']; avatar_url: Scalars['String']['output'];
email: Scalars['String']; email: Scalars['String']['output'];
first_name: Scalars['String']; first_name: Scalars['String']['output'];
id: Scalars['ID']; id: Scalars['ID']['output'];
language: CoreUserLanguageChoices; language: CoreUserLanguageChoices;
last_name: Scalars['String']; last_name: Scalars['String']['output'];
/** Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/_. */ /** Erforderlich. 150 Zeichen oder weniger. Nur Buchstaben, Ziffern und @/./+/-/_. */
username: Scalars['String']; username: Scalars['String']['output'];
}; };
export type SendFeedbackMutationMutationVariables = Exact<{ export type SendFeedbackMutationMutationVariables = Exact<{
@ -269,29 +271,29 @@ export type SendFeedbackMutationMutationVariables = Exact<{
export type SendFeedbackMutationMutation = { __typename?: 'Mutation', send_feedback?: { __typename?: 'SendFeedbackPayload', feedback_response?: { __typename?: 'FeedbackResponse', id: string } | null, errors?: Array<{ __typename?: 'ErrorType', field: string, messages: Array<string> } | null> | null } | null }; export type SendFeedbackMutationMutation = { __typename?: 'Mutation', send_feedback?: { __typename?: 'SendFeedbackPayload', feedback_response?: { __typename?: 'FeedbackResponse', id: string } | null, errors?: Array<{ __typename?: 'ErrorType', field: string, messages: Array<string> } | null> | null } | null };
export type UpsertAssignmentCompletionMutationVariables = Exact<{ export type UpsertAssignmentCompletionMutationVariables = Exact<{
assignmentId: Scalars['ID']; assignmentId: Scalars['ID']['input'];
courseSessionId: Scalars['ID']; courseSessionId: Scalars['ID']['input'];
assignmentUserId?: InputMaybe<Scalars['ID']>; assignmentUserId?: InputMaybe<Scalars['ID']['input']>;
completionStatus: AssignmentCompletionStatus; completionStatus: AssignmentCompletionStatus;
completionDataString: Scalars['String']; completionDataString: Scalars['String']['input'];
evaluationGrade?: InputMaybe<Scalars['Float']>; evaluationGrade?: InputMaybe<Scalars['Float']['input']>;
evaluationPoints?: InputMaybe<Scalars['Float']>; evaluationPoints?: InputMaybe<Scalars['Float']['input']>;
}>; }>;
export type UpsertAssignmentCompletionMutation = { __typename?: 'Mutation', upsert_assignment_completion?: { __typename?: 'AssignmentCompletionMutation', assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: any | null, evaluation_submitted_at?: any | null, evaluation_grade?: number | null, evaluation_points?: number | null, completion_data?: any | null } | null } | null }; export type UpsertAssignmentCompletionMutation = { __typename?: 'Mutation', upsert_assignment_completion?: { __typename?: 'AssignmentCompletionMutation', assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: any | null, evaluation_submitted_at?: any | null, evaluation_grade?: number | null, evaluation_points?: number | null, completion_data?: any | null } | null } | null };
export type AssignmentCompletionQueryQueryVariables = Exact<{ export type AssignmentCompletionQueryQueryVariables = Exact<{
assignmentId: Scalars['ID']; assignmentId: Scalars['ID']['input'];
courseSessionId: Scalars['ID']; courseSessionId: Scalars['ID']['input'];
assignmentUserId?: InputMaybe<Scalars['ID']>; assignmentUserId?: InputMaybe<Scalars['ID']['input']>;
}>; }>;
export type AssignmentCompletionQueryQuery = { __typename?: 'Query', assignment?: { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, content_type?: string | null, effort_required: string, evaluation_description: string, evaluation_document_url: string, evaluation_tasks?: any | null, id?: string | null, intro_text: string, performance_objectives?: any | null, slug?: string | null, tasks?: any | null, title?: string | null, translation_key?: string | null } | null, assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: any | null, evaluation_submitted_at?: any | null, evaluation_grade?: number | null, evaluation_points?: number | null, completion_data?: any | null, evaluation_user?: { __typename?: 'UserType', id: string } | null, assignment_user: { __typename?: 'UserType', id: string } } | null }; export type AssignmentCompletionQueryQuery = { __typename?: 'Query', assignment?: { __typename?: 'AssignmentObjectType', assignment_type: AssignmentAssignmentAssignmentTypeChoices, content_type?: string | null, effort_required: string, evaluation_description: string, evaluation_document_url: string, evaluation_tasks?: any | null, id?: string | null, intro_text: string, performance_objectives?: any | null, slug?: string | null, tasks?: any | null, title?: string | null, translation_key?: string | null } | null, assignment_completion?: { __typename?: 'AssignmentCompletionObjectType', id: string, completion_status: AssignmentAssignmentCompletionCompletionStatusChoices, submitted_at?: any | null, evaluation_submitted_at?: any | null, evaluation_grade?: number | null, evaluation_points?: number | null, completion_data?: any | null, evaluation_user?: { __typename?: 'UserType', id: string } | null, assignment_user: { __typename?: 'UserType', id: string } } | null };
export type CourseQueryQueryVariables = Exact<{ export type CourseQueryQueryVariables = Exact<{
courseId: Scalars['Int']; courseId: Scalars['Int']['input'];
}>; }>;

View File

@ -6,7 +6,7 @@ import AssignmentSubmissionResponses from "@/pages/learningPath/learningContentP
import type { import type {
Assignment, Assignment,
AssignmentCompletion, AssignmentCompletion,
CourseSessionAssignmentDetails, CourseSessionAssignment,
CourseSessionUser, CourseSessionUser,
} from "@/types"; } from "@/types";
import { useQuery } from "@urql/vue"; import { useQuery } from "@urql/vue";
@ -23,12 +23,12 @@ const props = defineProps<{
log.debug("AssignmentEvaluationPage created", props.assignmentId, props.userId); log.debug("AssignmentEvaluationPage created", props.assignmentId, props.userId);
interface StateInterface { interface StateInterface {
courseSessionAssignmentDetails: CourseSessionAssignmentDetails | undefined; courseSessionAssignment: CourseSessionAssignment | undefined;
assignmentUser: CourseSessionUser | undefined; assignmentUser: CourseSessionUser | undefined;
} }
const state: StateInterface = reactive({ const state: StateInterface = reactive({
courseSessionAssignmentDetails: undefined, courseSessionAssignment: undefined,
assignmentUser: undefined, assignmentUser: undefined,
}); });

View File

@ -60,9 +60,7 @@ function editTask(task: AssignmentEvaluationTask) {
const assignmentDetail = computed(() => findAssignmentDetail(props.assignment.id)); const assignmentDetail = computed(() => findAssignmentDetail(props.assignment.id));
const dueDate = computed(() => const dueDate = computed(() => dayjs(assignmentDetail.value?.evaluation_deadline_end));
dayjs(assignmentDetail.value?.evaluationDeadlineDateTimeUtc)
);
const inEvaluationTask = computed( const inEvaluationTask = computed(
() => stepIndex.value >= 1 && stepIndex.value <= numTasks.value () => stepIndex.value >= 1 && stepIndex.value <= numTasks.value

View File

@ -56,12 +56,12 @@ const assignmentDetail = computed(() =>
<div v-if="assignmentDetail"> <div v-if="assignmentDetail">
<span> <span>
Abgabetermin: Abgabetermin:
{{ dayjs(assignmentDetail.submissionDeadlineDateTimeUtc).format("DD.MM.YYYY") }} {{ dayjs(assignmentDetail.submission_deadline_end).format("DD.MM.YYYY") }}
</span> </span>
- -
<span> <span>
Freigabetermin: Freigabetermin:
{{ dayjs(assignmentDetail.evaluationDeadlineDateTimeUtc).format("DD.MM.YYYY") }} {{ dayjs(assignmentDetail.evaluation_deadline_end).format("DD.MM.YYYY") }}
</span> </span>
</div> </div>

View File

@ -3,6 +3,7 @@ import DateEmbedding from "@/components/dueDates/DateEmbedding.vue";
import type { Assignment } from "@/types"; import type { Assignment } from "@/types";
import { useRouteQuery } from "@vueuse/router"; import { useRouteQuery } from "@vueuse/router";
import type { Dayjs } from "dayjs"; import type { Dayjs } from "dayjs";
import log from "loglevel";
interface Props { interface Props {
assignment: Assignment; assignment: Assignment;
@ -13,6 +14,8 @@ const props = withDefaults(defineProps<Props>(), {
dueDate: undefined, dueDate: undefined,
}); });
log.debug("AssignmentIntroductionView created", props.assignment, props.dueDate);
// TODO: Test if submission deadline is set correctly, and evaluation_deadline is set. // TODO: Test if submission deadline is set correctly, and evaluation_deadline is set.
const step = useRouteQuery("step"); const step = useRouteQuery("step");

View File

@ -13,7 +13,7 @@ import type {
Assignment, Assignment,
AssignmentCompletion, AssignmentCompletion,
AssignmentTask, AssignmentTask,
CourseSessionAssignmentDetails, CourseSessionAssignment,
CourseSessionUser, CourseSessionUser,
LearningContentAssignment, LearningContentAssignment,
} from "@/types"; } from "@/types";
@ -29,11 +29,11 @@ const courseSession = useCurrentCourseSession();
const userStore = useUserStore(); const userStore = useUserStore();
interface State { interface State {
courseSessionAssignmentDetails: CourseSessionAssignmentDetails | undefined; courseSessionAssignment: CourseSessionAssignment | undefined;
} }
const state: State = reactive({ const state: State = reactive({
courseSessionAssignmentDetails: undefined, courseSessionAssignment: undefined,
}); });
const props = defineProps<{ const props = defineProps<{
@ -80,7 +80,7 @@ onMounted(async () => {
props.learningContent props.learningContent
); );
state.courseSessionAssignmentDetails = useCourseSessionsStore().findAssignmentDetails( state.courseSessionAssignment = useCourseSessionsStore().findCourseSessionAssignment(
props.learningContent.id props.learningContent.id
); );
@ -123,7 +123,7 @@ const showPreviousButton = computed(() => stepIndex.value != 0);
const showNextButton = computed(() => stepIndex.value + 1 < numPages.value); const showNextButton = computed(() => stepIndex.value + 1 < numPages.value);
const showExitButton = computed(() => numPages.value === stepIndex.value + 1); const showExitButton = computed(() => numPages.value === stepIndex.value + 1);
const dueDate = computed(() => const dueDate = computed(() =>
dayjs(state.courseSessionAssignmentDetails?.submissionDeadlineDateTimeUtc) dayjs(state.courseSessionAssignment?.submission_deadline_end)
); );
const currentTask = computed(() => { const currentTask = computed(() => {
if (stepIndex.value > 0 && stepIndex.value <= numTasks.value) { if (stepIndex.value > 0 && stepIndex.value <= numTasks.value) {

View File

@ -109,7 +109,7 @@ export function findAssignmentDetail(assignmentId: number) {
(lc) => lc.assignmentId === assignmentId (lc) => lc.assignmentId === assignmentId
); );
return courseSessionsStore.findAssignmentDetails(learningContent?.id); return courseSessionsStore.findCourseSessionAssignment(learningContent?.id);
} }
export function maxAssignmentPoints(assignment: Assignment) { export function maxAssignmentPoints(assignment: Assignment) {

View File

@ -3,7 +3,7 @@ import { deleteCircleDocument } from "@/services/files";
import type { import type {
CircleDocument, CircleDocument,
CourseSession, CourseSession,
CourseSessionAssignmentDetails, CourseSessionAssignment,
CourseSessionAttendanceCourse, CourseSessionAttendanceCourse,
CourseSessionUser, CourseSessionUser,
DueDate, DueDate,
@ -230,20 +230,18 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
): CourseSessionAttendanceCourse | undefined { ): CourseSessionAttendanceCourse | undefined {
if (currentCourseSession.value) { if (currentCourseSession.value) {
return currentCourseSession.value.attendance_courses.find( return currentCourseSession.value.attendance_courses.find(
(attendanceCourse) => attendanceCourse.learning_content === contentId (attendanceCourse) => attendanceCourse.learning_content_id === contentId
); );
} }
} }
function findAssignmentDetails( function findCourseSessionAssignment(
contentId?: number contentId?: number
): CourseSessionAssignmentDetails | undefined { ): CourseSessionAssignment | undefined {
if (contentId && currentCourseSession.value) { if (contentId && currentCourseSession.value) {
return; return currentCourseSession.value.assignments.find(
// TODO: Commented out because DueDate replaced assignment_details_list, not shure if other iformation is needed (a) => a.learning_content_id === contentId
// currentCourseSession.value.assignment_details_list.find( );
// (assignmentDetails) => assignmentDetails.learningContentId === contentId
// );
} }
} }
@ -261,7 +259,7 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
startUpload, startUpload,
removeDocument, removeDocument,
findAttendanceCourse, findAttendanceCourse,
findAssignmentDetails, findCourseSessionAssignment,
allDueDates, allDueDates,
// use `useCurrentCourseSession` whenever possible // use `useCurrentCourseSession` whenever possible

View File

@ -413,18 +413,24 @@ export interface CircleDocument {
} }
export interface CourseSessionAttendanceCourse { export interface CourseSessionAttendanceCourse {
learning_content: number; id: number;
course_session_id: number;
learning_content_id: number;
start: string; start: string;
end: string; end: string;
location: string; location: string;
trainer: string; trainer: string;
due_date: DueDate; due_date_id: number;
} }
export interface CourseSessionAssignmentDetails { export interface CourseSessionAssignment {
learningContentId: number; id: number;
submissionDeadlineDateTimeUtc: string; course_session_id: number;
evaluationDeadlineDateTimeUtc: string; learning_content_id: number;
submission_deadline_id: number;
submission_deadline_end: string;
evaluation_deadline_id: number;
evaluation_deadline_end: string;
} }
export interface CourseSession { export interface CourseSession {
@ -441,7 +447,7 @@ export interface CourseSession {
course_url: string; course_url: string;
media_library_url: string; media_library_url: string;
attendance_courses: CourseSessionAttendanceCourse[]; attendance_courses: CourseSessionAttendanceCourse[];
assignment_details_list: CourseSessionAssignmentDetails[]; assignments: CourseSessionAssignment[];
documents: CircleDocument[]; documents: CircleDocument[];
users: CourseSessionUser[]; users: CourseSessionUser[];
duedates: DueDate[]; duedates: DueDate[];

View File

@ -7,8 +7,12 @@ from vbv_lernwelt.course.models import (
CourseCompletion, CourseCompletion,
CourseSession, CourseSession,
) )
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse from vbv_lernwelt.course_session.models import (
CourseSessionAssignment,
CourseSessionAttendanceCourse,
)
from vbv_lernwelt.course_session.serializers import ( from vbv_lernwelt.course_session.serializers import (
CourseSessionAssignmentSerializer,
CourseSessionAttendanceCourseSerializer, CourseSessionAttendanceCourseSerializer,
) )
from vbv_lernwelt.duedate.models import DueDate from vbv_lernwelt.duedate.models import DueDate
@ -57,6 +61,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
media_library_url = serializers.SerializerMethodField() media_library_url = serializers.SerializerMethodField()
documents = serializers.SerializerMethodField() documents = serializers.SerializerMethodField()
attendance_courses = serializers.SerializerMethodField() attendance_courses = serializers.SerializerMethodField()
assignments = serializers.SerializerMethodField()
duedates = serializers.SerializerMethodField() duedates = serializers.SerializerMethodField()
def get_course(self, obj): def get_course(self, obj):
@ -88,6 +93,11 @@ class CourseSessionSerializer(serializers.ModelSerializer):
CourseSessionAttendanceCourse.objects.filter(course_session=obj), many=True CourseSessionAttendanceCourse.objects.filter(course_session=obj), many=True
).data ).data
def get_assignments(self, obj):
return CourseSessionAssignmentSerializer(
CourseSessionAssignment.objects.filter(course_session=obj), many=True
).data
def get_duedates(self, obj): def get_duedates(self, obj):
# TODO: Filter by user / userrole # TODO: Filter by user / userrole
duedates = DueDate.objects.filter(course_session=obj) duedates = DueDate.objects.filter(course_session=obj)
@ -105,7 +115,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
"end_date", "end_date",
"additional_json_data", "additional_json_data",
"attendance_courses", "attendance_courses",
# "assignment_details_list", "assignments",
"learning_path_url", "learning_path_url",
"cockpit_url", "cockpit_url",
"competence_url", "competence_url",

View File

@ -1,6 +1,9 @@
from rest_framework import serializers from rest_framework import serializers
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse from vbv_lernwelt.course_session.models import (
CourseSessionAssignment,
CourseSessionAttendanceCourse,
)
class CourseSessionAttendanceCourseSerializer(serializers.ModelSerializer): class CourseSessionAttendanceCourseSerializer(serializers.ModelSerializer):
@ -11,9 +14,9 @@ class CourseSessionAttendanceCourseSerializer(serializers.ModelSerializer):
model = CourseSessionAttendanceCourse model = CourseSessionAttendanceCourse
fields = [ fields = [
"id", "id",
"course_session", "course_session_id",
"learning_content", "learning_content_id",
"due_date", "due_date_id",
"location", "location",
"trainer", "trainer",
"start", "start",
@ -25,3 +28,28 @@ class CourseSessionAttendanceCourseSerializer(serializers.ModelSerializer):
def get_end(self, obj): def get_end(self, obj):
return obj.due_date.end return obj.due_date.end
class CourseSessionAssignmentSerializer(serializers.ModelSerializer):
submission_deadline_end = serializers.SerializerMethodField()
evaluation_deadline_end = serializers.SerializerMethodField()
class Meta:
model = CourseSessionAssignment
fields = [
"id",
"course_session_id",
"learning_content_id",
"submission_deadline_id",
"submission_deadline_end",
"evaluation_deadline_id",
"evaluation_deadline_end",
]
def get_evaluation_deadline_end(self, obj):
if obj.evaluation_deadline:
return obj.evaluation_deadline.end
def get_submission_deadline_end(self, obj):
if obj.submission_deadline:
return obj.submission_deadline.end