skillbox/server/books/schema/mutations/contentblock.py

146 lines
5.5 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 ..nodes import ContentBlockNode
from core.utils import set_hidden_for, set_visible_for
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)
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')
if block_type is not None: # only change the type if the user has set a type
content_block.type = set_user_defined_block_type(block_type)
module = content_block.get_parent().get_parent().specific
if visibility_list is not None:
if content_block.user_created:
set_visible_for(content_block, visibility_list)
else:
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.save()
return cls(content_block=content_block)
except ValidationError as e:
errors = get_errors(e)
raise errors
except Exception as e:
errors = ['Error: {}'.format(e)]
raise errors
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')