Allow to configure accent colors

This commit is contained in:
Raphael Michel
2018-11-13 12:56:52 +01:00
parent e523a4e610
commit 4e6f4716ec
8 changed files with 124 additions and 10 deletions
+8
View File
@@ -483,6 +483,14 @@ Your {event} team"""))
'default': '#8E44B3', 'default': '#8E44B3',
'type': str 'type': str
}, },
'theme_color_success': {
'default': '#50A167',
'type': str
},
'theme_color_danger': {
'default': '#D36060',
'type': str
},
'primary_font': { 'primary_font': {
'default': 'Open Sans', 'default': 'Open Sans',
'type': str 'type': str
+42
View File
@@ -5,6 +5,7 @@ from django import forms
from django.conf import settings from django.conf import settings
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.utils import from_current_timezone from django.forms.utils import from_current_timezone
from django.utils.deconstruct import deconstructible
from django.utils.html import conditional_escape from django.utils.html import conditional_escape
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@@ -185,3 +186,44 @@ class SplitDateTimeField(forms.SplitDateTimeField):
result = datetime.datetime.combine(*data_list) result = datetime.datetime.combine(*data_list)
return from_current_timezone(result) return from_current_timezone(result)
return None 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)
)
+31 -3
View File
@@ -22,8 +22,9 @@ from pretix.base.models.event import EventMetaValue, SubEvent
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
from pretix.base.settings import PERSON_NAME_SCHEMES from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.control.forms import ( from pretix.control.forms import (
ExtFileField, MultipleLanguagesWidget, SingleLanguageWidget, SlugWidget, ColorContrastValidator, ExtFileField, MultipleLanguagesWidget,
SplitDateTimeField, SplitDateTimePickerWidget, SingleLanguageWidget, SlugWidget, SplitDateTimeField,
SplitDateTimePickerWidget,
) )
from pretix.multidomain.urlreverse import build_absolute_uri from pretix.multidomain.urlreverse import build_absolute_uri
from pretix.plugins.banktransfer.payment import BankTransfer from pretix.plugins.banktransfer.payment import BankTransfer
@@ -935,10 +936,37 @@ class MailSettingsForm(SettingsForm):
class DisplaySettingsForm(SettingsForm): class DisplaySettingsForm(SettingsForm):
primary_color = forms.CharField( primary_color = forms.CharField(
label=_("Primary color"), 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, required=False,
validators=[ validators=[
RegexValidator(regex='^#[0-9a-fA-F]{6}$', 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'}) widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
) )
+30 -2
View File
@@ -10,7 +10,9 @@ from pretix.api.models import WebHook
from pretix.api.webhooks import get_all_webhook_events from pretix.api.webhooks import get_all_webhook_events
from pretix.base.forms import I18nModelForm, SettingsForm from pretix.base.forms import I18nModelForm, SettingsForm
from pretix.base.models import Device, Organizer, Team 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.multidomain.models import KnownDomain
from pretix.presale.style import get_fonts from pretix.presale.style import get_fonts
@@ -178,7 +180,33 @@ class OrganizerDisplaySettingsForm(SettingsForm):
required=False, required=False,
validators=[ validators=[
RegexValidator(regex='^#[0-9a-fA-F]{6}$', 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'}) widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
) )
@@ -20,8 +20,10 @@
<fieldset> <fieldset>
<legend>{% trans "Shop design" %}</legend> <legend>{% trans "Shop design" %}</legend>
{% url "control:organizer.display" organizer=request.organizer.slug as org_url %} {% url "control:organizer.display" organizer=request.organizer.slug as org_url %}
{% propagated request.event org_url "primary_color" "primary_font" %} {% propagated request.event org_url "primary_color" "primary_font" "theme_color_success" "theme_color_danger" %}
{% bootstrap_field form.primary_color layout="control" %} {% bootstrap_field form.primary_color layout="control" %}
{% bootstrap_field form.theme_color_success layout="control" %}
{% bootstrap_field form.theme_color_danger layout="control" %}
{% bootstrap_field form.primary_font layout="control" %} {% bootstrap_field form.primary_font layout="control" %}
{% endpropagated %} {% endpropagated %}
</fieldset> </fieldset>
@@ -23,6 +23,8 @@
{% endblocktrans %} {% endblocktrans %}
</p> </p>
{% bootstrap_field form.primary_color layout="control" %} {% bootstrap_field form.primary_color layout="control" %}
{% bootstrap_field form.theme_color_success layout="control" %}
{% bootstrap_field form.theme_color_danger layout="control" %}
{% bootstrap_field form.primary_font layout="control" %} {% bootstrap_field form.primary_font layout="control" %}
</fieldset> </fieldset>
<div class="form-group submit-group"> <div class="form-group submit-group">
+4
View File
@@ -40,6 +40,10 @@ def compile_scss(object, file="main.scss", fonts=True):
sassrules = [] sassrules = []
if object.settings.get('primary_color'): if object.settings.get('primary_color'):
sassrules.append('$brand-primary: {};'.format(object.settings.get('primary_color'))) sassrules.append('$brand-primary: {};'.format(object.settings.get('primary_color')))
if object.settings.get('theme_color_success'):
sassrules.append('$brand-success: {};'.format(object.settings.get('theme_color_success')))
if object.settings.get('theme_color_danger'):
sassrules.append('$brand-danger: {};'.format(object.settings.get('theme_color_danger')))
font = object.settings.get('primary_font') font = object.settings.get('primary_font')
if font != 'Open Sans' and fonts: if font != 'Open Sans' and fonts:
@@ -18,10 +18,10 @@ $text-color: #222222;
$text-muted: #999999; $text-muted: #999999;
$brand-primary: #7f5a91 !default; $brand-primary: #7f5a91 !default;
$brand-success: #50a167; $brand-success: #50a167 !default;
$brand-info: #5f9cd4; $brand-info: #5f9cd4 !default;
$brand-warning: #ffb419; $brand-warning: #ffb419 !default;
$brand-danger: #d36060; $brand-danger: #d36060 !default;
$btn-default-border: #CCCCCC; $btn-default-border: #CCCCCC;