CheckIns: Display a source_type icon (barcode/nfc) where known (#4628)

Co-authored-by: Raphael Michel <michel@rami.io>
This commit is contained in:
Martin Gross
2024-11-18 17:50:43 +01:00
committed by GitHub
parent f94227f00f
commit a601c75923
7 changed files with 205 additions and 6 deletions

View File

@@ -37,6 +37,16 @@ class BaseMediaType:
def verbose_name(self): def verbose_name(self):
raise NotImplementedError() raise NotImplementedError()
@property
def icon(self):
"""
This can be:
- The name of a Font Awesome icon to represent this channel type.
- The name of a SVG icon file that is resolvable through the static file system. We recommend to design for a size of 18x14 pixels.
"""
return "circle"
def generate_identifier(self, organizer): def generate_identifier(self, organizer):
if self.medium_created_by_server: if self.medium_created_by_server:
raise NotImplementedError() raise NotImplementedError()
@@ -59,6 +69,7 @@ class BaseMediaType:
class BarcodePlainMediaType(BaseMediaType): class BarcodePlainMediaType(BaseMediaType):
identifier = 'barcode' identifier = 'barcode'
verbose_name = _('Barcode / QR-Code') verbose_name = _('Barcode / QR-Code')
icon = 'qrcode'
medium_created_by_server = True medium_created_by_server = True
supports_giftcard = False supports_giftcard = False
supports_orderposition = True supports_orderposition = True
@@ -75,6 +86,7 @@ class BarcodePlainMediaType(BaseMediaType):
class NfcUidMediaType(BaseMediaType): class NfcUidMediaType(BaseMediaType):
identifier = 'nfc_uid' identifier = 'nfc_uid'
verbose_name = _('NFC UID-based') verbose_name = _('NFC UID-based')
icon = 'pretixbase/img/media/nfc_uid.svg'
medium_created_by_server = False medium_created_by_server = False
supports_giftcard = True supports_giftcard = True
supports_orderposition = False supports_orderposition = False
@@ -114,6 +126,7 @@ class NfcUidMediaType(BaseMediaType):
class NfcMf0aesMediaType(BaseMediaType): class NfcMf0aesMediaType(BaseMediaType):
identifier = 'nfc_mf0aes' identifier = 'nfc_mf0aes'
verbose_name = 'NFC Mifare Ultralight AES' verbose_name = 'NFC Mifare Ultralight AES'
icon = 'pretixbase/img/media/nfc_secure.svg'
medium_created_by_server = False medium_created_by_server = False
supports_giftcard = True supports_giftcard = True
supports_orderposition = False supports_orderposition = False

View File

@@ -127,6 +127,7 @@
<strong> <strong>
<a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=c.position.order.code %}">{{ c.position.order.code }}</a>-{{ c.position.positionid }} <a href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=c.position.order.code %}">{{ c.position.order.code }}</a>-{{ c.position.positionid }}
</strong> </strong>
{% include "pretixcontrol/checkin/fragment_checkin_source_type.html" with source_type=c.raw_source_type %}
{% if c.position.attendee_name %} {% if c.position.attendee_name %}
<br> <br>
<small> <small>
@@ -143,7 +144,7 @@
</small> </small>
{% endif %} {% endif %}
{% else %} {% else %}
<span class="fa fa-qrcode fa-fw"></span> {% include "pretixcontrol/checkin/fragment_checkin_source_type.html" with source_type=c.raw_source_type %}
<span title="{{ c.raw_barcode }}"> <span title="{{ c.raw_barcode }}">
{{ c.raw_barcode|slice:":16" }}{% if c.raw_barcode|length > 16 %}…{% endif %} {{ c.raw_barcode|slice:":16" }}{% if c.raw_barcode|length > 16 %}…{% endif %}
<button type="button" class="btn btn-xs btn-link btn-clipboard" data-clipboard-text="{{ c.raw_barcode }}"> <button type="button" class="btn btn-xs btn-link btn-clipboard" data-clipboard-text="{{ c.raw_barcode }}">

View File

@@ -0,0 +1,15 @@
{% load i18n %}
{% load static %}
{% load getitem %}
{% if source_type %}
{% with media_types|getitem:source_type as media_type %}
{% if "." in media_type.icon %}
<img src="{% static media_type.icon %}" class="fa-like-image"
data-toggle="tooltip" title="{{ media_type.verbose_name }}">
{% else %}
<span class="fa fa-fw fa-{{ media_type.icon }} text-muted"
data-toggle="tooltip" title="{{ media_type.verbose_name }}"></span>
{% endif %}
{% endwith %}
{% endif %}

View File

@@ -185,6 +185,7 @@
<span class="fa fa-magic text-muted" <span class="fa fa-magic text-muted"
data-toggle="tooltip" title="{% trans "Checked in automatically" %}"></span> data-toggle="tooltip" title="{% trans "Checked in automatically" %}"></span>
{% endif %} {% endif %}
{% include "pretixcontrol/checkin/fragment_checkin_source_type.html" with source_type=e.last_entry_source_type %}
{% endif %} {% endif %}
{% endif %} {% endif %}
</td> </td>

