From 4e6f4716ec983a0a34fc8f38319f6401277aaeee Mon Sep 17 00:00:00 2001
From: Raphael Michel
Date: Tue, 13 Nov 2018 12:56:52 +0100
Subject: [PATCH] Allow to configure accent colors
---
src/pretix/base/settings.py | 8 ++++
src/pretix/control/forms/__init__.py | 42 +++++++++++++++++++
src/pretix/control/forms/event.py | 34 +++++++++++++--
src/pretix/control/forms/organizer.py | 32 +++++++++++++-
.../pretixcontrol/event/display.html | 4 +-
.../pretixcontrol/organizers/display.html | 2 +
src/pretix/presale/style.py | 4 ++
.../static/pretixbase/scss/_variables.scss | 8 ++--
8 files changed, 124 insertions(+), 10 deletions(-)
diff --git a/src/pretix/base/settings.py b/src/pretix/base/settings.py
index 2ec0b2db5c..1d1c125806 100644
--- a/src/pretix/base/settings.py
+++ b/src/pretix/base/settings.py
@@ -483,6 +483,14 @@ Your {event} team"""))
'default': '#8E44B3',
'type': str
},
+ 'theme_color_success': {
+ 'default': '#50A167',
+ 'type': str
+ },
+ 'theme_color_danger': {
+ 'default': '#D36060',
+ 'type': str
+ },
'primary_font': {
'default': 'Open Sans',
'type': str
diff --git a/src/pretix/control/forms/__init__.py b/src/pretix/control/forms/__init__.py
index 34e86e49e1..ce1ea43da8 100644
--- a/src/pretix/control/forms/__init__.py
+++ b/src/pretix/control/forms/__init__.py
@@ -5,6 +5,7 @@ from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.forms.utils import from_current_timezone
+from django.utils.deconstruct import deconstructible
from django.utils.html import conditional_escape
from django.utils.translation import ugettext_lazy as _
@@ -185,3 +186,44 @@ class SplitDateTimeField(forms.SplitDateTimeField):
result = datetime.datetime.combine(*data_list)
return from_current_timezone(result)
return None
+
+
+@deconstructible
+class ColorContrastValidator:
+ message = _('This color is too bright to allow for proper contrast when used for text on white ground.')
+ code = 'contrast'
+
+ def __init__(self, message=None, code=None):
+ if message is not None:
+ self.message = message
+ if code is not None:
+ self.code = code
+
+ def __call__(self, value):
+ # See https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ fg_color = [int(str(value)[1:3], 16), int(str(value)[1:3], 16), int(str(value)[1:3], 16)]
+ bg_color = [255, 255, 255]
+ fg_lum = [
+ (float(cc) / 255) / 12.92
+ if (float(cc) / 255) < 0.03928
+ else (((float(cc) / 255) + 0.055) / 1.055) ** 2.4
+ for cc in fg_color
+ ]
+ bg_lum = [
+ (float(cc) / 255) / 12.92
+ if (float(cc) / 255) < 0.03928
+ else (((float(cc) / 255) + 0.055) / 1.055) ** 2.4
+ for cc in bg_color
+ ]
+ fg_rel_lum = 0.2126 * fg_lum[0] + 0.7152 * fg_lum[1] + 0.0722 * fg_lum[2]
+ bg_rel_lum = 0.2126 * bg_lum[0] + 0.7152 * bg_lum[1] + 0.0722 * bg_lum[2]
+ contrast_ratio = (bg_rel_lum + 0.05) / (fg_rel_lum + 0.05)
+ if contrast_ratio < 1.4:
+ raise ValidationError(self.message, code=self.code)
+
+ def __eq__(self, other):
+ return (
+ isinstance(other, ColorContrastValidator) and
+ (self.message == other.message) and
+ (self.code == other.code)
+ )
diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py
index 21242ecd5f..705d5d7c9b 100644
--- a/src/pretix/control/forms/event.py
+++ b/src/pretix/control/forms/event.py
@@ -22,8 +22,9 @@ from pretix.base.models.event import EventMetaValue, SubEvent
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.control.forms import (
- ExtFileField, MultipleLanguagesWidget, SingleLanguageWidget, SlugWidget,
- SplitDateTimeField, SplitDateTimePickerWidget,
+ ColorContrastValidator, ExtFileField, MultipleLanguagesWidget,
+ SingleLanguageWidget, SlugWidget, SplitDateTimeField,
+ SplitDateTimePickerWidget,
)
from pretix.multidomain.urlreverse import build_absolute_uri
from pretix.plugins.banktransfer.payment import BankTransfer
@@ -935,10 +936,37 @@ class MailSettingsForm(SettingsForm):
class DisplaySettingsForm(SettingsForm):
primary_color = forms.CharField(
label=_("Primary color"),
+ help_text=_("We strongly suggest to use a dark shade that has a good contrast for text on white ground."),
required=False,
validators=[
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
- message=_('Please enter the hexadecimal code of a color, e.g. #990000.'))
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+ ColorContrastValidator()
+ ],
+ widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
+ )
+ theme_color_success = forms.CharField(
+ label=_("Accent color for success"),
+ help_text=_("We strongly suggest to use a dark shade of green that has a good contrast for text on white "
+ "ground."),
+ required=False,
+ validators=[
+ RegexValidator(regex='^#[0-9a-fA-F]{6}$',
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+ ColorContrastValidator()
+ ],
+ widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
+ )
+ theme_color_danger = forms.CharField(
+ label=_("Accent color for errors"),
+ help_text=_("We strongly suggest to use a dark shade of red that has a good contrast for text on white "
+ "ground."),
+ required=False,
+ validators=[
+ RegexValidator(regex='^#[0-9a-fA-F]{6}$',
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+
+ ColorContrastValidator()
],
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
)
diff --git a/src/pretix/control/forms/organizer.py b/src/pretix/control/forms/organizer.py
index 0070b2708f..51fb4b8ba5 100644
--- a/src/pretix/control/forms/organizer.py
+++ b/src/pretix/control/forms/organizer.py
@@ -10,7 +10,9 @@ from pretix.api.models import WebHook
from pretix.api.webhooks import get_all_webhook_events
from pretix.base.forms import I18nModelForm, SettingsForm
from pretix.base.models import Device, Organizer, Team
-from pretix.control.forms import ExtFileField, MultipleLanguagesWidget
+from pretix.control.forms import (
+ ColorContrastValidator, ExtFileField, MultipleLanguagesWidget,
+)
from pretix.multidomain.models import KnownDomain
from pretix.presale.style import get_fonts
@@ -178,7 +180,33 @@ class OrganizerDisplaySettingsForm(SettingsForm):
required=False,
validators=[
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
- message=_('Please enter the hexadecimal code of a color, e.g. #990000.'))
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+ ColorContrastValidator()
+ ],
+ widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
+ )
+ theme_color_success = forms.CharField(
+ label=_("Accent color for success"),
+ help_text=_("We strongly suggest to use a dark shade of green that has a good contrast for text on white "
+ "ground."),
+ required=False,
+ validators=[
+ RegexValidator(regex='^#[0-9a-fA-F]{6}$',
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+ ColorContrastValidator()
+ ],
+ widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
+ )
+ theme_color_danger = forms.CharField(
+ label=_("Accent color for errors"),
+ help_text=_("We strongly suggest to use a dark shade of red that has a good contrast for text on white "
+ "ground."),
+ required=False,
+ validators=[
+ RegexValidator(regex='^#[0-9a-fA-F]{6}$',
+ message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
+
+ ColorContrastValidator()
],
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
)
diff --git a/src/pretix/control/templates/pretixcontrol/event/display.html b/src/pretix/control/templates/pretixcontrol/event/display.html
index 93230b4680..b92a42624d 100644
--- a/src/pretix/control/templates/pretixcontrol/event/display.html
+++ b/src/pretix/control/templates/pretixcontrol/event/display.html
@@ -20,8 +20,10 @@
diff --git a/src/pretix/control/templates/pretixcontrol/organizers/display.html b/src/pretix/control/templates/pretixcontrol/organizers/display.html
index 8b4deb9c37..aebd0c8ee2 100644
--- a/src/pretix/control/templates/pretixcontrol/organizers/display.html
+++ b/src/pretix/control/templates/pretixcontrol/organizers/display.html
@@ -23,6 +23,8 @@
{% endblocktrans %}