import uuid from django.db import models from django.utils.translation import gettext_lazy as _ from wagtail.admin.panels import FieldPanel from wagtail.blocks import RichTextBlock from wagtail.contrib.settings.models import BaseSiteSetting from wagtail.fields import StreamField from wagtail.models import Locale, Site, TranslatableMixin from wagtail.snippets.models import register_snippet from ocyan.plugin.wagtail.block_plugin import get_extra_ocyan_settings_blocks from ocyan.plugin.wagtail.blocks import ( AboutUsBlock, HeadedPagelistBlock, HeadedRichTextBlock, ) from mandelblog_content_guard.mixins import MultilingualValidationMixin @register_snippet class LocalizedFooterContent( MultilingualValidationMixin, TranslatableMixin, models.Model ): title = models.CharField(max_length=120, default="Footer content") site = models.ForeignKey( Site, on_delete=models.CASCADE, related_name="localized_footer_contents" ) locale = models.ForeignKey(Locale, on_delete=models.PROTECT, related_name="+") translation_key = models.UUIDField(default=uuid.uuid4, editable=False) footer = StreamField( [ ("about_us", AboutUsBlock()), ("text", HeadedRichTextBlock()), ("page_list", HeadedPagelistBlock()), ] + get_extra_ocyan_settings_blocks(), default=list, use_json_field=True, ) mini_footer = StreamField( [("text", RichTextBlock())], default=list, use_json_field=True, ) panels = [ FieldPanel("title"), FieldPanel("site"), FieldPanel("locale"), FieldPanel("footer"), FieldPanel("mini_footer"), ] class Meta(TranslatableMixin.Meta): verbose_name = _("Localized footer content") verbose_name_plural = _("Localized footer contents") constraints = [ models.UniqueConstraint( fields=["site", "locale"], name="unique_localized_footer_per_site_locale", ), ] def __str__(self): return f"{self.site.hostname} [{self.locale.language_code}]" class LocaleAuditRun(models.Model): started_at = models.DateTimeField(auto_now_add=True) finished_at = models.DateTimeField(null=True, blank=True) locale_codes = models.JSONField(default=list, blank=True) fix_enabled = models.BooleanField(default=False) total_urls_checked = models.PositiveIntegerField(default=0) issues_found = models.PositiveIntegerField(default=0) pages_with_issues = models.PositiveIntegerField(default=0) summary = models.JSONField(default=dict, blank=True) class Meta: ordering = ["-started_at"] class LocaleAuditIssue(models.Model): run = models.ForeignKey( LocaleAuditRun, related_name="issues", on_delete=models.CASCADE ) locale_code = models.CharField(max_length=12) object_id = models.PositiveIntegerField(null=True, blank=True) object_type = models.CharField(max_length=128, blank=True) url = models.TextField(blank=True) title = models.CharField(max_length=255, blank=True) severity = models.CharField(max_length=16) issue_type = models.CharField(max_length=64) field_path = models.CharField(max_length=512, blank=True) bad_value = models.TextField(blank=True) replacement = models.TextField(blank=True) fixed = models.BooleanField(default=False) extra = models.JSONField(default=dict, blank=True) class Meta: ordering = ["locale_code", "url", "field_path"]