Skip to content

Commit

Permalink
feat(form): multiple files in file questions - graphql schema changes
Browse files Browse the repository at this point in the history
The GraphQL schema is updated to allow saving and updating multiple
files on an answer. The semantics are as follows:

The answer's value is a list of dicts, each containing a file name,
and optionally an ID. When you're creating new files, add an entry without
ID to the value. Caluma will then save the file, and return it back WITH
and ID.
  • Loading branch information
winged committed Jul 1, 2022
1 parent 1bd8dee commit 10854c2
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 61 deletions.
46 changes: 33 additions & 13 deletions caluma/caluma_form/factories.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import faker
from factory import Faker, LazyAttribute, Maybe, SubFactory, lazy_attribute
from django.db.models.signals import post_save
from factory import (
Faker,
LazyAttribute,
Maybe,
SubFactory,
django,
lazy_attribute,
post_generation,
)

from ..caluma_core.factories import DjangoModelFactory
from . import models
Expand Down Expand Up @@ -141,13 +150,6 @@ class Meta:
model = models.Document


class FileFactory(DjangoModelFactory):
name = Faker("file_name")

class Meta:
model = models.File


class AnswerFactory(DjangoModelFactory):
question = SubFactory(QuestionFactory)
document = SubFactory(DocumentFactory)
Expand All @@ -166,26 +168,44 @@ def value(self):
return faker.Faker().pyint()
elif self.question.type not in [
models.Question.TYPE_TABLE,
models.Question.TYPE_FILE,
models.Question.TYPE_FILES,
models.Question.TYPE_DATE,
]:
return faker.Faker().name()

return None

file = Maybe(
"is_file", yes_declaration=SubFactory(FileFactory), no_declaration=None
)
date = Maybe("is_date", yes_declaration=Faker("date"), no_declaration=None)

@post_generation
@django.mute_signals(post_save)
def files(self, create, extracted, **kwargs):
if not create:
return
if self.question.type == models.Question.TYPE_FILES:
if extracted:
self.files.set(extracted)
else:
num_files = kwargs.pop("count", 1)
self.files.set(
FileFactory.create_batch(num_files, **kwargs, answer=self)
)

class Meta:
model = models.Answer

class Params:
is_file = LazyAttribute(lambda a: a.question.type == models.Question.TYPE_FILE)
is_date = LazyAttribute(lambda a: a.question.type == models.Question.TYPE_DATE)


class FileFactory(DjangoModelFactory):
name = Faker("file_name")
answer = SubFactory(AnswerFactory)

class Meta:
model = models.File


class AnswerDocumentFactory(DjangoModelFactory):
answer = SubFactory(AnswerFactory)
document = SubFactory(DocumentFactory)
Expand Down
14 changes: 6 additions & 8 deletions caluma/caluma_form/historical_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
QUESTION_ANSWER_TYPES,
Answer,
DateAnswer,
FileAnswer,
FilesAnswer,
FloatAnswer,
FormDjangoObjectType,
IntegerAnswer,
Expand Down Expand Up @@ -99,7 +99,7 @@ class HistoricalFile(ObjectType):
download_url = graphene.String()
metadata = generic.GenericScalar()
historical_answer = graphene.Field(
"caluma.caluma_form.historical_schema.HistoricalFileAnswer"
"caluma.caluma_form.historical_schema.HistoricalFilesAnswer"
)
history_date = graphene.types.datetime.DateTime(required=True)
history_user_id = graphene.String()
Expand All @@ -118,22 +118,20 @@ class Meta:
interfaces = (relay.Node,)


