diff --git a/client/src/components/modules/Module.vue b/client/src/components/modules/Module.vue index e04c74e4..364a5034 100644 --- a/client/src/components/modules/Module.vue +++ b/client/src/components/modules/Module.vue @@ -5,16 +5,15 @@ v-if="module.id" >
-
+

{{ module.metaTitle }}

-
-
+
@@ -178,12 +177,12 @@ display: flex; justify-content: flex-start; align-items: stretch; - margin-bottom: 10px; + margin-bottom: $small-spacing; } &__meta-title { @include meta-title; - margin-right: 20px; + margin-right: $medium-spacing; } diff --git a/client/src/components/modules/ModuleFilter.vue b/client/src/components/modules/ModuleFilter.vue index 894c9d4c..bd299d8f 100644 --- a/client/src/components/modules/ModuleFilter.vue +++ b/client/src/components/modules/ModuleFilter.vue @@ -36,13 +36,11 @@ diff --git a/client/src/pages/topic-page.vue b/client/src/pages/topic-page.vue index 51e9bdc9..14d494c2 100644 --- a/client/src/pages/topic-page.vue +++ b/client/src/pages/topic-page.vue @@ -14,9 +14,7 @@

{{ topic.teaser }}

-
- -
+
diff --git a/server/books/models/module.py b/server/books/models/module.py index 8aaeac95..236b49df 100644 --- a/server/books/models/module.py +++ b/server/books/models/module.py @@ -1,25 +1,20 @@ from django.db import models from django.utils import timezone -from wagtail.admin.panels import FieldPanel, InlinePanel, TabbedInterface, ObjectList, MultiFieldPanel, MultipleChooserPanel -from wagtail.fields import RichTextField from django.utils.translation import gettext_lazy as _ +from wagtail.admin.panels import FieldPanel, TabbedInterface, ObjectList +from wagtail.fields import RichTextField from core.constants import DEFAULT_RICH_TEXT_FEATURES from core.wagtail_utils import StrictHierarchyPage, get_default_settings from users.models import SchoolClass -from django.utils.text import slugify -FILTER_ATTRIBUTE_TYPE = ( - ('all', 'All'), - ('exact', 'Exact') -) +FILTER_ATTRIBUTE_TYPE = (("all", "All"), ("exact", "Exact")) + class ModuleLevel(models.Model): name = models.CharField(max_length=255, unique=True) filter_attribute_type = models.CharField( - max_length=16, - choices=FILTER_ATTRIBUTE_TYPE, - default='exact' + max_length=16, choices=FILTER_ATTRIBUTE_TYPE, default="exact" ) def __str__(self): @@ -42,9 +37,7 @@ class ModuleCategory(models.Model): name = models.CharField(max_length=255) filter_attribute_type = models.CharField( - max_length=16, - choices=FILTER_ATTRIBUTE_TYPE, - default='exact' + max_length=16, choices=FILTER_ATTRIBUTE_TYPE, default="exact" ) def __str__(self): @@ -57,9 +50,12 @@ class Module(StrictHierarchyPage): verbose_name_plural = "Module" meta_title = models.CharField(max_length=255, help_text="e.g. 'Intro' or 'Modul 1'") - level = models.ForeignKey(ModuleLevel, on_delete=models.SET_NULL, blank=True, null=True) - category = models.ForeignKey(ModuleCategory, on_delete=models.SET_NULL, blank=True, null=True) - + level = models.ForeignKey( + ModuleLevel, on_delete=models.SET_NULL, blank=True, null=True + ) + category = models.ForeignKey( + ModuleCategory, on_delete=models.SET_NULL, blank=True, null=True + ) hero_image = models.ForeignKey( "wagtailimages.Image", @@ -86,27 +82,6 @@ class Module(StrictHierarchyPage): FieldPanel("hero_source"), FieldPanel("teaser"), FieldPanel("intro"), - # TODO: Why is this commented out? - # InlinePanel( - # "assignments", - # label=_("Assignment"), - # classname="collapsed", - # heading=_("linked assignments"), - # help_text=_( - # "These %s are automatically linked, they are shown here only to provide an overview. Please don't change anything here." - # ) - # % _("assignments"), - # ), - # InlinePanel( - # "surveys", - # heading=_("linked surveys"), - # label=_("Survey"), - # classname="collapsed", - # help_text=_( - # "These %s are automatically linked, they are shown here only to provide an overview. Please don't change anything here." - # ) - # % _("surveys"), - # ), ] edit_handler = TabbedInterface( @@ -175,7 +150,6 @@ class Module(StrictHierarchyPage): return f"{self.meta_title} - {self.title}" - class RecentModule(models.Model): module = models.ForeignKey( Module, on_delete=models.CASCADE, related_name="recent_modules" diff --git a/server/books/schema/mutations/module.py b/server/books/schema/mutations/module.py index 1df5bf00..74bb94ab 100644 --- a/server/books/schema/mutations/module.py +++ b/server/books/schema/mutations/module.py @@ -117,6 +117,5 @@ class UpdateLastModuleLevel(relay.ClientIDMutation): id = args.get('id') module_level = get_object(ModuleLevel, id) - User.objects.filter(pk=user.id).update(last_module_level_id=module_level.id) return cls(user=user) diff --git a/server/books/schema/mutations/snapshot.py b/server/books/schema/mutations/snapshot.py index dde47661..e3d9808d 100644 --- a/server/books/schema/mutations/snapshot.py +++ b/server/books/schema/mutations/snapshot.py @@ -3,7 +3,7 @@ from graphene import relay from api.types import FailureNode, Success from api.utils import get_object -from books.models import Module, ContentBlock, Chapter +from books.models import Module from books.models.snapshot import Snapshot from books.schema.nodes import SnapshotNode, ModuleNode from users.models import SchoolClass diff --git a/server/books/schema/nodes/module.py b/server/books/schema/nodes/module.py index b38b4480..79a282b0 100644 --- a/server/books/schema/nodes/module.py +++ b/server/books/schema/nodes/module.py @@ -6,11 +6,16 @@ from graphene_django.filter import DjangoFilterConnectionField from assignments.models import StudentSubmission from assignments.schema.types import AssignmentNode, StudentSubmissionNode -from books.models import Module, Chapter, ContentBlock, RecentModule, ModuleLevel, ModuleCategory +from books.models import ( + Module, + Chapter, + ContentBlock, + RecentModule, +) from books.schema.interfaces.module import ModuleInterface from books.schema.nodes.chapter import ChapterNode -from books.schema.nodes.module_level import ModuleLevelNode from books.schema.nodes.module_category import ModuleCategoryNode +from books.schema.nodes.module_level import ModuleLevelNode from notes.models import ModuleBookmark, ContentBlockBookmark, ChapterBookmark from notes.schema import ( ModuleBookmarkNode, @@ -50,8 +55,7 @@ class ModuleNode(DjangoObjectType): bookmark = graphene.Field(ModuleBookmarkNode) my_submissions = DjangoFilterConnectionField(StudentSubmissionNode) my_answers = DjangoFilterConnectionField(AnswerNode) - my_content_bookmarks = DjangoFilterConnectionField( - ContentBlockBookmarkNode) + my_content_bookmarks = DjangoFilterConnectionField(ContentBlockBookmarkNode) my_chapter_bookmarks = DjangoFilterConnectionField(ChapterBookmarkNode) snapshots = graphene.List("books.schema.nodes.SnapshotNode") objective_groups = graphene.List(ObjectiveGroupNode) @@ -110,12 +114,6 @@ class ModuleNode(DjangoObjectType): def resolve_objective_groups(parent, info, **kwargs): return parent.objective_groups.all().prefetch_related("hidden_for") - def resolve_level(self, info, **kwargs): - return ModuleLevel.objects.get(pk=self.level_id) if self.level_id else None - - def resolve_category(self, info, **kwargs): - return ModuleCategory.objects.get(pk=self.category_id) if self.category_id else None - @staticmethod def resolve_snapshots(parent, info, **kwargs): user = info.context.user diff --git a/server/books/schema/nodes/module_category.py b/server/books/schema/nodes/module_category.py index 134d03ef..2e654311 100644 --- a/server/books/schema/nodes/module_category.py +++ b/server/books/schema/nodes/module_category.py @@ -1,5 +1,4 @@ from graphene import relay -from graphene import relay from graphene_django import DjangoObjectType from books.models import ModuleCategory @@ -9,8 +8,4 @@ class ModuleCategoryNode(DjangoObjectType): class Meta: model = ModuleCategory interfaces = (relay.Node,) - only_fields = [ - "id", - "name", - "filter_attribute_type", - ] + only_fields = "__all__" diff --git a/server/books/schema/nodes/module_level.py b/server/books/schema/nodes/module_level.py index ed6c8108..ab6b7bf6 100644 --- a/server/books/schema/nodes/module_level.py +++ b/server/books/schema/nodes/module_level.py @@ -1,5 +1,4 @@ from graphene import relay -from graphene import relay from graphene_django import DjangoObjectType from books.models import ModuleLevel @@ -9,9 +8,4 @@ class ModuleLevelNode(DjangoObjectType): class Meta: model = ModuleLevel interfaces = (relay.Node,) - only_fields = [ - "id", - "name", - "filter_attribute_type", - - ] + only_fields = "__all__" diff --git a/server/books/schema/queries.py b/server/books/schema/queries.py index 1de8e190..656fae43 100644 --- a/server/books/schema/queries.py +++ b/server/books/schema/queries.py @@ -5,10 +5,16 @@ from graphene_django.filter import DjangoFilterConnectionField from api.utils import get_object from core.logger import get_logger from .connections import TopicConnection, ModuleConnection -from .nodes import ContentBlockNode, ChapterNode, ModuleNode, NotFoundFailure, SnapshotNode, \ - TopicOr404Node -from .nodes.module_level import ModuleLevelNode +from .nodes import ( + ContentBlockNode, + ChapterNode, + ModuleNode, + NotFoundFailure, + SnapshotNode, + TopicOr404Node, +) from .nodes.module_category import ModuleCategoryNode +from .nodes.module_level import ModuleLevelNode from ..models import Book, Topic, Module, Chapter, Snapshot, ModuleLevel, ModuleCategory logger = get_logger(__name__) @@ -17,8 +23,7 @@ logger = get_logger(__name__) class BookQuery(object): node = relay.Node.Field() topic = graphene.Field(TopicOr404Node, slug=graphene.String()) - module = graphene.Field( - ModuleNode, slug=graphene.String(), id=graphene.ID()) + module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID()) chapter = relay.Node.Field(ChapterNode) content_block = relay.Node.Field(ContentBlockNode) snapshot = relay.Node.Field(SnapshotNode) @@ -46,13 +51,13 @@ class BookQuery(object): return Chapter.objects.filter(**kwargs).live() def resolve_snapshot(self, info, **kwargs): - id = kwargs.get('id') + id = kwargs.get("id") snapshot = get_object(Snapshot, id) return snapshot def resolve_module(self, info, **kwargs): - slug = kwargs.get('slug') - id = kwargs.get('id') + slug = kwargs.get("slug") + id = kwargs.get("id") module = None try: if id is not None: @@ -67,8 +72,8 @@ class BookQuery(object): return None def resolve_topic(self, info, **kwargs): - slug = kwargs.get('slug') - id = kwargs.get('id') + slug = kwargs.get("slug") + id = kwargs.get("id") if id is not None: return get_object(Topic, id) @@ -79,9 +84,8 @@ class BookQuery(object): return NotFoundFailure return None - def resolve_module_level(self, info, **kwargs): - module_level_id = kwargs.get('id') + module_level_id = kwargs.get("id") try: if module_level_id is not None: return get_object(Module, module_level_id) @@ -90,10 +94,10 @@ class BookQuery(object): return None def resolve_module_levels(self, *args, **kwargs): - return ModuleLevel.objects.filter(**kwargs) + return ModuleLevel.objects.all() def resolve_module_category(self, info, **kwargs): - id = kwargs.get('id') + id = kwargs.get("id") try: if id is not None: return get_object(Module, id) @@ -102,14 +106,7 @@ class BookQuery(object): return None def resolve_module_categories(self, *args, **kwargs): - return ModuleCategory.objects.filter(**kwargs) - - - - - - - + return ModuleCategory.objects.all() class ModuleTypeQuery(graphene.ObjectType): diff --git a/server/books/wagtail_hooks.py b/server/books/wagtail_hooks.py index 00630ef5..d940802e 100644 --- a/server/books/wagtail_hooks.py +++ b/server/books/wagtail_hooks.py @@ -3,8 +3,6 @@ from wagtail.contrib.modeladmin.options import ( ModelAdminGroup, modeladmin_register, ) -from wagtail import hooks - from .models.module import ModuleLevel, ModuleCategory, Module from django.utils.translation import gettext_lazy as _ diff --git a/server/graphql-schema-macos.sh b/server/graphql-schema-macos.sh new file mode 100755 index 00000000..9cbd2e36 --- /dev/null +++ b/server/graphql-schema-macos.sh @@ -0,0 +1,6 @@ +#!/bin/bash +python manage.py graphql_schema +sed -i '' 's/Node, Node/Node & Node/g' schema.graphql + +python manage.py graphql_schema --schema api.schema_public.schema --out schema-public.graphql +sed -i '' 's/Node, Node/Node & Node/g' schema-public.graphql