Add assignment handling on API

This commit is contained in:
Ramon Wenger 2018-09-27 16:07:48 +02:00
parent 826849f1e0
commit 8f7f8e4d4f
10 changed files with 97 additions and 27 deletions

View File

@ -22,12 +22,21 @@
:class="{'contents-form__chooser': type(element) === 'content-block-element-chooser-widget'}"
:element="element" v-bind="element" :index="index"
v-on:change-type="changeType"
v-on:link-change-url="changeLinkUrl"
v-on:link-change-text="changeLinkText"
v-on:text-change-value="changeTextValue"
v-on:document-change-url="changeDocumentUrl"
v-on:image-change-url="changeImageUrl"
v-on:video-change-url="changeVideoUrl">
v-on:video-change-url="changeVideoUrl"
v-on:assignment-change-title="changeAssignmentTitle"
v-on:assignment-change-assignment="changeAssignmentAssignment"
>
</component>
<a class="contents-form__remove" v-on:click="removeElement(index)">
<trash-icon v-if="type(element) !== 'content-block-element-chooser-widget'"
@ -56,7 +65,7 @@
import VideoForm from '@/components/content-forms/VideoForm';
import ImageForm from '@/components/content-forms/ImageForm';
import DocumentForm from '@/components/content-forms/DocumentForm';
import ExerciseForm from '@/components/content-forms/ExerciseForm';
import AssignmentForm from '@/components/content-forms/AssignmentForm';
import TextForm from '@/components/content-forms/TextForm';
import TrashIcon from '@/components/icons/TrashIcon';
@ -78,7 +87,7 @@
VideoForm,
ImageForm,
DocumentForm,
ExerciseForm,
AssignmentForm,
TextForm,
TrashIcon
},
@ -112,8 +121,8 @@
return 'image-form';
case 'text_block':
return 'text-form';
case 'exercise':
return 'exercise-form';
case 'assignment':
return 'assignment-form';
case 'document_block':
return 'document-form';
}
@ -147,6 +156,12 @@
changeTextValue(value, index) {
this._updateProperty(value, index, 'text')
},
changeAssignmentTitle(value, index) {
this._updateProperty(value, index, 'title')
},
changeAssignmentAssignment(value, index) {
this._updateProperty(value, index, 'assignment')
},
removeElement(index) {
this.localContentBlock.contents.splice(index, 1);
},

View File

@ -1,7 +1,15 @@
<template>
<div class="exercise-form">
<input class="exercise-form__title skillbox-input" placeholder="Aufgabentitel">
<textarea class="exercise-form__exercise-text skillbox-textarea" placeholder="Aufgabe erfassen..."></textarea>
<input class="exercise-form__title skillbox-input"
placeholder="Aufgabentitel"
:value="value.title"
v-on:input="$emit('assignment-change-title', $event.target.value, index)"
>
<textarea class="exercise-form__exercise-text skillbox-textarea"
placeholder="Aufgabe erfassen..."
:value="value.assignment"
v-on:input="$emit('assignment-change-assignment', $event.target.value, index)"
></textarea>
<info-icon class="exercise-form__help-icon help-text__icon"></info-icon>
<p class="exercise-form__help-description help-text__description">
Ein Eingabefeld für die Antwort wird automatisch hinzugefügt.
@ -13,6 +21,8 @@
import InfoIcon from '@/components/icons/InfoIcon';
export default {
props: ['value', 'index'],
components: {
InfoIcon
}
@ -44,6 +54,7 @@
height: 40px;
}
&__help-description {}
&__help-description {
}
}
</style>

View File

@ -16,7 +16,7 @@
<text-icon class="content-block-element-chooser-widget__link-icon"></text-icon>
<div class="content-block-element-chooser-widget__link-title">Text</div>
</div>
<div class="content-block-element-chooser-widget__link" v-on:click="$emit('change-type', index, 'exercise')">
<div class="content-block-element-chooser-widget__link" v-on:click="$emit('change-type', index, 'assignment')">
<speech-bubble-icon class="content-block-element-chooser-widget__link-icon"></speech-bubble-icon>
<div class="content-block-element-chooser-widget__link-title">Aufgabe&nbsp;& Ergebnis</div>
</div>

View File

@ -6,6 +6,8 @@ from graphene_django.converter import convert_django_field
from wagtail.core.fields import StreamField
from wagtail.images.models import Image
from assignments.models import Assignment
class GenericStreamFieldType(Scalar):
@staticmethod
@ -23,6 +25,15 @@ class GenericStreamFieldType(Scalar):
'path': Image.objects.get(id=_value).file.url
}
d['value'] = value
if _type == 'assignment':
_value = d['value']
assignment = Assignment.objects.get(pk=_value['assignment_id'])
value = {
'title' : assignment.title,
'assignment': assignment.assignment
}
d['value'] = value
# value = dict(d['value'])
# if 'document' in value:

View File

@ -38,12 +38,12 @@ class ImageUrlBlock(blocks.StructBlock):
url = blocks.URLBlock()
# 'student_entry'
class StudentEntryBlock(blocks.StructBlock):
# 'assignment'
class AssignmentBlock(blocks.StructBlock):
class Meta:
icon = 'download'
task_text = blocks.RichTextBlock()
assignment_id = blocks.IntegerBlock()
# 'video_block'

