From 90598342b8554126cf6b42d3e50b20f3d5c00e24 Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Wed, 2 Oct 2019 11:36:59 +0200 Subject: [PATCH 01/40] Move content block content handling to own component --- client/src/components/ContentBlock.vue | 47 ++-------- .../content-blocks/ContentComponent.vue | 92 +++++++++++++++++++ 2 files changed, 101 insertions(+), 38 deletions(-) create mode 100644 client/src/components/content-blocks/ContentComponent.vue diff --git a/client/src/components/ContentBlock.vue b/client/src/components/ContentBlock.vue index 6f85068e..c0b79ec8 100644 --- a/client/src/components/ContentBlock.vue +++ b/client/src/components/ContentBlock.vue @@ -17,11 +17,13 @@

{{instrumentLabel}}

{{contentBlock.title}}

- - + + + @@ -32,21 +34,6 @@ + + From 584b48a6a6fa3dac14726ae1181124eaeb1fdf39 Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Wed, 2 Oct 2019 11:38:53 +0200 Subject: [PATCH 02/40] Add notes app and a PoC for highlights --- .../gql/fragments/contentBlockParts.gql | 1 + .../0015_contentblock_highlights.py | 21 ++++++++++++++ server/books/models/contentblock.py | 7 ++++- server/books/schema/queries.py | 8 +++++ server/core/settings.py | 1 + server/notes/__init__.py | 0 server/notes/admin.py | 3 ++ server/notes/apps.py | 5 ++++ server/notes/migrations/0001_initial.py | 29 +++++++++++++++++++ server/notes/migrations/__init__.py | 0 server/notes/models.py | 18 ++++++++++++ server/notes/tests.py | 3 ++ server/notes/views.py | 3 ++ 13 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 server/books/migrations/0015_contentblock_highlights.py create mode 100644 server/notes/__init__.py create mode 100644 server/notes/admin.py create mode 100644 server/notes/apps.py create mode 100644 server/notes/migrations/0001_initial.py create mode 100644 server/notes/migrations/__init__.py create mode 100644 server/notes/models.py create mode 100644 server/notes/tests.py create mode 100644 server/notes/views.py diff --git a/client/src/graphql/gql/fragments/contentBlockParts.gql b/client/src/graphql/gql/fragments/contentBlockParts.gql index 229c87cc..ec389fc3 100644 --- a/client/src/graphql/gql/fragments/contentBlockParts.gql +++ b/client/src/graphql/gql/fragments/contentBlockParts.gql @@ -6,6 +6,7 @@ fragment ContentBlockParts on ContentBlockNode { contents userCreated mine + highlights hiddenFor { edges { node { diff --git a/server/books/migrations/0015_contentblock_highlights.py b/server/books/migrations/0015_contentblock_highlights.py new file mode 100644 index 00000000..c56d12bf --- /dev/null +++ b/server/books/migrations/0015_contentblock_highlights.py @@ -0,0 +1,21 @@ +# Generated by Django 2.0.6 on 2019-10-01 13:25 + +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('notes', '0001_initial'), + ('books', '0014_auto_20190912_1228'), + ] + + operations = [ + migrations.AddField( + model_name='contentblock', + name='highlights', + field=models.ManyToManyField(related_name='highlighted_content_blocks', through='notes.ContentBlockHighlight', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/server/books/models/contentblock.py b/server/books/models/contentblock.py index f8e1ca3f..5eafff98 100644 --- a/server/books/models/contentblock.py +++ b/server/books/models/contentblock.py @@ -10,8 +10,9 @@ from books.blocks import TextBlock, BasicKnowledgeBlock, LinkBlock, VideoBlock, ImageUrlBlock, AssignmentBlock, InfogramBlock, GeniallyBlock, SubtitleBlock, SurveyBlock, ModuleRoomSlugBlock from books.utils import get_type_and_value from core.wagtail_utils import StrictHierarchyPage +from notes.models import Highlight, ContentBlockHighlight from surveys.models import Survey -from users.models import SchoolClass +from users.models import SchoolClass, User logger = logging.getLogger(__name__) @@ -33,10 +34,14 @@ class ContentBlock(StrictHierarchyPage): (BASE_SOCIETY, 'Instrument Gesellschaft'), ) + # blocks without owner are visible by default, need to be hidden for each class hidden_for = models.ManyToManyField(SchoolClass, related_name='hidden_content_blocks') + # blocks with owner are hidden by default, need to be shown for each class visible_for = models.ManyToManyField(SchoolClass, related_name='visible_content_blocks') user_created = models.BooleanField(default=False) + highlights = models.ManyToManyField(User, through=ContentBlockHighlight, related_name='highlighted_content_blocks') + content_blocks = [ ('text_block', TextBlock()), ('basic_knowledge', BasicKnowledgeBlock()), diff --git a/server/books/schema/queries.py b/server/books/schema/queries.py index c184e509..94881356 100644 --- a/server/books/schema/queries.py +++ b/server/books/schema/queries.py @@ -5,6 +5,7 @@ from graphene_django.filter import DjangoFilterConnectionField from api.utils import get_object from books.utils import are_solutions_enabled_for +from notes.models import ContentBlockHighlight from rooms.models import ModuleRoomSlug from ..models import Book, Topic, Module, Chapter, ContentBlock @@ -24,6 +25,7 @@ def process_module_room_slug_block(content): class ContentBlockNode(DjangoObjectType): mine = graphene.Boolean() + highlights = graphene.List(graphene.String) class Meta: model = ContentBlock @@ -54,6 +56,12 @@ class ContentBlockNode(DjangoObjectType): self.contents.stream_data = updated_stream_data return self.contents + def resolve_highlights(self, info, **kwargs): + return [highlight.id for highlight in ContentBlockHighlight.objects.filter( + user=info.context.user, + content_block=self + )] + class ChapterNode(DjangoObjectType): content_blocks = DjangoFilterConnectionField(ContentBlockNode) diff --git a/server/core/settings.py b/server/core/settings.py index 8437b685..9131a58a 100644 --- a/server/core/settings.py +++ b/server/core/settings.py @@ -54,6 +54,7 @@ INSTALLED_APPS = [ 'portfolio', 'statistics', 'surveys', + 'notes', 'wagtail.contrib.forms', 'wagtail.contrib.redirects', diff --git a/server/notes/__init__.py b/server/notes/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/notes/admin.py b/server/notes/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/server/notes/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/server/notes/apps.py b/server/notes/apps.py new file mode 100644 index 00000000..b6155aca --- /dev/null +++ b/server/notes/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class NotesConfig(AppConfig): + name = 'notes' diff --git a/server/notes/migrations/0001_initial.py b/server/notes/migrations/0001_initial.py new file mode 100644 index 00000000..83165dd3 --- /dev/null +++ b/server/notes/migrations/0001_initial.py @@ -0,0 +1,29 @@ +# Generated by Django 2.0.6 on 2019-10-01 13:25 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('books', '0014_auto_20190912_1228'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='ContentBlockHighlight', + fields=[ + ('id', models.UUIDField(primary_key=True, serialize=False)), + ('content_block', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.ContentBlock')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/server/notes/migrations/__init__.py b/server/notes/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/notes/models.py b/server/notes/models.py new file mode 100644 index 00000000..e01d9a25 --- /dev/null +++ b/server/notes/models.py @@ -0,0 +1,18 @@ +from django.db import models + +# Create your models here. +from core.wagtail_utils import StrictHierarchyPage +from users.models import User + + +# todo: change from Highlight to Bookmark / Note (tbd) +class Highlight(models.Model): + id = models.UUIDField(primary_key=True) + user = models.ForeignKey(User, on_delete=models.CASCADE) + + class Meta: + abstract = True + + +class ContentBlockHighlight(Highlight): + content_block = models.ForeignKey('books.ContentBlock', on_delete=models.CASCADE) diff --git a/server/notes/tests.py b/server/notes/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/server/notes/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/server/notes/views.py b/server/notes/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/server/notes/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From 4247164067f5a5cbaf35df99acef73c1d5bd9902 Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Wed, 2 Oct 2019 11:39:40 +0200 Subject: [PATCH 03/40] Add highlight mutation --- .../gql/mutations/updateContentHighlight.gql | 5 +++ server/books/schema/mutations/contentblock.py | 35 +++++++++++++++++++ server/books/schema/mutations/main.py | 4 ++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 client/src/graphql/gql/mutations/updateContentHighlight.gql diff --git a/client/src/graphql/gql/mutations/updateContentHighlight.gql b/client/src/graphql/gql/mutations/updateContentHighlight.gql new file mode 100644 index 00000000..4a50f696 --- /dev/null +++ b/client/src/graphql/gql/mutations/updateContentHighlight.gql @@ -0,0 +1,5 @@ +mutation UpdateContentHighlight($input: UpdateContentHighlightInput!) { + updateContentHighlight(input: $input) { + success + } +} diff --git a/server/books/schema/mutations/contentblock.py b/server/books/schema/mutations/contentblock.py index c557dfa9..653a1c50 100644 --- a/server/books/schema/mutations/contentblock.py +++ b/server/books/schema/mutations/contentblock.py @@ -10,6 +10,7 @@ from books.models import ContentBlock, Chapter, SchoolClass from books.schema.inputs import ContentBlockInput from books.schema.queries import ContentBlockNode from core.utils import set_hidden_for, set_visible_for +from notes.models import ContentBlockHighlight from .utils import handle_content_block, set_user_defined_block_type @@ -145,3 +146,37 @@ class DeleteContentBlock(relay.ClientIDMutation): return cls(success=True) except ContentBlock.DoesNotExist: return cls(success=False, errors='Content block not found') + + +class UpdateContentHighlight(relay.ClientIDMutation): + class Input: + id = graphene.String(required=True) + content_block = graphene.ID(required=True) + highlight = graphene.Boolean(required=True) + + success = graphene.Boolean() + errors = graphene.String() + + @classmethod + def mutate_and_get_payload(cls, root, info, **kwargs): + id = kwargs.get('id') + user = info.context.user + content_block_id = kwargs.get('content_block') + highlight = kwargs.get('highlight') + + content_block = get_object(ContentBlock, content_block_id) + + if highlight: + ContentBlockHighlight.objects.create( + content_block=content_block, + id=id, + user=user + ) + else: + ContentBlockHighlight.objects.get( + content_block=content_block, + id=id, + user=user + ).delete() + + return cls(success=True) diff --git a/server/books/schema/mutations/main.py b/server/books/schema/mutations/main.py index 5d2bb6f4..08b06c3b 100644 --- a/server/books/schema/mutations/main.py +++ b/server/books/schema/mutations/main.py @@ -1,4 +1,5 @@ -from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock +from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock, \ + UpdateContentHighlight from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule @@ -8,3 +9,4 @@ class BookMutations(object): delete_content_block = DeleteContentBlock.Field() update_solution_visibility = UpdateSolutionVisibility.Field() update_last_module = UpdateLastModule.Field() + update_content_highlight = UpdateContentHighlight.Field() From 5fd81a2bd6dce6ed669178a6fa20c985c5b43cc9 Mon Sep 17 00:00:00 2001 From: Ramon Wenger Date: Mon, 7 Oct 2019 17:10:39 +0200 Subject: [PATCH 04/40] Rename Highlight to Bookmark --- client/src/components/ContentBlock.vue | 3 +-- .../content-blocks/ContentComponent.vue | 22 +++++++++---------- .../gql/fragments/contentBlockParts.gql | 2 +- .../gql/mutations/updateContentBookmark.gql | 5 +++++ .../gql/mutations/updateContentHighlight.gql | 5 ----- ...ghts.py => 0015_contentblock_bookmarks.py} | 6 ++--- server/books/models/contentblock.py | 4 ++-- server/books/schema/mutations/contentblock.py | 14 ++++++------ server/books/schema/mutations/main.py | 4 ++-- server/books/schema/queries.py | 8 +++---- server/notes/migrations/0001_initial.py | 4 ++-- server/notes/models.py | 5 ++--- 12 files changed, 40 insertions(+), 42 deletions(-) create mode 100644 client/src/graphql/gql/mutations/updateContentBookmark.gql delete mode 100644 client/src/graphql/gql/mutations/updateContentHighlight.gql rename server/books/migrations/{0015_contentblock_highlights.py => 0015_contentblock_bookmarks.py} (63%) diff --git a/client/src/components/ContentBlock.vue b/client/src/components/ContentBlock.vue index c0b79ec8..a8b22d32 100644 --- a/client/src/components/ContentBlock.vue +++ b/client/src/components/ContentBlock.vue @@ -17,12 +17,11 @@

{{instrumentLabel}}

{{contentBlock.title}}

- + :bookmarks="contentBlock.bookmarks"> diff --git a/client/src/components/content-blocks/ContentComponent.vue b/client/src/components/content-blocks/ContentComponent.vue index 4b063a84..4be91e1e 100644 --- a/client/src/components/content-blocks/ContentComponent.vue +++ b/client/src/components/content-blocks/ContentComponent.vue @@ -1,9 +1,9 @@