Add account links to footer

Putting them in the navbar is too crowded.
This commit is contained in:
Jake Howard 2022-09-02 09:28:35 +01:00
parent 6d60cedc6f
commit 7026aca934
Signed by: jake
GPG key ID: 57AFB45680EDD477
14 changed files with 114 additions and 8 deletions

View file

@ -23,6 +23,7 @@ sentry-sdk
wagtail-favicon wagtail-favicon
django-sri django-sri
wagtail-2fa wagtail-2fa
django-fontawesome-6
# Pinned due to lack of Wagtail 3 support # Pinned due to lack of Wagtail 3 support
git+https://github.com/wagtail/wagtail-autocomplete@03f46a0c256989690d0a43fc21fe0f37f9ede765 git+https://github.com/wagtail/wagtail-autocomplete@03f46a0c256989690d0a43fc21fe0f37f9ede765

View file

@ -15,9 +15,10 @@ click==8.1.3 # via rq
coreapi==2.3.3 # via drf-yasg coreapi==2.3.3 # via drf-yasg
coreschema==0.0.4 # via coreapi, drf-yasg coreschema==0.0.4 # via coreapi, drf-yasg
deprecated==1.2.13 # via redis deprecated==1.2.13 # via redis
django==4.0.6 # via -r requirements/base.in, django-filter, django-htmx, django-modelcluster, django-otp, django-permissionedforms, django-plausible, django-redis, django-rq, django-sri, django-taggit, django-treebeard, djangorestframework, drf-yasg, wagtail, wagtail-2fa django==4.0.6 # via -r requirements/base.in, django-filter, django-fontawesome-6, django-htmx, django-modelcluster, django-otp, django-permissionedforms, django-plausible, django-redis, django-rq, django-sri, django-taggit, django-treebeard, djangorestframework, drf-yasg, wagtail, wagtail-2fa
django-environ==0.9.0 # via -r requirements/base.in django-environ==0.9.0 # via -r requirements/base.in
django-filter==21.1 # via wagtail django-filter==21.1 # via wagtail
django-fontawesome-6==1.0.0.0 # via -r requirements/base.in
django-htmx==1.12.1 # via -r requirements/base.in django-htmx==1.12.1 # via -r requirements/base.in
django-modelcluster==6.0 # via wagtail django-modelcluster==6.0 # via wagtail
django-otp==1.1.3 # via wagtail-2fa django-otp==1.1.3 # via wagtail-2fa

View file

@ -20,11 +20,12 @@ coreschema==0.0.4 # via -r requirements/base.txt, coreapi, drf-yasg
coverage==6.4.4 # via -r requirements/dev.in coverage==6.4.4 # via -r requirements/dev.in
curlylint==0.13.1 # via -r requirements/dev.in curlylint==0.13.1 # via -r requirements/dev.in
deprecated==1.2.13 # via -r requirements/base.txt, redis deprecated==1.2.13 # via -r requirements/base.txt, redis
django==4.0.6 # via -r requirements/base.txt, django-browser-reload, django-debug-toolbar, django-filter, django-htmx, django-modelcluster, django-otp, django-permissionedforms, django-plausible, django-redis, django-rq, django-sri, django-taggit, django-treebeard, djangorestframework, drf-yasg, wagtail, wagtail-2fa django==4.0.6 # via -r requirements/base.txt, django-browser-reload, django-debug-toolbar, django-filter, django-fontawesome-6, django-htmx, django-modelcluster, django-otp, django-permissionedforms, django-plausible, django-redis, django-rq, django-sri, django-taggit, django-treebeard, djangorestframework, drf-yasg, wagtail, wagtail-2fa
django-browser-reload==1.6.0 # via -r requirements/dev.in django-browser-reload==1.6.0 # via -r requirements/dev.in
django-debug-toolbar==3.5.0 # via -r requirements/dev.in django-debug-toolbar==3.5.0 # via -r requirements/dev.in
django-environ==0.9.0 # via -r requirements/base.txt django-environ==0.9.0 # via -r requirements/base.txt
django-filter==21.1 # via -r requirements/base.txt, wagtail django-filter==21.1 # via -r requirements/base.txt, wagtail
django-fontawesome-6==1.0.0.0 # via -r requirements/base.txt
django-htmx==1.12.1 # via -r requirements/base.txt django-htmx==1.12.1 # via -r requirements/base.txt
django-modelcluster==6.0 # via -r requirements/base.txt, wagtail django-modelcluster==6.0 # via -r requirements/base.txt, wagtail
django-otp==1.1.3 # via -r requirements/base.txt, wagtail-2fa django-otp==1.1.3 # via -r requirements/base.txt, wagtail-2fa

