162 lines
6.1 KiB
Python
162 lines
6.1 KiB
Python
import json
|
|
|
|
import graphene
|
|
from django.core.exceptions import ValidationError
|
|
from graphene import relay
|
|
from graphql_relay import from_global_id
|
|
|
|
from api.utils import get_object, get_errors
|
|
from books.models import ContentBlock, Chapter, SchoolClass
|
|
from books.schema.inputs import ContentBlockInput
|
|
from books.schema.queries import ContentBlockNode
|
|
from .utils import handle_content_block, set_user_defined_block_type
|
|
|
|
|
|
class MutateContentBlock(relay.ClientIDMutation):
|
|
class Input:
|
|
id = graphene.ID(required=True)
|
|
content_block = graphene.Argument(ContentBlockInput)
|
|
|
|
errors = graphene.List(graphene.String)
|
|
content_block = graphene.Field(ContentBlockNode)
|
|
|
|
@classmethod
|
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
|
try:
|
|
id_param = kwargs['id']
|
|
content_block_data = kwargs.get('content_block')
|
|
# type_param = content_block_data.get('type')
|
|
title = content_block_data.get('title', None)
|
|
contents = content_block_data.get('contents', None)
|
|
visibility_list = content_block_data.get('visibility', None)
|
|
|
|
content_block = get_object(ContentBlock, id_param)
|
|
|
|
block_type = content_block_data.get('type', content_block.type.upper())
|
|
module = content_block.get_parent().get_parent().specific
|
|
|
|
if visibility_list is not None:
|
|
if content_block.user_created:
|
|
cls.set_visible_for(content_block, visibility_list)
|
|
else:
|
|
cls.set_hidden_for(content_block, visibility_list)
|
|
|
|
if title is not None:
|
|
content_block.title = title
|
|
|
|
if contents is not None:
|
|
content_block.contents = json.dumps([handle_content_block(c, info.context, module) for c in contents])
|
|
|
|
content_block.type = set_user_defined_block_type(block_type)
|
|
content_block.save()
|
|
|
|
return cls(content_block=content_block)
|
|
|
|
except ValidationError as e:
|
|
errors = get_errors(e)
|
|
except Exception as e:
|
|
errors = ['Error: {}'.format(e)]
|
|
|
|
return cls(content_block=None, errors=errors)
|
|
|
|
@classmethod
|
|
def set_hidden_for(cls, content_block, visibility_list):
|
|
for v in visibility_list:
|
|
school_class = get_object(SchoolClass, v.school_class_id)
|
|
if v.hidden:
|
|
content_block.hidden_for.add(school_class)
|
|
else:
|
|
content_block.hidden_for.remove(school_class)
|
|
|
|
@classmethod
|
|
def set_visible_for(cls, content_block, visibility_list):
|
|
for v in visibility_list:
|
|
school_class = get_object(SchoolClass, v.school_class_id)
|
|
if v.hidden:
|
|
content_block.visible_for.remove(school_class)
|
|
else:
|
|
content_block.visible_for.add(school_class)
|
|
|
|
|
|
class AddContentBlock(relay.ClientIDMutation):
|
|
class Input:
|
|
content_block = graphene.Argument(ContentBlockInput)
|
|
parent = graphene.ID() # ID of chapter node; new content block will be inserted at the start of it
|
|
after = graphene.ID() # ID of content block node; new content block will be inserted after this content block node
|
|
|
|
new_content_block = graphene.Field(ContentBlockNode)
|
|
errors = graphene.List(graphene.String)
|
|
|
|
@classmethod
|
|
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')
|
|
|
|
title = content_block_data.get('title')
|
|
contents = content_block_data.get('contents')
|
|
block_type = set_user_defined_block_type(content_block_data.get('type', ContentBlock.NORMAL))
|
|
|
|
new_content_block = ContentBlock(title=title, user_created=True, owner=context.user, type=block_type)
|
|
|
|
if parent is not None:
|
|
parent_chapter = get_object(Chapter, parent).specific
|
|
first_sibling = parent_chapter.get_first_child()
|
|
if first_sibling is not None:
|
|
first_sibling.add_sibling(instance=new_content_block, pos='left')
|
|
else:
|
|
parent_chapter.add_child(instance=new_content_block)
|
|
elif after is not None:
|
|
sibling = get_object(ContentBlock, after).specific
|
|
sibling.add_sibling(instance=new_content_block, pos='right')
|
|
|
|
revision = new_content_block.save_revision()
|
|
revision.publish()
|
|
new_content_block.save()
|
|
|
|
module = new_content_block.get_parent().get_parent().specific
|
|
|
|
new_content_block.contents = json.dumps([handle_content_block(c, context, module) for c in
|
|
contents]) # can only do this after the content block has been saved
|
|
new_content_block.save()
|
|
|
|
return new_content_block
|
|
|
|
@classmethod
|
|
def mutate_and_get_payload(cls, root, info, **args):
|
|
try:
|
|
parent = args.get('parent', None)
|
|
after = args.get('after', None)
|
|
new_content_block = cls.create_content_block(content_block_data=args.get('content_block'),
|
|
parent=parent,
|
|
after=after,
|
|
context=info.context)
|
|
|
|
return cls(new_content_block=new_content_block)
|
|
|
|
except ValidationError as e:
|
|
errors = get_errors(e)
|
|
except Exception as e:
|
|
errors = ['Error: {}'.format(e)]
|
|
|
|
return cls(new_content_block=None, errors=errors)
|
|
|
|
|
|
class DeleteContentBlock(relay.ClientIDMutation):
|
|
class Input:
|
|
id = graphene.ID(required=True)
|
|
|
|
success = graphene.Boolean()
|
|
errors = graphene.String()
|
|
|
|
@classmethod
|
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
|
id = from_global_id(kwargs.get('id'))[1]
|
|
user = info.context.user
|
|
|
|
try:
|
|
content_block = ContentBlock.objects.get(pk=id, owner=user)
|
|
content_block.delete()
|
|
return cls(success=True)
|
|
except ContentBlock.DoesNotExist:
|
|
return cls(success=False, errors='Content block not found')
|