diff --git a/books/migrations/0156_book_content_warning.py b/books/migrations/0156_book_content_warning.py
new file mode 100644
index 000000000..1cfb5c6f0
--- /dev/null
+++ b/books/migrations/0156_book_content_warning.py
@@ -0,0 +1,26 @@
+# Generated by Django 5.0.6 on 2024-06-26 16:58
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("books", "0155_alter_book_book_cover_text_color_and_more"),
+ ("snippets", "0036_contentwarning"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="book",
+ name="content_warning",
+ field=models.ForeignKey(
+ blank=True,
+ help_text="Message shown in the content warning modal.",
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="content_warnings_content_warning",
+ to="snippets.contentwarning",
+ ),
+ ),
+ ]
diff --git a/books/models.py b/books/models.py
index 065b38fe7..03e3f5086 100644
--- a/books/models.py
+++ b/books/models.py
@@ -551,6 +551,14 @@ class Book(Page):
description = RichTextField(
blank=True, help_text="Description shown on Book Detail page.")
+ content_warning = models.ForeignKey(
+ snippets.ContentWarning,
+ on_delete=models.SET_NULL,
+ null=True,
+ blank=True,
+ related_name='content_warnings_content_warning',
+ help_text="Message shown in the content warning modal.")
+
cover = models.ForeignKey(
'wagtaildocs.Document',
null=True, blank=True,
@@ -731,7 +739,7 @@ def get_community_resource_feature_link_url(self):
support_statement = models.TextField(blank=True, null=True,
default="With philanthropic support, this book is used in classrooms, saving students dollars this school year. Learn more about our impact and how you can help.",
help_text="Updating this statement updates it for all book pages.")
-
+
promote_snippet = StreamField(PromoteSnippetBlock(), null=True, blank=True, use_json_field=True)
videos = StreamField([
@@ -773,6 +781,7 @@ def get_community_resource_feature_link_url(self):
InlinePanel('k12book_subjects', label='K12 Subjects'),
FieldPanel('is_ap'),
FieldPanel('description', classname="full"),
+ FieldPanel('content_warning'),
FieldPanel('cover'),
FieldPanel('title_image'),
FieldPanel('cover_color'),
@@ -870,6 +879,7 @@ def get_community_resource_feature_link_url(self):
APIField('k12book_subjects'),
APIField('is_ap'),
APIField('description'),
+ APIField('content_warning_text'),
APIField('cover_url'),
APIField('title_image_url'),
APIField('cover_color'),
@@ -978,6 +988,10 @@ def errata_content(self):
return snippets.ErrataContent.objects.filter(locale=self.locale).first().content
return snippets.ErrataContent.objects.filter(book_state=self.book_state, locale=self.locale).first().content
+ @property
+ def content_warning_text(self):
+ return self.content_warning.content_warning if self.content_warning else None
+
def get_slug(self):
return 'books/{}'.format(self.slug)
diff --git a/snippets/migrations/0036_contentwarning.py b/snippets/migrations/0036_contentwarning.py
new file mode 100644
index 000000000..ccaf91ef9
--- /dev/null
+++ b/snippets/migrations/0036_contentwarning.py
@@ -0,0 +1,37 @@
+# Generated by Django 5.0.6 on 2024-06-25 18:22
+
+import django.db.models.deletion
+import uuid
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("snippets", "0035_alter_k12subject_subject_color_and_more"),
+ ("wagtailcore", "0089_log_entry_data_json_null_to_object"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="ContentWarning",
+ fields=[
+ ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
+ ("translation_key", models.UUIDField(default=uuid.uuid4, editable=False)),
+ ("content_warning", models.TextField()),
+ (
+ "locale",
+ models.ForeignKey(
+ editable=False,
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="+",
+ to="wagtailcore.locale",
+ ),
+ ),
+ ],
+ options={
+ "abstract": False,
+ "unique_together": {("translation_key", "locale")},
+ },
+ ),
+ ]
diff --git a/snippets/models.py b/snippets/models.py
index 9e43b85ce..e0a461d37 100644
--- a/snippets/models.py
+++ b/snippets/models.py
@@ -485,3 +485,19 @@ def __str__(self):
register_snippet(AmazonBookBlurb)
+
+class ContentWarning(TranslatableMixin, models.Model):
+ content_warning = models.TextField()
+
+ api_fields = ('content_warning')
+
+ panels = [
+ FieldPanel('content_warning')
+ ]
+
+ def __str__(self):
+ return (self.content_warning[:100] + '...') if len(self.content_warning) > 100 else self.content_warning
+
+
+
+register_snippet(ContentWarning)
diff --git a/snippets/serializers.py b/snippets/serializers.py
index c60b2fee7..216d1eb2f 100644
--- a/snippets/serializers.py
+++ b/snippets/serializers.py
@@ -39,11 +39,11 @@ class K12SubjectSerializer(serializers.ModelSerializer):
class Meta:
model = K12Subject
fields = ('id',
- 'name',
- 'intro_text',
- 'subject_image',
- 'subject_category' ,
- 'subject_color',
+ 'name',
+ 'intro_text',
+ 'subject_image',
+ 'subject_category' ,
+ 'subject_color',
'subject_link'
)
read_only_fields = ('id',
@@ -132,5 +132,3 @@ class Meta:
model = AmazonBookBlurb
fields = ('amazon_book_blurb',)
read_only_fields = ('amazon_book_blurb',)
-
-
diff --git a/snippets/signals.py b/snippets/signals.py
index 2def15780..39ef27cb2 100644
--- a/snippets/signals.py
+++ b/snippets/signals.py
@@ -2,7 +2,7 @@
from django.dispatch import receiver
from global_settings.functions import invalidate_cloudfront_caches
-from snippets.models import Subject, Role, ErrataContent, SubjectCategory, GiveBanner, BlogContentType, BlogCollection, \
+from snippets.models import ContentWarning, Subject, Role, ErrataContent, SubjectCategory, GiveBanner, BlogContentType, BlogCollection, \
WebinarCollection, AmazonBookBlurb, PromoteSnippet
@@ -53,3 +53,6 @@ def clear_cloudfront_on_assignable_available_save(sender, **kwargs):
def clear_cloudfront_on_amazon_book_blurb_save(sender, **kwargs):
invalidate_cloudfront_caches('snippets/amazonbookblurb')
+@receiver(post_save, sender=ContentWarning)
+def clear_cloudfront_on_content_warning_save(sender, **kwargs):
+ invalidate_cloudfront_caches('snippets/contentwarning')
diff --git a/snippets/tests.py b/snippets/tests.py
index c08b51990..752e7c49a 100644
--- a/snippets/tests.py
+++ b/snippets/tests.py
@@ -6,7 +6,7 @@
from django.conf import settings
from django.urls import reverse
-from snippets.models import Subject, ErrataContent, GiveBanner, BlogContentType, NoWebinarMessage, K12Subject, \
+from snippets.models import ContentWarning, Subject, ErrataContent, GiveBanner, BlogContentType, NoWebinarMessage, K12Subject, \
FacultyResource, StudentResource, Role, SharedContent, NewsSource, SubjectCategory, BlogCollection, \
AmazonBookBlurb, PromoteSnippet
@@ -72,6 +72,11 @@ def setUp(self):
amazon_book_blurb="Amazon Book Blurb. Amazon Book Blurb. Amazon Book Blurb.")
self.amazon_book_blurb.save()
+ self.content_warning = ContentWarning(
+ content_warning = "Content Warning"
+ )
+ self.content_warning.save()
+
def test_can_create_subject(self):
subject = Subject(name="Science", page_content="Science page content.", seo_title="Science SEO Title",
@@ -151,4 +156,3 @@ def test_can_create_promote_snippet(self):
promote_snippet.save()
self.assertEqual(promote_snippet.name, "Assignable")
-