from django.db import models from django.utils import timezone from wagtail.admin.panels import FieldPanel, InlinePanel, TabbedInterface, ObjectList from wagtail.fields import RichTextField from django.utils.translation import ugettext_lazy as _ from core.constants import DEFAULT_RICH_TEXT_FEATURES from core.wagtail_utils import StrictHierarchyPage, get_default_settings from users.models import SchoolClass class Module(StrictHierarchyPage): class Meta: verbose_name = "Modul" verbose_name_plural = "Module" meta_title = models.CharField(max_length=255, help_text="e.g. 'Intro' or 'Modul 1'") hero_image = models.ForeignKey( "wagtailimages.Image", null=True, blank=True, on_delete=models.SET_NULL, related_name="+", ) hero_source = models.CharField( max_length=255, help_text="e.g. 'Reuters', 'Wikipedia'", blank=True ) teaser = models.TextField() intro = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES) solutions_enabled_for = models.ManyToManyField(SchoolClass) content_panels = [ FieldPanel("title", classname="full title"), FieldPanel("meta_title", classname="full title"), FieldPanel("hero_image"), FieldPanel("hero_source"), FieldPanel("teaser"), FieldPanel("intro"), # 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( [ObjectList(content_panels, heading="Content"), get_default_settings()] ) template = "generic_page.html" parent_page_types = ["books.Topic"] subpage_types = ["books.Chapter"] # todo: isn't this a duplicate definition? def get_child_ids(self): return self.get_children().values_list("id", flat=True) def sync_from_school_class(self, school_class_template, school_class_to_sync): # import here so we don't get a circular import error from books.models import Chapter, ContentBlock # get chapters of module chapters = Chapter.get_by_parent(self) content_block_query = ContentBlock.objects.none() # get content blocks of chapters for chapter in chapters: content_block_query = content_block_query.union( ContentBlock.get_by_parent(chapter) ) # clear all `hidden for` and `visible for` for class `school_class_to_sync` for content_block in school_class_to_sync.hidden_content_blocks.intersection( content_block_query ): content_block.hidden_for.remove(school_class_to_sync) for content_block in school_class_to_sync.visible_content_blocks.intersection( content_block_query ): content_block.visible_for.remove(school_class_to_sync) # get all content blocks with `hidden for` for class `school_class_pattern` for content_block in school_class_template.hidden_content_blocks.intersection( content_block_query ): # add `school_class_to_sync` to these blocks' `hidden for` content_block.hidden_for.add(school_class_to_sync) # get all content blocks with `visible for` for class `school_class_pattern` for content_block in school_class_template.visible_content_blocks.intersection( content_block_query ): # add `school_class_to_sync` to these blocks' `visible for` content_block.visible_for.add(school_class_to_sync) for chapter in chapters: chapter.sync_title_visibility(school_class_template, school_class_to_sync) chapter.sync_description_visibility( school_class_template, school_class_to_sync ) objective_groups = self.objective_groups.all() for objective_group in objective_groups: objective_group.sync_visibility(school_class_template, school_class_to_sync) def get_admin_display_title(self): return f"{self.meta_title} - {self.title}" class RecentModule(models.Model): module = models.ForeignKey( Module, on_delete=models.CASCADE, related_name="recent_modules" ) user = models.ForeignKey("users.User", on_delete=models.CASCADE) visited = models.DateTimeField(default=timezone.now) class Meta: get_latest_by = "visited"