mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Allowing more options to style pretix shops (#1585)
* Fix caching issues in SASS compilation * Allow to set a custom page background color * Allow to disable round corners * Support larger header pictures * Allow to show title despite header * Move language picker * FIx widget styles
This commit is contained in:
@@ -1298,6 +1298,14 @@ Your {event} team"""))
|
||||
'default': '#D36060',
|
||||
'type': str
|
||||
},
|
||||
'theme_color_background': {
|
||||
'default': '#FFFFFF',
|
||||
'type': str
|
||||
},
|
||||
'theme_round_borders': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
},
|
||||
'primary_font': {
|
||||
'default': 'Open Sans',
|
||||
'type': str
|
||||
@@ -1322,6 +1330,22 @@ Your {event} team"""))
|
||||
'default': None,
|
||||
'type': File
|
||||
},
|
||||
'logo_image_large': {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
},
|
||||
'logo_show_title': {
|
||||
'default': 'True',
|
||||
'type': bool
|
||||
},
|
||||
'organizer_logo_image': {
|
||||
'default': None,
|
||||
'type': File
|
||||
},
|
||||
'organizer_logo_image_large': {
|
||||
'default': 'False',
|
||||
'type': bool
|
||||
},
|
||||
'og_image': {
|
||||
'default': None,
|
||||
'type': File
|
||||
|
||||
@@ -355,11 +355,23 @@ class EventSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
)
|
||||
logo_image = ExtFileField(
|
||||
label=_('Logo image'),
|
||||
label=_('Header image'),
|
||||
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
|
||||
required=False,
|
||||
help_text=_('If you provide a logo image, we will by default not show your events name and date '
|
||||
'in the page header. We will show your logo with a maximal height of 120 pixels.')
|
||||
help_text=_('If you provide a logo image, we will by default not show your event name and date '
|
||||
'in the page header. By default, we show your logo with a size of up to 1140x120 pixels. You '
|
||||
'can increase the size with the setting below. We recommend not using small details on the picture '
|
||||
'as it will be resized on smaller screens.')
|
||||
)
|
||||
logo_image_large = forms.BooleanField(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
required=False,
|
||||
)
|
||||
logo_show_title = forms.BooleanField(
|
||||
label=_('Show event title even if a header image is present'),
|
||||
help_text=_('The title will only be shown on the event front page.'),
|
||||
required=False,
|
||||
)
|
||||
og_image = ExtFileField(
|
||||
label=_('Social media image'),
|
||||
@@ -399,6 +411,20 @@ class EventSettingsForm(SettingsForm):
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
primary_font = forms.ChoiceField(
|
||||
label=_('Font'),
|
||||
choices=[
|
||||
|
||||
@@ -250,6 +250,20 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield'})
|
||||
)
|
||||
theme_color_background = forms.CharField(
|
||||
label=_("Page background color"),
|
||||
required=False,
|
||||
validators=[
|
||||
RegexValidator(regex='^#[0-9a-fA-F]{6}$',
|
||||
message=_('Please enter the hexadecimal code of a color, e.g. #990000.')),
|
||||
|
||||
],
|
||||
widget=forms.TextInput(attrs={'class': 'colorpickerfield no-contrast'})
|
||||
)
|
||||
theme_round_borders = forms.BooleanField(
|
||||
label=_("Use round edges"),
|
||||
required=False,
|
||||
)
|
||||
organizer_homepage_text = I18nFormField(
|
||||
label=_('Homepage text'),
|
||||
required=False,
|
||||
@@ -257,11 +271,18 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
help_text=_('This will be displayed on the organizer homepage.')
|
||||
)
|
||||
organizer_logo_image = ExtFileField(
|
||||
label=_('Logo image'),
|
||||
label=_('Header image'),
|
||||
ext_whitelist=(".png", ".jpg", ".gif", ".jpeg"),
|
||||
required=False,
|
||||
help_text=_('If you provide a logo image, we will by default not show your organization name '
|
||||
'in the page header. We will show your logo with a maximal height of 120 pixels.')
|
||||
'in the page header. By default, we show your logo with a size of up to 1140x120 pixels. You '
|
||||
'can increase the size with the setting below. We recommend not using small details on the picture '
|
||||
'as it will be resized on smaller screens.')
|
||||
)
|
||||
organizer_logo_image_large = forms.BooleanField(
|
||||
label=_('Use header image in its full size'),
|
||||
help_text=_('We recommend to upload a picture at least 1170 pixels wide.'),
|
||||
required=False,
|
||||
)
|
||||
event_list_type = forms.ChoiceField(
|
||||
label=_('Default overview style'),
|
||||
|
||||
@@ -98,12 +98,16 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Shop design" %}</legend>
|
||||
{% bootstrap_field sform.logo_image layout="control" %}
|
||||
{% bootstrap_field sform.logo_image_large layout="control" %}
|
||||
{% bootstrap_field sform.logo_show_title layout="control" %}
|
||||
{% bootstrap_field sform.og_image layout="control" %}
|
||||
{% url "control:organizer.edit" organizer=request.organizer.slug as org_url %}
|
||||
{% propagated request.event org_url "primary_color" "primary_font" "theme_color_success" "theme_color_danger" %}
|
||||
{% bootstrap_field sform.primary_color layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_success layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_danger layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_background layout="control" %}
|
||||
{% bootstrap_field sform.theme_round_borders layout="control" %}
|
||||
{% bootstrap_field sform.primary_font layout="control" %}
|
||||
{% endpropagated %}
|
||||
</fieldset>
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<fieldset>
|
||||
<legend>{% trans "Organizer page" %}</legend>
|
||||
{% bootstrap_field sform.organizer_logo_image layout="control" %}
|
||||
{% bootstrap_field sform.organizer_logo_image_large layout="control" %}
|
||||
{% bootstrap_field sform.organizer_homepage_text layout="control" %}
|
||||
{% bootstrap_field sform.event_list_type layout="control" %}
|
||||
{% bootstrap_field sform.event_list_availability layout="control" %}
|
||||
@@ -57,6 +58,8 @@
|
||||
{% bootstrap_field sform.primary_color layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_success layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_danger layout="control" %}
|
||||
{% bootstrap_field sform.theme_color_background layout="control" %}
|
||||
{% bootstrap_field sform.theme_round_borders layout="control" %}
|
||||
{% bootstrap_field sform.primary_font layout="control" %}
|
||||
{% bootstrap_field sform.favicon layout="control" %}
|
||||
</fieldset>
|
||||
|
||||
@@ -156,6 +156,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
})
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders',
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
|
||||
@@ -278,6 +278,7 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
|
||||
)
|
||||
display_properties = (
|
||||
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
|
||||
'theme_color_background', 'theme_round_borders'
|
||||
)
|
||||
if any(p in self.sform.changed_data for p in display_properties):
|
||||
change_css = True
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import hashlib
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.core.files.base import ContentFile, File
|
||||
from django.core.files.storage import default_storage
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.models import Event_SettingsStore, Organizer_SettingsStore
|
||||
@@ -16,12 +18,27 @@ from ...style import regenerate_css, regenerate_organizer_css
|
||||
class Command(BaseCommand):
|
||||
help = "Re-generate all custom stylesheets and scripts"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--organizer', action='store', type=str)
|
||||
parser.add_argument('--event', action='store', type=str)
|
||||
|
||||
@scopes_disabled()
|
||||
def handle(self, *args, **options):
|
||||
for es in Organizer_SettingsStore.objects.filter(key="presale_css_file"):
|
||||
# Reset compile cache
|
||||
cache.set('sass_compile_prefix', now().isoformat())
|
||||
|
||||
ostore = Organizer_SettingsStore.objects.filter(key="presale_css_file")
|
||||
if options.get('organizer'):
|
||||
ostore = ostore.filter(object__slug=options['organizer'])
|
||||
for es in ostore:
|
||||
regenerate_organizer_css.apply_async(args=(es.object_id,))
|
||||
|
||||
for es in Event_SettingsStore.objects.filter(key="presale_css_file").order_by('-object__date_from'):
|
||||
estore = Event_SettingsStore.objects.filter(key="presale_css_file").order_by('-object__date_from')
|
||||
if options.get('event'):
|
||||
estore = estore.filter(object__slug=options['event'])
|
||||
if options.get('organizer'):
|
||||
estore = estore.filter(object__organizer__slug=options['event'])
|
||||
for es in estore:
|
||||
regenerate_css.apply_async(args=(es.object_id,))
|
||||
|
||||
gs = GlobalSettingsObject()
|
||||
|
||||
@@ -12,6 +12,7 @@ from django.core.files.base import ContentFile
|
||||
from django.core.files.storage import default_storage
|
||||
from django.dispatch import Signal
|
||||
from django.templatetags.static import static as _static
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scope
|
||||
|
||||
from pretix.base.models import Event, Event_SettingsStore, Organizer
|
||||
@@ -49,6 +50,12 @@ def compile_scss(object, file="main.scss", fonts=True):
|
||||
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')))
|
||||
if object.settings.get('theme_color_background'):
|
||||
sassrules.append('$body-bg: {};'.format(object.settings.get('theme_color_background')))
|
||||
if not object.settings.get('theme_round_borders'):
|
||||
sassrules.append('$border-radius-base: 0;')
|
||||
sassrules.append('$border-radius-large: 0;')
|
||||
sassrules.append('$border-radius-small: 0;')
|
||||
|
||||
font = object.settings.get('primary_font')
|
||||
if font != 'Open Sans' and fonts:
|
||||
@@ -72,7 +79,8 @@ def compile_scss(object, file="main.scss", fonts=True):
|
||||
sasssrc = "\n".join(sassrules)
|
||||
srcchecksum = hashlib.sha1(sasssrc.encode('utf-8')).hexdigest()
|
||||
|
||||
css = cache.get('sass_compile_{}'.format(srcchecksum))
|
||||
cp = cache.get_or_set('sass_compile_prefix', now().isoformat())
|
||||
css = cache.get('sass_compile_{}_{}'.format(cp, srcchecksum))
|
||||
if not css:
|
||||
cf = dict(django_libsass.CUSTOM_FUNCTIONS)
|
||||
cf['static'] = static
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
{{ html_page_header|safe }}
|
||||
{% block above %}
|
||||
{% endblock %}
|
||||
<div class="container">
|
||||
<div class="container main-box">
|
||||
{% block page %}
|
||||
{% endblock %}
|
||||
<footer>
|
||||
|
||||
@@ -30,20 +30,40 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block page %}
|
||||
<div class="page-header">
|
||||
<div class="container page-header-links">
|
||||
{% if event.settings.locales|length > 1 %}
|
||||
{% if event.settings.theme_color_background|upper != "#FFFFFF" or event.settings.logo_image_large %}
|
||||
<div class="pull-right header-part flip">
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if request.event.settings.organizer_link_back %}
|
||||
<p>
|
||||
<div class="pull-left header-part flip">
|
||||
<a href="{% eventurl request.organizer "presale:organizer.index" %}">
|
||||
« {% blocktrans trimmed with name=request.organizer.name %}
|
||||
Show all events of {{ name }}
|
||||
{% endblocktrans %}
|
||||
Show all events of {{ name }}
|
||||
{% endblocktrans %}
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="pull-left flip">
|
||||
{% if event_logo %}
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block page %}
|
||||
<div class="page-header {% if event_logo and event.settings.logo_image_large %}logo-large{% endif %}">
|
||||
<div class="{% if not event_logo or not event.settings.logo_image_large %}pull-left flip{% endif %}">
|
||||
{% if event_logo and event.settings.logo_image_large %}
|
||||
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}"
|
||||
title="{{ event.name }}">
|
||||
<img src="{{ event_logo|thumb:'1170x5000' }}" alt="{{ event.name }}" class="event-logo" />
|
||||
</a>
|
||||
{% elif event_logo %}
|
||||
<a href="{% eventurl event "presale:event.index" cart_namespace=cart_namespace|default_if_none:"" %}"
|
||||
title="{{ event.name }}">
|
||||
<img src="{{ event_logo|thumb:'5000x120' }}" alt="{{ event.name }}" class="event-logo" />
|
||||
@@ -57,16 +77,18 @@
|
||||
</h1>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="pull-right flip loginbox">
|
||||
{% if request.event.settings.locales|length > 1 %}
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
{% if event.settings.locales|length > 1 %}
|
||||
{% if event.settings.theme_color_background|upper == "#FFFFFF" and not event.settings.logo_image_large %}
|
||||
<div class="{% if not event_logo or not event.settings.logo_image_large %}pull-right flip{% endif %} loginbox">
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% if request.event.testmode %}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
{{ ev.event_microdata }}
|
||||
</script>
|
||||
{% endautoescape %}
|
||||
|
||||
{% if show_cart %}
|
||||
<details class="panel panel-primary cart" open>
|
||||
<summary class="panel-heading">
|
||||
@@ -126,6 +127,14 @@
|
||||
<h2 class="subevent-head">{{ subevent.name }}</h2>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if event_logo and request.event.settings.logo_show_title and not subevent %}
|
||||
<h2 class="content-header">
|
||||
{{ event.name }}
|
||||
{% if not event.has_subevents %}
|
||||
<small>{{ event.get_date_range_display }}</small>
|
||||
{% endif %}
|
||||
</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if frontpage_text and not cart_namespace %}
|
||||
<div>
|
||||
|
||||
@@ -6,10 +6,31 @@
|
||||
{% block thetitle %}
|
||||
{% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }}
|
||||
{% endblock %}
|
||||
{% block above %}
|
||||
{% if organizer.settings.locales|length > 1 %}
|
||||
{% if organizer.settings.theme_color_background|upper != "#FFFFFF" or organizer.settings.organizer_logo_image_large %}
|
||||
<div class="container page-header-links">
|
||||
<div class="pull-right header-part flip">
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block page %}
|
||||
<div class="page-header">
|
||||
<div class="pull-left flip">
|
||||
{% if organizer_logo %}
|
||||
<div class="page-header {% if organizer_logo and organizer.settings.organizer_logo_image_large %}logo-large{% endif %}">
|
||||
<div class="{% if not organizer_logo or not organizer.settings.organizer_logo_image_large %}pull-left flip{% endif %}">
|
||||
{% if organizer_logo and organizer.settings.organizer_logo_image_large %}
|
||||
<a href="{% eventurl organizer "presale:organizer.index" %}" title="{{ organizer.name }}">
|
||||
<img src="{{ organizer_logo|thumb:'1170x5000' }}" alt="{{ organizer.name }}"
|
||||
class="organizer-logo" />
|
||||
</a>
|
||||
{% elif organizer_logo %}
|
||||
<a href="{% eventurl organizer "presale:organizer.index" %}" title="{{ organizer.name }}">
|
||||
<img src="{{ organizer_logo|thumb:'5000x120' }}" alt="{{ organizer.name }}"
|
||||
class="organizer-logo" />
|
||||
@@ -18,16 +39,18 @@
|
||||
<h1><a href="{% eventurl organizer "presale:organizer.index" %}">{{ organizer.name }}</a></h1>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="pull-right flip loginbox">
|
||||
{% if organizer.settings.locales|length > 1 %}
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
{% if organizer.settings.locales|length > 1 %}
|
||||
{% if organizer.settings.theme_color_background|upper == "#FFFFFF" and not organizer.settings.organizer_logo_image_large %}
|
||||
<div class="{% if not organizer_logo or not organizer.settings.organizer_logo_image_large %}pull-right flip{% endif %} loginbox">
|
||||
<div class="locales">
|
||||
{% for l in languages %}
|
||||
<a href="{% url "presale:locale.set" %}?locale={{ l.code }}&next={{ request.path }}%3F{{ request.META.QUERY_STRING|urlencode }}" class="{% if l.code == request.LANGUAGE_CODE %}active{% endif %}" rel="nofollow">
|
||||
{{ l.name_local }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{% if messages %}
|
||||
|
||||
329
src/pretix/static/pretixbase/scss/_contrast.scss
Normal file
329
src/pretix/static/pretixbase/scss/_contrast.scss
Normal file
@@ -0,0 +1,329 @@
|
||||
// https://medium.com/dev-channel/using-sass-to-automatically-pick-text-colors-4ba7645d2796
|
||||
//
|
||||
// Copyright 2017 Google Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
// Precomputed linear color channel values, for use in contrast calculations.
|
||||
// See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
|
||||
//
|
||||
// Algorithm, for c in 0 to 255:
|
||||
// f(c) {
|
||||
// c = c / 255;
|
||||
// return c < 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
||||
// }
|
||||
//
|
||||
// This lookup table is needed since there is no `pow` in SASS.
|
||||
$linear-channel-values:
|
||||
0
|
||||
.0003035269835488375
|
||||
.000607053967097675
|
||||
.0009105809506465125
|
||||
.00121410793419535
|
||||
.0015176349177441874
|
||||
.001821161901293025
|
||||
.0021246888848418626
|
||||
.0024282158683907
|
||||
.0027317428519395373
|
||||
.003035269835488375
|
||||
.003346535763899161
|
||||
.003676507324047436
|
||||
.004024717018496307
|
||||
.004391442037410293
|
||||
.004776953480693729
|
||||
.005181516702338386
|
||||
.005605391624202723
|
||||
.006048833022857054
|
||||
.006512090792594475
|
||||
.006995410187265387
|
||||
.007499032043226175
|
||||
.008023192985384994
|
||||
.008568125618069307
|
||||
.009134058702220787
|
||||
.00972121732023785
|
||||
.010329823029626936
|
||||
.010960094006488246
|
||||
.011612245179743885
|
||||
.012286488356915872
|
||||
.012983032342173012
|
||||
.013702083047289686
|
||||
.014443843596092545
|
||||
.01520851442291271
|
||||
.01599629336550963
|
||||
.016807375752887384
|
||||
.017641954488384078
|
||||
.018500220128379697
|
||||
.019382360956935723
|
||||
.0202885630566524
|
||||
.021219010376003555
|
||||
.022173884793387385
|
||||
.02315336617811041
|
||||
.024157632448504756
|
||||
.02518685962736163
|
||||
.026241221894849898
|
||||
.027320891639074894
|
||||
.028426039504420793
|
||||
.0295568344378088
|
||||
.030713443732993635
|
||||
.03189603307301153
|
||||
.033104766570885055
|
||||
.03433980680868217
|
||||
.03560131487502034
|
||||
.03688945040110004
|
||||
.0382043715953465
|
||||
.03954623527673284
|
||||
.04091519690685319
|
||||
.042311410620809675
|
||||
.043735029256973465
|
||||
.04518620438567554
|
||||
.046665086336880095
|
||||
.04817182422688942
|
||||
.04970656598412723
|
||||
.05126945837404324
|
||||
.052860647023180246
|
||||
.05448027644244237
|
||||
.05612849004960009
|
||||
.05780543019106723
|
||||
.0595112381629812
|
||||
.06124605423161761
|
||||
.06301001765316767
|
||||
.06480326669290577
|
||||
.06662593864377289
|
||||
.06847816984440017
|
||||
.07036009569659588
|
||||
.07227185068231748
|
||||
.07421356838014963
|
||||
.07618538148130785
|
||||
.07818742180518633
|
||||
.08021982031446832
|
||||
.0822827071298148
|
||||
.08437621154414882
|
||||
.08650046203654976
|
||||
.08865558628577294
|
||||
.09084171118340768
|
||||
.09305896284668745
|
||||
.0953074666309647
|
||||
.09758734714186246
|
||||
.09989872824711389
|
||||
.10224173308810132
|
||||
.10461648409110419
|
||||
.10702310297826761
|
||||
.10946171077829933
|
||||
.1119324278369056
|
||||
.11443537382697373
|
||||
.11697066775851084
|
||||
.11953842798834562
|
||||
.12213877222960187
|
||||
.12477181756095049
|
||||
.12743768043564743
|
||||
.1301364766903643
|
||||
.13286832155381798
|
||||
.13563332965520566
|
||||
.13843161503245183
|
||||
.14126329114027164
|
||||
.14412847085805777
|
||||
.14702726649759498
|
||||
.14995978981060856
|
||||
.15292615199615017
|
||||
.1559264637078274
|
||||
.1589608350608804
|
||||
.162029375639111
|
||||
.1651321945016676
|
||||
.16826940018969075
|
||||
.1714411007328226
|
||||
.17464740365558504
|
||||
.17788841598362912
|
||||
.18116424424986022
|
||||
.184474994500441
|
||||
.18782077230067787
|
||||
.19120168274079138
|
||||
.1946178304415758
|
||||
.19806931955994886
|
||||
.20155625379439707
|
||||
.20507873639031693
|
||||
.20863687014525575
|
||||
.21223075741405523
|
||||
.21586050011389926
|
||||
.2195261997292692
|
||||
.2232279573168085
|
||||
.22696587351009836
|
||||
.23074004852434915
|
||||
.23455058216100522
|
||||
.238397573812271
|
||||
.24228112246555486
|
||||
.24620132670783548
|
||||
.25015828472995344
|
||||
.25415209433082675
|
||||
.2581828529215958
|
||||
.26225065752969623
|
||||
.26635560480286247
|
||||
.2704977910130658
|
||||
.27467731206038465
|
||||
.2788942634768104
|
||||
.2831487404299921
|
||||
.2874408377269175
|
||||
.29177064981753587
|
||||
.2961382707983211
|
||||
.3005437944157765
|
||||
.3049873140698863
|
||||
.30946892281750854
|
||||
.31398871337571754
|
||||
.31854677812509186
|
||||
.32314320911295075
|
||||
.3277780980565422
|
||||
.33245153634617935
|
||||
.33716361504833037
|
||||
.3419144249086609
|
||||
.3467040563550296
|
||||
.35153259950043936
|
||||
.3564001441459435
|
||||
.3613067797835095
|
||||
.3662525955988395
|
||||
.3712376804741491
|
||||
.3762621229909065
|
||||
.38132601143253014
|
||||
.386429433787049
|
||||
.39157247774972326
|
||||
.39675523072562685
|
||||
.4019777798321958
|
||||
.4072402119017367
|
||||
.41254261348390375
|
||||
.4178850708481375
|
||||
.4232676699860717
|
||||
.4286904966139066
|
||||
.43415363617474895
|
||||
.4396571738409188
|
||||
.44520119451622786
|
||||
.45078578283822346
|
||||
.45641102318040466
|
||||
.4620769996544071
|
||||
.467783796112159
|
||||
.47353149614800955
|
||||
.4793201831008268
|
||||
.4851499400560704
|
||||
.4910208498478356
|
||||
.4969329950608704
|
||||
.5028864580325687
|
||||
.5088813208549338
|
||||
.5149176653765214
|
||||
.5209955732043543
|
||||
.5271151257058131
|
||||
.5332764040105052
|
||||
.5394794890121072
|
||||
.5457244613701866
|
||||
.5520114015120001
|
||||
.5583403896342679
|
||||
.5647115057049292
|
||||
.5711248294648731
|
||||
.5775804404296506
|
||||
.5840784178911641
|
||||
.5906188409193369
|
||||
.5972017883637634
|
||||
.6038273388553378
|
||||
.6104955708078648
|
||||
.6172065624196511
|
||||
.6239603916750761
|
||||
.6307571363461468
|
||||
.6375968739940326
|
||||
.6444796819705821
|
||||
.6514056374198242
|
||||
.6583748172794485
|
||||
.665387298282272
|
||||
.6724431569576875
|
||||
.6795424696330938
|
||||
.6866853124353135
|
||||
.6938717612919899
|
||||
.7011018919329731
|
||||
.7083757798916868
|
||||
.7156935005064807
|
||||
.7230551289219693
|
||||
.7304607400903537
|
||||
.7379104087727308
|
||||
.7454042095403874
|
||||
.7529422167760779
|
||||
.7605245046752924
|
||||
.768151147247507
|
||||
.7758222183174236
|
||||
.7835377915261935
|
||||
.7912979403326302
|
||||
.799102738014409
|
||||
.8069522576692516
|
||||
.8148465722161012
|
||||
.8227857543962835
|
||||
.8307698767746546
|
||||
.83879901174074
|
||||
.846873231509858
|
||||
.8549926081242338
|
||||
.8631572134541023
|
||||
.8713671191987972
|
||||
.8796223968878317
|
||||
.8879231178819663
|
||||
.8962693533742664
|
||||
.9046611743911496
|
||||
.9130986517934192
|
||||
.9215818562772946
|
||||
.9301108583754237
|
||||
.938685728457888
|
||||
.9473065367331999
|
||||
.9559733532492861
|
||||
.9646862478944651
|
||||
.9734452903984125
|
||||
.9822505503331171
|
||||
.9911020971138298
|
||||
1;
|
||||
|
||||
/**
|
||||
* Calculate the luminance for a color.
|
||||
* See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
|
||||
*/
|
||||
@function luminance($color) {
|
||||
$red: nth($linear-channel-values, red($color) + 1);
|
||||
$green: nth($linear-channel-values, green($color) + 1);
|
||||
$blue: nth($linear-channel-values, blue($color) + 1);
|
||||
|
||||
@return .2126 * $red + .7152 * $green + .0722 * $blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the contrast ratio between two colors.
|
||||
* See https://www.w3.org/TR/WCAG20-TECHS/G17.html#G17-tests
|
||||
*/
|
||||
@function contrast($back, $front) {
|
||||
$backLum: luminance($back) + .05;
|
||||
$foreLum: luminance($front) + .05;
|
||||
|
||||
@return max($backLum, $foreLum) / min($backLum, $foreLum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to use dark or light text on top of given color.
|
||||
* Returns black for dark text and white for light text.
|
||||
*/
|
||||
@function choose-contrast-color($color, $l, $d) {
|
||||
$lightContrast: contrast($color, $l);
|
||||
$darkContrast: contrast($color, $d);
|
||||
|
||||
@if ($lightContrast > $darkContrast) {
|
||||
@return $l;
|
||||
}
|
||||
@else {
|
||||
@return $d;
|
||||
}
|
||||
}
|
||||
@@ -56,3 +56,6 @@ $panel-warning-border: tint($brand-warning, 50%);
|
||||
$panel-warning-heading-bg: tint($brand-warning, 50%);
|
||||
$panel-default-border: #e5e5e5 !default;
|
||||
$panel-default-heading-bg: #e5e5e5 !default;
|
||||
|
||||
$body-bg: #FFFFFF !default;
|
||||
$main-box-bg: #FFFFFF;
|
||||
|
||||
@@ -226,19 +226,21 @@ var form_handlers = function (el) {
|
||||
if ($(this).val() === "") {
|
||||
$note.remove();
|
||||
}
|
||||
if (c > 7) {
|
||||
$note.html("<span class='fa fa-fw fa-check-circle'></span>")
|
||||
.append(gettext('Your color has great contrast and is very easy to read!'));
|
||||
$note.addClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else if (c > 2.5) {
|
||||
$note.html("<span class='fa fa-fw fa-info-circle'></span>")
|
||||
.append(gettext('Your color has decent contrast and is probably good-enough to read!'));
|
||||
$note.removeClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else {
|
||||
$note.html("<span class='fa fa-fw fa-warning'></span>")
|
||||
.append(gettext('Your color has bad contrast for text on white background, please choose a darker ' +
|
||||
'shade.'));
|
||||
$note.addClass("text-danger").removeClass("text-success").removeClass("text-warning");
|
||||
if (!$(this).is(".no-contrast")) {
|
||||
if (c > 7) {
|
||||
$note.html("<span class='fa fa-fw fa-check-circle'></span>")
|
||||
.append(gettext('Your color has great contrast and is very easy to read!'));
|
||||
$note.addClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else if (c > 2.5) {
|
||||
$note.html("<span class='fa fa-fw fa-info-circle'></span>")
|
||||
.append(gettext('Your color has decent contrast and is probably good-enough to read!'));
|
||||
$note.removeClass("text-success").removeClass("text-warning").removeClass("text-danger");
|
||||
} else {
|
||||
$note.html("<span class='fa fa-fw fa-warning'></span>")
|
||||
.append(gettext('Your color has bad contrast for text on white background, please choose a darker ' +
|
||||
'shade.'));
|
||||
$note.addClass("text-danger").removeClass("text-success").removeClass("text-warning");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
display: block;
|
||||
background: $brand-primary;
|
||||
color: white;
|
||||
border-radius: 5px;
|
||||
border-radius: $border-radius-large;
|
||||
padding: 3px 5px;
|
||||
margin-top: 3px;
|
||||
font-size: 12px;
|
||||
|
||||
@@ -153,7 +153,7 @@ section.front-page {
|
||||
line-height: 22px;
|
||||
}
|
||||
@media (max-width: $screen-sm-max) {
|
||||
.page-header h1 small {
|
||||
.page-header h1 small, h1.content-header small {
|
||||
display: block;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
.in-iframe .page-header {
|
||||
.in-iframe .page-header, .in-iframe .page-header-links {
|
||||
display: none;
|
||||
}
|
||||
body.in-iframe {
|
||||
background: white !important;
|
||||
}
|
||||
.in-iframe .main-box {
|
||||
margin: auto;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.in-iframe .container {
|
||||
padding-top: 10px;
|
||||
width: 100%;
|
||||
|
||||
@@ -47,7 +47,7 @@ html.rtl {
|
||||
.fa-arrow-left::before {
|
||||
content: $fa-var-arrow-right;
|
||||
}
|
||||
.page-header h1 {
|
||||
.page-header h1, h2.content-header {
|
||||
direction: rtl;
|
||||
* {
|
||||
display: inline-block;
|
||||
|
||||
95
src/pretix/static/pretixpresale/scss/_theme.scss
Normal file
95
src/pretix/static/pretixpresale/scss/_theme.scss
Normal file
@@ -0,0 +1,95 @@
|
||||
@import "../../pretixbase/scss/_contrast.scss";
|
||||
|
||||
.page-header {
|
||||
position: relative;
|
||||
padding-bottom: 9px;
|
||||
margin-top: 20px;
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
h1 small {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.loginbox {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.event-logo, .organizer-logo {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
background: $main-box-bg;
|
||||
}
|
||||
|
||||
.page-header-links > div.header-part {
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
|
||||
a {
|
||||
color: choose-contrast-color($body-bg, white, $link-color);
|
||||
}
|
||||
a.active, .locales a.active {
|
||||
border-bottom-color: choose-contrast-color($body-bg, white, $link-color) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header.logo-large {
|
||||
margin: 0 -15px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loginbox {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
html.rtl & {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
h2.content-header {
|
||||
margin-top: 0;
|
||||
}
|
||||
@media (max-width: $screen-xs-max) {
|
||||
h2.content-header small {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.main-box {
|
||||
@if ($body-bg != #FFFFFF) {
|
||||
margin: 20px auto;
|
||||
border-radius: $border-radius-large;
|
||||
}
|
||||
}
|
||||
.page-header-links {
|
||||
padding: 0;
|
||||
}
|
||||
.page-header-links > div.header-part {
|
||||
@if ($body-bg != #FFFFFF) {
|
||||
padding: 10px 0;
|
||||
margin-bottom: -20px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-header.logo-large {
|
||||
img {
|
||||
@if ($body-bg != #FFFFFF) {
|
||||
border-top-right-radius: $border-radius-large;
|
||||
border-top-left-radius: $border-radius-large;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-header .loginbox {
|
||||
@if ($body-bg != #FFFFFF) {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
@import "../../datetimepicker/_bootstrap-datetimepicker.scss";
|
||||
@import "../../fontawesome/scss/font-awesome.scss";
|
||||
|
||||
@import "_theme.scss";
|
||||
@import "_event.scss";
|
||||
@import "_cart.scss";
|
||||
@import "_forms.scss";
|
||||
@@ -21,24 +22,6 @@ footer {
|
||||
padding: 10px 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
.page-header {
|
||||
position: relative;
|
||||
padding-bottom: 9px;
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
h1 small {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.loginbox {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.event-logo, .organizer-logo {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.js-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user