View file

@ -0,0 +1,56 @@
# Generated by Django 4.0.6 on 2022-09-02 08:14
import django.db.models.deletion
import wagtail.fields
import wagtail.snippets.blocks
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("wagtailcore", "0069_log_entry_jsonfield"),
("common", "0021_alter_contentpage_body_alter_listingpage_body"),
]
operations = [
migrations.CreateModel(
name="FooterSetting",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"icons",
wagtail.fields.StreamField(
[
(
"icon",
wagtail.snippets.blocks.SnippetChooserBlock(
"contact.OnlineAccount", icon="user"
),
)
],
use_json_field=None,
),
),
(
"site",
models.OneToOneField(
editable=False,
on_delete=django.db.models.deletion.CASCADE,
to="wagtailcore.site",
),
),
],
options={
"verbose_name": "Footer",
},
),
]

View file

@ -12,11 +12,13 @@ from django.utils.functional import cached_property, classproperty
from django.utils.text import slugify from django.utils.text import slugify
from wagtail.admin.panels import FieldPanel from wagtail.admin.panels import FieldPanel
from wagtail.contrib.routable_page.models import RoutablePageMixin, route from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.contrib.settings.models import BaseSetting, register_setting
from wagtail.fields import StreamField from wagtail.fields import StreamField
from wagtail.images import get_image_model_string from wagtail.images import get_image_model_string
from wagtail.images.views.serve import generate_image_url from wagtail.images.views.serve import generate_image_url
from wagtail.models import Page, PageQuerySet from wagtail.models import Page, PageQuerySet
from wagtail.search import index from wagtail.search import index
from wagtail.snippets.blocks import SnippetChooserBlock
from wagtail.snippets.models import register_snippet from wagtail.snippets.models import register_snippet
from wagtailmetadata.models import MetadataMixin from wagtailmetadata.models import MetadataMixin
@ -246,3 +248,15 @@ class ReferralLink(models.Model, index.Indexed):
def __str__(self) -> str: def __str__(self) -> str:
return self.name return self.name
@register_setting(icon="arrow-down")
class FooterSetting(BaseSetting):
icons = StreamField(
[("icon", SnippetChooserBlock("contact.OnlineAccount", icon="user"))]
)
panels = [FieldPanel("icons")]
class Meta:
verbose_name = "Footer"

View file

@ -2,7 +2,14 @@
<footer class="footer"> <footer class="footer">
<div class="content has-text-centered"> <div class="content has-text-centered">
<p> {% if online_accounts %}
<p class="is-size-3">
{% for online_account in online_accounts %}
<a href="{{ online_account.url }}" title="{{ online_account.name }}">{{ online_account.icon.as_html }}</a>
{% endfor %}
</p>
{% endif %}
<p class="is-size-6">
&copy; <a href="{{ homepage_url }}">TheOrangeOne</a> {% now "Y" %} &copy; <a href="{{ homepage_url }}">TheOrangeOne</a> {% now "Y" %}
</p> </p>
<p id="to-top" class="is-size-7"> <p id="to-top" class="is-size-7">

View file

@ -1,5 +1,6 @@
from django.template import Library from django.template import Library
from website.common.models import FooterSetting
from website.contrib.singleton_page.utils import SingletonPageCache from website.contrib.singleton_page.utils import SingletonPageCache
from website.home.models import HomePage from website.home.models import HomePage
@ -9,6 +10,8 @@ register = Library()
@register.inclusion_tag("common/footer.html", takes_context=True) @register.inclusion_tag("common/footer.html", takes_context=True)
def footer(context: dict) -> dict: def footer(context: dict) -> dict:
request = context["request"] request = context["request"]
footer_setting = FooterSetting.for_request(request)
return { return {
"homepage_url": SingletonPageCache.get_url(HomePage, request), "homepage_url": SingletonPageCache.get_url(HomePage, request),
"online_accounts": [block.value for block in footer_setting.icons],
} }

