106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
from django.db import models
|
|
from django.utils import timezone
|
|
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList
|
|
from wagtail.core.fields import RichTextField
|
|
from wagtail.images.edit_handlers import ImageChooserPanel
|
|
|
|
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='+'
|
|
)
|
|
|
|
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"),
|
|
ImageChooserPanel('hero_image'),
|
|
FieldPanel('teaser'),
|
|
FieldPanel('intro'),
|
|
]
|
|
|
|
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'
|