194 lines
6.5 KiB
Python
194 lines
6.5 KiB
Python
import json
|
|
|
|
import graphene
|
|
from api.utils import get_errors, get_object
|
|
from books.models import Chapter, ContentBlock
|
|
from books.schema.inputs import ContentBlockInput
|
|
from core.logger import get_logger
|
|
from core.utils import set_hidden_for, set_visible_for
|
|
from django.core.exceptions import ValidationError
|
|
from graphene import relay
|
|
from graphql_relay import from_global_id
|
|
|
|
from ..nodes import ContentBlockNode
|
|
from .utils import handle_content_block, set_user_defined_block_type
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
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,
|
|
previous_contents=content_block.contents,
|
|
)
|
|
for c in contents
|
|
if c is not None
|
|
]
|
|
)
|
|
|
|
content_block.save()
|
|
|
|
return cls(content_block=content_block)
|
|
|
|
except ValidationError as e:
|
|
errors = get_errors(e)
|
|
raise errors
|
|
except Exception as e:
|
|
logger.error(e)
|
|
raise e
|
|
|
|
|
|
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")
|
|
|
|
|
|
class DuplicateContentBlock(relay.ClientIDMutation):
|
|
class Input:
|
|
id = graphene.ID(required=True)
|
|
|
|
content_block = graphene.Field(ContentBlockNode)
|
|
|
|
@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)
|
|
new_content_block = ContentBlock.objects.duplicate(
|
|
content_block=content_block, user=user
|
|
)
|
|
return cls(content_block=new_content_block)
|
|
except ContentBlock.DoesNotExist:
|
|
return cls(content_block=None)
|