View file

@ -35,7 +35,7 @@ class ContentPageTestCase(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_queries(self) -> None: def test_queries(self) -> None:
with self.assertNumQueries(28): with self.assertNumQueries(32):
self.client.get(self.page.url) self.client.get(self.page.url)
@ -52,7 +52,7 @@ class ListingPageTestCase(TestCase):
ContentPageFactory(parent=cls.page) ContentPageFactory(parent=cls.page)
def test_accessible(self) -> None: def test_accessible(self) -> None:
with self.assertNumQueries(32): with self.assertNumQueries(36):
response = self.client.get(self.page.url) response = self.client.get(self.page.url)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.context["listing_pages"]), 2) self.assertEqual(len(response.context["listing_pages"]), 2)

View file

@ -16,7 +16,7 @@ class Error404PageTestCase(TestCase):
) )
def test_queries(self) -> None: def test_queries(self) -> None:
with self.assertNumQueries(16): with self.assertNumQueries(20):
self.client.get(self.url) self.client.get(self.url)

View file

@ -0,0 +1,19 @@
# Generated by Django 4.0.6 on 2022-09-02 07:38
import fontawesome_6.fields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("contact", "0006_alter_contactpage_body"),
]
operations = [
migrations.AddField(
model_name="onlineaccount",
name="icon",
field=fontawesome_6.fields.IconField(blank=True, max_length=60),
),
]

View file

@ -2,6 +2,7 @@ from django.db import models
from django.http.request import HttpRequest from django.http.request import HttpRequest
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils.text import slugify from django.utils.text import slugify
from fontawesome_6.fields import IconField
from wagtail.admin.panels import FieldPanel from wagtail.admin.panels import FieldPanel
from wagtail.search import index from wagtail.search import index
from wagtail.snippets.models import register_snippet from wagtail.snippets.models import register_snippet
@ -15,9 +16,11 @@ class OnlineAccount(models.Model, index.Indexed):
name = models.CharField(max_length=64, unique=True) name = models.CharField(max_length=64, unique=True)
url = models.URLField() url = models.URLField()
username = models.CharField(max_length=64) username = models.CharField(max_length=64)
icon = IconField()
panels = [ panels = [
FieldPanel("name"), FieldPanel("name"),
FieldPanel("icon"),
FieldPanel("username"), FieldPanel("username"),
FieldPanel("url"), FieldPanel("url"),
] ]

View file

@ -7,7 +7,7 @@
<div class="card-content"> <div class="card-content">
<div class="media"> <div class="media">
<div class="media-content"> <div class="media-content">
<p class="title is-4"><a href="{{ account.url }}">{{ account.name }}</a></p> <p class="title is-4"><a href="{{ account.url }}">{{ account.icon.as_html }} {{ account.name }}</a></p>
<p class="subtitle is-6">{{ account.username }}</p> <p class="subtitle is-6">{{ account.username }}</p>
</div> </div>
</div> </div>

View file

@ -89,7 +89,7 @@ class SearchPageResultsTestCase(TestCase):
) )
def test_too_high_page(self) -> None: def test_too_high_page(self) -> None:
with self.assertNumQueries(46): with self.assertNumQueries(50):
response = self.client.get( response = self.client.get(
self.url, {"q": "post", "page": 3}, HTTP_HX_REQUEST="true" self.url, {"q": "post", "page": 3}, HTTP_HX_REQUEST="true"
) )

View file

@ -72,6 +72,7 @@ INSTALLED_APPS = [
"wagtail_2fa", "wagtail_2fa",
"django_otp", "django_otp",
"django_otp.plugins.otp_totp", "django_otp.plugins.otp_totp",
"fontawesome_6",
"django.contrib.auth", "django.contrib.auth",
"django.contrib.contenttypes", "django.contrib.contenttypes",
"django.contrib.sessions", "django.contrib.sessions",