From 83737917d32caf5d9e70b46b2320582a9b0dbad8 Mon Sep 17 00:00:00 2001
From: Shahbaz Shabbir <32649010+shahbaz-shabbir05@users.noreply.github.com>
Date: Fri, 19 Jan 2024 18:08:50 +0500
Subject: [PATCH] feat: enterprise page (#2834)
* feat: enterprise page
* fix: enterprise page tests
* fix: richtext fields
* fix: migration file
* fix: code formatting
* fix: cta description gap
* fix: nav border line
* fix: update richtext field tags and styles
* fix: learning journey background
* fix: update banner background design structure
* fix: addressed review feedback
* fix: updated migrations file
* fix: code formatting
* fix: failed tests
* fix: enterprise page slug
* fix: update configure_wagtail command for enterprise page
* fix: configure_wagtail command comments
---
app.json | 4 +
cms/api.py | 34 +-
cms/blocks.py | 42 +++
cms/constants.py | 1 +
cms/factories.py | 76 ++++
cms/migrations/0068_enterprisepage.py | 351 ++++++++++++++++++
cms/models.py | 343 ++++++++++++++++-
cms/models_test.py | 140 ++++++-
cms/templates/enterprise_page.html | 40 ++
cms/templates/partials/enterprise/banner.html | 52 +++
.../enterprise/companies_logo_carousel.html | 16 +
.../partials/enterprise/learning_journey.html | 23 ++
.../enterprise/learning_strategy_form.html | 27 ++
.../partials/enterprise/success_stories.html | 24 ++
cms/views_test.py | 27 ++
mitxpro/settings.py | 5 +
static/images/enterprise/ctrl-left.png | Bin 0 -> 4531 bytes
static/images/enterprise/ctrl-right.png | Bin 0 -> 4547 bytes
.../enterprise/enterprise-page-banner-bg.png | Bin 0 -> 174017 bytes
.../enterprise-page-banner-hero.png | Bin 0 -> 275732 bytes
.../enterprise/enterprise-page-dots-bg.png | Bin 0 -> 3847 bytes
.../enterprise-page-learning-path.png | Bin 0 -> 41353 bytes
static/js/companies_logo_carousel.js | 40 ++
static/js/entry/django.js | 4 +
static/js/success_stories_carousel.js | 41 ++
.../enterprise/companies-logo-carousel.scss | 110 ++++++
.../detail/enterprise/learning-journey.scss | 170 +++++++++
.../enterprise/learning-strategy-form.scss | 237 ++++++++++++
.../detail/enterprise/success-stories.scss | 246 ++++++++++++
static/scss/enterprise.scss | 237 ++++++++++++
static/scss/layout.scss | 6 +
static/scss/variables.scss | 4 +
32 files changed, 2294 insertions(+), 6 deletions(-)
create mode 100644 cms/migrations/0068_enterprisepage.py
create mode 100644 cms/templates/enterprise_page.html
create mode 100644 cms/templates/partials/enterprise/banner.html
create mode 100644 cms/templates/partials/enterprise/companies_logo_carousel.html
create mode 100644 cms/templates/partials/enterprise/learning_journey.html
create mode 100644 cms/templates/partials/enterprise/learning_strategy_form.html
create mode 100644 cms/templates/partials/enterprise/success_stories.html
create mode 100644 static/images/enterprise/ctrl-left.png
create mode 100644 static/images/enterprise/ctrl-right.png
create mode 100644 static/images/enterprise/enterprise-page-banner-bg.png
create mode 100644 static/images/enterprise/enterprise-page-banner-hero.png
create mode 100644 static/images/enterprise/enterprise-page-dots-bg.png
create mode 100644 static/images/enterprise/enterprise-page-learning-path.png
create mode 100644 static/js/companies_logo_carousel.js
create mode 100644 static/js/success_stories_carousel.js
create mode 100644 static/scss/detail/enterprise/companies-logo-carousel.scss
create mode 100644 static/scss/detail/enterprise/learning-journey.scss
create mode 100644 static/scss/detail/enterprise/learning-strategy-form.scss
create mode 100644 static/scss/detail/enterprise/success-stories.scss
create mode 100644 static/scss/enterprise.scss
diff --git a/app.json b/app.json
index 4ad97eddf..2f4318520 100644
--- a/app.json
+++ b/app.json
@@ -250,6 +250,10 @@
"description": "Form ID for Hubspot Forms API",
"required": false
},
+ "HUBSPOT_ENTERPRISE_PAGE_FORM_ID": {
+ "description": "Form ID for Hubspot for Enterprise Page",
+ "required": false
+ },
"HUBSPOT_FOOTER_FORM_GUID": {
"description": "Form guid over hub spot for footer block.",
"required": false
diff --git a/cms/api.py b/cms/api.py
index a2a0b3029..606b02ade 100644
--- a/cms/api.py
+++ b/cms/api.py
@@ -7,7 +7,7 @@
from django.contrib.contenttypes.models import ContentType
from wagtail.models import Page, Site
from cms import models as cms_models
-from cms.constants import CERTIFICATE_INDEX_SLUG
+from cms.constants import CERTIFICATE_INDEX_SLUG, ENTERPRISE_PAGE_SLUG
log = logging.getLogger(__name__)
@@ -201,6 +201,37 @@ def ensure_index_pages(): # pylint: disable=too-many-branches
home_page.add_child(instance=blog_index)
+def ensure_enterprise_page():
+ """
+ Ensures that an enterprise page with the correct slug exists.
+ """
+ enterprise_page = cms_models.EnterprisePage.objects.first()
+
+ if enterprise_page and enterprise_page.slug == ENTERPRISE_PAGE_SLUG:
+ return
+
+ enterprise_page_data = {
+ "title": "Enterprise Page",
+ "slug": ENTERPRISE_PAGE_SLUG,
+ "description": "Deepen your team’s career knowledge and expand their abilities with MIT xPRO’s online "
+ "courses for professionals.",
+ "action_title": "Find out what MIT xPRO can do for your team.",
+ "headings": [
+ {
+ "type": "heading",
+ "value": {
+ "upper_head": "THE BEST COMPANIES",
+ "middle_head": "CONNECT WITH",
+ "bottom_head": "THE BEST MINDS AT MIT",
+ },
+ },
+ ],
+ }
+ enterprise_page = cms_models.EnterprisePage(**enterprise_page_data)
+ home_page = get_home_page()
+ home_page.add_child(instance=enterprise_page)
+
+
def configure_wagtail():
"""
Ensures that all appropriate changes have been made to Wagtail that will
@@ -209,3 +240,4 @@ def configure_wagtail():
ensure_home_page_and_site()
ensure_catalog_page()
ensure_index_pages()
+ ensure_enterprise_page()
diff --git a/cms/blocks.py b/cms/blocks.py
index ce0070f99..bd26451f1 100644
--- a/cms/blocks.py
+++ b/cms/blocks.py
@@ -116,6 +116,48 @@ class CourseRunCertificateOverrides(blocks.StructBlock):
)
+class BannerHeadingBlock(blocks.StructBlock):
+ """
+ A custom block designed for creating banner headings on an enterprise page.
+ """
+
+ upper_head = blocks.CharBlock(max_length=25, help_text="The main heading.")
+ middle_head = blocks.CharBlock(max_length=25, help_text="Secondary heading.")
+ bottom_head = blocks.CharBlock(max_length=25, help_text="Lower heading.")
+
+ class Meta:
+ icon = "title"
+ label = "Banner Headings"
+
+
+class SuccessStoriesBlock(blocks.StructBlock):
+ """
+ A custom block designed to represent an individual success story.
+ """
+
+ title = blocks.CharBlock(
+ max_length=255, help_text="Enter the title of the success story."
+ )
+ image = ImageChooserBlock(
+ help_text="Select an image to accompany the success story.",
+ )
+ content = blocks.TextBlock(
+ help_text="Provide the detailed content or description of the success story."
+ )
+ call_to_action = blocks.CharBlock(
+ max_length=100,
+ default="Read More",
+ help_text="Enter the text for the call-to-action button (e.g., 'Read More').",
+ )
+ action_url = blocks.URLBlock(
+ help_text="Provide the URL that the call-to-action button should link to.",
+ )
+
+ class Meta:
+ icon = "tick-inverse"
+ label = "Success Story"
+
+
def validate_unique_readable_ids(value):
"""
Validates that all of the course run override blocks in this stream field have
diff --git a/cms/constants.py b/cms/constants.py
index ad7166927..99441f460 100644
--- a/cms/constants.py
+++ b/cms/constants.py
@@ -6,6 +6,7 @@
CERTIFICATE_INDEX_SLUG = "certificate"
WEBINAR_INDEX_SLUG = "webinars"
BLOG_INDEX_SLUG = "blog"
+ENTERPRISE_PAGE_SLUG = "enterprise"
ALL_TOPICS = "All Topics"
ALL_TAB = "all-tab"
diff --git a/cms/factories.py b/cms/factories.py
index 1f11f093a..e82beb248 100644
--- a/cms/factories.py
+++ b/cms/factories.py
@@ -11,6 +11,7 @@
FacultyBlock,
LearningTechniqueBlock,
ResourceBlock,
+ SuccessStoriesBlock,
UserTestimonialBlock,
)
from cms.constants import UPCOMING_WEBINAR
@@ -18,9 +19,11 @@
BlogIndexPage,
CatalogPage,
CertificatePage,
+ CompaniesLogoCarouselSection,
CourseIndexPage,
CoursePage,
CoursesInProgramPage,
+ EnterprisePage,
ExternalCoursePage,
ExternalProgramPage,
FacultyMembersPage,
@@ -29,7 +32,9 @@
FrequentlyAskedQuestionPage,
HomePage,
ImageCarouselPage,
+ LearningJourneySection,
LearningOutcomesPage,
+ LearningStrategyFormSection,
LearningTechniquesPage,
NewsAndEventsBlock,
NewsAndEventsPage,
@@ -38,6 +43,7 @@
ResourcePage,
SignatoryPage,
SiteNotification,
+ SuccessStoriesSection,
TextSection,
TextVideoSection,
UserTestimonialsPage,
@@ -500,3 +506,73 @@ class BlogIndexPageFactory(wagtail_factories.PageFactory):
class Meta:
model = BlogIndexPage
+
+
+class EnterprisePageFactory(wagtail_factories.PageFactory):
+ """EnterprisePage factory"""
+
+ class Meta:
+ model = EnterprisePage
+
+
+class CompaniesLogoCarouselPageFactory(wagtail_factories.PageFactory):
+ """CompaniesLogoCarouselPage factory class"""
+
+ heading = factory.fuzzy.FuzzyText(prefix="heading")
+ images = wagtail_factories.StreamFieldFactory(
+ {"image": factory.SubFactory(wagtail_factories.ImageChooserBlockFactory)}
+ )
+
+ class Meta:
+ model = CompaniesLogoCarouselSection
+
+
+class LearningJourneyPageFactory(wagtail_factories.PageFactory):
+ """LearningJourneyPage factory class"""
+
+ heading = factory.fuzzy.FuzzyText(prefix="heading ")
+ description = factory.fuzzy.FuzzyText()
+ journey_image = factory.SubFactory(wagtail_factories.ImageFactory)
+ journey_items = factory.SubFactory(wagtail_factories.StreamFieldFactory)
+ call_to_action = factory.fuzzy.FuzzyText(prefix="call_to_action ")
+ action_url = factory.Faker("uri")
+ pdf_file = factory.SubFactory(wagtail_factories.DocumentFactory)
+
+ class Meta:
+ model = LearningJourneySection
+
+
+class SuccessStoriesBlockFactory(wagtail_factories.StructBlockFactory):
+ """SuccessStoriesBlock factory class"""
+
+ title = factory.fuzzy.FuzzyText(prefix="title ")
+ image = factory.SubFactory(wagtail_factories.ImageChooserBlockFactory)
+ content = factory.fuzzy.FuzzyText(prefix="content ")
+ call_to_action = factory.fuzzy.FuzzyText(prefix="call_to_action ")
+ action_url = factory.Faker("uri")
+
+ class Meta:
+ model = SuccessStoriesBlock
+
+
+class SuccessStoriesPageFactory(wagtail_factories.PageFactory):
+ """SuccessStoriesPage factory class"""
+
+ heading = factory.fuzzy.FuzzyText(prefix="heading ")
+ subhead = factory.fuzzy.FuzzyText(prefix="Subhead ")
+ success_stories = wagtail_factories.StreamFieldFactory(
+ {"success_story": factory.SubFactory(SuccessStoriesBlockFactory)}
+ )
+
+ class Meta:
+ model = SuccessStoriesSection
+
+
+class LearningStrategyFormPageFactory(wagtail_factories.PageFactory):
+ """LearningStrategyForm factory class"""
+
+ heading = factory.fuzzy.FuzzyText(prefix="heading ")
+ subhead = factory.fuzzy.FuzzyText(prefix="Subhead ")
+
+ class Meta:
+ model = LearningStrategyFormSection
diff --git a/cms/migrations/0068_enterprisepage.py b/cms/migrations/0068_enterprisepage.py
new file mode 100644
index 000000000..08c3e4cde
--- /dev/null
+++ b/cms/migrations/0068_enterprisepage.py
@@ -0,0 +1,351 @@
+# Generated by Django 3.2.23 on 2024-01-11 10:03
+
+import cms.models
+from django.db import migrations, models
+import django.db.models.deletion
+import wagtail.blocks
+import wagtail.fields
+import wagtail.images.blocks
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("wagtailcore", "0089_log_entry_data_json_null_to_object"),
+ ("wagtailimages", "0025_alter_image_file_alter_rendition_file"),
+ ("wagtaildocs", "0012_uploadeddocument"),
+ ("cms", "0067_wagtail_5_upgrade"),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name="CompaniesLogoCarouselSection",
+ fields=[
+ (
+ "page_ptr",
+ models.OneToOneField(
+ auto_created=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ serialize=False,
+ to="wagtailcore.page",
+ ),
+ ),
+ (
+ "images",
+ wagtail.fields.StreamField(
+ [
+ (
+ "image",
+ wagtail.images.blocks.ImageChooserBlock(
+ help_text="Choose an image to upload."
+ ),
+ )
+ ],
+ help_text="Add images for this section.",
+ use_json_field=True,
+ ),
+ ),
+ (
+ "heading",
+ wagtail.fields.RichTextField(
+ help_text="The main heading of the Companies Logo Carousel section."
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Companies Logo Carousel",
+ },
+ bases=("wagtailcore.page",),
+ ),
+ migrations.CreateModel(
+ name="LearningStrategyFormSection",
+ fields=[
+ (
+ "page_ptr",
+ models.OneToOneField(
+ auto_created=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ serialize=False,
+ to="wagtailcore.page",
+ ),
+ ),
+ (
+ "heading",
+ wagtail.fields.RichTextField(
+ help_text="Enter the main heading for the learning strategy form section."
+ ),
+ ),
+ (
+ "subhead",
+ wagtail.fields.RichTextField(
+ help_text="A subheading to provide additional context or information."
+ ),
+ ),
+ (
+ "consent",
+ wagtail.fields.RichTextField(
+ help_text="Enter the consent message to be displayed when users submit the form."
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Learning Strategy Form",
+ },
+ bases=("wagtailcore.page",),
+ ),
+ migrations.CreateModel(
+ name="SuccessStoriesSection",
+ fields=[
+ (
+ "page_ptr",
+ models.OneToOneField(
+ auto_created=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ serialize=False,
+ to="wagtailcore.page",
+ ),
+ ),
+ (
+ "heading",
+ wagtail.fields.RichTextField(
+ help_text="The main heading for the success stories section."
+ ),
+ ),
+ (
+ "subhead",
+ wagtail.fields.RichTextField(
+ help_text="A subheading to provide additional context or information."
+ ),
+ ),
+ (
+ "success_stories",
+ wagtail.fields.StreamField(
+ [
+ (
+ "success_story",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "title",
+ wagtail.blocks.CharBlock(
+ help_text="Enter the title of the success story.",
+ max_length=255,
+ ),
+ ),
+ (
+ "image",
+ wagtail.images.blocks.ImageChooserBlock(
+ help_text="Select an image to accompany the success story."
+ ),
+ ),
+ (
+ "content",
+ wagtail.blocks.TextBlock(
+ help_text="Provide the detailed content or description of the success story."
+ ),
+ ),
+ (
+ "call_to_action",
+ wagtail.blocks.CharBlock(
+ default="Read More",
+ help_text="Enter the text for the call-to-action button (e.g., 'Read More').",
+ max_length=100,
+ ),
+ ),
+ (
+ "action_url",
+ wagtail.blocks.URLBlock(
+ help_text="Provide the URL that the call-to-action button should link to."
+ ),
+ ),
+ ]
+ ),
+ )
+ ],
+ help_text="Manage the individual success stories. Each story is a separate block.",
+ use_json_field=True,
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Success Stories",
+ },
+ bases=("wagtailcore.page",),
+ ),
+ migrations.CreateModel(
+ name="LearningJourneySection",
+ fields=[
+ (
+ "page_ptr",
+ models.OneToOneField(
+ auto_created=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ serialize=False,
+ to="wagtailcore.page",
+ ),
+ ),
+ (
+ "heading",
+ wagtail.fields.RichTextField(
+ help_text="The main heading of the learning journey section."
+ ),
+ ),
+ (
+ "description",
+ wagtail.fields.RichTextField(
+ help_text="A detailed description of the learning journey section."
+ ),
+ ),
+ (
+ "journey_items",
+ wagtail.fields.StreamField(
+ [("journey", wagtail.blocks.TextBlock(icon="plus"))],
+ help_text="Enter the text for this learning journey item.",
+ use_json_field=True,
+ ),
+ ),
+ (
+ "call_to_action",
+ models.CharField(
+ default="View Full Diagram",
+ help_text="Text for the call-to-action button.",
+ max_length=30,
+ ),
+ ),
+ (
+ "action_url",
+ models.URLField(
+ blank=True,
+ help_text="URL for the call-to-action button, used if no PDF is linked.",
+ null=True,
+ ),
+ ),
+ (
+ "journey_image",
+ models.ForeignKey(
+ blank=True,
+ help_text="Optional image to visually represent the learning journey at least 560x618 pixels.",
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="+",
+ to="wagtailimages.image",
+ ),
+ ),
+ (
+ "pdf_file",
+ models.ForeignKey(
+ blank=True,
+ help_text="PDF document linked to the call-to-action button, prioritized over the URL.",
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="+",
+ to="wagtaildocs.document",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Learning Journey",
+ },
+ bases=("wagtailcore.page",),
+ ),
+ migrations.CreateModel(
+ name="EnterprisePage",
+ fields=[
+ (
+ "page_ptr",
+ models.OneToOneField(
+ auto_created=True,
+ on_delete=django.db.models.deletion.CASCADE,
+ parent_link=True,
+ primary_key=True,
+ serialize=False,
+ to="wagtailcore.page",
+ ),
+ ),
+ (
+ "headings",
+ wagtail.fields.StreamField(
+ [
+ (
+ "heading",
+ wagtail.blocks.StructBlock(
+ [
+ (
+ "upper_head",
+ wagtail.blocks.CharBlock(
+ help_text="The main heading.",
+ max_length=25,
+ ),
+ ),
+ (
+ "middle_head",
+ wagtail.blocks.CharBlock(
+ help_text="Secondary heading.",
+ max_length=25,
+ ),
+ ),
+ (
+ "bottom_head",
+ wagtail.blocks.CharBlock(
+ help_text="Lower heading.",
+ max_length=25,
+ ),
+ ),
+ ]
+ ),
+ )
+ ],
+ help_text="Add banner headings for this page.",
+ use_json_field=True,
+ ),
+ ),
+ (
+ "description",
+ wagtail.fields.RichTextField(
+ help_text="Enter a description for the call-to-action section under banner."
+ ),
+ ),
+ (
+ "action_title",
+ models.CharField(
+ help_text="The text to show on the call to action button",
+ max_length=100,
+ ),
+ ),
+ (
+ "background_image",
+ models.ForeignKey(
+ blank=True,
+ help_text="Background image size must be at least 1440x613 pixels.",
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="+",
+ to="wagtailimages.image",
+ ),
+ ),
+ (
+ "overlay_image",
+ models.ForeignKey(
+ blank=True,
+ help_text="Select an overlay image for the banner section at leasr 544x444 pixels.",
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="+",
+ to="wagtailimages.image",
+ ),
+ ),
+ ],
+ options={
+ "verbose_name": "Enterprise",
+ },
+ bases=(cms.models.WagtailCachedPageMixin, "wagtailcore.page"),
+ ),
+ ]
diff --git a/cms/models.py b/cms/models.py
index 5db378618..8205f1ea2 100644
--- a/cms/models.py
+++ b/cms/models.py
@@ -19,7 +19,12 @@
from django.utils.functional import cached_property
from django.utils.text import slugify
from modelcluster.fields import ParentalKey, ParentalManyToManyField
-from wagtail.admin.panels import FieldPanel, InlinePanel, TitleFieldPanel
+from wagtail.admin.panels import (
+ FieldPanel,
+ InlinePanel,
+ MultiFieldPanel,
+ TitleFieldPanel,
+)
from wagtail.blocks import (
CharBlock,
PageChooserBlock,
@@ -30,6 +35,7 @@
)
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.coreutils import WAGTAIL_APPEND_SLASH
+from wagtail.documents.models import Document
from wagtail.fields import RichTextField, StreamField
from wagtail.images.blocks import ImageChooserBlock
from wagtail.images.models import Image
@@ -40,11 +46,13 @@
from blog.api import fetch_blog
from cms.api import filter_and_sort_catalog_pages
from cms.blocks import (
+ BannerHeadingBlock,
CourseRunCertificateOverrides,
FacultyBlock,
LearningTechniqueBlock,
NewsAndEventsBlock,
ResourceBlock,
+ SuccessStoriesBlock,
UserTestimonialBlock,
validate_unique_readable_ids,
)
@@ -54,6 +62,7 @@
BLOG_INDEX_SLUG,
CERTIFICATE_INDEX_SLUG,
COURSE_INDEX_SLUG,
+ ENTERPRISE_PAGE_SLUG,
FORMAT_ONLINE,
FORMAT_OTHER,
ON_DEMAND_WEBINAR,
@@ -765,6 +774,7 @@ class HomePage(RoutablePageMixin, MetadataPageMixin, WagtailCachedPageMixin, Pag
"SignatoryIndexPage",
"WebinarIndexPage",
"BlogIndexPage",
+ "EnterprisePage",
]
@property
@@ -1867,9 +1877,9 @@ class FacultyMembersPage(CourseProgramChildPage):
]
-class ImageCarouselPage(CourseProgramChildPage):
+class AbstractImageCarousel(Page):
"""
- Page that holds image carousel.
+ Abstract class that holds image carousel.
"""
images = StreamField(
@@ -1881,6 +1891,15 @@ class ImageCarouselPage(CourseProgramChildPage):
content_panels = [FieldPanel("title"), FieldPanel("images")]
+ class Meta:
+ abstract = True
+
+
+class ImageCarouselPage(CourseProgramChildPage, AbstractImageCarousel):
+ """
+ Page that holds image carousel.
+ """
+
class Meta:
verbose_name = "Image Carousel"
@@ -2219,3 +2238,321 @@ class SiteNotification(models.Model):
def __str__(self):
return str(self.message)
+
+
+class EnterpriseChildPage(Page):
+ """
+ Abstract base class for pages that are children of an Enterprise Page.
+
+ This model is not intended to be used directly but as a base for other specific page types.
+ It provides basic functionalities like auto-generating slugs and limiting page creation.
+ """
+
+ class Meta:
+ abstract = True
+
+ parent_page_types = ["EnterprisePage"]
+ promote_panels = []
+ subpage_types = []
+
+ @classmethod
+ def can_create_at(cls, parent):
+ """
+ Ensures that only one instance of this page type can be created
+ under each parent.
+ """
+ return (
+ super().can_create_at(parent)
+ and not parent.get_children().type(cls).exists()
+ )
+
+ def save(self, clean=True, user=None, log_action=False, **kwargs):
+ """
+ Auto-generates a slug for this page if it doesn't already have one.
+
+ The slug is generated from the page title and its ID to ensure uniqueness.
+ """
+ if not self.title:
+ self.title = self.__class__._meta.verbose_name.title()
+
+ if not self.slug:
+ self.slug = slugify(f"{self.title}-{self.id}")
+
+ super().save(clean=clean, user=user, log_action=log_action, **kwargs)
+
+ def serve(self, request, *args, **kwargs):
+ """
+ Prevents direct access to this page type by raising a 404 error.
+
+ These pages are not intended to be standalone and should not be accessible by URL.
+ """
+ raise Http404
+
+
+class CompaniesLogoCarouselSection(EnterpriseChildPage, AbstractImageCarousel):
+ """
+ A custom page model for displaying a carousel of company trust logos.
+ """
+
+ heading = RichTextField(
+ help_text="The main heading of the Companies Logo Carousel section."
+ )
+
+ content_panels = [FieldPanel("heading"), FieldPanel("images")]
+
+ class Meta:
+ verbose_name = "Companies Logo Carousel"
+
+
+class LearningJourneySection(EnterpriseChildPage):
+ """
+ A page model representing a section of a learning journey.
+
+ This model includes a heading, a descriptive text, an optional image, and
+ a call-to-action button. The call-to-action button can be linked to either
+ a URL or a PDF document. The section also contains a list of learning
+ journey items.
+ """
+
+ heading = RichTextField(
+ help_text="The main heading of the learning journey section."
+ )
+ description = RichTextField(
+ help_text="A detailed description of the learning journey section.",
+ )
+ journey_image = models.ForeignKey(
+ Image,
+ null=True,
+ blank=True,
+ on_delete=models.SET_NULL,
+ related_name="+",
+ help_text="Optional image to visually represent the learning journey at least 560x618 pixels.",
+ )
+ journey_items = StreamField(
+ [("journey", TextBlock(icon="plus"))],
+ blank=False,
+ help_text="Enter the text for this learning journey item.",
+ use_json_field=True,
+ )
+ call_to_action = models.CharField(
+ max_length=30,
+ default="View Full Diagram",
+ help_text="Text for the call-to-action button.",
+ )
+ action_url = models.URLField(
+ null=True,
+ blank=True,
+ help_text="URL for the call-to-action button, used if no PDF is linked.",
+ )
+ pdf_file = models.ForeignKey(
+ Document,
+ null=True,
+ blank=True,
+ on_delete=models.SET_NULL,
+ related_name="+",
+ help_text="PDF document linked to the call-to-action button, prioritized over the URL.",
+ )
+
+ content_panels = [
+ FieldPanel("heading"),
+ FieldPanel("journey_image"),
+ FieldPanel("journey_items"),
+ FieldPanel("description"),
+ MultiFieldPanel(
+ [
+ FieldPanel("call_to_action"),
+ FieldPanel("action_url"),
+ FieldPanel("pdf_file"),
+ ],
+ heading="Button Settings",
+ ),
+ ]
+
+ @property
+ def button_url(self):
+ """
+ Determines the URL for the call-to-action button.
+
+ The method gives priority to the linked PDF file's URL,
+ if no PDF is linked, it falls back to the action_url.
+ """
+ return self.pdf_file.url if self.pdf_file else self.action_url
+
+ def clean(self):
+ """Validates that either action_url or pdf_file must be added."""
+ super().clean()
+ if not self.action_url and not self.pdf_file:
+ raise ValidationError(
+ "Please enter an Action URL or select a PDF document."
+ )
+
+ class Meta:
+ verbose_name = "Learning Journey"
+
+
+class SuccessStoriesSection(EnterpriseChildPage):
+ """
+ A page model for showcasing success stories related to an enterprise.
+
+ This page includes a primary heading, an optional subheading, and a collection of
+ success stories.
+ """
+
+ heading = RichTextField(
+ help_text="The main heading for the success stories section."
+ )
+ subhead = RichTextField(
+ help_text="A subheading to provide additional context or information.",
+ )
+ success_stories = StreamField(
+ [("success_story", SuccessStoriesBlock())],
+ blank=False,
+ help_text="Manage the individual success stories. Each story is a separate block.",
+ use_json_field=True,
+ )
+
+ content_panels = [
+ FieldPanel("heading"),
+ FieldPanel("subhead"),
+ FieldPanel("success_stories"),
+ ]
+
+ class Meta:
+ verbose_name = "Success Stories"
+
+
+class LearningStrategyFormSection(EnterpriseChildPage):
+ """
+ A page model for a section dedicated to a learning strategy form.
+
+ This section includes a main heading and an optional subheading.
+ The actual form is added by Hubspot in template.
+ """
+
+ heading = RichTextField(
+ help_text="Enter the main heading for the learning strategy form section.",
+ )
+ subhead = RichTextField(
+ help_text="A subheading to provide additional context or information.",
+ )
+ consent = RichTextField(
+ help_text="Enter the consent message to be displayed when users submit the form."
+ )
+
+ content_panels = [
+ FieldPanel("heading"),
+ FieldPanel("subhead"),
+ FieldPanel("consent"),
+ ]
+
+ class Meta:
+ verbose_name = "Learning Strategy Form"
+
+
+class EnterprisePage(WagtailCachedPageMixin, Page):
+ """
+ Represents an enterprise page in the CMS.
+ """
+
+ slug = ENTERPRISE_PAGE_SLUG
+ template = "enterprise_page.html"
+ parent_page_types = ["HomePage"]
+ subpage_types = [
+ "CompaniesLogoCarouselSection",
+ "LearningJourneySection",
+ "SuccessStoriesSection",
+ "LearningStrategyFormSection",
+ ]
+
+ headings = StreamField(
+ [("heading", BannerHeadingBlock())],
+ help_text="Add banner headings for this page.",
+ use_json_field=True,
+ )
+ background_image = models.ForeignKey(
+ Image,
+ null=True,
+ blank=True,
+ on_delete=models.SET_NULL,
+ related_name="+",
+ help_text="Background image size must be at least 1440x613 pixels.",
+ )
+ overlay_image = models.ForeignKey(
+ Image,
+ null=True,
+ blank=True,
+ on_delete=models.SET_NULL,
+ related_name="+",
+ help_text="Select an overlay image for the banner section at leasr 544x444 pixels.",
+ )
+ description = RichTextField(
+ help_text="Enter a description for the call-to-action section under banner."
+ )
+ action_title = models.CharField(
+ max_length=100,
+ help_text="The text to show on the call to action button",
+ )
+
+ content_panels = Page.content_panels + [
+ FieldPanel("headings"),
+ FieldPanel("background_image"),
+ FieldPanel("overlay_image"),
+ FieldPanel("description"),
+ FieldPanel("action_title"),
+ ]
+
+ class Meta:
+ verbose_name = "Enterprise"
+
+ def serve(self, request, *args, **kwargs):
+ """
+ Serves the enterprise page.
+
+ This method is overridden to handle specific rendering needs for
+ the enterprise template, especially during previews.
+ """
+ return Page.serve(self, request, *args, **kwargs)
+
+ @property
+ def companies_logo_carousel(self):
+ """
+ Gets the "Companies Logo Carousel" section subpage
+ """
+ return self._get_child_page_of_type(CompaniesLogoCarouselSection)
+
+ @property
+ def learning_journey(self):
+ """
+ Gets the "Learning Journey" section subpage
+ """
+ return self._get_child_page_of_type(LearningJourneySection)
+
+ @property
+ def success_stories_carousel(self):
+ """
+ Gets the "Success Stories Carousel" section subpage
+ """
+ return self._get_child_page_of_type(SuccessStoriesSection)
+
+ @property
+ def learning_strategy_form(self):
+ """
+ Gets the "Learning Strategy Form" section subpage
+ """
+ return self._get_child_page_of_type(LearningStrategyFormSection)
+
+ def get_context(self, request, *args, **kwargs):
+ """
+ Builds the context for rendering the enterprise page.
+ """
+ return {
+ **super().get_context(request, *args, **kwargs),
+ **get_base_context(request),
+ "companies_logo_carousel": self.companies_logo_carousel,
+ "learning_journey": self.learning_journey,
+ "success_stories_carousel": self.success_stories_carousel,
+ "learning_strategy_form": self.learning_strategy_form,
+ "hubspot_enterprise_page_form_id": settings.HUBSPOT_CONFIG.get(
+ "HUBSPOT_ENTERPRISE_PAGE_FORM_ID"
+ ),
+ }
diff --git a/cms/models_test.py b/cms/models_test.py
index b733cb1e5..6e77bf0a5 100644
--- a/cms/models_test.py
+++ b/cms/models_test.py
@@ -11,18 +11,20 @@
from wagtail.coreutils import WAGTAIL_APPEND_SLASH
from cms.constants import (
+ FORMAT_ONLINE,
+ FORMAT_OTHER,
ON_DEMAND_WEBINAR,
ON_DEMAND_WEBINAR_BUTTON_TITLE,
UPCOMING_WEBINAR,
UPCOMING_WEBINAR_BUTTON_TITLE,
WEBINAR_HEADER_BANNER,
- FORMAT_ONLINE,
- FORMAT_OTHER,
)
from cms.factories import (
CertificatePageFactory,
+ CompaniesLogoCarouselPageFactory,
CoursePageFactory,
CoursesInProgramPageFactory,
+ EnterprisePageFactory,
ExternalCoursePageFactory,
ExternalProgramPageFactory,
FacultyMembersPageFactory,
@@ -31,7 +33,9 @@
FrequentlyAskedQuestionPageFactory,
HomePageFactory,
ImageCarouselPageFactory,
+ LearningJourneyPageFactory,
LearningOutcomesPageFactory,
+ LearningStrategyFormPageFactory,
LearningTechniquesPageFactory,
NewsAndEventsPageFactory,
ProgramFactory,
@@ -39,6 +43,7 @@
ResourcePageFactory,
SignatoryPageFactory,
SiteNotificationFactory,
+ SuccessStoriesPageFactory,
TextSectionFactory,
TextVideoSectionFactory,
UserTestimonialsPageFactory,
@@ -51,6 +56,7 @@
CoursesInProgramPage,
ForTeamsPage,
FrequentlyAskedQuestionPage,
+ LearningJourneySection,
LearningOutcomesPage,
LearningTechniquesPage,
SignatoryPage,
@@ -1602,3 +1608,133 @@ def _assert_news_and_events_values(news_and_events_page):
assert news_and_events.value.get("content") == f"content-{count}"
assert news_and_events.value.get("call_to_action") == f"call_to_action-{count}"
assert news_and_events.value.get("action_url") == f"action_url-{count}"
+
+
+def test_enterprise_page_companies_logo_carousel():
+ """
+ companies_logo_carousel property should return expected values.
+ """
+
+ enterprise_page = EnterprisePageFactory.create(
+ action_title="title", description="description"
+ )
+ assert not enterprise_page.companies_logo_carousel
+
+ del enterprise_page.child_pages
+
+ companies_logo_carousel = CompaniesLogoCarouselPageFactory.create(
+ parent=enterprise_page,
+ heading="heading",
+ images__0__image__image__title="image-title-0",
+ images__1__image__image__title="image-title-1",
+ images__2__image__image__title="image-title-2",
+ images__3__image__image__title="image-title-3",
+ )
+
+ assert enterprise_page.companies_logo_carousel == companies_logo_carousel
+ assert companies_logo_carousel.heading == "heading"
+
+ for index, image in enumerate(companies_logo_carousel.images):
+ assert image.value.title == "image-title-{}".format(index)
+
+
+def test_enterprise_page_learning_journey():
+ """
+ LearningJourneyPage should return expected values if it exists
+ """
+
+ enterprise_page = EnterprisePageFactory.create(
+ action_title="title", description="description"
+ )
+
+ assert not enterprise_page.learning_journey
+ assert LearningJourneySection.can_create_at(enterprise_page)
+
+ learning_journey = LearningJourneyPageFactory(
+ parent=enterprise_page,
+ heading="heading",
+ description="description",
+ journey_items=json.dumps([{"type": "journey", "value": "value"}]),
+ journey_image__title="background-image",
+ )
+
+ assert learning_journey.get_parent() == enterprise_page
+ assert learning_journey.heading == "heading"
+ assert learning_journey.description == "description"
+
+ for block in learning_journey.journey_items: # pylint: disable=not-an-iterable
+ assert block.block_type == "journey"
+ assert block.value == "value"
+
+ assert learning_journey.action_url
+ assert learning_journey.pdf_file
+
+ del enterprise_page.child_pages
+
+ assert enterprise_page.learning_journey == learning_journey
+ assert not LearningOutcomesPage.can_create_at(enterprise_page)
+
+
+def test_enterprise_page_success_stories():
+ """
+ SuccessStories subpage should provide expected values
+ """
+
+ enterprise_page = EnterprisePageFactory.create(
+ action_title="title", description="description"
+ )
+
+ assert not enterprise_page.success_stories_carousel
+ del enterprise_page.child_pages
+
+ success_stories_carousel = SuccessStoriesPageFactory.create(
+ parent=enterprise_page,
+ heading="heading",
+ subhead="subhead",
+ success_stories__0__success_story__title="title",
+ success_stories__0__success_story__image__image__title="image",
+ success_stories__0__success_story__content="content",
+ success_stories__0__success_story__call_to_action="call_to_action",
+ success_stories__0__success_story__action_url="action_url",
+ success_stories__1__success_story__title="title",
+ success_stories__1__success_story__image__image__title="image",
+ success_stories__1__success_story__content="content",
+ success_stories__1__success_story__call_to_action="call_to_action",
+ success_stories__1__success_story__action_url="action_url",
+ )
+
+ assert enterprise_page.success_stories_carousel == success_stories_carousel
+ assert success_stories_carousel.heading == "heading"
+ assert success_stories_carousel.subhead == "subhead"
+
+ for success_stories in success_stories_carousel.success_stories:
+ assert success_stories.value.get("title") == "title"
+ assert success_stories.value.get("image").title == "image"
+ assert success_stories.value.get("content") == "content"
+ assert success_stories.value.get("call_to_action") == "call_to_action"
+ assert success_stories.value.get("action_url") == "action_url"
+
+
+def test_enterprise_page_learning_strategy_form():
+ """
+ LearningStrategyForm subpage should provide expected values
+ """
+
+ enterprise_page = EnterprisePageFactory.create(
+ action_title="title", description="description"
+ )
+
+ assert not enterprise_page.learning_strategy_form
+ del enterprise_page.child_pages
+
+ learning_strategy_form = LearningStrategyFormPageFactory.create(
+ parent=enterprise_page,
+ heading="heading",
+ subhead="subhead",
+ consent="consent",
+ )
+
+ assert enterprise_page.learning_strategy_form == learning_strategy_form
+ assert learning_strategy_form.heading == "heading"
+ assert learning_strategy_form.subhead == "subhead"
+ assert learning_strategy_form.consent == "consent"
diff --git a/cms/templates/enterprise_page.html b/cms/templates/enterprise_page.html
new file mode 100644
index 000000000..4f3c88512
--- /dev/null
+++ b/cms/templates/enterprise_page.html
@@ -0,0 +1,40 @@
+{% extends "base.html" %}
+
+{% load static render_bundle image_version_url %}
+
+{% block title %}{{ page.title }}{% endblock %}
+
+{% block headercontent %}
+
+{% render_bundle 'header' %}
+{% endblock %}
+
+
+{% block content %}
+
+
+
+ {% include "partials/enterprise/banner.html" %}
+
+ {% if companies_logo_carousel %}
+ {% include "partials/enterprise/companies_logo_carousel.html" with page=companies_logo_carousel %}
+ {% endif %}
+
+ {% if learning_journey %}
+
+ {% include "partials/enterprise/learning_journey.html" with page=learning_journey %}
+ {% endif %}
+
+ {% if success_stories_carousel %}
+ {% include "partials/enterprise/success_stories.html" with page=success_stories_carousel %}
+ {% endif %}
+
+ {% if hubspot_portal_id and hubspot_enterprise_page_form_id %}
+
+ {% if learning_strategy_form %}
+ {% include "partials/enterprise/learning_strategy_form.html" with page=learning_strategy_form %}
+ {% endif %}
+ {% endif %}
+
+
+{% endblock %}
diff --git a/cms/templates/partials/enterprise/banner.html b/cms/templates/partials/enterprise/banner.html
new file mode 100644
index 000000000..c7084242c
--- /dev/null
+++ b/cms/templates/partials/enterprise/banner.html
@@ -0,0 +1,52 @@
+{% load static wagtailembeds_tags image_version_url wagtailcore_tags %}
+
+{% block extrahead %}
+
+{% endblock %}
+
+
+
+
+
+ {% for block in page.headings %}
+
{{ block.value.upper_head|upper }}
+
{{ block.value.middle_head|upper }}
+
{{ block.value.bottom_head|upper }}
+ {% endfor %}
+
Inquire Now
+
+ {% if page.overlay_image %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
+
diff --git a/cms/templates/partials/enterprise/companies_logo_carousel.html b/cms/templates/partials/enterprise/companies_logo_carousel.html
new file mode 100644
index 000000000..d7209b12f
--- /dev/null
+++ b/cms/templates/partials/enterprise/companies_logo_carousel.html
@@ -0,0 +1,16 @@
+{% load image_version_url wagtailcore_tags %}
+
+
+
+
{{ companies_logo_carousel.heading|richtext }}
+
+ {% for image in companies_logo_carousel.images %}
+
+
+
+
+
+ {% endfor %}
+
+
+
diff --git a/cms/templates/partials/enterprise/learning_journey.html b/cms/templates/partials/enterprise/learning_journey.html
new file mode 100644
index 000000000..dbfcc85c8
--- /dev/null
+++ b/cms/templates/partials/enterprise/learning_journey.html
@@ -0,0 +1,23 @@
+{% load static image_version_url wagtailcore_tags %}
+
+
+
+
{{ page.heading|richtext }}
+
+
+
+ {% for journey_item in page.journey_items %}
+ - {{ journey_item }}
+ {% endfor %}
+
+
{{ page.description|richtext }}
+
{{ page.call_to_action|upper }}
+
+ {% if page.journey_image %}
+
+ {% else %}
+
+ {% endif %}
+
+
+
diff --git a/cms/templates/partials/enterprise/learning_strategy_form.html b/cms/templates/partials/enterprise/learning_strategy_form.html
new file mode 100644
index 000000000..ac2a9c9e1
--- /dev/null
+++ b/cms/templates/partials/enterprise/learning_strategy_form.html
@@ -0,0 +1,27 @@
+{% load wagtailcore_tags %}
+
+
diff --git a/cms/templates/partials/enterprise/success_stories.html b/cms/templates/partials/enterprise/success_stories.html
new file mode 100644
index 000000000..bb16f5df3
--- /dev/null
+++ b/cms/templates/partials/enterprise/success_stories.html
@@ -0,0 +1,24 @@
+{% load image_version_url wagtailcore_tags %}
+
+
+
+
+
{{ page.heading|richtext }}
+
{{ page.subhead|richtext }}
+
+
+ {% for block in page.success_stories %}
+
+ {% endfor %}
+
+
+
diff --git a/cms/views_test.py b/cms/views_test.py
index 99e97635e..22afeb63b 100644
--- a/cms/views_test.py
+++ b/cms/views_test.py
@@ -4,6 +4,7 @@
import factory
import pytest
+from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.urls import reverse
@@ -17,6 +18,7 @@
WEBINAR_DEFAULT_IMAGES,
)
from cms.factories import (
+ EnterprisePageFactory,
BlogIndexPageFactory,
CatalogPageFactory,
CourseIndexPageFactory,
@@ -580,3 +582,28 @@ def test_blog_page_context(client, wagtail_basics):
context = resp.context_data
assert "posts" in context
+
+
+def test_enterprise_page_context(client, wagtail_basics):
+ """
+ Test that enterprise page show correctly
+ """
+ enterprise_page = EnterprisePageFactory.create(
+ parent=wagtail_basics.root, action_title="Read More", description="description"
+ )
+ enterprise_page.save_revision().publish()
+
+ resp = client.get(enterprise_page.get_url())
+ context = resp.context_data
+
+ assert resp.status_code == status.HTTP_200_OK
+ assert context["page"] == enterprise_page
+
+ assert "companies_logo_carousel" in context
+ assert "learning_journey" in context
+ assert "success_stories_carousel" in context
+ assert "learning_strategy_form" in context
+
+ assert context["hubspot_enterprise_page_form_id"] == settings.HUBSPOT_CONFIG.get(
+ "HUBSPOT_ENTERPRISE_PAGE_FORM_ID"
+ )
diff --git a/mitxpro/settings.py b/mitxpro/settings.py
index 13ba4eda7..914218c88 100644
--- a/mitxpro/settings.py
+++ b/mitxpro/settings.py
@@ -1261,6 +1261,11 @@
default=None,
description="Form ID for Hubspot Forms API",
),
+ "HUBSPOT_ENTERPRISE_PAGE_FORM_ID": get_string(
+ name="HUBSPOT_ENTERPRISE_PAGE_FORM_ID",
+ default=None,
+ description="Form ID for Hubspot for Enterprise Page",
+ ),
}
# Sheets settings
diff --git a/static/images/enterprise/ctrl-left.png b/static/images/enterprise/ctrl-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..283a2786e4336ddcc8788fab30f9a7ca8667f391
GIT binary patch
literal 4531
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
literal 0
HcmV?d00001
diff --git a/static/images/enterprise/enterprise-page-banner-bg.png b/static/images/enterprise/enterprise-page-banner-bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..7db16716a5a2930938594e56dfca4bcfe032d380
GIT binary patch
literal 174017
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