VBV-525: Feedback can only be sent once per person

This commit is contained in:
Daniel Egger 2023-09-22 12:07:25 +02:00
parent 70655935b0
commit 733063399f
12 changed files with 144 additions and 38 deletions

View File

@ -20,7 +20,7 @@ const documents = {
"\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n }\n assignment_user {\n id\n }\n evaluation_grade\n evaluation_points\n completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
"\n query courseQuery($courseId: Int!) {\n course(id: $courseId) {\n id\n slug\n title\n category_name\n learning_path {\n id\n }\n }\n }\n": types.CourseQueryDocument,
"\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n }\n learning_content {\n title\n id\n slug\n content_type\n frontend_url\n circle {\n ...CoursePageFields\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateQueryDocument,
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n ) {\n feedback_response {\n id\n data\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
};
/**
@ -68,7 +68,7 @@ export function graphql(source: "\n query competenceCertificateQuery($courseSlu
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n ) {\n feedback_response {\n id\n data\n }\n errors {\n field\n messages\n }\n }\n }\n"): (typeof documents)["\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n ) {\n feedback_response {\n id\n data\n }\n errors {\n field\n messages\n }\n }\n }\n"];
export function graphql(source: "\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n"): (typeof documents)["\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n"];
export function graphql(source: string) {
return (documents as any)[source] ?? {};

View File

@ -274,6 +274,7 @@ export type FeedbackResponseObjectType = {
__typename?: 'FeedbackResponseObjectType';
data?: Maybe<Scalars['GenericScalar']['output']>;
id: Scalars['UUID']['output'];
submitted: Scalars['Boolean']['output'];
};
export type LearningContentAssignmentObjectType = LearningContentInterface & {
@ -544,6 +545,7 @@ export type MutationSendFeedbackArgs = {
course_session_id: Scalars['ID']['input'];
data?: InputMaybe<Scalars['GenericScalar']['input']>;
learning_content_page_id: Scalars['ID']['input'];
submitted?: InputMaybe<Scalars['Boolean']['input']>;
};
@ -792,11 +794,12 @@ export type CompetenceCertificateQueryQuery = { __typename?: 'Query', competence
export type SendFeedbackMutationMutationVariables = Exact<{
courseSessionId: Scalars['ID']['input'];
learningContentId: Scalars['ID']['input'];
data?: InputMaybe<Scalars['GenericScalar']['input']>;
data: Scalars['GenericScalar']['input'];
submitted?: InputMaybe<Scalars['Boolean']['input']>;
}>;
export type SendFeedbackMutationMutation = { __typename?: 'Mutation', send_feedback?: { __typename?: 'SendFeedbackMutation', feedback_response?: { __typename?: 'FeedbackResponseObjectType', id: any, data?: any | null } | null, errors?: Array<{ __typename?: 'ErrorType', field: string, messages: Array<string> } | null> | null } | null };
export type SendFeedbackMutationMutation = { __typename?: 'Mutation', send_feedback?: { __typename?: 'SendFeedbackMutation', feedback_response?: { __typename?: 'FeedbackResponseObjectType', id: any, data?: any | null, submitted: boolean } | null, errors?: Array<{ __typename?: 'ErrorType', field: string, messages: Array<string> } | null> | null } | null };
export const CoursePageFieldsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode<CoursePageFieldsFragment, unknown>;
export const AttendanceCheckMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AttendanceCheckMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AttendanceUserInputType"}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update_course_session_attendance_course_users"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceCourseId"}}},{"kind":"Argument","name":{"kind":"Name","value":"attendance_user_list"},"value":{"kind":"Variable","name":{"kind":"Name","value":"attendanceUserList"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course_session_attendance_course"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"attendance_user_list"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user_id"}},{"kind":"Field","name":{"kind":"Name","value":"first_name"}},{"kind":"Field","name":{"kind":"Name","value":"last_name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"status"}}]}}]}}]}}]}}]} as unknown as DocumentNode<AttendanceCheckMutationMutation, AttendanceCheckMutationMutationVariables>;
@ -805,4 +808,4 @@ export const AttendanceCheckQueryDocument = {"kind":"Document","definitions":[{"
export const AssignmentCompletionQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"assignmentCompletionQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"effort_required"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_description"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_document_url"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_tasks"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"intro_text"}},{"kind":"Field","name":{"kind":"Name","value":"performance_objectives"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"tasks"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"translation_key"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificate"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"assignment_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"assignment_user_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"assignmentUserId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"assignment_user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_grade"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}},{"kind":"Field","name":{"kind":"Name","value":"completion_data"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode<AssignmentCompletionQueryQuery, AssignmentCompletionQueryQueryVariables>;
export const CourseQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"courseQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"course"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"category_name"}},{"kind":"Field","name":{"kind":"Name","value":"learning_path"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode<CourseQueryQuery, CourseQueryQueryVariables>;
export const CompetenceCertificateQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"competenceCertificateQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"competence_certificate_list"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSlug"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"competence_certificates"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignments"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}},{"kind":"Field","name":{"kind":"Name","value":"assignment_type"}},{"kind":"Field","name":{"kind":"Name","value":"max_points"}},{"kind":"Field","name":{"kind":"Name","value":"completion"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"completion_status"}},{"kind":"Field","name":{"kind":"Name","value":"submitted_at"}},{"kind":"Field","name":{"kind":"Name","value":"evaluation_points"}}]}},{"kind":"Field","name":{"kind":"Name","value":"learning_content"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}},{"kind":"Field","name":{"kind":"Name","value":"circle"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"CoursePageFields"}}]}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"CoursePageFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"CoursePageInterface"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"content_type"}},{"kind":"Field","name":{"kind":"Name","value":"frontend_url"}}]}}]} as unknown as DocumentNode<CompetenceCertificateQueryQuery, CompetenceCertificateQueryQueryVariables>;
export const SendFeedbackMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SendFeedbackMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"GenericScalar"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"send_feedback"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"feedback_response"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"field"}},{"kind":"Field","name":{"kind":"Name","value":"messages"}}]}}]}}]}}]} as unknown as DocumentNode<SendFeedbackMutationMutation, SendFeedbackMutationMutationVariables>;
export const SendFeedbackMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SendFeedbackMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"data"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GenericScalar"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"submitted"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"send_feedback"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"course_session_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"courseSessionId"}}},{"kind":"Argument","name":{"kind":"Name","value":"learning_content_page_id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"learningContentId"}}},{"kind":"Argument","name":{"kind":"Name","value":"data"},"value":{"kind":"Variable","name":{"kind":"Name","value":"data"}}},{"kind":"Argument","name":{"kind":"Name","value":"submitted"},"value":{"kind":"Variable","name":{"kind":"Name","value":"submitted"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"feedback_response"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"data"}},{"kind":"Field","name":{"kind":"Name","value":"submitted"}}]}},{"kind":"Field","name":{"kind":"Name","value":"errors"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"field"}},{"kind":"Field","name":{"kind":"Name","value":"messages"}}]}}]}}]}}]} as unknown as DocumentNode<SendFeedbackMutationMutation, SendFeedbackMutationMutationVariables>;

View File

@ -546,7 +546,7 @@ type CompetenceCertificateListObjectType implements CoursePageInterface {
}
type Mutation {
send_feedback(course_session_id: ID!, data: GenericScalar, learning_content_page_id: ID!): SendFeedbackMutation
send_feedback(course_session_id: ID!, data: GenericScalar, learning_content_page_id: ID!, submitted: Boolean = false): SendFeedbackMutation
update_course_session_attendance_course_users(attendance_user_list: [AttendanceUserInputType]!, id: ID!): AttendanceCourseUserMutation
upsert_assignment_completion(assignment_id: ID!, assignment_user_id: UUID, completion_data_string: String, completion_status: AssignmentCompletionStatus, course_session_id: ID!, evaluation_grade: Float, evaluation_points: Float, initialize_completion: Boolean, learning_content_page_id: ID): AssignmentCompletionMutation
}
@ -561,6 +561,7 @@ type SendFeedbackMutation {
type FeedbackResponseObjectType {
id: UUID!
data: GenericScalar
submitted: Boolean!
}
type ErrorType {

View File

@ -55,16 +55,19 @@ const sendFeedbackMutation = graphql(`
mutation SendFeedbackMutation(
$courseSessionId: ID!
$learningContentId: ID!
$data: GenericScalar
$data: GenericScalar!
$submitted: Boolean
) {
send_feedback(
course_session_id: $courseSessionId
learning_content_page_id: $learningContentId
data: $data
submitted: $submitted
) {
feedback_response {
id
data
submitted
}
errors {
field
@ -74,6 +77,8 @@ const sendFeedbackMutation = graphql(`
}
`);
const feedbackSubmitted = ref(false);
const { executeMutation } = useMutation(sendFeedbackMutation);
const feedbackData = reactive({
@ -139,8 +144,6 @@ const questionData = [
},
];
const mutationResult = ref<any>(null);
const previousStep = () => {
if (stepNo.value > 0) {
stepNo.value -= 1;
@ -152,28 +155,42 @@ const nextStep = () => {
stepNo.value += 1;
}
log.debug(`next step ${stepNo.value} of ${numSteps}`);
mutateFeedback();
mutateFeedback(feedbackData);
};
function hasStepValidInput(stepNumber: number) {
const question = questionData[stepNumber - 1];
if (question) {
return Boolean(feedbackData[question.modelKey]);
return feedbackData[question.modelKey] !== null;
}
return true;
}
function mutateFeedback() {
function mutateFeedback(data, submit = false) {
log.debug("mutate feedback", feedbackData);
executeMutation({
return executeMutation({
courseSessionId: courseSession.value.id.toString(),
learningContentId: props.content.id.toString(),
data: feedbackData,
data: data,
submitted: submit,
})
.then((result) => {
log.debug("feedback mutation result", result);
if (result.data?.send_feedback?.feedback_response?.data) {
Object.assign(feedbackData, result.data.send_feedback.feedback_response.data);
const responseData = result.data.send_feedback.feedback_response.data;
if (!responseData.instructor_open_feedback) {
responseData.instructor_open_feedback = "";
}
if (!responseData.course_negative_feedback) {
responseData.course_negative_feedback = "";
}
if (!responseData.course_positive_feedback) {
responseData.course_positive_feedback = "";
}
Object.assign(feedbackData, responseData);
log.debug("feedback data", feedbackData);
feedbackSubmitted.value =
result.data?.send_feedback?.feedback_response?.submitted || false;
}
})
.catch((e) => log.error(e));
@ -181,7 +198,10 @@ function mutateFeedback() {
onMounted(async () => {
log.debug("Feedback mounted");
mutateFeedback();
await mutateFeedback({});
if (feedbackSubmitted.value) {
stepNo.value = numSteps - 1;
}
});
</script>
@ -193,7 +213,7 @@ onMounted(async () => {
:show-start-button="stepNo === 0"
:show-next-button="stepNo > 0 && stepNo + 1 < numSteps"
:disable-next-button="!hasStepValidInput(stepNo)"
:show-previous-button="stepNo > 0"
:show-previous-button="stepNo > 0 && !feedbackSubmitted"
:show-exit-button="stepNo + 1 === numSteps"
:current-step="stepNo"
:steps-count="numSteps"
@ -232,8 +252,8 @@ onMounted(async () => {
})
"
:description="$t('feedback.completionDescription')"
:feedback-sent="mutationResult != null"
@send-feedback="sendFeedback"
:feedback-sent="feedbackSubmitted"
@send-feedback="mutateFeedback(feedbackData, true)"
/>
</div>
</LearningContentMultiLayout>

View File

@ -1,11 +1,11 @@
<template>
<div>
<h1 class="hidden lg:mb-12 lg:block">{{ title }}</h1>
<h2 class="hidden lg:mb-12 lg:block">{{ title }}</h2>
<div
class="b-0 flex flex-col lg:flex-row lg:items-center lg:border lg:border-gray-400 lg:p-8"
>
<img :src="avatarUrl" class="mb-6 h-16 w-16 rounded-full lg:mr-12" />
<h1 class="mb-8 block lg:hidden">{{ title }}</h1>
<h2 class="mb-8 block lg:hidden">{{ title }}</h2>
<div>
<p class="mb-6">{{ description }}</p>
<button v-if="!feedbackSent" class="btn-primary" @click="$emit('sendFeedback')">

View File

@ -3,8 +3,9 @@ import structlog
from graphene.types.generic import GenericScalar
from graphene_django.types import ErrorType
from vbv_lernwelt.course.models import CourseSession
from vbv_lernwelt.course.models import CourseCompletionStatus, CourseSession
from vbv_lernwelt.course.permissions import has_course_session_access
from vbv_lernwelt.course.services import mark_course_completion
from vbv_lernwelt.feedback.graphql.types import (
FeedbackResponseObjectType as FeedbackResponseType,
)
@ -26,6 +27,7 @@ class SendFeedbackMutation(graphene.Mutation):
course_session_id = graphene.ID(required=True)
learning_content_page_id = graphene.ID(required=True)
data = GenericScalar()
submitted = graphene.Boolean(required=False, default_value=False)
@classmethod
def mutate(
@ -35,6 +37,7 @@ class SendFeedbackMutation(graphene.Mutation):
course_session_id,
learning_content_page_id,
data,
submitted,
):
feedback_user_id = info.context.user.id
learning_content = LearningContentFeedback.objects.get(
@ -82,16 +85,42 @@ class SendFeedbackMutation(graphene.Mutation):
circle_id=circle.id,
course_session=course_session,
)
original_data = feedback_response.data
updated_data = serializer.validated_data
merged_data = {
key: updated_data[key] if updated_data.get(key) else original_data.get(key)
for key in updated_data.keys()
initial_data = {
"satisfaction": None,
"goal_attainment": None,
"proficiency": None,
"preparation_task_clarity": None,
"instructor_competence": None,
"instructor_respect": None,
"instructor_open_feedback": "",
"would_recommend": None,
"course_negative_feedback": "",
"course_positive_feedback": "",
}
merged_data = initial_data | {
key: updated_data[key]
if updated_data.get(key, "") != ""
else original_data.get(key)
for key in initial_data.keys()
}
feedback_response.data = merged_data
if submitted:
feedback_response.submitted = submitted
feedback_response.save()
if submitted:
mark_course_completion(
user=info.context.user,
page=learning_content,
course_session=course_session,
completion_status=CourseCompletionStatus.SUCCESS.value,
)
logger.info(
"feedback successfully created",
label="feedback",

View File

@ -11,5 +11,6 @@ class FeedbackResponseObjectType(DjangoObjectType):
model = FeedbackResponseModel
fields = [
"id",
"submitted",
"data",
]

View File

@ -1,22 +1,25 @@
# Generated by Django 3.2.20 on 2023-09-21 13:30
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('feedback', '0003_alter_feedbackresponse_course_session'),
("feedback", "0003_alter_feedbackresponse_course_session"),
]
operations = [
migrations.AddField(
model_name='feedbackresponse',
name='feedback_user',
field=models.ForeignKey(default='872efd96-3bd7-4a1e-a239-2d72cad9f604', on_delete=django.db.models.deletion.CASCADE, to='core.user'),
model_name="feedbackresponse",
name="feedback_user",
field=models.ForeignKey(
default="872efd96-3bd7-4a1e-a239-2d72cad9f604",
on_delete=django.db.models.deletion.CASCADE,
to="core.user",
),
preserve_default=False,
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 3.2.20 on 2023-09-22 09:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("feedback", "0004_feedbackresponse_feedback_user"),
]
operations = [
migrations.AddField(
model_name="feedbackresponse",
name="submitted",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="feedbackresponse",
name="notification_sent",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="feedbackresponse",
name="updated_at",
field=models.DateTimeField(auto_now=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.20 on 2023-09-22 09:31
from django.db import migrations
def set_feedback_submitted_true(apps, schema_editor):
FeedbackResponse = apps.get_model("feedback", "FeedbackResponse")
FeedbackResponse.objects.update(submitted=True)
FeedbackResponse.objects.update(notification_sent=True)
class Migration(migrations.Migration):
dependencies = [
("feedback", "0005_auto_20230922_1131"),
]
operations = [
migrations.RunPython(set_feedback_submitted_true),
]

View File

@ -49,14 +49,10 @@ class FeedbackResponse(models.Model):
HUNDRED = 100, "100%"
def save(self, *args, **kwargs):
# with `id=UUIDField` it is always set...
create_new = self._state.adding
super(FeedbackResponse, self).save(*args, **kwargs)
try:
if create_new:
# with `id=UUIDField` it is always set...
if self.submitted and not self.notification_sent:
course_session_users = CourseSessionUser.objects.filter(
role="EXPERT",
course_session=self.course_session,
@ -67,6 +63,8 @@ class FeedbackResponse(models.Model):
recipient=csu.user,
feedback_response=self,
)
self.notification_sent = True
self.save()
except Exception:
logger.exception(
"Failed to send feedback notification",
@ -76,6 +74,9 @@ class FeedbackResponse(models.Model):
data = models.JSONField(default=dict)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
submitted = models.BooleanField(default=False)
notification_sent = models.BooleanField(default=False)
circle = models.ForeignKey("learnpath.Circle", models.PROTECT)
course_session = models.ForeignKey("course.CourseSession", models.CASCADE)

View File

@ -30,7 +30,8 @@ def get_expert_feedbacks_for_course(request, course_session_id):
raise PermissionDenied()
feedbacks = FeedbackResponse.objects.filter(
course_session__id=course_session_id
course_session__id=course_session_id,
submitted=True,
).order_by("circle_id")
circle_count = []
@ -54,6 +55,7 @@ def get_feedback_for_circle(request, course_session_id, circle_id):
feedbacks = FeedbackResponse.objects.filter(
course_session__id=course_session_id,
submitted=True,
circle_id=circle_id,
).order_by("created_at")