diff --git a/server/notes/inputs.py b/server/notes/inputs.py index cbf8440c..a764392f 100644 --- a/server/notes/inputs.py +++ b/server/notes/inputs.py @@ -13,3 +13,14 @@ class AddNoteArgument(InputObjectType): class UpdateNoteArgument(InputObjectType): id = graphene.ID(required=True) text = graphene.String(required=True) + + +class AddHighlightArgument(InputObjectType): + content_block = graphene.String(required=True) + content_index = graphene.Int(required=True) + content_uuid = graphene.UUID(required=True) + paragraph_index = graphene.Int(required=True) + text = graphene.String(required=True) + start_position = graphene.Int(required=True) + selection_length = graphene.Int(required=True) + color = graphene.String(required=True) diff --git a/server/notes/mutations.py b/server/notes/mutations.py index 924b36c4..358d1449 100644 --- a/server/notes/mutations.py +++ b/server/notes/mutations.py @@ -7,12 +7,19 @@ from django.db import IntegrityError from graphene import relay from graphql_relay import from_global_id -from api.utils import get_object +from api.utils import get_by_id, get_object from basicknowledge.models import BasicKnowledge from books.models import ContentBlock, Chapter, Module -from notes.inputs import AddNoteArgument, UpdateNoteArgument -from notes.models import ContentBlockBookmark, Note, ChapterBookmark, ModuleBookmark, InstrumentBookmark -from notes.schema import NoteNode +from notes.inputs import AddNoteArgument, UpdateNoteArgument, AddHighlightArgument +from notes.models import ( + ContentBlockBookmark, + Highlight, + Note, + ChapterBookmark, + ModuleBookmark, + InstrumentBookmark, +) +from notes.schema import HighlightNode, NoteNode class UpdateContentBookmark(relay.ClientIDMutation): @@ -26,28 +33,24 @@ class UpdateContentBookmark(relay.ClientIDMutation): @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): - uuid = kwargs.get('uuid') + uuid = kwargs.get("uuid") user = info.context.user - content_block_id = kwargs.get('content_block') - bookmarked = kwargs.get('bookmarked') + 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 + 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 + content_block=content_block, uuid=uuid, user=user ).delete() return cls(success=True) @@ -63,42 +66,32 @@ class AddNote(relay.ClientIDMutation): 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') + 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': + 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 + 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 + 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 - ) + 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 = ChapterBookmark.objects.get(chapter__id=id, user=user) bookmark.note = Note.objects.create(text=text) bookmark.save() @@ -116,14 +109,19 @@ class UpdateNote(relay.ClientIDMutation): 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 = 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: + 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 @@ -141,21 +139,15 @@ class UpdateChapterBookmark(relay.ClientIDMutation): @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user - chapter_id = kwargs.get('chapter') - bookmarked = kwargs.get('bookmarked') + chapter_id = kwargs.get("chapter") + bookmarked = kwargs.get("bookmarked") chapter = get_object(Chapter, chapter_id) if bookmarked: - ChapterBookmark.objects.create( - chapter=chapter, - user=user - ) + ChapterBookmark.objects.create(chapter=chapter, user=user) else: - ChapterBookmark.objects.get( - chapter=chapter, - user=user - ).delete() + ChapterBookmark.objects.get(chapter=chapter, user=user).delete() return cls(success=True) @@ -170,21 +162,15 @@ class UpdateModuleBookmark(relay.ClientIDMutation): @classmethod def mutate_and_get_payload(cls, root, info, **kwargs): user = info.context.user - module_slug = kwargs.get('module') - bookmarked = kwargs.get('bookmarked') + 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 - ) + ModuleBookmark.objects.create(module=module, user=user) else: - ModuleBookmark.objects.get( - module=module, - user=user - ).delete() + ModuleBookmark.objects.get(module=module, user=user).delete() return cls(success=True) @@ -200,34 +186,72 @@ class UpdateInstrumentBookmark(relay.ClientIDMutation): @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_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 + 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 + instrument=instrument, uuid=uuid, user=user ).delete() return cls(success=True) +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_note = UpdateNote.Field() update_content_bookmark = UpdateContentBookmark.Field() update_chapter_bookmark = UpdateChapterBookmark.Field() diff --git a/server/schema.graphql b/server/schema.graphql index d894170a..bc377258 100644 --- a/server/schema.graphql +++ b/server/schema.graphql @@ -1035,6 +1035,7 @@ type DjangoDebugException { type Mutation { spellCheck(input: SpellCheckInput!): SpellCheckPayload addNote(input: AddNoteInput!): AddNotePayload + addHighlight(input: AddHighlightInput!): AddHighlightPayload updateNote(input: UpdateNoteInput!): UpdateNotePayload updateContentBookmark(input: UpdateContentBookmarkInput!): UpdateContentBookmarkPayload updateChapterBookmark(input: UpdateChapterBookmarkInput!): UpdateChapterBookmarkPayload @@ -1134,6 +1135,27 @@ input AddNoteArgument { text: String! } +type AddHighlightPayload { + highlight: HighlightNode + clientMutationId: String +} + +input AddHighlightInput { + highlight: AddHighlightArgument + clientMutationId: String +} + +input AddHighlightArgument { + contentBlockId: String! + contentIndex: Int! + contentUuid: UUID! + paragraphIndex: Int! + text: String! + startPosition: Int! + selectionLength: Int! + color: String! +} + type UpdateNotePayload { note: NoteNode clientMutationId: String