View File

@ -5,8 +5,8 @@ from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList,
from wagtail.core.fields import StreamField
from wagtail.images.blocks import ImageChooserBlock
from book.blocks import TextBlock, BasicKnowledgeBlock, StudentEntryBlock, LinkBlock, VideoBlock, DocumentBlock, \
ImageUrlBlock
from book.blocks import TextBlock, BasicKnowledgeBlock, LinkBlock, VideoBlock, DocumentBlock, \
ImageUrlBlock, AssignmentBlock
from core.wagtail_utils import StrictHierarchyPage
from user.models import UserGroup
@ -35,7 +35,7 @@ class ContentBlock(StrictHierarchyPage):
contents = StreamField([
('text_block', TextBlock()),
('basic_knowledge', BasicKnowledgeBlock()),
('student_entry', StudentEntryBlock()),
('assignment', AssignmentBlock()),
('image_block', ImageChooserBlock()),
('image_url_block', ImageUrlBlock()),
('link_block', LinkBlock()),

View File

@ -9,7 +9,6 @@ class InputTypes(graphene.Enum):
image_block = 'image_block'
image_url_block = 'image_url_block'
link_block = 'link_block'
task = 'task'
video_block = 'video_block'
document_block = 'document_block'
@ -20,8 +19,8 @@ class ContentElementValueInput(InputObjectType):
text = graphene.String(description='To be used for link_block, text_block types')
url = graphene.String(description='To be used for link, basic_knowledge, image_block types')
description = graphene.String(description='To be used for basic_knowledge type')
title = graphene.String(description='To be used for image_block type')
task_text = graphene.String(description='To be used for task type')
title = graphene.String(description='To be used for image_block, assignment type')
assignment = graphene.String(description='To be used for assignment type')
class ContentElementInput(InputObjectType):

View File

@ -21,7 +21,7 @@ class MutateContentBlock(relay.ClientIDMutation):
content_block = graphene.Field(ContentBlockNode)
@classmethod
def mutate_and_get_payload(cls, *args, **kwargs):
def mutate_and_get_payload(cls, root, info, **kwargs):
try:
id_param = kwargs['id']
content_block_data = kwargs.get('content_block')
@ -44,7 +44,7 @@ class MutateContentBlock(relay.ClientIDMutation):
content_block.title = title
if contents is not None:
content_block.contents = json.dumps(list(map(handle_content_block, contents)))
content_block.contents = json.dumps([handle_content_block(c, info.context) for c in contents])
content_block.save()
@ -68,7 +68,7 @@ class AddContentBlock(relay.ClientIDMutation):
errors = graphene.List(graphene.String)
@classmethod
def create_content_block(cls, content_block_data, parent=None, after=None):
def create_content_block(cls, content_block_data, parent=None, after=None, context=None):
if after is None and parent is None:
raise Exception('Define either a parent or a sibling id')
@ -92,8 +92,8 @@ class AddContentBlock(relay.ClientIDMutation):
revision.publish()
new_content_block.save()
new_content_block.contents = json.dumps(
list(map(handle_content_block, contents))) # can only do this after the content block has been saved
new_content_block.contents = json.dumps([handle_content_block(c, context) for c in
contents]) # can only do this after the content block has been saved
new_content_block.save()
return new_content_block
@ -105,7 +105,8 @@ class AddContentBlock(relay.ClientIDMutation):
after = args.get('after', None)
new_content_block = cls.create_content_block(content_block_data=args.get('content_block'),
parent=parent,
after=after)
after=after,
context=info.context)
return cls(new_content_block=new_content_block)

View File

@ -11,6 +11,8 @@
import bleach
import re
from assignments.models import Assignment
def newlines_to_paragraphs(text):
parts = re.split(r'[\r\n]+', text)
@ -24,11 +26,12 @@ ALLOWED_BLOCKS = (
'image_url_block',
'link_block',
'video_block',
'assignment',
'document_block',
)
def handle_content_block(content, allowed_blocks=ALLOWED_BLOCKS):
def handle_content_block(content, context, allowed_blocks=ALLOWED_BLOCKS):
# todo: add all the content blocks
# todo: sanitize user inputs!
if content['type'] not in allowed_blocks:
@ -40,8 +43,18 @@ def handle_content_block(content, allowed_blocks=ALLOWED_BLOCKS):
'value': {
'text': newlines_to_paragraphs(bleach.clean(content['value']['text'], strip=True))
}}
elif content['type'] == 'student_entry':
return
elif content['type'] == 'assignment':
assignment = Assignment.objects.create(
title=content['value']['title'],
assignment=content['value']['assignment'],
owner=context.user
)
return {
'type': 'assignment',
'value': {
'assignment_id': assignment.id
}}
elif content['type'] == 'image_url_block':
return {
'type': 'image_url_block',

View File

@ -0,0 +1,20 @@
# Generated by Django 2.0.6 on 2018-09-27 09:45
from django.db import migrations
import wagtail.core.blocks
import wagtail.core.fields
class Migration(migrations.Migration):
dependencies = [
('rooms', '0002_auto_20180911_1414'),
]
operations = [
migrations.AlterField(
model_name='roomentry',
name='contents',
field=wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())])), ('image_url_block', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.RichTextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('link_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True),
),
]