Compare commits

...
Author SHA1 Message Date
Martin Gross de1e7abc48 base/pdf: Only call get_fonts() once per generation 2024-03-08 11:23:31 +01:00
Martin Gross 5fa5810670 Invoices: Add support for event-fonts 2024-02-28 22:03:43 +01:00
Martin Gross 572fcf4751 Editor/webfonts.css: Do not create a font section for "pdf_only" 2024-02-28 21:46:33 +01:00
Martin Gross c11f718253 isort 2024-02-28 21:31:39 +01:00
Martin Gross 7949be15b7 Review Comments: Do not run signal for every single textbox on page 2024-02-28 21:30:03 +01:00
Martin Gross cc020f24a2 Review Comments: Check for // instead of https for web-webfonts 2024-02-28 21:21:52 +01:00
Martin Gross f0a76a3ee0 Add register_event_fonts signal and facilities for web-embedded webfonts 2024-02-13 10:20:12 +01:00
Phin WolkwitzandGitHub cb17d80b63 Widget: Fix variations collapse indicator placement (#3883) 2024-02-12 13:51:25 +01:00
Raphael MichelandGitHub 86b28b9b53 Get rid of unmaintained dependency python-u2flib-server (#3879) 2024-02-12 13:03:56 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
fac404631c Update sentry-sdk requirement from ==1.15.* to ==1.40.* (#3850)
Updates the requirements on [sentry-sdk](https://github.com/getsentry/sentry-python) to permit the latest version.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.15.0...1.40.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 12:53:01 +01:00
Phin WolkwitzandRaphael Michel fd547014a9 Translations: Update German (informal) (de_Informal)
Currently translated at 99.1% (223 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de_Informal/

powered by weblate
2024-02-12 10:17:44 +01:00
Phin WolkwitzandRaphael Michel d23a625415 Translations: Update German
Currently translated at 99.1% (223 of 225 strings)

Translation: pretix/pretix (JavaScript parts)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/de/

powered by weblate
2024-02-12 10:17:44 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
199416b904 Update django-redis requirement from ==5.2.* to ==5.4.* (#3877)
Updates the requirements on [django-redis](https://github.com/jazzband/django-redis) to permit the latest version.
- [Release notes](https://github.com/jazzband/django-redis/releases)
- [Changelog](https://github.com/jazzband/django-redis/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/jazzband/django-redis/compare/5.2.0...5.4.0)

---
updated-dependencies:
- dependency-name: django-redis
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 10:01:52 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
0a7a113b4e Update pytest-rerunfailures requirement from ==11.* to ==13.* (#3878)
Updates the requirements on [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) to permit the latest version.
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/11.0...13.0)

---
updated-dependencies:
- dependency-name: pytest-rerunfailures
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:47:04 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5978a715b5 Update aiohttp requirement from ==3.8.* to ==3.9.* (#3875)
Updates the requirements on [aiohttp](https://github.com/aio-libs/aiohttp) to permit the latest version.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.0a0...v3.9.3)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:41:41 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
71beb54eb4 Bump django-formtools from 2.4.1 to 2.5.1 (#3876)
Bumps [django-formtools](https://github.com/jazzband/django-formtools) from 2.4.1 to 2.5.1.
- [Changelog](https://github.com/jazzband/django-formtools/blob/master/docs/changelog.rst)
- [Commits](https://github.com/jazzband/django-formtools/compare/2.4.1...2.5.1)

---
updated-dependencies:
- dependency-name: django-formtools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:35:10 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
b92981353f Update django-statici18n requirement from ==2.3.* to ==2.4.* (#3874)
Updates the requirements on [django-statici18n](https://github.com/zyegfryed/django-statici18n) to permit the latest version.
- [Changelog](https://github.com/zyegfryed/django-statici18n/blob/main/docs/changelog.rst)
- [Commits](https://github.com/zyegfryed/django-statici18n/commits)

---
updated-dependencies:
- dependency-name: django-statici18n
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 09:34:55 +01:00
21 changed files with 221 additions and 81 deletions
+2
View File
@@ -84,6 +84,8 @@ convenient to you:
.. automethod:: _register_fonts
.. automethod:: _register_event_fonts
.. automethod:: _on_first_page
.. automethod:: _on_other_page
+6 -7
View File
@@ -42,7 +42,7 @@ dependencies = [
"django-countries==7.5.*",
"django-filter==23.2",
"django-formset-js-improved==0.5.0.3",
"django-formtools==2.4.1",
"django-formtools==2.5.1",
"django-hierarkey==1.1.*",
"django-hijack==3.3.*",
"django-i18nfield==1.9.*,>=1.9.4",
@@ -52,9 +52,9 @@ dependencies = [
"django-oauth-toolkit==2.2.*",
"django-otp==1.2.*",
"django-phonenumber-field==7.1.*",
"django-redis==5.2.*",
"django-redis==5.4.*",
"django-scopes==2.0.*",
"django-statici18n==2.3.*",
"django-statici18n==2.4.*",
"djangorestframework==3.14.*",
"dnspython==2.3.*",
"drf_ujson2==1.7.*",
@@ -85,7 +85,6 @@ dependencies = [
"pypdf==3.9.*",
"python-bidi==0.4.*", # Support for Arabic in reportlab
"python-dateutil==2.8.*",
"python-u2flib-server==4.*",
"pytz",
"pytz-deprecation-shim==0.1.*",
"pyuca",
@@ -93,7 +92,7 @@ dependencies = [
"redis==4.6.*",
"reportlab==4.0.*",
"requests==2.31.*",
"sentry-sdk==1.15.*",
"sentry-sdk==1.40.*",
"sepaxml==2.6.*",
"slimit",
"static3==0.7.*",
@@ -110,7 +109,7 @@ dependencies = [
[project.optional-dependencies]
memcached = ["pylibmc"]
dev = [
"aiohttp==3.8.*",
"aiohttp==3.9.*",
"coverage",
"coveralls",
"fakeredis==2.18.*",
@@ -126,7 +125,7 @@ dev = [
"pytest-cov",
"pytest-django==4.*",
"pytest-mock==3.10.*",
"pytest-rerunfailures==11.*",
"pytest-rerunfailures==13.*",
"pytest-sugar",
"pytest-xdist==3.3.*",
"pytest==7.3.*",
+1 -1
View File
@@ -182,7 +182,7 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
pdfmetrics.registerFontFamily('OpenSans', normal='OpenSans', bold='OpenSansBd',
italic='OpenSansIt', boldItalic='OpenSansBI')
for family, styles in get_fonts().items():
for family, styles in get_fonts(event=self.event, pdf_support_required=True).items():
if family == self.event.settings.invoice_renderer_font:
pdfmetrics.registerFont(TTFont(family, finders.find(styles['regular']['truetype'])))
self.font_regular = family
+19 -2
View File
@@ -20,7 +20,7 @@
# <https://www.gnu.org/licenses/>.
#
from collections import OrderedDict
from urllib.parse import urlsplit
from urllib.parse import urlparse, urlsplit
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
from django.conf import settings
@@ -40,6 +40,7 @@ from pretix.base.settings import global_settings_object
from pretix.multidomain.urlreverse import (
get_event_domain, get_organizer_domain,
)
from pretix.presale.style import get_fonts
_supported = None
@@ -240,6 +241,14 @@ class SecurityMiddleware(MiddlewareMixin):
)
def process_response(self, request, resp):
def nested_dict_values(d):
for v in d.values():
if isinstance(v, dict):
yield from nested_dict_values(v)
else:
if isinstance(v, str):
yield v
url = resolve(request.path_info)
if settings.DEBUG and resp.status_code >= 400:
@@ -259,6 +268,14 @@ class SecurityMiddleware(MiddlewareMixin):
if gs.settings.leaflet_tiles:
img_src.append(gs.settings.leaflet_tiles[:gs.settings.leaflet_tiles.index("/", 10)].replace("{s}", "*"))
font_src = set()
if hasattr(request, 'event'):
for font in get_fonts(request.event, pdf_support_required=False).values():
for path in list(nested_dict_values(font)):
font_location = urlparse(path)
if font_location.scheme and font_location.netloc:
font_src.add('{}://{}'.format(font_location.scheme, font_location.netloc))
h = {
'default-src': ["{static}"],
'script-src': ['{static}'],
@@ -267,7 +284,7 @@ class SecurityMiddleware(MiddlewareMixin):
'style-src': ["{static}", "{media}"],
'connect-src': ["{dynamic}", "{media}"],
'img-src': ["{static}", "{media}", "data:"] + img_src,
'font-src': ["{static}"],
'font-src': ["{static}"] + list(font_src),
'media-src': ["{static}", "data:"],
# form-action is not only used to match on form actions, but also on URLs
# form-actions redirect to. In the context of e.g. payment providers or
+1 -3
View File
@@ -53,13 +53,11 @@ from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django_otp.models import Device
from django_scopes import scopes_disabled
from u2flib_server.utils import (
pub_key_from_der, websafe_decode, websafe_encode,
)
from pretix.base.i18n import language
from pretix.helpers.urls import build_absolute_uri
from ...helpers.u2f import pub_key_from_der, websafe_decode, websafe_encode
from .base import LoggingMixin
+10 -3
View File
@@ -78,7 +78,7 @@ from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Paragraph
from pretix.base.i18n import language
from pretix.base.models import Order, OrderPosition, Question
from pretix.base.models import Event, Order, OrderPosition, Question
from pretix.base.settings import PERSON_NAME_SCHEMES
from pretix.base.signals import layout_image_variables, layout_text_variables
from pretix.base.templatetags.money import money_filter
@@ -738,9 +738,10 @@ class Renderer:
else:
self.bg_bytes = None
self.bg_pdf = None
self.event_fonts = list(get_fonts(event, pdf_support_required=True).keys()) + ['Open Sans']
@classmethod
def _register_fonts(cls):
def _register_fonts(cls, event: Event = None):
if hasattr(cls, '_fonts_registered'):
return
pdfmetrics.registerFont(TTFont('Open Sans', finders.find('fonts/OpenSans-Regular.ttf')))
@@ -748,7 +749,7 @@ class Renderer:
pdfmetrics.registerFont(TTFont('Open Sans B', finders.find('fonts/OpenSans-Bold.ttf')))
pdfmetrics.registerFont(TTFont('Open Sans B I', finders.find('fonts/OpenSans-BoldItalic.ttf')))
for family, styles in get_fonts().items():
for family, styles in get_fonts(event, pdf_support_required=True).items():
pdfmetrics.registerFont(TTFont(family, finders.find(styles['regular']['truetype'])))
if 'italic' in styles:
pdfmetrics.registerFont(TTFont(family + ' I', finders.find(styles['italic']['truetype'])))
@@ -939,6 +940,12 @@ class Renderer:
if o['italic']:
font += ' I'
# Since pdfmetrics.registerFont is global, we want to make sure that no one tries to sneak in a font, they
# should not have access to.
if font not in self.event_fonts:
logger.warning(f'Unauthorized use of font "{font}"')
font = 'Open Sans'
try:
ad = getAscentDescent(font, float(o['fontsize']))
except KeyError: # font not known, fall back
+1 -1
View File
@@ -89,7 +89,7 @@ def primary_font_kwargs():
choices = [('Open Sans', 'Open Sans')]
choices += sorted([
(a, {"title": a, "data": v}) for a, v in get_fonts().items() if not v.get('pdf_only', False)
(a, {"title": a, "data": v}) for a, v in get_fonts(pdf_support_required=False).items()
], key=lambda a: a[0])
return {
'choices': choices,
+7
View File
@@ -79,6 +79,7 @@ from pretix.helpers.countries import CachedCountries
from pretix.multidomain.models import KnownDomain
from pretix.multidomain.urlreverse import build_absolute_uri
from pretix.plugins.banktransfer.payment import BankTransfer
from pretix.presale.style import get_fonts
class EventWizardFoundationForm(forms.Form):
@@ -651,6 +652,9 @@ class EventSettingsForm(EventSettingsValidationMixin, FormPlaceholderMixin, Sett
del self.fields['event_list_available_only']
del self.fields['event_list_filters']
del self.fields['event_calendar_future_only']
self.fields['primary_font'].choices += [
(a, {"title": a, "data": v}) for a, v in get_fonts(self.event, pdf_support_required=False).items()
]
# create "virtual" fields for better UX when editing <name>_asked and <name>_required fields
self.virtual_keys = []
@@ -931,6 +935,9 @@ class InvoiceSettingsForm(EventSettingsValidationMixin, SettingsForm):
)
)
self.fields['invoice_generate'].choices = generate_choices
self.fields['invoice_renderer_font'].choices += [
(a, a) for a in get_fonts(event, pdf_support_required=True).keys()
]
def contains_web_channel_validate(val):
@@ -7,7 +7,7 @@
{% block title %}{% trans "General settings" %}{% endblock %}
{% block custom_header %}
{{ block.super }}
<link type="text/css" rel="stylesheet" href="{% url "control:pdf.css" %}">
<link type="text/css" rel="stylesheet" href="{% url "control:pdf.css" organizer=request.organizer.slug event=request.event.slug %}">
{% endblock %}
{% block inside %}
<h1>{% trans "General settings" %}</h1>
@@ -8,7 +8,7 @@
{% compress css %}
<link type="text/css" rel="stylesheet" href="{% static "pretixcontrol/scss/pdfeditor.css" %}">
{% endcompress %}
<link type="text/css" rel="stylesheet" href="{% url "control:pdf.css" %}">
<link type="text/css" rel="stylesheet" href="{% url "control:pdf.css" organizer=request.organizer.slug event=request.event.slug %}">
{% endblock %}
{% block content %}
<h1>
@@ -1,4 +1,5 @@
{% load static %}
@font-face {
font-family: 'AND';
font-style: normal;
@@ -14,7 +15,7 @@
{% for family, styles in fonts.items %}
{% for style, formats in styles.items %}
{% if "sample" not in style %}
{% if "sample" not in style and "pdf_only" not in style %}
@font-face {
font-family: '{{ family }}';
{% if style == "italic" or style == "bolditalic" %}
@@ -27,9 +28,9 @@
{% else %}
font-weight: normal;
{% endif %}
src: {% if "woff2" in formats %}url('{% static formats.woff2 %}') format('woff2'),{% endif %}
{% if "woff" in formats %}url('{% static formats.woff %}') format('woff'),{% endif %}
{% if "truetype" in formats %}url('{% static formats.truetype %}') format('truetype'){% endif %};
src: {% if "woff2" in formats %}{% if '//' in formats.woff2 %}url('{{ formats.woff2 }}'){% else %}url('{% static formats.woff2 %}'){% endif %} format('woff2'),{% endif %}
{% if "woff" in formats %}{% if '//' in formats.woff %}url('{{ formats.woff }}'){% else %}url('{% static formats.woff %}'){% endif %} format('woff'),{% endif %}
{% if "truetype" in formats %}{% if '//' in formats.truetype %}url('{{ formats.truetype }}'){% else %}url('{% static formats.truetype %}'){% endif %} format('truetype'){% endif %};
}
.preload-font[data-family="{{family}}"][data-style="{{style}}"] {
font-family: '{{ family }}', 'AND';
+2 -2
View File
@@ -262,7 +262,7 @@ class BaseEditorView(EventPermissionRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['fonts'] = get_fonts()
ctx['fonts'] = get_fonts(self.request.event, pdf_support_required=True)
ctx['pdf'] = self.get_current_background()
ctx['variables'] = self.get_variables()
ctx['images'] = self.get_images()
@@ -278,7 +278,7 @@ class FontsCSSView(TemplateView):
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['fonts'] = get_fonts()
ctx['fonts'] = get_fonts(self.request.event if hasattr(self.request, 'event') else None, pdf_support_required=True)
return ctx
+76
View File
@@ -0,0 +1,76 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
# Backwards compatibility for old U2F key material, with code taken from
#
# https://github.com/Yubico/python-u2flib-server/blob/python-u2flib-server-4.0.1/u2flib_server/utils.py
#
# Copyright (c) 2013 Yubico AB
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from base64 import urlsafe_b64decode, urlsafe_b64encode
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_der_public_key
PUB_KEY_DER_PREFIX = b'\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01' \
b'\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00'
def pub_key_from_der(der):
return load_der_public_key(PUB_KEY_DER_PREFIX + der, default_backend())
def websafe_decode(data):
if isinstance(data, str):
data = data.encode('ascii')
data += b'=' * (-len(data) % 4)
return urlsafe_b64decode(data)
def websafe_encode(data):
if isinstance(data, str):
data = data.encode('ascii')
return urlsafe_b64encode(data).replace(b'=', b'').decode('ascii')
+8 -19
View File
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-09 14:51+0000\n"
"PO-Revision-Date: 2023-11-28 15:36+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"PO-Revision-Date: 2024-02-10 00:00+0000\n"
"Last-Translator: Phin Wolkwitz <wolkwitz@rami.io>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
"de/>\n"
"Language: de\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.2.1\n"
"X-Generator: Weblate 5.3.1\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -826,24 +826,19 @@ msgid "Only available with a voucher"
msgstr "Nur mit Gutschein verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:35
#, fuzzy
#| msgid "Payment method unavailable"
msgctxt "widget"
msgid "Not yet available"
msgstr "Zahlungsmethode nicht verfügbar"
msgstr "Noch nicht verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"
msgid "Not available anymore"
msgstr ""
msgstr "Nicht mehr verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:37
#, fuzzy
#| msgctxt "widget"
#| msgid "currently available: %s"
msgctxt "widget"
msgid "Currently not available"
msgstr "aktuell verfügbar: %s"
msgstr "Aktuell nicht verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:38
#, javascript-format
@@ -935,20 +930,14 @@ msgid "Continue"
msgstr "Fortfahren"
#: pretix/static/pretixpresale/js/widget/widget.js:56
#, fuzzy
#| msgctxt "widget"
#| msgid "Select variant %s"
msgctxt "widget"
msgid "Show variants"
msgstr "Variante %s auswählen"
msgstr "Varianten zeigen"
#: pretix/static/pretixpresale/js/widget/widget.js:57
#, fuzzy
#| msgctxt "widget"
#| msgid "Select variant %s"
msgctxt "widget"
msgid "Hide variants"
msgstr "Variante %s auswählen"
msgstr "Varianten verstecken"
#: pretix/static/pretixpresale/js/widget/widget.js:58
msgctxt "widget"
@@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-09 14:51+0000\n"
"PO-Revision-Date: 2023-11-28 15:36+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"PO-Revision-Date: 2024-02-10 00:00+0000\n"
"Last-Translator: Phin Wolkwitz <wolkwitz@rami.io>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
"pretix/pretix-js/de_Informal/>\n"
"Language: de_Informal\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.2.1\n"
"X-Generator: Weblate 5.3.1\n"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
@@ -825,24 +825,19 @@ msgid "Only available with a voucher"
msgstr "Nur mit Gutschein verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:35
#, fuzzy
#| msgid "Payment method unavailable"
msgctxt "widget"
msgid "Not yet available"
msgstr "Zahlungsmethode nicht verfügbar"
msgstr "Noch nicht verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"
msgid "Not available anymore"
msgstr ""
msgstr "Nicht mehr verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:37
#, fuzzy
#| msgctxt "widget"
#| msgid "currently available: %s"
msgctxt "widget"
msgid "Currently not available"
msgstr "aktuell verfügbar: %s"
msgstr "Aktuell nicht verfügbar"
#: pretix/static/pretixpresale/js/widget/widget.js:38
#, javascript-format
@@ -934,20 +929,14 @@ msgid "Continue"
msgstr "Fortfahren"
#: pretix/static/pretixpresale/js/widget/widget.js:56
#, fuzzy
#| msgctxt "widget"
#| msgid "Select variant %s"
msgctxt "widget"
msgid "Show variants"
msgstr "Variante %s auswählen"
msgstr "Varianten zeigen"
#: pretix/static/pretixpresale/js/widget/widget.js:57
#, fuzzy
#| msgctxt "widget"
#| msgid "Select variant %s"
msgctxt "widget"
msgid "Hide variants"
msgstr "Variante %s auswählen"
msgstr "Varianten verstecken"
#: pretix/static/pretixpresale/js/widget/widget.js:58
msgctxt "widget"
@@ -41,7 +41,7 @@ from pretix.plugins.ticketoutputpdf.models import (
TicketLayout, TicketLayoutItem,
)
from pretix.presale.style import ( # NOQA: legacy import
get_fonts, register_fonts,
get_fonts, register_event_fonts, register_fonts,
)
@@ -92,7 +92,7 @@ class PdfTicketOutput(BaseTicketOutput):
return self.event._ticketoutputpdf_cache_default_layout
def _register_fonts(self):
Renderer._register_fonts()
Renderer._register_fonts(self.event)
def _draw_page(self, layout: TicketLayout, op: OrderPosition, order: Order):
buffer = BytesIO()
+1 -1
View File
@@ -264,7 +264,7 @@ class LayoutEditorView(BaseEditorView):
return static('pretixpresale/pdf/ticket_default_a4.pdf')
def generate(self, op: OrderPosition, override_layout=None, override_background=None):
Renderer._register_fonts()
Renderer._register_fonts(self.request.event)
buffer = BytesIO()
if override_background:
+66 -12
View File
@@ -41,6 +41,7 @@ from pretix.base.models import Event, Event_SettingsStore, Organizer
from pretix.base.services.tasks import (
TransactionAwareProfiledEventTask, TransactionAwareTask,
)
from pretix.base.signals import EventPluginSignal
from pretix.celery_app import app
from pretix.multidomain.urlreverse import (
get_event_domain, get_organizer_domain,
@@ -86,7 +87,7 @@ def compile_scss(object, file="main.scss", fonts=True):
font = object.settings.get('primary_font')
if font != 'Open Sans' and fonts:
sassrules.append(get_font_stylesheet(font))
sassrules.append(get_font_stylesheet(font, event=object if isinstance(object, Event) else None))
sassrules.append(
'$font-family-sans-serif: "{}", "Open Sans", "OpenSans", "Helvetica Neue", Helvetica, Arial, sans-serif '
'!default'.format(
@@ -202,7 +203,8 @@ def regenerate_organizer_css(organizer_id: int, regenerate_events=True):
register_fonts = Signal()
"""
Return a dictionaries of the following structure. Paths should be relative to static root.
Return a dictionaries of the following structure. Paths should be relative to static root or an absolute URL. In the
latter case, the fonts won't be available for PDF-rendering.
{
"font name": {
@@ -225,17 +227,69 @@ Return a dictionaries of the following structure. Paths should be relative to st
}
"""
register_event_fonts = EventPluginSignal()
"""
Return a dictionaries of the following structure. Paths should be relative to static root or an absolute URL. In the
latter case, the fonts won't be available for PDF-rendering.
As with all plugin signals, the ``sender`` keyword argument will contain the event.
{
"font name": {
"regular": {
"truetype": "….ttf",
"woff": "",
"woff2": ""
},
"bold": {
...
},
"italic": {
...
},
"bolditalic": {
...
},
"pdf_only": False, # if True, font is not usable on the web,
}
}
"""
def get_fonts(event: Event = None, pdf_support_required=False):
def nested_dict_values(d):
for v in d.values():
if isinstance(v, dict):
yield from nested_dict_values(v)
else:
if isinstance(v, str):
yield v
def get_fonts():
f = {}
received_fonts = {}
for recv, value in register_fonts.send(0):
f.update(value)
received_fonts.update(value)
if event:
for recv, value in register_event_fonts.send(event):
received_fonts.update(value)
for font, payload in received_fonts.items():
if pdf_support_required:
if any('//' in v for v in list(nested_dict_values(payload))):
continue
f.update({font: payload})
else:
if payload.get('pdf_only', False):
continue
f.update({font: payload})
return f
def get_font_stylesheet(font_name):
def get_font_stylesheet(font_name, event: Event = None):
stylesheet = []
font = get_fonts()[font_name]
font = get_fonts(event)[font_name]
for sty, formats in font.items():
if sty == 'sample':
continue
@@ -251,12 +305,12 @@ def get_font_stylesheet(font_name):
stylesheet.append("font-weight: normal;")
srcs = []
if "woff2" in formats:
srcs.append("url(static('{}')) format('woff2')".format(formats['woff2']))
if "woff" in formats:
srcs.append("url(static('{}')) format('woff')".format(formats['woff']))
if "truetype" in formats:
srcs.append("url(static('{}')) format('truetype')".format(formats['truetype']))
for f in ["woff2", "woff", "truetype"]:
if f in formats:
if formats[f].startswith('https'):
srcs.append(f"url('{formats[f]}') format('{f}')")
else:
srcs.append(f"url(static('{formats[f]}')) format('{f}')")
stylesheet.append("src: {};".format(", ".join(srcs)))
stylesheet.append("font-display: swap;")
stylesheet.append("}")
@@ -503,7 +503,7 @@ Vue.component('item', {
// Availability
+ '<div class="pretix-widget-item-availability-col">'
+ '<a v-if="show_toggle" :href="\'#\' + item.id + \'-variants\'" @click.prevent.stop="expand" role="button" tabindex="0"'
+ '<a class="pretix-widget-collapse-indicator" v-if="show_toggle" :href="\'#\' + item.id + \'-variants\'" @click.prevent.stop="expand" role="button" tabindex="0"'
+ ' v-bind:aria-expanded="expanded ? \'true\': \'false\'" v-bind:aria-controls="item.id + \'-variants\'">{{ variationsToggleLabel }}</a>'
+ '<availbox v-if="!item.has_variations" :item="item"></availbox>'
+ '</div>'
@@ -430,7 +430,7 @@
.pretix-widget-item-availability-col {
text-align: center;
a::before {
.pretix-widget-collapse-indicator::before {
content: "";
display: inline-block;
width: $font-size-base;
@@ -438,7 +438,8 @@
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 14 14' xmlns='http://www.w3.org/2000/svg' xml:space='preserve'%3E%3Cpath fill='#{url-friendly-colour($link-color)}' d='M6.395 4.151a.268.268 0 0 0-.177.077l-.386.386a.259.259 0 0 0-.077.177c.002.067.029.13.077.179l3.033 3.031-3.033 3.032a.255.255 0 0 0-.077.177.253.253 0 0 0 .077.178l.386.385a.268.268 0 0 0 .177.077.27.27 0 0 0 .178-.077l3.595-3.595a.259.259 0 0 0 .077-.177.255.255 0 0 0-.077-.176L6.573 4.228a.257.257 0 0 0-.178-.077Z'/%3E%3C/svg%3E");
transition: transform .5s;
}
a[aria-expanded=true]::before {
.pretix-widget-collapse-indicator[aria-expanded=true]::before {
transform: rotate(90deg);
}
}