Skip to content

Commit

Permalink
[FE/BE] - Mozfest Hero updates (#7585)
Browse files Browse the repository at this point in the history
* Create integration branch for frontend and backend

* Bump wagtailmedia to 0.8.0

* Add EmbeddedVideoBlock

* Add WagtailVideoChooserBlock

* Add BannerCarouselSlideBlock

* Set new banner_video_type 'featured' instead of 'hardcoded'

* Add banner_carousel and banner_video to MozfestHomepage model

* Add new banner_video_type 'featured' in HTML templates

* Add faker for MozfestHomepage carousel

* Add faker for MozfestHomepage banner video

* Make migrations

* Fix spacing in HTML file

Co-authored-by: boggs ⚓ <hello@boggs.xyz>

* [7533] - FE Mozfest homepage hero (#7589)

* Current events slider styles

* Install swiper and style event cards

* video play on hover styling

* Minor spacing

* Mozfest homepage banner start

* Homepage header, mobile styling and slideshow styling

* Homepage banner cleanup and organization

* Link mobile and background image sliders

* Add loops for test hero content

* Rebase on to BE branch

* Thumbnail fixes for hosted cms video

* carousel js cleanup

* Integrate old video functionality back into branch

* Make old functionality work

* Change flag to featured again

* Revert name to homepage banner handler

* Remove carousel.scss

* Add spacing back to tailwind config

* Remove extra space from main.scss

* Add animation for sliding progress bar

* Make carousel clickable

* Only show carousel if there are carousels

* Remove uneeded carousel check

* Update migrations

* Fix template

* Add thumbnail

* Fix video thumbnail overlay fade out for external videos

* Remove unused template blocks, simplify external_video

* Update fake data

* CI fixes

* Use brand colors instead of rgb values

* Add stylelint-disable

* Add wagtailcore_tags

* Fix video conditionals on front end, remove minimum requirement on carousel

* Fix issue on FE template when there is no video thumbnail

* Update migrations

* Add help texts for banner_carousel and banner_video

* Scroll to video with offset through JS

* Still autoplay after interacting with banner carousel

* Add blue hover to CTA button

* Change selector to string instead of function for hero carousel

* Fix eslint issues

* Fix Percy issues

* Update comment on `banner_video_type` #7585 (comment)

* Remove fallback text for <video> #7585 (comment)

* Run npm run optimize:svg on play-circle-grey #7585 (comment)

* Change "PLAY VIDEO" and "PAUSE VIDEO" to normal case, use text-transform to transform them to uppercase

* Use template literals for query selectors, use forEach instead of for

Co-authored-by: Sharmaine Lim <amanda.lim@torchbox.com>
Co-authored-by: Sharmaine Lim <SharmaineLim@users.noreply.github.com>
Co-authored-by: Steve Stein <steven_ts@hotmail.com>
Co-authored-by: Daniel Miranda <manieldiranda@gmail.com>
  • Loading branch information
5 people committed Oct 21, 2021
1 parent 8dd7893 commit 6e98f07
Show file tree
Hide file tree
Showing 25 changed files with 668 additions and 121 deletions.
3 changes: 3 additions & 0 deletions network-api/networkapi/mozfest/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class Meta:
banner_video_url = Faker('url')
banner_heading_text = Faker('sentence', nb_words=6, variable_nb_words=True)

banner_carousel = Faker('streamfield', fields=['banner_carousel'])
banner_video = Faker('streamfield', fields=['banner_video'])

signup = SubFactory(SignupFactory)


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.1.11 on 2021-10-15 16:07

from django.db import migrations
import networkapi.wagtailpages.pagemodels.customblocks.video_block
import wagtail.core.blocks
import wagtail.core.fields
import wagtail.images.blocks


class Migration(migrations.Migration):

dependencies = [
('mozfest', '0021_add_spaces_cards'),
]

operations = [
migrations.AddField(
model_name='mozfesthomepage',
name='banner_carousel',
field=wagtail.core.fields.StreamField([('slide', wagtail.core.blocks.StructBlock([('image', wagtail.images.blocks.ImageChooserBlock()), ('heading', wagtail.core.blocks.CharBlock(required=False)), ('description', wagtail.core.blocks.CharBlock(required=False))]))], blank=True, help_text='The slides shown on the new Hero. Please ensure that there are exactly 3 slides. The old Hero will be shown if there are no slides present.', null=True),
),
migrations.AddField(
model_name='mozfesthomepage',
name='banner_video',
field=wagtail.core.fields.StreamField([('CMS_video', networkapi.wagtailpages.pagemodels.customblocks.video_block.WagtailVideoChooserBlock()), ('external_video', wagtail.core.blocks.StructBlock([('video_url', wagtail.core.blocks.URLBlock(help_text='For YouTube: go to your YouTube video and click “Share,” then “Embed,” and then copy and paste the provided URL only. For example: https://www.youtube.com/embed/3FIVXBawyQw For Vimeo: follow similar steps to grab the embed URL. For example: https://player.vimeo.com/video/9004979')), ('thumbnail', wagtail.images.blocks.ImageChooserBlock(help_text='The image to show before the video is played.'))]))], blank=True, help_text='The video to play when users click "Watch Video". This is only shown on the new Hero.', null=True),
),
]
56 changes: 50 additions & 6 deletions network-api/networkapi/mozfest/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from wagtail.snippets.edit_handlers import SnippetChooserPanel
from wagtail_localize.fields import SynchronizedField, TranslatableField


from networkapi.wagtailpages.utils import (
set_main_site_nav_information,
get_page_tree_information
Expand Down Expand Up @@ -126,10 +125,15 @@ class MozfestHomepage(MozfestPrimaryPage):
MozFest Homepage
'banner_video_type' determines what version of banner design the page should load
"""
# this tells the templates to load a hardcoded, pre-defined video in the banner background
banner_video_type = "hardcoded"
If the value of `banner_video_type` is `hardcoded`, it displays a hardcoded,
predefined video in the banner background.
If the value of `banner_video_type` is `featured`, it displays a carousel of
cards with their associated headings and body content (`banner_carousel`),
and an embedded user-defined video (`banner_video`).
"""
banner_video_type = "featured"

cta_button_label = models.CharField(
max_length=250,
Expand All @@ -156,12 +160,39 @@ class MozfestHomepage(MozfestPrimaryPage):
help_text='A banner paragraph specific to the homepage'
)

# For banner_video_type == 'hardcoded'
banner_video_url = models.URLField(
max_length=2048,
blank=True,
help_text='The video to play when users click "watch video"'
)

# For banner_video_type == 'featured'
banner_carousel = StreamField(
[
('slide', customblocks.BannerCarouselSlideBlock()),
],
max_num=3,
help_text='The slides shown on the new Hero. Please ensure that there '
'are exactly 3 slides. The old Hero will be shown if there '
'are no slides present.',
blank=True,
null=True,
)

# For banner_video_type == 'featured'
banner_video = StreamField(
[
('CMS_video', customblocks.WagtailVideoChooserBlock()),
('external_video', customblocks.ExternalVideoBlock()),
],
max_num=1,
help_text='The video to play when users click "Watch Video". This is '
'only shown on the new Hero.',
blank=True,
null=True,
)

subpage_types = [
'MozfestPrimaryPage',
'MozfestHomepage',
Expand All @@ -176,16 +207,29 @@ class MozfestHomepage(MozfestPrimaryPage):
FieldPanel('cta_button_label'),
FieldPanel('cta_button_destination'),
FieldPanel('banner_heading'),
StreamFieldPanel('banner_carousel'),
FieldPanel('banner_guide_text'),
FieldPanel('banner_video_url'),
StreamFieldPanel('banner_video'),
] + parent_panels[n:]

if banner_video_type == "hardcoded":
# Hide all the panels that aren't relevant for the video banner version of the MozFest Homepage
content_panels = [
field for field in all_panels
if field.field_name not in
['banner', 'header', 'intro', 'banner_guide_text', 'banner_video_url']
if field.field_name not in [
'banner', 'header', 'intro', 'banner_carousel', 'banner_guide_text',
'banner_video', 'banner_video_url',
]
]
elif banner_video_type == "featured":
# Hide all the panels that aren't relevant for the video banner version of the MozFest Homepage
content_panels = [
field for field in all_panels
if field.field_name not in [
'banner', 'banner_guide_text', 'banner_video_url', 'cta_button_destination',
'cta_button_label', 'header', 'hero_image', 'intro',
]
]
else:
content_panels = all_panels
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<div class="tw-flex tw-justify-center tw-items-start tw-flex-col tw-mb-5 medium:tw-flex-row medium:tw-justify-between medium:tw-items-center">
<h2 class="font-weight-bold h3-heading tw-font-semibold tw-mb-4">{{ title }}</h2>
<div class="tw-flex tw-flex-row tw-justify-between tw-items-center">
<div class="swiper-button-prev">
<svg class="swiper-button-prev__icon" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M20.75 10.5c0-.70761-.5099-1.28125-1.1389-1.28125H1.38889C.759899 9.21875.25 9.79239.25 10.5c0 .7076.509899 1.2812 1.13889 1.2812H19.6111c.629 0 1.1389-.5736 1.1389-1.2812Z"
fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.1664.625269c-.44474-.500359-1.16584-.500359-1.6106 0L.583572 9.59402c-.444763.50038-.444763 1.31158 0 1.81198L8.5558 20.3747c.44476.5004 1.16586.5004 1.6106 0 .4448-.5003.4448-1.3116 0-1.8119L2.99952 10.5l7.16688-8.06277c.4448-.50036.4448-1.3116 0-1.811961Z"
fill="currentColor"/>
</svg>
</div>
<div class="swiper-button-next">
<svg class="swiper-button-next__icon" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M.25 10.5c0-.70761.509898-1.28125 1.13889-1.28125H19.6111c.629 0 1.1389.57364 1.1389 1.28125 0 .7076-.5099 1.2812-1.1389 1.2812H1.38889C.759898 11.7812.25 11.2076.25 10.5Z"
fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.8336.625269c.4447-.500359 1.1658-.500359 1.6106 0l7.9722 8.968751c.4448.50038.4448 1.31158 0 1.81198l-7.9722 8.9687c-.4448.5004-1.1659.5004-1.6106 0-.4448-.5003-.4448-1.3116 0-1.8119L18.0005 10.5l-7.1669-8.06277c-.4448-.50036-.4448-1.3116 0-1.811961Z"
fill="currentColor"/>
</svg>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{% load i18n wagtailimages_tags %}
<div data-mozfest-hero-carousel>
<div class="tw-relative tw-pt-[120px] tw-flex tw-flex-col tw-justify-end{% if not page.banner_video %} tw-pb-6 medium:tw-pb-[120px]{% endif %}">

{# Background images slider #}
<div class="tw-absolute tw-inset-0">
<div class="tw-absolute tw-inset-0 tw-bg-black tw-z-20 tw-opacity-40"></div>
<div class="tw-bg-gradient-to-t tw-from-festival-blue-100 tw-via-festival-blue-100 tw-to-festival-purple-100 tw-w-full tw-h-full tw-absolute tw-inset-0 tw-z-10 tw-opacity-75"></div>
</div>

{# Background Images slider #}
<div class="tw-absolute tw-w-full tw-h-full tw-top-0 tw-left-0">
<div class="swiper-hero-carousel tw-h-full tw-overflow-hidden">
<div class="swiper-wrapper">
{% for slide_block in page.specific.banner_carousel %}
{% with slide=slide_block.value %}
{% image slide.image fill-1600x900 as img %}
<div class="swiper-slide tw-bg-cover tw-bg-center tw-bg-no-repeat tw-filter tw-grayscale" style="background-image: url({{ img.url }});"></div>
{% endwith %}
{% endfor %}
</div>
</div>
</div>

{# Text slider #}
<div class="tw-container tw-relative tw-z-20 tw-text-white">
<div>
<h1 class="tw-text-white tw-font-bold tw-mb-5">{{ page.banner_heading }}</h1>
{% if page.banner_video %}
<button id="mozfest-hero-video-cta" class="btn btn-primary tw-bg-white tw-text-black hover:tw-bg-blue hover:tw-text-white">{% trans "Watch last year’s recap video" %}</button>
{% endif %}
</div>

<div class="tw-relative tw-pt-[60px] medium:tw-pt-[100px] tw-hidden medium:tw-block">

{# pagination progress bars on desktop #}
<div class="swiper-hero-pagination tw-bottom-3 tw-relative tw-z-40 tw-grid tw-grid-cols-3 tw-gap-3 medium:tw-gap-4"></div>

{# Text #}
<div class="tw-grid tw-grid-cols-3 tw-gap-3 medium:tw-gap-4">
{% for slide_block in page.specific.banner_carousel %}
{% with slide=slide_block.value %}
<div>
<span class="tw-font-zilla tw-font-bold tw-inline-block h4-heading tw-text-white">{{ slide.heading }}</span>
<p class="tw-text-white">{{ slide.description }}</p>
</div>
{% endwith %}
{% endfor %}
</div>
</div>

{# mobile slider #}
{% include 'fragments/hero/hero_mobile_slider.html' with items=page.hero_slides %}
</div>

{# Video block #}
{% if page.banner_video %}
{% include 'fragments/hero/featured_video.html' %}
{% endif %}

</div>
</div>

{# Spacing for top of content section when there is no video #}
{% if not page.banner_video %}
<div class="tw-w-full tw-bg-white tw-h-7"></div>
{% endif %}


Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{% load i18n static wagtailcore_tags wagtailimages_tags %}
<div id="mozfest-hero-video" class="tw-relative tw-z-20 tw-pb-5 medium:tw-pb-[60px] tw-mt-7 medium:tw-mt-[60px]">

{# Overlay spacer #}
<div class="tw-bg-white tw-absolute tw-w-full tw-h-[80%] medium:tw-h-[90%] tw-bottom-0"></div>

{# Video Container #}
<div class="container">
{% for block in page.banner_video %}
<div style="padding-bottom: 56.25%;" class="embed-responsive tw-bg-black tw-text-black">

{# Thumbnail and overlay #}
<button
id="mozfest-home-watch-featured-video-button"
aria-label="{% trans "Watch Video" %}"
class="tw-bg-black tw-w-full tw-h-full tw-absolute tw-inset-0 tw-group tw-z-10 tw-bg-cover tw-bg-center tw-transition tw-duration-500"
{% if block.block_type == 'external_video' %}
{% image block.value.thumbnail fill-1200x600 as img %}
data-video-url="{{ block.value.video_url }}?&autoplay=1"
style="background-image: url({{ img.url }});"
{% endif %}
{% if block.block_type == 'CMS_video' %}
{% if block.value.thumbnail %}
style="background-image: url({{ block.value.thumbnail.url }});"
{% endif %}
{% endif %}
>
<span class="tw-relative tw-w-full tw-h-full tw-flex tw-justify-center tw-items-center">
{# Opacity layer #}
<div class="tw-absolute tw-bg-black tw-opacity-25 tw-inset-0 tw-w-full tw-h-full"></div>
{# Play Icon #}
<img src="{% static "_images/mozfest/play-circle-grey.svg" %}"
class="group-hover:tw--translate-y-1 tw-relative tw-z-10 tw-transition tw-w-[75px] tw-h-[75px] medium:tw-w-[108px] medium:tw-h-[108px]" alt=""/>
</span>
</button>

{# Video #}
{% if block.block_type == 'external_video' %}
<iframe
src=""
frameborder="0"
class="embed-responsive-item"
allow="autoplay; encrypted-media"
allowfullscreen>
</iframe>
{% else %}
{{ block }}
{% endif %}
</div>
{% endfor %}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{% load i18n wagtailcore_tags %}
<div class="banner">
<div class="background-wrapper">
<div class="overlay"></div>
<video class="banner-video" playsinline muted loop preload
poster="https://s3.amazonaws.com/mofo-assets/foundation/video/mozfest-banner-video-poster.jpg">
<source
src="https://s3.amazonaws.com/mofo-assets/foundation/video/mozfest-banner-video.mp4"
type="video/mp4">
</video>

<div class="video-control-wrapper dark-theme">
<div class="container">
<div class="row">
<div class="col-12">
<button class="btn btn-video-control btn-pause btn-secondary d-none">
<span>{% trans "Pause video" context "Pause button for video" %}</span>
</button>
<button class="btn btn-video-control btn-play btn-secondary d-none">
<span>{% trans "Play video" context "Play button for video" %}</span>
</button>
</div>
</div>
</div>
</div>
</div>

<div class="homepage-banner-content container">
<div class="row">
<div class="col-10 col-lg-8 dark-theme">
<h1 class="h1-heading">{{ page.banner_heading }}</h1>
</div>
</div>
</div>
</div>

{# Bottom overlaping spacing bar #}
<div class="container">
<div class="row cutout-wrapper-row">
<div class="cutout col-12 pt-4">
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="swiper-hero-mobile tw-overflow-hidden medium:tw-hidden tw-mt-7">

<div class="swiper-wrapper">
{% for slide_block in page.banner_carousel %}
{% with slide=slide_block.value %}
<div class="swiper-slide">
<div class="swiper-mobile-progress-bar"></div>
<span class="tw-font-zilla tw-font-bold tw-inline-block h4-heading tw-text-white tw-mt-4">{{ slide.heading }}</span>
<p class="tw-text-white">{{ slide.description }}</p>
</div>
{% endwith %}
{% endfor %}
</div>
</div>


50 changes: 0 additions & 50 deletions network-api/networkapi/mozfest/templates/fragments/hero/large.html

This file was deleted.

0 comments on commit 6e98f07

Please sign in to comment.