class HistoricalFileAnswer(FileAnswer):
value = graphene.Field(
class HistoricalFilesAnswer(FilesAnswer):
value = graphene.List(
HistoricalFile,
required=False,
as_of=graphene.types.datetime.DateTime(required=True),
)

def resolve_value(self, info, as_of, **args):
# we need to use the HistoricalFile of the correct revision
return models.File.history.filter(
id=self.file_id, history_date__lte=as_of
).first()
return models.File.history.filter(answer_id=self.id, history_date__lte=as_of)

class Meta:
model = models.Answer.history.model
exclude = ("document", "date")
exclude = ("document", "date", "files")
use_connection = False
interfaces = (HistoricalAnswer, graphene.Node)

Expand Down
45 changes: 26 additions & 19 deletions caluma/caluma_form/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ class Meta:
interfaces = (Question, graphene.Node)


class FileQuestion(QuestionQuerysetMixin, FormDjangoObjectType):
class FilesQuestion(QuestionQuerysetMixin, FormDjangoObjectType):
hint_text = graphene.String()

class Meta:
Expand Down Expand Up @@ -735,7 +735,7 @@ class Meta:
return_field_type = Question


class SaveFileQuestion(SaveQuestion):
class SaveFilesQuestion(SaveQuestion):
class Meta:
serializer_class = serializers.SaveFileQuestionSerializer
return_field_type = Question
Expand Down Expand Up @@ -799,7 +799,7 @@ class IntegerAnswer(AnswerQuerysetMixin, FormDjangoObjectType):

class Meta:
model = models.Answer
exclude = ("document", "documents", "file", "date")
exclude = ("document", "documents", "files", "date")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand All @@ -809,7 +809,7 @@ class FloatAnswer(AnswerQuerysetMixin, FormDjangoObjectType):

class Meta:
model = models.Answer
exclude = ("document", "documents", "file", "date")
exclude = ("document", "documents", "files", "date")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand All @@ -822,7 +822,7 @@ def resolve_value(self, info, **args):

class Meta:
model = models.Answer
exclude = ("document", "documents", "file")
exclude = ("document", "documents", "files")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand All @@ -847,7 +847,7 @@ def resolve_selected_option(self, info, **args):

class Meta:
model = models.Answer
exclude = ("document", "documents", "file", "date")
exclude = ("document", "documents", "files", "date")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand All @@ -858,7 +858,7 @@ class ListAnswer(AnswerQuerysetMixin, FormDjangoObjectType):

class Meta:
model = models.Answer
exclude = ("document", "documents", "file", "date")
exclude = ("document", "documents", "files", "date")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand Down Expand Up @@ -896,7 +896,7 @@ def resolve_value(self, info, **args):

class Meta:
model = models.Answer
exclude = ("documents", "file", "date")
exclude = ("documents", "files", "date")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand All @@ -906,23 +906,22 @@ class File(FormDjangoObjectType):
upload_url = graphene.String()
download_url = graphene.String()
metadata = generic.GenericScalar()
answer = graphene.Field("caluma.caluma_form.schema.FileAnswer")

class Meta:
model = models.File
interfaces = (relay.Node,)
fields = "__all__"


class FileAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.Field(File, required=True)
class FilesAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.List(File, required=True)

def resolve_value(self, info, **args):
return self.file
return self.files.all()

class Meta:
model = models.Answer
exclude = ("document", "documents", "date")
exclude = ("document", "documents", "date", "files")
use_connection = False
interfaces = (Answer, graphene.Node)

Expand Down Expand Up @@ -992,9 +991,17 @@ class Meta:
return_field_type = Answer


class SaveDocumentFileAnswer(SaveDocumentAnswer):
class SaveFile(graphene.InputObjectType):
id = graphene.String()
name = graphene.String()


class SaveDocumentFilesAnswer(SaveDocumentAnswer):
class Input:
value = graphene.List(SaveFile, required=False)

class Meta:
serializer_class = serializers.SaveDocumentFileAnswerSerializer
serializer_class = serializers.SaveDocumentFilesAnswerSerializer
return_field_type = Answer


Expand Down Expand Up @@ -1087,7 +1094,7 @@ class Mutation(object):
save_integer_question = SaveIntegerQuestion().Field()
save_table_question = SaveTableQuestion().Field()
save_form_question = SaveFormQuestion().Field()
save_file_question = SaveFileQuestion().Field()
save_files_question = SaveFilesQuestion().Field()
save_static_question = SaveStaticQuestion().Field()
save_calculated_float_question = SaveCalculatedFloatQuestion().Field()
save_action_button_question = SaveActionButtonQuestion().Field()
Expand All @@ -1100,7 +1107,7 @@ class Mutation(object):
save_document_date_answer = SaveDocumentDateAnswer().Field()
save_document_list_answer = SaveDocumentListAnswer().Field()
save_document_table_answer = SaveDocumentTableAnswer().Field()
save_document_file_answer = SaveDocumentFileAnswer().Field()
save_document_files_answer = SaveDocumentFilesAnswer().Field()

save_default_string_answer = SaveDefaultStringAnswer().Field()
save_default_integer_answer = SaveDefaultIntegerAnswer().Field()
Expand Down Expand Up @@ -1200,7 +1207,7 @@ def resolve_document_validity(self, info, id, **kwargs):
models.Question.TYPE_TEXTAREA: StringAnswer,
models.Question.TYPE_TEXT: StringAnswer,
models.Question.TYPE_TABLE: TableAnswer,
models.Question.TYPE_FILE: FileAnswer,
models.Question.TYPE_FILES: FilesAnswer,
models.Question.TYPE_DYNAMIC_CHOICE: StringAnswer,
models.Question.TYPE_DYNAMIC_MULTIPLE_CHOICE: ListAnswer,
models.Question.TYPE_CALCULATED_FLOAT: FloatAnswer,
Expand All @@ -1218,7 +1225,7 @@ def resolve_document_validity(self, info, id, **kwargs):
models.Question.TYPE_DATE: DateQuestion,
models.Question.TYPE_TABLE: TableQuestion,
models.Question.TYPE_FORM: FormQuestion,
models.Question.TYPE_FILE: FileQuestion,
models.Question.TYPE_FILES: FilesQuestion,
models.Question.TYPE_STATIC: StaticQuestion,
models.Question.TYPE_CALCULATED_FLOAT: CalculatedFloatQuestion,
models.Question.TYPE_ACTION_BUTTON: ActionButtonQuestion,
Expand Down
6 changes: 3 additions & 3 deletions caluma/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@
form_schema.DateQuestion,
form_schema.TableQuestion,
form_schema.FormQuestion,
form_schema.FileQuestion,
form_schema.FilesQuestion,
form_schema.StaticQuestion,
form_schema.StringAnswer,
form_schema.ListAnswer,
form_schema.IntegerAnswer,
form_schema.FloatAnswer,
form_schema.DateAnswer,
form_schema.TableAnswer,
form_schema.FileAnswer,
form_schema.FilesAnswer,
form_schema.CalculatedFloatQuestion,
form_schema.ActionButtonQuestion,
workflow_schema.SimpleTask,
Expand All @@ -73,7 +73,7 @@
form_historical_schema.HistoricalFloatAnswer,
form_historical_schema.HistoricalDateAnswer,
form_historical_schema.HistoricalTableAnswer,
form_historical_schema.HistoricalFileAnswer,
form_historical_schema.HistoricalFilesAnswer,
]

if settings.ENABLE_HISTORICAL_API:
Expand Down
Loading

0 comments on commit 10854c2

Please sign in to comment.