Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor OG image selection and supporting bits #180

Merged
merged 4 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 3 additions & 18 deletions cdhweb/context_processors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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),
Expand All @@ -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):
Expand Down
22 changes: 22 additions & 0 deletions cdhweb/pages/migrations/0061_purplemode_to_genericsetting.py
Original file line number Diff line number Diff line change
@@ -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 '),
),
]
21 changes: 20 additions & 1 deletion cdhweb/pages/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
24 changes: 15 additions & 9 deletions cdhweb/pages/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 = [
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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")]
Expand Down
49 changes: 34 additions & 15 deletions cdhweb/pages/utils.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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))
1 change: 0 additions & 1 deletion cdhweb/pages/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 3 additions & 4 deletions cdhweb/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
7 changes: 3 additions & 4 deletions templates/snippets/head_meta.html
Original file line number Diff line number Diff line change
@@ -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 %}
Expand All @@ -8,18 +8,17 @@
{# html metadata #}
{% if page.tags.exists %}<meta name="keywords" content="{{ page.tags.all|join:', ' }}"/>{% endif %}
<meta name="description" content="{% firstof self.search_description self.intro|default:''|striptags self.body_excerpt|default:''|striptags|truncatewords:40 self.title %}">
{# determine preview image: specified by page, cdh icon based on url, or default image #}
{# open graph metadata #}
<meta property="og:title" content="{{ meta_title }}" />
<meta property="og:type" content="{{ opengraph_type|default:'website' }}" />
<meta property="og:url" content="{{ request.build_absolute_uri }}" />
<meta property="og:image" content="{{ meta_preview_image }}" />
<meta property="og:image" content="{{ meta_preview_image_url }}" />
{% if meta_description %}<meta property="og:description" content="{{ meta_description|striptags }}"/>{% endif %}
<meta property="og:site_name" content="{{ site.root_page.seo_title }}"/>
{# twitter card #}
<meta name="twitter:card" content="{{ twitter_card_type|default:'summary' }}" />
<meta name="twitter:site" content="@PrincetonDH" />
<meta name="twitter:title" content="{{ meta_title }}"/>
{% if meta_description %}<meta name="twitter:description" content="{{ meta_description|striptags }}"/>{% endif %}
<meta name="twitter:image" content="{% firstof twitter_image meta_preview_image %}" />
<meta name="twitter:image" content="{% firstof twitter_image meta_preview_image_url %}" />
{% endautoescape %}
Loading