diff --git a/cdhweb/context_processors.py b/cdhweb/context_processors.py
index 29bdc1c4..0ed3b322 100644
--- a/cdhweb/context_processors.py
+++ b/cdhweb/context_processors.py
@@ -2,7 +2,7 @@
from django.templatetags.static import static
from wagtail.models import Site
-from cdhweb.pages.utils import absolutize_url
+from cdhweb.pages.utils import get_default_preview_img_url
def template_settings(request):
@@ -11,19 +11,10 @@ def template_settings(request):
feature_flags = getattr(settings, "FEATURE_FLAGS", [])
- # default social preview image, relative to static url
- if "purple-mode" in feature_flags:
- default_preview_img = "img/alt-modes/purple/cdhlogo_square.png"
- else:
- default_preview_img = "images/cdhlogo_square.jpg"
-
context_extras = {
"SHOW_TEST_WARNING": getattr(settings, "SHOW_TEST_WARNING", False),
"site": Site.find_for_request(request),
- "default_preview_image": request.build_absolute_uri(
- static(default_preview_img)
- ),
- # try using template tag import static tag and use here instead of join django utils static
+ "default_preview_image": get_default_preview_img_url(),
# Include analytics based on settings.DEBUG or override in settings.py
# Defaults to opposite of settings.DEBUG
"INCLUDE_ANALYTICS": getattr(settings, "INCLUDE_ANALYTICS", not settings.DEBUG),
@@ -41,18 +32,12 @@ def favicon_path():
"""Determine which favicon to use based on any feature flags and test warning.
Returns full local path, including static url.
"""
- feature_flags = getattr(settings, "FEATURE_FLAGS", [])
-
- base_path = ""
- if "purple-mode" in feature_flags:
- base_path = "img/alt-modes/purple/"
-
icon_version = "favicon.ico"
# use test favicon when test warning is enabled as another visual indicator
if getattr(settings, "SHOW_TEST_WARNING", False):
icon_version = "favicon-test.ico"
- return "".join([settings.STATIC_URL, base_path, icon_version])
+ return static(icon_version)
def show_test_warning(request):
diff --git a/cdhweb/pages/migrations/0061_purplemode_to_genericsetting.py b/cdhweb/pages/migrations/0061_purplemode_to_genericsetting.py
new file mode 100644
index 00000000..821d6304
--- /dev/null
+++ b/cdhweb/pages/migrations/0061_purplemode_to_genericsetting.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.0.8 on 2024-09-03 00:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('cdhpages', '0060_alter_contentpage_body_alter_homepage_body_and_more'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='purplemode',
+ name='site',
+ ),
+ migrations.AlterField(
+ model_name='purplemode',
+ name='purple_mode',
+ field=models.BooleanField(default=False, help_text='\n This will turn the site purple by transforming\n all shades of cyan on the site into shades of\n purple\n '),
+ ),
+ ]
diff --git a/cdhweb/pages/mixin.py b/cdhweb/pages/mixin.py
index 1f8cac59..45aea1f7 100644
--- a/cdhweb/pages/mixin.py
+++ b/cdhweb/pages/mixin.py
@@ -10,7 +10,12 @@
from wagtail.models import Page
from wagtail.search import index
-from .utils import LengthOverrideWidget
+from .utils import (
+ LengthOverrideWidget,
+ absolutize_url,
+ get_default_preview_img_url,
+ get_first_of,
+)
class HomePageHeroMixin(models.Model):
@@ -158,3 +163,17 @@ def sidebar_navigation(self):
class Meta:
abstract = True
+
+
+class OpenGraphMixin(models.Model):
+ class Meta:
+ abstract = True
+
+ @cached_property
+ def og_image_url(self):
+ image = get_first_of(self, "feed_image", "image", "hero_image")
+ if not image:
+ return get_default_preview_img_url()
+
+ rendition = image.get_rendition("fill-1200x627")
+ return absolutize_url(rendition.url)
diff --git a/cdhweb/pages/models.py b/cdhweb/pages/models.py
index 0025bc45..803581aa 100644
--- a/cdhweb/pages/models.py
+++ b/cdhweb/pages/models.py
@@ -3,17 +3,15 @@
import bleach
from django.apps import apps
-from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.template.defaultfilters import striptags, truncatechars_html
-from django.utils.functional import cached_property
from springkit.blocks import CTABlock, JumplinkableH2Block
from springkit.models.mixins import JumplinksMixin
from taggit.managers import TaggableManager
from wagtail.admin.panels import FieldPanel, MultiFieldPanel
from wagtail.blocks import RichTextBlock, StreamBlock, StructBlock, TextBlock
-from wagtail.contrib.settings.models import BaseSiteSetting, register_setting
+from wagtail.contrib.settings.models import BaseGenericSetting, register_setting
from wagtail.documents.blocks import DocumentChooserBlock
from wagtail.documents.models import AbstractDocument, DocumentQuerySet
from wagtail.embeds.blocks import EmbedBlock
@@ -25,7 +23,7 @@
from wagtail.snippets.models import register_snippet
from wagtailcodeblock.blocks import CodeBlock
-from cdhweb.pages import snippets # needed for import order
+from cdhweb.pages import snippets # noqa needed for import order
from .blocks.accordion_block import AccordionBlock
from .blocks.article_index_block import ArticleTileBlock
@@ -42,7 +40,12 @@
from .blocks.table_block import TableBlock
from .blocks.tile_block import StandardTileBlock
from .blocks.video_block import Video
-from .mixin import HomePageHeroMixin, SidebarNavigationMixin, StandardHeroMixin
+from .mixin import (
+ HomePageHeroMixin,
+ OpenGraphMixin,
+ SidebarNavigationMixin,
+ StandardHeroMixin,
+)
#: common features for paragraph text
PARAGRAPH_FEATURES = [
@@ -246,7 +249,7 @@ class LinkPage(Page):
is_creatable = False
-class BasePage(Page):
+class BasePage(OpenGraphMixin, Page):
"""Abstract Page class from which all Wagtail page types are derived."""
body = StreamField(
@@ -587,11 +590,14 @@ def clean_fields(self, exclude=None):
@register_setting(icon="edit")
-class PurpleMode(BaseSiteSetting):
+class PurpleMode(BaseGenericSetting):
purple_mode = models.BooleanField(
default=False,
- help_text="""This will turn the site purple
- by transforming all shades of cyan on the site into shades of purple""",
+ help_text="""
+ This will turn the site purple by transforming
+ all shades of cyan on the site into shades of
+ purple
+ """,
)
panels = [FieldPanel("purple_mode", icon="pick")]
diff --git a/cdhweb/pages/utils.py b/cdhweb/pages/utils.py
index 22f94399..e06e44e1 100644
--- a/cdhweb/pages/utils.py
+++ b/cdhweb/pages/utils.py
@@ -1,31 +1,28 @@
-from django.contrib.sites.models import Site
+from urllib.parse import urljoin
+from wagtail.models import Site
from django.forms.widgets import TextInput
+from django.templatetags.static import static
-def absolutize_url(local_url):
+
+def absolutize_url(local_url, request=None):
"""Convert a local url to an absolute url, with scheme and server name,
based on the current configured :class:`~django.contrib.sites.models.Site`.
:param local_url: local url to be absolutized, e.g. something generated by
:meth:`~django.core.urlresolvers.reverse`
"""
- if local_url.startswith("https"):
+ if local_url.startswith("https://") or local_url.startswith("http://"):
return local_url
# add scheme and server (i.e., the http://example.com) based
- # on the django Sites infrastructure.
- root = Site.objects.get_current().domain
- # but also add the http:// if necessary, since most sites docs
- # suggest using just the domain name
- # NOTE: this is problematic for dev/test sites without https
- if not root.startswith("https"):
- root = "https://" + root
-
- # make sure there is no double slash between site url and local url
- if local_url.startswith("/"):
- root = root.rstrip("/")
+ # on the Wagtail request or default Site
+ site = Site.objects.order_by("is_default_site").first()
+ if request:
+ site = Site.find_for_request(request)
+ root = site.root_url
- return root + local_url
+ return urljoin(root, local_url)
class LengthOverrideWidget(TextInput):
@@ -55,3 +52,25 @@ def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
context["widget"]["attrs"]["maxlength"] = self.max_length
return context
+
+
+def get_first_of(instance, *fields, default=None):
+ """
+ Return the first non empty value from fields on `instance` - or `default`
+ """
+ return next(
+ (value for field in fields if (value := getattr(instance, field, ""))), default
+ )
+
+
+def get_default_preview_img_url():
+ from cdhweb.pages.models import PurpleMode
+
+ # default social preview image, relative to static url
+ purple_mode_setting = PurpleMode.load()
+ if purple_mode_setting.purple_mode:
+ default_preview_img = "images/alt-modes/purple/cdhlogo_square.png"
+ else:
+ default_preview_img = "images/cdhlogo_square.jpg"
+
+ return absolutize_url(static(default_preview_img))
diff --git a/cdhweb/pages/views.py b/cdhweb/pages/views.py
index e4a66bca..2f45f89b 100644
--- a/cdhweb/pages/views.py
+++ b/cdhweb/pages/views.py
@@ -74,7 +74,6 @@ def get_queryset(self):
form = self.get_form()
if not form.is_valid():
- print(form.errors)
return queryset.none()
# get keyword query; support filters & phrase matching with double quotes
diff --git a/cdhweb/projects/models.py b/cdhweb/projects/models.py
index 971d93fd..8e14bd5f 100644
--- a/cdhweb/projects/models.py
+++ b/cdhweb/projects/models.py
@@ -5,15 +5,14 @@
from django.utils import timezone
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from modelcluster.models import ClusterableModel
-from wagtail import blocks
from wagtail.admin.panels import FieldPanel, FieldRowPanel, InlinePanel, MultiFieldPanel
-from wagtail.fields import RichTextField, StreamField
+from wagtail.fields import StreamField
from wagtail.models import Page, PageManager, PageQuerySet
from wagtail.search import index
from wagtailautocomplete.edit_handlers import AutocompletePanel
from cdhweb.pages.blocks.accordion_block import ProjectAccordion
-from cdhweb.pages.mixin import StandardHeroMixin
+from cdhweb.pages.mixin import OpenGraphMixin, StandardHeroMixin
from cdhweb.pages.models import BasePage, DateRange, LandingPage, LinkPage, RelatedLink
from cdhweb.people.models import Person
@@ -80,7 +79,7 @@ def recent(self):
ProjectManager = PageManager.from_queryset(ProjectQuerySet)
-class Project(BasePage, ClusterableModel, StandardHeroMixin):
+class Project(BasePage, OpenGraphMixin, ClusterableModel, StandardHeroMixin):
"""Page type for a CDH sponsored project or working group."""
template = "projects/project_page.html"
diff --git a/docker-compose.yml b/docker-compose.yml
index 7868bab7..0f9fd116 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -42,7 +42,7 @@ services:
volumes:
- "./docker/database:/docker-entrypoint-initdb.d/:ro"
environment:
- WAGTAIL_SITE_HOSTNAME: "${SITE_HOSTNAME}"
+ WAGTAIL_SITE_HOSTNAME: "cdh.dev.springload.nz"
WAGTAIL_SITE_PORT: "443"
POSTGRES_DB: "cdhweb"
POSTGRES_USER: "cdhweb"
diff --git a/templates/snippets/head_meta.html b/templates/snippets/head_meta.html
index 694268e2..b3072eba 100644
--- a/templates/snippets/head_meta.html
+++ b/templates/snippets/head_meta.html
@@ -1,5 +1,5 @@
{% load static cdh_tags %}
-{% firstof preview_image page.get_url|url_to_icon_path default_preview_image as meta_preview_image %}
+{% firstof preview_image page.og_image_url default_preview_image as meta_preview_image_url %}
{% firstof page_title page.seo_title page.title as meta_title %}
{% autoescape off %}
{% firstof page.get_plaintext_description page_intro.paragraph as meta_description %}
@@ -8,12 +8,11 @@
{# html metadata #}
{% if page.tags.exists %}{% endif %}
-{# determine preview image: specified by page, cdh icon based on url, or default image #}
{# open graph metadata #}
-
+
{% if meta_description %}{% endif %}
{# twitter card #}
@@ -21,5 +20,5 @@
{% if meta_description %}{% endif %}
-
+
{% endautoescape %}