diff --git a/src/pretix/control/templates/pretixcontrol/event/index.html b/src/pretix/control/templates/pretixcontrol/event/index.html index 1c9c46e0ba..88f5fd3748 100644 --- a/src/pretix/control/templates/pretixcontrol/event/index.html +++ b/src/pretix/control/templates/pretixcontrol/event/index.html @@ -16,6 +16,42 @@ {% endif %} +
+ {% trans "Shop URL:" %} + {% abseventurl request.event "presale:event.index" %} + +
+ + +
+
+
{% if has_overpaid_orders %}
{% blocktrans trimmed %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index e4e95546c0..845e7b656e 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -231,6 +231,7 @@ urlpatterns = [ re_path(r'^search/payments/$', search.PaymentSearch.as_view(), name='search.payments'), re_path(r'^event/(?P[^/]+)/(?P[^/]+)/', include([ re_path(r'^$', dashboards.event_index, name='event.index'), + re_path(r'^qrcode.(?P(png|jpeg|gif|svg))$', event.EventQRCode.as_view(), name='event.qrcode'), re_path(r'^widgets.json$', dashboards.event_index_widgets_lazy, name='event.index.widgets'), re_path(r'^logs/embed$', dashboards.event_index_log_lazy, name='event.index.logs'), re_path(r'^live/$', event.EventLive.as_view(), name='event.live'), diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 635ae8f0e5..7696e7c22c 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -38,10 +38,13 @@ import operator import re from collections import OrderedDict from decimal import Decimal +from io import BytesIO from itertools import groupby from urllib.parse import urlsplit import bleach +import qrcode +import qrcode.image.svg from django.apps import apps from django.conf import settings from django.contrib import messages @@ -86,7 +89,7 @@ from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views.mailsetup import MailSettingsSetupView from pretix.control.views.user import RecentAuthenticationRequiredMixin from pretix.helpers.database import rolledback_transaction -from pretix.multidomain.urlreverse import get_event_domain +from pretix.multidomain.urlreverse import build_absolute_uri, get_event_domain from pretix.plugins.stripe.payment import StripeSettingsHolder from pretix.presale.style import regenerate_css @@ -1504,3 +1507,35 @@ class QuickSetupView(FormView): }, ] if self.request.method != "POST" else [] ) + + +class EventQRCode(EventPermissionRequiredMixin, View): + permission = 'can_change_event_settings' + + def get(self, request, *args, filetype, **kwargs): + url = build_absolute_uri(request.event, 'presale:event.index') + + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_M, + box_size=10, + border=4, + ) + qr.add_data(url) + qr.make(fit=True) + + if filetype == 'svg': + factory = qrcode.image.svg.SvgPathImage + img = qrcode.make('Some data here', image_factory=factory) + r = HttpResponse(img.to_string(), content_type='image/svg+xml') + r['Content-Disposition'] = f'inline; filename="qrcode-{request.event.slug}.{filetype}"' + return r + elif filetype in ('jpeg', 'png', 'gif'): + img = qr.make_image(fill_color="black", back_color="white") + + byte_io = BytesIO() + img.save(byte_io, filetype.upper()) + byte_io.seek(0) + r = HttpResponse(byte_io.read(), content_type='image/' + filetype) + r['Content-Disposition'] = f'inline; filename="qrcode-{request.event.slug}.{filetype}"' + return r diff --git a/src/pretix/static/pretixcontrol/scss/main.scss b/src/pretix/static/pretixcontrol/scss/main.scss index 3a0218b643..d0c561d8b1 100644 --- a/src/pretix/static/pretixcontrol/scss/main.scss +++ b/src/pretix/static/pretixcontrol/scss/main.scss @@ -139,12 +139,18 @@ p.bigger { font-size: 16px; } +.helper-position-relative { + position: relative; +} .helper-display-block { display: block !important; } .helper-display-inline { display: inline !important; } +.helper-display-inline-block { + display: inline-block !important; +} .helper-display-none-soft { display: none; } diff --git a/src/setup.py b/src/setup.py index 49fbab57bd..267c0b0639 100644 --- a/src/setup.py +++ b/src/setup.py @@ -218,6 +218,7 @@ setup( 'python-u2flib-server==4.*', 'pytz', 'pyuca', + 'qrcode==7.4.*', 'redis==4.5.*,>=4.5.4', 'reportlab==3.6.*', 'requests==2.28.*', diff --git a/src/tests/control/test_views.py b/src/tests/control/test_views.py index 113a3d7986..bfa33f5832 100644 --- a/src/tests/control/test_views.py +++ b/src/tests/control/test_views.py @@ -142,6 +142,10 @@ def logged_in_client(client, event): ('/control/events/add', 200), ('/control/event/{orga}/{event}/', 200), + ('/control/event/{orga}/{event}/qrcode.png', 200), + ('/control/event/{orga}/{event}/qrcode.jpeg', 200), + ('/control/event/{orga}/{event}/qrcode.svg', 200), + ('/control/event/{orga}/{event}/qrcode.gif', 200), ('/control/event/{orga}/{event}/live/', 200), ('/control/event/{orga}/{event}/dangerzone/', 200), ('/control/event/{orga}/{event}/cancel/', 200),