diff --git a/poetry.lock b/poetry.lock index 16ba4b398..84dfd382e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3162,6 +3162,25 @@ wagtail = ">=5.2" [package.extras] testing = ["coverage (>=4.5)"] +[[package]] +name = "wagtailmedia" +version = "0.16.0" +description = "A Wagtail module for audio and video files." +optional = false +python-versions = ">=3.9" +files = [ + {file = "wagtailmedia-0.16.0-py3-none-any.whl", hash = "sha256:40e3adc077ed6251b9c43a7177649e8cdefa4f94828dff6f1ca3e48ba61dcdca"}, + {file = "wagtailmedia-0.16.0.tar.gz", hash = "sha256:1f757984240822a7ddfe3eda8e58243f31a3c29935ce8014499e7e664923d4c9"}, +] + +[package.dependencies] +Django = ">=4.2" +Wagtail = ">=6.3" + +[package.extras] +linting = ["pre-commit (>=4.2.0)"] +testing = ["coverage (>=7.8.0)"] + [[package]] name = "watchdog" version = "4.0.0" @@ -3384,4 +3403,4 @@ gunicorn = ["gunicorn"] [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "c819112da4982095811643daf1919d4170691b8339d012f53819578d12927870" +content-hash = "ea1090f0985026a23a3f3ad0fcd93706d91f3965a1c200f09601b9816db1d4e0" diff --git a/pyproject.toml b/pyproject.toml index 5343eb64c..79561fb86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,7 @@ urllib3 = "^2.3.0" whitenoise = "^6.9.0" social-auth-app-django = "^5.4.3" # Release 5.5 drops support for Django 4.2 django-xff = "^1.5.0" +wagtailmedia = "^0.16.0" [tool.poetry.extras] gunicorn = ["gunicorn"] diff --git a/rca/home/blocks.py b/rca/home/blocks.py index 6f4cc5459..e24132a95 100644 --- a/rca/home/blocks.py +++ b/rca/home/blocks.py @@ -2,9 +2,12 @@ from itertools import chain from django.core.exceptions import ValidationError +from django.forms.utils import ErrorList from django.utils import timezone from wagtail import blocks +from wagtail.blocks.struct_block import StructBlockValidationError from wagtail.images.blocks import ImageChooserBlock +from wagtailmedia.blocks import VideoChooserBlock from rca.editorial.models import EditorialPage from rca.events.models import EventDetailPage @@ -234,7 +237,8 @@ class PromoBannerBlock(blocks.StructBlock): default="light", help_text="Select the background color for this promo banner", ) - image = ImageChooserBlock() + image = ImageChooserBlock(required=False) + video = VideoChooserBlock(required=False) title = blocks.CharBlock() strapline = blocks.CharBlock() cta = LinkBlock(label="Call to Action") @@ -244,6 +248,23 @@ class Meta: icon = "image" label = "Promo Banner" + def clean(self, value): + value = super().clean(value) + errors = {} + + if value["image"] and value["video"]: + error = ["Please select either an image or a video, but not both."] + errors["image"] = errors["video"] = ErrorList(error) + + if not value["image"] and not value["video"]: + error = ["Please select either an image or a video."] + errors["image"] = errors["video"] = ErrorList(error) + + if errors: + raise StructBlockValidationError(errors) + + return value + class HomePageBodyBlock(blocks.StreamBlock): body_section = BodySectionBlock() diff --git a/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/promo_banner_block.html b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/promo_banner_block.html index 088a55b3c..28cf16125 100644 --- a/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/promo_banner_block.html +++ b/rca/project_styleguide/templates/patterns/molecules/streamfield/blocks/promo_banner_block.html @@ -6,7 +6,7 @@ {# Match the background color of the previous section if it exists, otherwise use the value's background color #}
-
+

{{ value.title }}

{{ value.strapline }}

@@ -19,8 +19,14 @@

{{ value.title }}

{% endif %} -
- {% include "patterns/atoms/image/image--lazyload.html" with image_small=image_small width=580 height=607 image_large=image_large classList='promo-banner__image' %} +
+ {% if value.image %} + {% include "patterns/atoms/image/image--lazyload.html" with image_small=image_small width=580 height=607 image_large=image_large classList='promo-banner__image' %} + {% else %} + + {% endif %}
diff --git a/rca/settings/base.py b/rca/settings/base.py index 9e0cc4da0..769067e65 100644 --- a/rca/settings/base.py +++ b/rca/settings/base.py @@ -110,6 +110,7 @@ "rca.project_styleguide.apps.ProjectStyleguideConfig", "rest_framework", "corsheaders", + "wagtailmedia", "wagtail_rangefilter", "rangefilter", "wagtail_modeladmin", diff --git a/rca/static_src/sass/components/_promo-banner.scss b/rca/static_src/sass/components/_promo-banner.scss index 952a9e106..f4f4e1bca 100644 --- a/rca/static_src/sass/components/_promo-banner.scss +++ b/rca/static_src/sass/components/_promo-banner.scss @@ -10,11 +10,18 @@ } @include media-query(large) { + width: 100%; min-height: ($gutter * 20); padding-top: ($gutter * 7); padding-bottom: ($gutter * 3.5); } + &__grid { + @include media-query(large) { + overflow: visible; + } + } + &__intro { grid-column: 1 / span 2; margin-bottom: ($gutter * 2); @@ -63,32 +70,33 @@ } } - &__image-container { + &__media-container { grid-column: 1 / span 2; order: -1; margin-bottom: ($gutter * 2); @include media-query(large) { - grid-column: auto; + grid-column: 4 / span 2; + margin-bottom: -($gutter * 3.5); order: 0; - margin-bottom: 0; + position: relative; + // 100% + the last grid item in `grid-layout` + width: 116.74%; } - #{$root}__image { + #{$root}__image, + #{$root}__video { @include z-index(above-gridlines); height: 250px; + max-width: 100%; object-fit: cover; @include media-query(large) { bottom: 0; - height: calc(100% + 140px); + height: calc(100% + 280px); position: absolute; } } - - @include media-query(large) { - display: block; - } } &.bg--dark {