Merge branch 'feature/feedback-json' into develop
This commit is contained in:
commit
aac1c638df
|
|
@ -157,12 +157,9 @@ const MAX_STEPS = 12;
|
|||
const sendFeedbackMutation = graphql(`
|
||||
mutation SendFeedbackMutation($input: SendFeedbackInput!) {
|
||||
sendFeedback(input: $input) {
|
||||
id
|
||||
satisfaction
|
||||
goalAttainment
|
||||
proficiency
|
||||
receivedMaterials
|
||||
materialsRating
|
||||
feedbackResponse {
|
||||
id
|
||||
}
|
||||
errors {
|
||||
field
|
||||
messages
|
||||
|
|
@ -205,17 +202,19 @@ const sendFeedback = () => {
|
|||
return;
|
||||
}
|
||||
const input: SendFeedbackInput = reactive({
|
||||
materialsRating,
|
||||
courseNegativeFeedback,
|
||||
coursePositiveFeedback,
|
||||
goalAttainment,
|
||||
instructorCompetence,
|
||||
instructorRespect,
|
||||
instructorOpenFeedback,
|
||||
satisfaction,
|
||||
proficiency,
|
||||
receivedMaterials,
|
||||
wouldRecommend,
|
||||
data: {
|
||||
materials_rating: materialsRating,
|
||||
course_negative_feedback: courseNegativeFeedback,
|
||||
course_positive_feedback: coursePositiveFeedback,
|
||||
goald_attainment: goalAttainment,
|
||||
instructor_competence: instructorCompetence,
|
||||
instructor_respect: instructorRespect,
|
||||
instructor_open_feedback: instructorOpenFeedback,
|
||||
satisfaction,
|
||||
proficiency,
|
||||
received_materials: receivedMaterials,
|
||||
would_recommend: wouldRecommend,
|
||||
},
|
||||
page: props.page.translation_key,
|
||||
courseSession: courseSession.id,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-
|
|||
import * as types from "./graphql";
|
||||
|
||||
const documents = {
|
||||
"\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n id\n satisfaction\n goalAttainment\n proficiency\n receivedMaterials\n materialsRating\n errors {\n field\n messages\n }\n }\n }\n":
|
||||
"\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n feedbackResponse {\n id\n }\n errors {\n field\n messages\n }\n }\n }\n":
|
||||
types.SendFeedbackMutationDocument,
|
||||
};
|
||||
|
||||
export function graphql(
|
||||
source: "\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n id\n satisfaction\n goalAttainment\n proficiency\n receivedMaterials\n materialsRating\n errors {\n field\n messages\n }\n }\n }\n"
|
||||
): typeof documents["\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n id\n satisfaction\n goalAttainment\n proficiency\n receivedMaterials\n materialsRating\n errors {\n field\n messages\n }\n }\n }\n"];
|
||||
source: "\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n feedbackResponse {\n id\n }\n errors {\n field\n messages\n }\n }\n }\n"
|
||||
): typeof documents["\n mutation SendFeedbackMutation($input: SendFeedbackInput!) {\n sendFeedback(input: $input) {\n feedbackResponse {\n id\n }\n errors {\n field\n messages\n }\n }\n }\n"];
|
||||
|
||||
export function graphql(source: string): unknown;
|
||||
export function graphql(source: string) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ export type Scalars = {
|
|||
Int: number;
|
||||
Float: number;
|
||||
DateTime: any;
|
||||
GenericScalar: any;
|
||||
JSONString: any;
|
||||
PositiveInt: any;
|
||||
UUID: any;
|
||||
|
|
@ -152,6 +153,11 @@ export type CircleSiblingsArgs = {
|
|||
searchQuery?: InputMaybe<Scalars["String"]>;
|
||||
};
|
||||
|
||||
export type CircleDocument = {
|
||||
__typename?: "CircleDocument";
|
||||
id?: Maybe<Scalars["ID"]>;
|
||||
};
|
||||
|
||||
export type CollectionObjectType = {
|
||||
__typename?: "CollectionObjectType";
|
||||
ancestors: Array<Maybe<CollectionObjectType>>;
|
||||
|
|
@ -520,6 +526,14 @@ export type ErrorType = {
|
|||
messages: Array<Scalars["String"]>;
|
||||
};
|
||||
|
||||
export type FeedbackResponse = Node & {
|
||||
__typename?: "FeedbackResponse";
|
||||
circle: Circle;
|
||||
courseSession: CourseSession;
|
||||
data?: Maybe<Scalars["GenericScalar"]>;
|
||||
id: Scalars["ID"];
|
||||
};
|
||||
|
||||
export type FloatBlock = StreamFieldInterface & {
|
||||
__typename?: "FloatBlock";
|
||||
blockType: Scalars["String"];
|
||||
|
|
@ -1170,6 +1184,10 @@ export type MutationSendFeedbackArgs = {
|
|||
input: SendFeedbackInput;
|
||||
};
|
||||
|
||||
export type Node = {
|
||||
id: Scalars["ID"];
|
||||
};
|
||||
|
||||
export type Page = PageInterface & {
|
||||
__typename?: "Page";
|
||||
aliasOf?: Maybe<Page>;
|
||||
|
|
@ -1581,6 +1599,7 @@ export type RichTextBlock = StreamFieldInterface & {
|
|||
|
||||
export type Search =
|
||||
| Circle
|
||||
| CircleDocument
|
||||
| CompetencePage
|
||||
| CompetenceProfilePage
|
||||
| Course
|
||||
|
|
@ -1609,37 +1628,16 @@ export type SecurityRequestResponseLog = {
|
|||
|
||||
export type SendFeedbackInput = {
|
||||
clientMutationId?: InputMaybe<Scalars["String"]>;
|
||||
courseNegativeFeedback?: InputMaybe<Scalars["String"]>;
|
||||
coursePositiveFeedback?: InputMaybe<Scalars["String"]>;
|
||||
goalAttainment?: InputMaybe<Scalars["Int"]>;
|
||||
id?: InputMaybe<Scalars["Int"]>;
|
||||
instructorCompetence?: InputMaybe<Scalars["Int"]>;
|
||||
instructorOpenFeedback?: InputMaybe<Scalars["String"]>;
|
||||
instructorRespect?: InputMaybe<Scalars["Int"]>;
|
||||
materialsRating?: InputMaybe<Scalars["Int"]>;
|
||||
courseSession: Scalars["Int"];
|
||||
data?: InputMaybe<Scalars["GenericScalar"]>;
|
||||
page: Scalars["String"];
|
||||
proficiency?: InputMaybe<Scalars["Int"]>;
|
||||
receivedMaterials?: InputMaybe<Scalars["Boolean"]>;
|
||||
satisfaction?: InputMaybe<Scalars["Int"]>;
|
||||
wouldRecommend?: InputMaybe<Scalars["Boolean"]>;
|
||||
};
|
||||
|
||||
export type SendFeedbackPayload = {
|
||||
__typename?: "SendFeedbackPayload";
|
||||
clientMutationId?: Maybe<Scalars["String"]>;
|
||||
courseNegativeFeedback?: Maybe<Scalars["String"]>;
|
||||
coursePositiveFeedback?: Maybe<Scalars["String"]>;
|
||||
errors?: Maybe<Array<Maybe<ErrorType>>>;
|
||||
goalAttainment?: Maybe<Scalars["Int"]>;
|
||||
id?: Maybe<Scalars["Int"]>;
|
||||
instructorCompetence?: Maybe<Scalars["Int"]>;
|
||||
instructorOpenFeedback?: Maybe<Scalars["String"]>;
|
||||
instructorRespect?: Maybe<Scalars["Int"]>;
|
||||
materialsRating?: Maybe<Scalars["Int"]>;
|
||||
proficiency?: Maybe<Scalars["Int"]>;
|
||||
receivedMaterials?: Maybe<Scalars["Boolean"]>;
|
||||
satisfaction?: Maybe<Scalars["Int"]>;
|
||||
wouldRecommend?: Maybe<Scalars["Boolean"]>;
|
||||
feedbackResponse?: Maybe<FeedbackResponse>;
|
||||
};
|
||||
|
||||
export type SiteObjectType = {
|
||||
|
|
@ -1851,12 +1849,7 @@ export type SendFeedbackMutationMutation = {
|
|||
__typename?: "Mutation";
|
||||
sendFeedback?: {
|
||||
__typename?: "SendFeedbackPayload";
|
||||
id?: number | null;
|
||||
satisfaction?: number | null;
|
||||
goalAttainment?: number | null;
|
||||
proficiency?: number | null;
|
||||
receivedMaterials?: boolean | null;
|
||||
materialsRating?: number | null;
|
||||
feedbackResponse?: { __typename?: "FeedbackResponse"; id: string } | null;
|
||||
errors?: Array<{
|
||||
__typename?: "ErrorType";
|
||||
field: string;
|
||||
|
|
@ -1901,12 +1894,16 @@ export const SendFeedbackMutationDocument = {
|
|||
selectionSet: {
|
||||
kind: "SelectionSet",
|
||||
selections: [
|
||||
{ kind: "Field", name: { kind: "Name", value: "id" } },
|
||||
{ kind: "Field", name: { kind: "Name", value: "satisfaction" } },
|
||||
{ kind: "Field", name: { kind: "Name", value: "goalAttainment" } },
|
||||
{ kind: "Field", name: { kind: "Name", value: "proficiency" } },
|
||||
{ kind: "Field", name: { kind: "Name", value: "receivedMaterials" } },
|
||||
{ kind: "Field", name: { kind: "Name", value: "materialsRating" } },
|
||||
{
|
||||
kind: "Field",
|
||||
name: { kind: "Name", value: "feedbackResponse" },
|
||||
selectionSet: {
|
||||
kind: "SelectionSet",
|
||||
selections: [
|
||||
{ kind: "Field", name: { kind: "Name", value: "id" } },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "Field",
|
||||
name: { kind: "Name", value: "errors" },
|
||||
|
|
|
|||
|
|
@ -79,6 +79,10 @@ type Circle implements PageInterface {
|
|||
ancestors(limit: PositiveInt, offset: PositiveInt, order: String, searchQuery: String, id: ID): [PageInterface!]!
|
||||
}
|
||||
|
||||
type CircleDocument {
|
||||
id: ID
|
||||
}
|
||||
|
||||
type CollectionObjectType {
|
||||
id: ID!
|
||||
path: String!
|
||||
|
|
@ -281,6 +285,13 @@ type ErrorType {
|
|||
messages: [String!]!
|
||||
}
|
||||
|
||||
type FeedbackResponse implements Node {
|
||||
id: ID!
|
||||
data: GenericScalar
|
||||
circle: Circle!
|
||||
courseSession: CourseSession!
|
||||
}
|
||||
|
||||
type FloatBlock implements StreamFieldInterface {
|
||||
id: String
|
||||
blockType: String!
|
||||
|
|
@ -289,6 +300,8 @@ type FloatBlock implements StreamFieldInterface {
|
|||
value: Float!
|
||||
}
|
||||
|
||||
scalar GenericScalar
|
||||
|
||||
type ImageChooserBlock implements StreamFieldInterface {
|
||||
id: String
|
||||
blockType: String!
|
||||
|
|
@ -608,6 +621,10 @@ type Mutation {
|
|||
sendFeedback(input: SendFeedbackInput!): SendFeedbackPayload
|
||||
}
|
||||
|
||||
interface Node {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Page implements PageInterface {
|
||||
id: ID
|
||||
path: String!
|
||||
|
|
@ -783,42 +800,21 @@ type RichTextBlock implements StreamFieldInterface {
|
|||
value: String!
|
||||
}
|
||||
|
||||
union Search = CoursePage | LearningPath | Topic | Circle | LearningSequence | LearningUnit | LearningContent | CompetenceProfilePage | CompetencePage | PerformanceCriteria | MediaLibraryPage | MediaCategoryPage | Page | LibraryDocument | User | SecurityRequestResponseLog | Course | CourseCategory | CourseCompletion | CourseSession | CourseSessionUser
|
||||
union Search = CoursePage | LearningPath | Topic | Circle | LearningSequence | LearningUnit | LearningContent | CompetenceProfilePage | CompetencePage | PerformanceCriteria | MediaLibraryPage | MediaCategoryPage | Page | LibraryDocument | User | SecurityRequestResponseLog | Course | CourseCategory | CourseCompletion | CourseSession | CourseSessionUser | CircleDocument
|
||||
|
||||
type SecurityRequestResponseLog {
|
||||
id: ID
|
||||
}
|
||||
|
||||
input SendFeedbackInput {
|
||||
id: Int
|
||||
page: String!
|
||||
satisfaction: Int
|
||||
goalAttainment: Int
|
||||
proficiency: Int
|
||||
receivedMaterials: Boolean
|
||||
materialsRating: Int
|
||||
instructorCompetence: Int
|
||||
instructorRespect: Int
|
||||
instructorOpenFeedback: String
|
||||
wouldRecommend: Boolean
|
||||
coursePositiveFeedback: String
|
||||
courseNegativeFeedback: String
|
||||
courseSession: Int!
|
||||
data: GenericScalar
|
||||
clientMutationId: String
|
||||
}
|
||||
|
||||
type SendFeedbackPayload {
|
||||
id: Int
|
||||
satisfaction: Int
|
||||
goalAttainment: Int
|
||||
proficiency: Int
|
||||
receivedMaterials: Boolean
|
||||
materialsRating: Int
|
||||
instructorCompetence: Int
|
||||
instructorRespect: Int
|
||||
instructorOpenFeedback: String
|
||||
wouldRecommend: Boolean
|
||||
coursePositiveFeedback: String
|
||||
courseNegativeFeedback: String
|
||||
feedbackResponse: FeedbackResponse
|
||||
errors: [ErrorType]
|
||||
clientMutationId: String
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from factory import Dict
|
||||
from factory.django import DjangoModelFactory
|
||||
from factory.fuzzy import FuzzyChoice, FuzzyInteger
|
||||
|
||||
|
|
@ -5,33 +6,37 @@ from vbv_lernwelt.feedback.models import FeedbackResponse
|
|||
|
||||
|
||||
class FeedbackFactory(DjangoModelFactory):
|
||||
data = Dict(
|
||||
{
|
||||
"satisfaction": FuzzyInteger(2, 4),
|
||||
"goal_attainment": FuzzyInteger(3, 4),
|
||||
"proficiency": FuzzyChoice([20, 40, 60, 80]),
|
||||
"received_materials": FuzzyChoice([True, False]),
|
||||
"materials_rating": FuzzyInteger(2, 4),
|
||||
"instructor_competence": FuzzyInteger(3, 4),
|
||||
"instructor_respect": FuzzyInteger(3, 4),
|
||||
"instructor_open_feedback": FuzzyChoice(
|
||||
[
|
||||
"Alles gut, manchmal etwas langfädig",
|
||||
"Super, bin begeistert",
|
||||
"Ok, enspricht den Erwartungen",
|
||||
]
|
||||
),
|
||||
"would_recommend": FuzzyChoice([True, False]),
|
||||
"course_positive_feedback": FuzzyChoice(
|
||||
[
|
||||
"Die Präsentation war super",
|
||||
"Das Beispiel mit der Katze fand ich sehr gut veranschaulicht!",
|
||||
]
|
||||
),
|
||||
"course_negative_feedback": FuzzyChoice(
|
||||
[
|
||||
"Es wäre praktisch, Zugang zu einer FAQ zu haben.",
|
||||
"Es wäre schön, mehr Videos hinzuzufügen.",
|
||||
]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = FeedbackResponse
|
||||
|
||||
satisfaction = FuzzyInteger(2, 4)
|
||||
goal_attainment = FuzzyInteger(3, 4)
|
||||
proficiency = FuzzyChoice([20, 40, 60, 80])
|
||||
received_materials = FuzzyChoice([True, False])
|
||||
materials_rating = FuzzyInteger(2, 4)
|
||||
instructor_competence = FuzzyInteger(3, 4)
|
||||
instructor_respect = FuzzyInteger(3, 4)
|
||||
instructor_open_feedback = FuzzyChoice(
|
||||
[
|
||||
"Alles gut, manchmal etwas langfädig",
|
||||
"Super, bin begeistert",
|
||||
"Ok, enspricht den Erwartungen",
|
||||
]
|
||||
)
|
||||
would_recommend = FuzzyChoice([True, False])
|
||||
course_positive_feedback = FuzzyChoice(
|
||||
[
|
||||
"Die Präsentation war super",
|
||||
"Das Beispiel mit der Katze fand ich sehr gut veranschaulicht!",
|
||||
]
|
||||
)
|
||||
course_negative_feedback = FuzzyChoice(
|
||||
[
|
||||
"Es wäre praktisch, Zugang zu einer FAQ zu haben.",
|
||||
"Es wäre schön, mehr Videos hinzuzufügen.",
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,56 @@
|
|||
import graphene
|
||||
from graphene_django.rest_framework.mutation import SerializerMutation
|
||||
import structlog
|
||||
from graphene import ClientIDMutation, Field, Int, List, String
|
||||
from graphene.types.generic import GenericScalar
|
||||
from graphene_django.types import ErrorType
|
||||
|
||||
from vbv_lernwelt.feedback.serializers import FeedbackResponseSerializer
|
||||
from vbv_lernwelt.course.models import CourseSession
|
||||
from vbv_lernwelt.feedback.graphql.types import FeedbackResponse as FeedbackResponseType
|
||||
from vbv_lernwelt.feedback.models import FeedbackResponse
|
||||
from vbv_lernwelt.feedback.serializers import CourseFeedbackSerializer
|
||||
from wagtail.models import Page
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class SendFeedback(SerializerMutation):
|
||||
class Meta:
|
||||
serializer_class = FeedbackResponseSerializer
|
||||
model_operations = ["create"]
|
||||
# https://medium.com/open-graphql/jsonfield-models-in-graphene-django-308ae43d14ee
|
||||
class SendFeedback(ClientIDMutation):
|
||||
feedback_response = Field(FeedbackResponseType)
|
||||
errors = List(
|
||||
ErrorType, description="May contain more than one error for same field."
|
||||
)
|
||||
|
||||
class Input:
|
||||
page = String(required=True)
|
||||
course_session = Int(required=True)
|
||||
data = GenericScalar()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, _, info, **input):
|
||||
page_key = input["page"]
|
||||
course_session_id = input["course_session"]
|
||||
logger.info("creating feedback")
|
||||
|
||||
learning_content = Page.objects.get(
|
||||
translation_key=page_key, locale__language_code="de-CH"
|
||||
)
|
||||
circle = learning_content.get_parent().specific
|
||||
course_session = CourseSession.objects.get(id=course_session_id)
|
||||
data = input.get("data", {})
|
||||
|
||||
serializer = CourseFeedbackSerializer(data=data)
|
||||
|
||||
if not serializer.is_valid():
|
||||
logger.error(serializer.errors)
|
||||
return SendFeedback(errors=serializer.errors)
|
||||
|
||||
feedback_response = FeedbackResponse.objects.create(
|
||||
circle=circle,
|
||||
course_session=course_session,
|
||||
data=serializer.validated_data,
|
||||
)
|
||||
logger.info(feedback_response)
|
||||
|
||||
return SendFeedback(feedback_response=feedback_response)
|
||||
|
||||
|
||||
class Mutation(object):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
from graphene.relay import Node
|
||||
from graphene.types.generic import GenericScalar
|
||||
from graphene_django import DjangoObjectType
|
||||
|
||||
from vbv_lernwelt.feedback.models import Feedback
|
||||
from vbv_lernwelt.feedback.models import FeedbackResponse as FeedbackResponseModel
|
||||
|
||||
|
||||
# class FeedbackType(DjangoObjectType):
|
||||
# class Meta:
|
||||
# model = Feedback
|
||||
class FeedbackResponse(DjangoObjectType):
|
||||
data = GenericScalar()
|
||||
|
||||
class Meta:
|
||||
model = FeedbackResponseModel
|
||||
interfaces = (Node,)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
# Generated by Django 3.2.13 on 2023-02-06 10:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("feedback", "0002_auto_20230111_1044"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="course_negative_feedback",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="course_positive_feedback",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="goal_attainment",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="instructor_competence",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="instructor_open_feedback",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="instructor_respect",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="materials_rating",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="proficiency",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="received_materials",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="satisfaction",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="feedbackresponse",
|
||||
name="would_recommend",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="feedbackresponse",
|
||||
name="data",
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="feedbackresponse",
|
||||
name="created_at",
|
||||
field=models.DateTimeField(auto_now_add=True),
|
||||
),
|
||||
]
|
||||
|
|
@ -37,17 +37,20 @@ class FeedbackResponse(models.Model):
|
|||
EIGHTY = 80, "80%"
|
||||
HUNDRED = 100, "100%"
|
||||
|
||||
satisfaction = FeedbackIntegerField()
|
||||
goal_attainment = FeedbackIntegerField()
|
||||
proficiency = models.IntegerField(null=True)
|
||||
received_materials = models.BooleanField(null=True)
|
||||
materials_rating = FeedbackIntegerField()
|
||||
instructor_competence = FeedbackIntegerField()
|
||||
instructor_respect = FeedbackIntegerField()
|
||||
instructor_open_feedback = models.TextField(blank=True)
|
||||
would_recommend = models.BooleanField(null=True)
|
||||
course_positive_feedback = models.TextField(blank=True)
|
||||
course_negative_feedback = models.TextField(blank=True)
|
||||
# satisfaction = FeedbackIntegerField()
|
||||
# goal_attainment = FeedbackIntegerField()
|
||||
# proficiency = models.IntegerField(null=True)
|
||||
# received_materials = models.BooleanField(null=True)
|
||||
# materials_rating = FeedbackIntegerField()
|
||||
# instructor_competence = FeedbackIntegerField()
|
||||
# instructor_respect = FeedbackIntegerField()
|
||||
# instructor_open_feedback = models.TextField(blank=True)
|
||||
# would_recommend = models.BooleanField(null=True)
|
||||
# course_positive_feedback = models.TextField(blank=True)
|
||||
# course_negative_feedback = models.TextField(blank=True)
|
||||
|
||||
data = models.JSONField(default=dict)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
circle = models.ForeignKey("learnpath.Circle", models.PROTECT)
|
||||
course_session = models.ForeignKey("course.CourseSession", models.PROTECT)
|
||||
|
|
|
|||
|
|
@ -1,32 +1,31 @@
|
|||
import structlog
|
||||
from rest_framework import serializers
|
||||
from wagtail.models import Page
|
||||
|
||||
from vbv_lernwelt.course.models import CourseSession
|
||||
from vbv_lernwelt.feedback.models import FeedbackResponse
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
class FeedbackResponseSerializer(serializers.ModelSerializer):
|
||||
page = serializers.CharField(write_only=True)
|
||||
course_session = serializers.CharField(write_only=True)
|
||||
|
||||
class Meta:
|
||||
model = FeedbackResponse
|
||||
exclude = ["circle"]
|
||||
# extra_kwargs = {"course", {"read_only": True}}
|
||||
|
||||
def create(self, validated_data):
|
||||
logger.info("creating feedback")
|
||||
page_key = validated_data.pop("page")
|
||||
course_session_id = validated_data.pop("course_session")
|
||||
|
||||
learning_content = Page.objects.get(
|
||||
translation_key=page_key, locale__language_code="de-CH"
|
||||
)
|
||||
circle = learning_content.get_parent().specific
|
||||
course_session = CourseSession.objects.get(id=course_session_id)
|
||||
return FeedbackResponse.objects.create(
|
||||
**validated_data, circle=circle, course_session=course_session
|
||||
class FeedbackIntegerField(serializers.IntegerField):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(
|
||||
required=False, allow_null=True, min_value=1, max_value=5, **kwargs
|
||||
)
|
||||
|
||||
|
||||
class CourseFeedbackSerializer(serializers.Serializer):
|
||||
satisfaction = FeedbackIntegerField()
|
||||
goal_attainment = FeedbackIntegerField()
|
||||
proficiency = serializers.IntegerField(required=False, allow_null=True)
|
||||
received_materials = serializers.BooleanField(required=False, allow_null=True)
|
||||
materials_rating = FeedbackIntegerField()
|
||||
instructor_competence = FeedbackIntegerField()
|
||||
instructor_respect = FeedbackIntegerField()
|
||||
instructor_open_feedback = serializers.CharField(
|
||||
required=False, allow_null=True, allow_blank=True
|
||||
)
|
||||
would_recommend = serializers.BooleanField(required=False, allow_null=True)
|
||||
course_positive_feedback = serializers.CharField(
|
||||
required=False, allow_null=True, allow_blank=True
|
||||
)
|
||||
course_negative_feedback = serializers.CharField(
|
||||
required=False, allow_null=True, allow_blank=True
|
||||
)
|
||||
|
|
|
|||
|
|
@ -159,17 +159,25 @@ class FeedbackDetailApiTestCase(FeedbackApiBaseTestCase):
|
|||
FeedbackFactory(
|
||||
circle=circle,
|
||||
course_session=csu.course_session,
|
||||
satisfaction=feedback_data["satisfaction"][i],
|
||||
goal_attainment=feedback_data["goal_attainment"][i],
|
||||
proficiency=feedback_data["proficiency"][i],
|
||||
received_materials=feedback_data["received_materials"][i],
|
||||
materials_rating=feedback_data["materials_rating"][i],
|
||||
instructor_competence=feedback_data["instructor_competence"][i],
|
||||
instructor_open_feedback=feedback_data["instructor_open_feedback"][i],
|
||||
instructor_respect=feedback_data["instructor_respect"][i],
|
||||
would_recommend=feedback_data["would_recommend"][i],
|
||||
course_positive_feedback=feedback_data["course_positive_feedback"][i],
|
||||
course_negative_feedback=feedback_data["course_negative_feedback"][i],
|
||||
data={
|
||||
"satisfaction": feedback_data["satisfaction"][i],
|
||||
"goal_attainment": feedback_data["goal_attainment"][i],
|
||||
"proficiency": feedback_data["proficiency"][i],
|
||||
"received_materials": feedback_data["received_materials"][i],
|
||||
"materials_rating": feedback_data["materials_rating"][i],
|
||||
"instructor_competence": feedback_data["instructor_competence"][i],
|
||||
"instructor_open_feedback": feedback_data[
|
||||
"instructor_open_feedback"
|
||||
][i],
|
||||
"instructor_respect": feedback_data["instructor_respect"][i],
|
||||
"would_recommend": feedback_data["would_recommend"][i],
|
||||
"course_positive_feedback": feedback_data[
|
||||
"course_positive_feedback"
|
||||
][i],
|
||||
"course_negative_feedback": feedback_data[
|
||||
"course_negative_feedback"
|
||||
][i],
|
||||
},
|
||||
).save()
|
||||
|
||||
response = self.client.get(
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ def get_feedback_for_circle(request, course_id, circle_id):
|
|||
course_session__course_id=course_id,
|
||||
circle__expert__user=request.user,
|
||||
circle_id=circle_id,
|
||||
)
|
||||
).order_by("created_at")
|
||||
|
||||
# I guess this is ok for the üK case
|
||||
feedback_data = {"amount": len(feedbacks), "questions": {}}
|
||||
|
|
@ -62,6 +62,8 @@ def get_feedback_for_circle(request, course_id, circle_id):
|
|||
|
||||
for feedback in feedbacks:
|
||||
for field in FEEDBACK_FIELDS:
|
||||
feedback_data["questions"][field].append(getattr(feedback, field))
|
||||
data = feedback.data.get(field, None)
|
||||
if data is not None:
|
||||
feedback_data["questions"][field].append(data)
|
||||
|
||||
return Response(status=200, data=feedback_data)
|
||||
|
|
|
|||
Loading…
Reference in New Issue