Skip to content

Commit

Permalink
[#2030] Add option to upload and use custom fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
pi-sigma committed Jan 23, 2024
1 parent 71f1268 commit 1df2bb7
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/open_inwoner/configurations/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from ..utils.css import ALLOWED_PROPERTIES
from ..utils.fields import CSSEditorWidget
from ..utils.iteration import split
from .models import CustomFont, SiteConfiguration, SiteConfigurationPage
from .models import CustomFontSet, SiteConfiguration, SiteConfigurationPage


@admin.action(description=_("Delete selected websites"))
Expand Down Expand Up @@ -86,7 +86,7 @@ class SiteConfigurationPageInline(OrderedTabularInline):


class FontConfigurationInline(admin.StackedInline):
model = CustomFont
model = CustomFontSet
verbose_name = "Fonts"
min_num = 1
can_delete = False
Expand Down
7 changes: 7 additions & 0 deletions src/open_inwoner/configurations/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _


class FontFileName(models.TextChoices):
body = _("text_body_font"), _("Text body font")
heading = _("heading_font"), _("Heading font")
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by Django 3.2.23 on 2024-01-19 09:19
# Generated by Django 3.2.23 on 2024-01-23 15:38

import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import open_inwoner.configurations.models
Expand All @@ -14,7 +15,7 @@ class Migration(migrations.Migration):

operations = [
migrations.CreateModel(
name="CustomFont",
name="CustomFontSet",
fields=[
(
"id",
Expand All @@ -29,27 +30,35 @@ class Migration(migrations.Migration):
"text_body_font",
open_inwoner.configurations.models.CustomFontField(
blank=True,
help_text="Regular font for the text body. Supported are files with the .ttf extension.",
null=True,
storage=open_inwoner.utils.files.OverwriteStorage(),
upload_to=open_inwoner.configurations.models.CustomFont.update_filename_body,
upload_to=open_inwoner.configurations.models.CustomFontSet.update_filename_body,
validators=[
django.core.validators.FileExtensionValidator(["ttf"])
],
verbose_name="Text body font",
),
),
(
"heading_font",
open_inwoner.configurations.models.CustomFontField(
blank=True,
help_text="Regular font for headings. Supported are files with the .ttf extension.",
null=True,
storage=open_inwoner.utils.files.OverwriteStorage(),
upload_to=open_inwoner.configurations.models.CustomFont.update_filename_heading,
upload_to=open_inwoner.configurations.models.CustomFontSet.update_filename_heading,
validators=[
django.core.validators.FileExtensionValidator(["ttf"])
],
verbose_name="Heading font",
),
),
(
"configuration",
"site_configuration",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="font_configuration",
related_name="custom_fonts",
to="configurations.siteconfiguration",
verbose_name="Configuration",
),
Expand Down
20 changes: 14 additions & 6 deletions src/open_inwoner/configurations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,53 +594,61 @@ def __init__(self, file_name: str = "", **kwargs):
super().__init__(**kwargs)


class CustomFont(models.Model):
class CustomFontSet(models.Model):
def update_filename(self, filename: str, new_name: str, path: str) -> str:
ext = filename.split(".")[1]
filename = f"{new_name}.{ext}"
return "{path}/{filename}".format(path=path, filename=filename)

def update_filename_body(self, filename: str) -> str:
return CustomFont.update_filename(
return CustomFontSet.update_filename(
self,
filename,
new_name=CustomFontName.body,
path="custom_fonts/",
)

def update_filename_heading(self, filename: str) -> str:
return CustomFont.update_filename(
return CustomFontSet.update_filename(
self,
filename,
new_name=CustomFontName.heading,
path="custom_fonts/",
)

configuration = models.OneToOneField(
site_configuration = models.OneToOneField(
SiteConfiguration,
verbose_name=_("Configuration"),
related_name="font_configuration",
related_name="custom_fonts",
on_delete=models.CASCADE,
)
text_body_font = CustomFontField(
verbose_name=_("Text body font"),
upload_to=update_filename_body,
file_name=CustomFontName.body,
storage=OverwriteStorage(),
validators=[FileExtensionValidator(["ttf"])],
blank=True,
null=True,
help_text=_(
"Regular font for the text body. Supported are files with the .ttf extension."
),
)
heading_font = CustomFontField(
verbose_name=_("Heading font"),
upload_to=update_filename_heading,
file_name=CustomFontName.heading,
storage=OverwriteStorage(),
validators=[FileExtensionValidator(["ttf"])],
blank=True,
null=True,
help_text=_(
"Regular font for headings. Supported are files with the .ttf extension."
),
)


@receiver(post_save, sender=CustomFont)
@receiver(post_save, sender=CustomFontSet)
def remove_orphan_files(sender, instance, *args, **kwargs):
"""
Remove font files corresponding to `CustomFont` fields that have been cleared
Expand Down
71 changes: 71 additions & 0 deletions src/open_inwoner/configurations/tests/test_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from django.urls import reverse

from django_webtest import WebTest
from webtest import Upload

from open_inwoner.accounts.tests.factories import UserFactory

from ...utils.test import ClearCachesMixin
from ..models import CustomFontSet, SiteConfiguration


class CustomFontsTest(ClearCachesMixin, WebTest):
def setUp(self):
self.user = UserFactory(is_superuser=True, is_staff=True)

self.config = SiteConfiguration.get_solo()
self.config.custom_fonts = CustomFontSet()
self.config.save()

self.form = self.app.get(
reverse("admin:configurations_siteconfiguration_change"), user=self.user
).forms["siteconfiguration_form"]

def test_upload_font_correct_filetype(self):
font_file = Upload("valid.ttf", b"content", content_type="font/ttf")
self.form["name"] = "Test"
self.form["custom_fonts-0-text_body_font"] = font_file
self.form["custom_fonts-0-heading_font"] = font_file

self.form.submit()

custom_font_set = CustomFontSet.objects.first()
body_font = custom_font_set.text_body_font
heading_font = custom_font_set.heading_font

self.assertEqual(body_font.name, "custom_fonts/text_body_font.ttf")
self.assertEqual(heading_font.name, "custom_fonts/heading_font.ttf")

# test file overwrite: upload again
another_font_file = Upload(
"valid_encore.ttf", b"content", content_type="font/ttf"
)
self.form["custom_fonts-0-text_body_font"] = another_font_file
self.form["custom_fonts-0-heading_font"] = another_font_file

self.form.submit()

self.assertEqual(len(CustomFontSet.objects.all()), 1)

custom_font_set = CustomFontSet.objects.first()
body_font = custom_font_set.text_body_font
heading_font = custom_font_set.heading_font

self.assertEqual(body_font.name, "custom_fonts/text_body_font.ttf")
self.assertEqual(heading_font.name, "custom_fonts/heading_font.ttf")

def test_upload_font_incorrect_filetype(self):
font_file = Upload("invalid.svg", b"content", content_type="font/svg")
self.form["name"] = "Test"
self.form["custom_fonts-0-text_body_font"] = font_file

response = self.form.submit()

self.assertEquals(
response.context["errors"],
[
[
"Bestandsextensie ‘svg’ is niet toegestaan. Toegestane extensies zijn: ‘ttf’."
]
],
)

0 comments on commit 1df2bb7

Please sign in to comment.