import json from builtins import PermissionError import graphene from api.utils import get_by_id, get_object from basicknowledge.models import BasicKnowledge from books.models import Chapter, ContentBlock, Module from django.db import IntegrityError from graphene import relay from graphql_relay import from_global_id from notes.inputs import AddHighlightArgument, AddNoteArgument, UpdateNoteArgument from notes.models import ( ChapterBookmark, ContentBlockBookmark, Highlight, InstrumentBookmark, ModuleBookmark, Note, ) from notes.schema import HighlightNode, NoteNode class UpdateContentBookmark(relay.ClientIDMutation): class Input: uuid = graphene.UUID(required=True) content_block = graphene.ID(required=True) bookmarked = graphene.Boolean(required=True) success = graphene.Boolean() errors = graphene.String() @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): uuid = kwargs.get("uuid") user = info.context.user content_block_id = kwargs.get("content_block") bookmarked = kwargs.get("bookmarked") content_block = get_object(ContentBlock, content_block_id) if bookmarked: try: ContentBlockBookmark.objects.create( content_block=content_block, uuid=uuid, user=user ) except IntegrityError: # already exists, probably fine return cls(success=True) else: ContentBlockBookmark.objects.get( content_block=content_block, uuid=uuid, user=user ).delete() return cls(success=True) class AddNote(relay.ClientIDMutation): class Input: note = graphene.Argument(AddNoteArgument) note = graphene.Field(NoteNode) @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user note = kwargs.get("note") content_uuid = note.get("content", "") content_block_id = note.get("block", "") parent = note.get("parent") text = note.get("text") if content_uuid != "": type = note.get("type") if type == "ContentBlockNode": content_block = get_object(ContentBlock, content_block_id) bookmark = ContentBlockBookmark.objects.get( content_block=content_block, uuid=content_uuid, user=user ) else: instrument = BasicKnowledge.objects.get(slug=content_block_id) bookmark = InstrumentBookmark.objects.get( instrument=instrument, uuid=content_uuid, user=user ) else: type = note.get("type", "chapter") if type == "module": bookmark = ModuleBookmark.objects.get(module__slug=parent, user=user) else: _, id = from_global_id(parent) bookmark = ChapterBookmark.objects.get(chapter__id=id, user=user) bookmark.note = Note.objects.create(text=text) bookmark.save() return cls(note=bookmark.note) class UpdateNote(relay.ClientIDMutation): class Input: note = graphene.Argument(UpdateNoteArgument) note = graphene.Field(NoteNode) @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user note = kwargs.get("note") id = note.get("id") text = note.get("text") note = get_object(Note, id) if ( hasattr(note, "contentblockbookmark") and note.contentblockbookmark.user != user or hasattr(note, "chapterbookmark") and note.chapterbookmark.user != user or hasattr(note, "modulebookmark") and note.modulebookmark.user != user ): raise PermissionError note.text = text note.save() return cls(note=note) class UpdateChapterBookmark(relay.ClientIDMutation): class Input: chapter = graphene.ID(required=True) bookmarked = graphene.Boolean(required=True) success = graphene.Boolean() @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user chapter_id = kwargs.get("chapter") bookmarked = kwargs.get("bookmarked") chapter = get_object(Chapter, chapter_id) if bookmarked: ChapterBookmark.objects.create(chapter=chapter, user=user) else: ChapterBookmark.objects.get(chapter=chapter, user=user).delete() return cls(success=True) class UpdateModuleBookmark(relay.ClientIDMutation): class Input: module = graphene.String(required=True) bookmarked = graphene.Boolean(required=True) success = graphene.Boolean() @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user module_slug = kwargs.get("module") bookmarked = kwargs.get("bookmarked") module = Module.objects.get(slug=module_slug) if bookmarked: ModuleBookmark.objects.create(module=module, user=user) else: ModuleBookmark.objects.get(module=module, user=user).delete() return cls(success=True) class UpdateInstrumentBookmark(relay.ClientIDMutation): class Input: uuid = graphene.UUID(required=True) instrument = graphene.String(required=True) bookmarked = graphene.Boolean(required=True) success = graphene.Boolean() @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user instrument_slug = kwargs.get("instrument") uuid = kwargs.get("uuid") bookmarked = kwargs.get("bookmarked") instrument = BasicKnowledge.objects.get(slug=instrument_slug) if bookmarked: try: InstrumentBookmark.objects.create( instrument=instrument, uuid=uuid, user=user ) except IntegrityError: # already exists, that's probably ok return cls(success=True) else: InstrumentBookmark.objects.get( instrument=instrument, uuid=uuid, user=user ).delete() return cls(success=True) class UpdateHighlight(relay.ClientIDMutation): class Input: color = graphene.Argument(graphene.String) class AddHighlight(relay.ClientIDMutation): class Input: highlight = graphene.Argument(AddHighlightArgument) highlight = graphene.Field(HighlightNode) @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user highlight = kwargs.get("highlight") if highlight is None: raise Exception("No highlight provided, should not happen") content_block_id = highlight.get("content_block") content_index = highlight.get("content_index") content_uuid = highlight.get("content_uuid") paragraph_index = highlight.get("paragraph_index") text = highlight.get("text") start_position = highlight.get("start_position") selection_length = highlight.get("selection_length") color = highlight.get("color") content_block = get_object(ContentBlock, content_block_id) new_highlight = Highlight.objects.create( content_block=content_block, user=user, content_index=content_index, content_uuid=content_uuid, paragraph_index=paragraph_index, text=text, start_position=start_position, selection_length=selection_length, color=color, ) return cls(highlight=new_highlight) class NoteMutations: add_note = AddNote.Field() add_highlight = AddHighlight.Field() update_highlight = UpdateHighlight.Field() update_note = UpdateNote.Field() update_content_bookmark = UpdateContentBookmark.Field() update_chapter_bookmark = UpdateChapterBookmark.Field() update_module_bookmark = UpdateModuleBookmark.Field() update_instrument_bookmark = UpdateInstrumentBookmark.Field()