View File

@@ -49,6 +49,7 @@ from django.views.generic import FormView, ListView, TemplateView
from i18nfield.strings import LazyI18nString from i18nfield.strings import LazyI18nString
from pretix.api.views.checkin import _redeem_process from pretix.api.views.checkin import _redeem_process
from pretix.base.media import MEDIA_TYPES
from pretix.base.models import Checkin, Order, OrderPosition from pretix.base.models import Checkin, Order, OrderPosition
from pretix.base.models.checkin import CheckinList from pretix.base.models.checkin import CheckinList
from pretix.base.services.checkin import ( from pretix.base.services.checkin import (
@@ -81,9 +82,7 @@ class CheckInListQueryMixin:
position_id=OuterRef('pk'), position_id=OuterRef('pk'),
list_id=self.list.pk, list_id=self.list.pk,
type=Checkin.TYPE_ENTRY type=Checkin.TYPE_ENTRY
).order_by().values('position_id').annotate( ).order_by('-datetime').values('position_id')
m=Max('datetime')
).values('m')
cqs_exit = Checkin.objects.filter( cqs_exit = Checkin.objects.filter(
position_id=OuterRef('pk'), position_id=OuterRef('pk'),
list_id=self.list.pk, list_id=self.list.pk,
@@ -103,7 +102,7 @@ class CheckInListQueryMixin:
status_q, status_q,
order__event=self.request.event, order__event=self.request.event,
).annotate( ).annotate(
last_entry=Subquery(cqs), last_entry=Subquery(cqs[:1].values('datetime')),
last_exit=Subquery(cqs_exit), last_exit=Subquery(cqs_exit),
auto_checked_in=Exists( auto_checked_in=Exists(
Checkin.objects.filter( Checkin.objects.filter(
@@ -112,7 +111,8 @@ class CheckInListQueryMixin:
list_id=self.list.pk, list_id=self.list.pk,
auto_checked_in=True auto_checked_in=True
) )
) ),
last_entry_source_type=Subquery(cqs[:1].values('raw_source_type'))
).select_related( ).select_related(
'item', 'variation', 'order', 'addon_to' 'item', 'variation', 'order', 'addon_to'
).prefetch_related( ).prefetch_related(
@@ -157,6 +157,7 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInList
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs) ctx = super().get_context_data(**kwargs)
ctx['media_types'] = MEDIA_TYPES
ctx['checkinlist'] = self.list ctx['checkinlist'] = self.list
if self.request.event.has_subevents: if self.request.event.has_subevents:
ctx['seats'] = ( ctx['seats'] = (
@@ -497,6 +498,7 @@ class CheckinListView(EventPermissionRequiredMixin, PaginationMixin, ListView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super().get_context_data() ctx = super().get_context_data()
ctx['filter_form'] = self.filter_form ctx['filter_form'] = self.filter_form
ctx['media_types'] = MEDIA_TYPES
return ctx return ctx

View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="20px"
viewBox="0 -960 960 960"
width="20px"
fill="#767676"
version="1.1"
id="svg2496"
sodipodi:docname="nfc_secure.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><g
aria-label="#"
id="text352"
style="font-weight:bold;font-size:448px;line-height:576px;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;stroke-width:8.19202;stroke-linecap:square;stroke-linejoin:bevel;stop-color:#000000"
transform="translate(1.91606,3.01846)" /><defs
id="defs2500" /><sodipodi:namedview
id="namedview2498"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="47.2"
inkscape:cx="9.8516949"
inkscape:cy="9.809322"
inkscape:window-width="3374"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2496"
showguides="true"><sodipodi:guide
position="816,480"
orientation="0,-1"
id="guide3345"
inkscape:locked="false" /><sodipodi:guide
position="48,480"
orientation="-1,0"
id="guide3349"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="912,688.47458"
orientation="-1,0"
id="guide858"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="645.5,912"
orientation="0,1"
id="guide860"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /><sodipodi:guide
position="645.5,48"
orientation="0,1"
id="guide862"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" /></sodipodi:namedview><path
d="m 384.48572,-841.27671 v -70.71067 c 69.29646,-0.4714 136.01199,12.2683 200.14657,38.21912 64.13459,25.95082 121.88164,64.60599 173.24116,115.96551 51.35952,51.35952 90.00291,109.09479 115.93016,173.20581 25.92725,64.11101 38.65516,130.81475 38.18376,200.11121 h -72.12489 c 0,-59.39697 -11.07801,-116.90831 -33.23402,-172.53405 -22.15601,-55.62574 -55.39002,-105.59461 -99.70205,-149.90664 -44.31203,-44.31203 -94.28091,-77.78174 -149.90664,-100.40916 -55.62573,-22.62742 -113.13708,-33.94113 -172.53405,-33.94113 z m 264.45793,456.79098 c -1.41421,-34.41252 -8.24958,-67.64655 -20.50609,-99.70205 -12.25652,-32.05551 -31.46626,-61.16474 -57.62921,-87.32769 -26.16295,-26.16295 -55.15433,-45.25483 -86.97413,-57.27565 -31.81981,-12.02081 -64.93598,-18.73833 -99.3485,-20.15254 v -72.12489 c 44.31202,0.9428 86.62058,9.31023 126.92566,25.10229 40.30509,15.79205 77.07464,40.30508 110.30866,73.5391 33.23402,33.23402 57.8649,70.12143 73.89266,110.66221 16.02776,40.54079 24.51304,82.9672 25.45584,127.27922 z"
id="path2494"
sodipodi:nodetypes="ccsssccsssccsssccssscc" /><g
style="fill:#767676;fill-opacity:1"
id="g929"
transform="matrix(0.4768212,-0.4768212,0.4768212,0.4768212,305.48344,152.26491)"><path
d="m 280,-400 q -33,0 -56.5,-23.5 Q 200,-447 200,-480 q 0,-33 23.5,-56.5 23.5,-23.5 56.5,-23.5 33,0 56.5,23.5 23.5,23.5 23.5,56.5 0,33 -23.5,56.5 Q 313,-400 280,-400 Z m 0,160 q -100,0 -170,-70 -70,-70 -70,-170 0,-100 70,-170 70,-70 170,-70 67,0 121.5,33 54.5,33 86.5,87 h 352 l 120,120 -180,180 -80,-60 -80,60 -85,-60 h -47 q -32,54 -86.5,87 -54.5,33 -121.5,33 z m 0,-80 q 56,0 98.5,-34 42.5,-34 56.5,-86 h 125 l 58,41 82,-61 71,55 75,-75 -40,-40 H 435 q -14,-52 -56.5,-86 -42.5,-34 -98.5,-34 -66,0 -113,47 -47,47 -47,113 0,66 47,113 47,47 113,47 z"
id="path920"
style="fill:#767676;fill-opacity:1" /></g></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="20px"
viewBox="0 -960 960 960"
width="20px"
fill="#767676"
version="1.1"
id="svg2496"
sodipodi:docname="nfc_uid.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<g
aria-label="#"
id="text352"
style="font-weight:bold;font-size:448px;line-height:576px;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;stroke-width:8.19202;stroke-linecap:square;stroke-linejoin:bevel;stop-color:#000000"
transform="translate(1.91606,3.01846)" />
<defs
id="defs2500" />
<sodipodi:namedview
id="namedview2498"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="47.2"
inkscape:cx="9.8516949"
inkscape:cy="9.809322"
inkscape:window-width="3374"
inkscape:window-height="1371"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2496"
showguides="true">
<sodipodi:guide
position="816,480"
orientation="0,-1"
id="guide3345"
inkscape:locked="false" />
<sodipodi:guide
position="48,480"
orientation="-1,0"
id="guide3349"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="912,688.47458"
orientation="-1,0"
id="guide858"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="645.5,912"
orientation="0,1"
id="guide860"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="645.5,48"
orientation="0,1"
id="guide862"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<path
d="m 384.48572,-841.27671 v -70.71067 c 69.29646,-0.4714 136.01199,12.2683 200.14657,38.21912 64.13459,25.95082 121.88164,64.60599 173.24116,115.96551 51.35952,51.35952 90.00291,109.09479 115.93016,173.20581 25.92725,64.11101 38.65516,130.81475 38.18376,200.11121 h -72.12489 c 0,-59.39697 -11.07801,-116.90831 -33.23402,-172.53405 -22.15601,-55.62574 -55.39002,-105.59461 -99.70205,-149.90664 -44.31203,-44.31203 -94.28091,-77.78174 -149.90664,-100.40916 -55.62573,-22.62742 -113.13708,-33.94113 -172.53405,-33.94113 z m 264.45793,456.79098 c -1.41421,-34.41252 -8.24958,-67.64655 -20.50609,-99.70205 -12.25652,-32.05551 -31.46626,-61.16474 -57.62921,-87.32769 -26.16295,-26.16295 -55.15433,-45.25483 -86.97413,-57.27565 -31.81981,-12.02081 -64.93598,-18.73833 -99.3485,-20.15254 v -72.12489 c 44.31202,0.9428 86.62058,9.31023 126.92566,25.10229 40.30509,15.79205 77.07464,40.30508 110.30866,73.5391 33.23402,33.23402 57.8649,70.12143 73.89266,110.66221 16.02776,40.54079 24.51304,82.9672 25.45584,127.27922 z"
id="path2494"
sodipodi:nodetypes="ccsssccsssccsssccssscc" />
<text
xml:space="preserve"
style="font-weight:bold;font-size:768px;line-height:987.432px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;text-anchor:middle;fill:#767676;stroke-width:8.19202;stroke-linecap:square;stroke-linejoin:bevel;stop-color:#000000"
x="279.16797"
y="-48"
id="text866"><tspan
sodipodi:role="line"
id="tspan864"
style="font-size:768px;stroke-width:8.192"
x="279.16797"
y="-48">#</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB