Add assignment handling on API
This commit is contained in:
parent
826849f1e0
commit
8f7f8e4d4f
|
|
@ -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);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 & Ergebnis</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
),
|
||||
]
|
||||
Loading…
Reference in New Issue