mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
Allow to configure accent colors
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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'})
|
||||
)
|
||||
|
||||
@@ -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'})
|
||||
)
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Shop design" %}</legend>
|
||||
{% 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.theme_color_success layout="control" %}
|
||||
{% bootstrap_field form.theme_color_danger layout="control" %}
|
||||
{% bootstrap_field form.primary_font layout="control" %}
|
||||
{% endpropagated %}
|
||||
</fieldset>
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% 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" %}
|
||||
</fieldset>
|
||||
<div class="form-group submit-group">
|
||||
|
||||
@@ -40,6 +40,10 @@ def compile_scss(object, file="main.scss", fonts=True):
|
||||
sassrules = []
|
||||
if 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')
|
||||
if font != 'Open Sans' and fonts:
|
||||
|
||||
@@ -18,10 +18,10 @@ $text-color: #222222;
|
||||
$text-muted: #999999;
|
||||
|
||||
$brand-primary: #7f5a91 !default;
|
||||
$brand-success: #50a167;
|
||||
$brand-info: #5f9cd4;
|
||||
$brand-warning: #ffb419;
|
||||
$brand-danger: #d36060;
|
||||
$brand-success: #50a167 !default;
|
||||
$brand-info: #5f9cd4 !default;
|
||||
$brand-warning: #ffb419 !default;
|
||||
$brand-danger: #d36060 !default;
|
||||
|
||||
$btn-default-border: #CCCCCC;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user