forked from CGM_Public/pretix_original
Replace quota widgets
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
{% load i18n %}
|
||||
{% for q in quotas %}
|
||||
{% include "pretixcontrol/fragment_quota_box.html" with quota=q full=1 %}
|
||||
{% endfor %}
|
||||
@@ -75,8 +75,30 @@
|
||||
|
||||
{% if not request.event.has_subevents %}
|
||||
{% include "pretixcontrol/event/fragment_timeline.html" %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-12 dashboard-quota-row">
|
||||
<div hx-get="{% url "control:event.index.quotas" organizer=request.organizer.slug event=request.event.slug %}"
|
||||
hx-trigger="load">
|
||||
{% for i in "12" %}
|
||||
<a class="quotabox quotabox-full">
|
||||
<strong>
|
||||
<span class="loading-mock loading-mock-text-short"></span>
|
||||
</strong>
|
||||
<div class="progress loading-mock"></div>
|
||||
<div class="numbers">
|
||||
<span class="loading-mock loading-mock-text-short"></span>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12">
|
||||
Checkin-lists
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% if widgets_override %}
|
||||
{% if widgets_override and 0 %}
|
||||
{{ widgets_override|safe }}
|
||||
{% endif %}
|
||||
{% if widgets %}
|
||||
@@ -112,7 +134,6 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<p> </p>
|
||||
{% if "event.orders:read" in request.eventpermset or "event.orders:write" in request.eventpermset or "event.settings.general:write" in request.eventpermset or "event.items:write" in request.eventpermset %}
|
||||
<div class="panel panel-default">
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
</td>
|
||||
<td>
|
||||
{% for q in e.first_quotas|slice:":3" %}
|
||||
{% include "pretixcontrol/fragment_quota_box_paid.html" with quota=q %}
|
||||
{% include "pretixcontrol/fragment_quota_box.html" with quota=q %}
|
||||
{% endfor %}
|
||||
{% if e.first_quotas|length > 3 %}
|
||||
<a href="{% url "control:event.items.quotas" organizer=e.organizer.slug event=e.slug %}"
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
{% load i18n %}
|
||||
<div class="quotabox availability" data-toggle="tooltip_html" data-placement="top"
|
||||
title="{% trans "Quota:" %} {{ q.name|force_escape|force_escape }}<br>{% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}">
|
||||
<a class="quotabox {% if full %}quotabox-full{% endif %}" data-toggle="tooltip_html" data-placement="top"
|
||||
title="{% trans "Quota:" %} {{ q.name|force_escape|force_escape }}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}"
|
||||
href="{% url "control:event.items.quotas.show" event=q.event.slug organizer=q.event.organizer.slug quota=q.pk %}">
|
||||
{% if full %}
|
||||
<strong>{{ q.name }}</strong>
|
||||
{% endif %}
|
||||
{% if q.size|default_if_none:"NONE" == "NONE" %}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success progress-bar-100">
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-{% if q.cached_avail.0 <= 10 or q.cached_avail.0 >= 100 %}danger{% else %}warning{% endif %} progress-bar-{{ q.inv_percent }}">
|
||||
<div class="progress-bar progress-bar-{% if q.cached_avail.0 < 10 %}danger{% elif q.cached_avail.0 < 100 %}warning{% else %}success{% endif %} progress-bar-{{ q.percent_paid }}">
|
||||
</div>
|
||||
<div class="progress-bar progress-bar-{% if q.cached_avail.0 < 10 %}danger{% elif q.cached_avail.0 < 100 %}warning{% else %}success{% endif %} progress-bar-unconfirmed progress-bar-{{ q.percent_other }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="numbers">
|
||||
{{ q.cached_avail.1|default_if_none:"∞" }} / {{ q.size|default_if_none:"∞" }}
|
||||
{{ q.cached_availability_paid_orders|default_if_none:"?" }} / {{ q.size|default_if_none:"∞" }}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{% load i18n %}
|
||||
<a class="quotabox" data-toggle="tooltip_html" data-placement="top"
|
||||
title="{% trans "Quota:" %} {{ q.name|force_escape|force_escape }}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}"
|
||||
href="{% url "control:event.items.quotas.show" event=q.event.slug organizer=q.event.organizer.slug quota=q.pk %}">
|
||||
{% if q.size|default_if_none:"NONE" == "NONE" %}
|
||||
<div class="progress">
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-{% if q.cached_avail.0 < 10 %}danger{% elif q.cached_avail.0 < 100 %}warning{% else %}success{% endif %} progress-bar-{{ q.percent_paid }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="numbers">
|
||||
{{ q.cached_availability_paid_orders|default_if_none:"?" }} / {{ q.size|default_if_none:"∞" }}
|
||||
</div>
|
||||
</a>
|
||||
@@ -155,7 +155,7 @@
|
||||
</td>
|
||||
<td>
|
||||
{% for q in s.first_quotas|slice:":3" %}
|
||||
{% include "pretixcontrol/fragment_quota_box_paid.html" with quota=q %}
|
||||
{% include "pretixcontrol/fragment_quota_box.html" with quota=q %}
|
||||
{% endfor %}
|
||||
{% if s.first_quotas|length > 3 %}
|
||||
<a href="{% url "control:event.items.quotas" organizer=request.event.organizer.slug event=request.event.slug %}?subevent={{ s.id }}"
|
||||
|
||||
@@ -275,6 +275,7 @@ urlpatterns = [
|
||||
re_path(r'^widgets.json$', dashboards.event_index_widgets_lazy, name='event.index.widgets'),
|
||||
re_path(r'^dashboard/partials/logs$', dashboards.event_index_log_lazy, name='event.index.logs'),
|
||||
re_path(r'^dashboard/partials/warnings$', dashboards.event_index_warnings_lazy, name='event.index.warnings'),
|
||||
re_path(r'^dashboard/partials/quotas$', dashboards.event_index_quotas_lazy, name='event.index.quotas'),
|
||||
re_path(r'^dashboard/partials/comment$', event.EventComment.as_view(), name='event.index.comment'),
|
||||
re_path(r'^live/$', event.EventLive.as_view(), name='event.live'),
|
||||
re_path(r'^transfer_session/$', event.EventTransferSession.as_view(), name='event.transfer_session'),
|
||||
|
||||
@@ -44,7 +44,7 @@ from django.db.models import (
|
||||
)
|
||||
from django.db.models.functions import Coalesce, Greatest
|
||||
from django.dispatch import receiver
|
||||
from django.http import JsonResponse
|
||||
from django.http import Http404, JsonResponse
|
||||
from django.shortcuts import render
|
||||
from django.template.loader import get_template
|
||||
from django.urls import reverse
|
||||
@@ -58,7 +58,6 @@ from pretix.base.models import (
|
||||
Item, ItemCategory, ItemVariation, Order, OrderPosition, OrderRefund,
|
||||
Question, Quota, SubEvent, Voucher, WaitingListEntry,
|
||||
)
|
||||
from pretix.base.services.quotas import QuotaAvailability
|
||||
from pretix.base.timeline import timeline_for_event
|
||||
from pretix.control.signals import (
|
||||
event_dashboard_widgets, event_dashboard_widgets_override,
|
||||
@@ -70,6 +69,7 @@ from ...base.models.orders import CancellationRequest
|
||||
from ...base.models.organizer import TeamQuerySet
|
||||
from ...base.templatetags.money import money_filter
|
||||
from ..logdisplay import OVERVIEW_BANLIST
|
||||
from .utils import prepare_quotas_for_boxes
|
||||
|
||||
NUM_WIDGET = '<div class="numwidget"><span class="num">{num}</span><span class="text">{text}</span></div>'
|
||||
|
||||
@@ -239,37 +239,6 @@ def waitinglist_widgets(sender, subevent=None, lazy=False, **kwargs):
|
||||
return widgets
|
||||
|
||||
|
||||
@receiver(signal=event_dashboard_widgets)
|
||||
def quota_widgets(sender, subevent=None, lazy=False, **kwargs):
|
||||
widgets = []
|
||||
quotas = sender.quotas.filter(subevent=subevent)
|
||||
|
||||
qa = QuotaAvailability()
|
||||
if quotas:
|
||||
qa.queue(*quotas)
|
||||
qa.compute(allow_cache=True)
|
||||
|
||||
for q in quotas:
|
||||
if not lazy:
|
||||
status, left = qa.results[q] if q in qa.results else q.availability(allow_cache=True)
|
||||
widgets.append({
|
||||
'content': None if lazy else format_html(
|
||||
NUM_WIDGET,
|
||||
num='{}/{}'.format(intcomma(left), intcomma(q.size)) if q.size is not None else '\u221e',
|
||||
text=format_html(_('{quota} left'), quota=q.name)
|
||||
),
|
||||
'lazy': 'quota-{}'.format(q.pk),
|
||||
'display_size': 'small',
|
||||
'priority': 50,
|
||||
'url': reverse('control:event.items.quotas.show', kwargs={
|
||||
'event': sender.slug,
|
||||
'organizer': sender.organizer.slug,
|
||||
'quota': q.id
|
||||
})
|
||||
})
|
||||
return widgets
|
||||
|
||||
|
||||
@receiver(signal=event_dashboard_widgets)
|
||||
def checkin_widget(sender, subevent=None, lazy=False, **kwargs):
|
||||
widgets = []
|
||||
@@ -421,6 +390,21 @@ def event_index_warnings_lazy(request, organizer, event):
|
||||
)
|
||||
|
||||
|
||||
def event_index_quotas_lazy(request, organizer, event):
|
||||
if request.event.has_subevents:
|
||||
raise Http404()
|
||||
|
||||
quotas = request.event.quotas.filter(subevent=None)[:10]
|
||||
prepare_quotas_for_boxes(quotas)
|
||||
return render(
|
||||
request,
|
||||
'pretixcontrol/event/dashboard_partial_quotas.html',
|
||||
{
|
||||
'quotas': quotas,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def event_index_log_lazy(request, organizer, event):
|
||||
qs = request.event.logentry_set.all().select_related('user', 'content_type', 'api_token', 'oauth_application',
|
||||
'device').order_by('-datetime')
|
||||
|
||||
@@ -52,13 +52,13 @@ from pretix.base.forms import SafeSessionWizardView
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import Event, EventMetaValue, Organizer, Quota, Team
|
||||
from pretix.base.models.organizer import TeamQuerySet
|
||||
from pretix.base.services.quotas import QuotaAvailability
|
||||
from pretix.control.forms.event import (
|
||||
EventWizardBasicsForm, EventWizardCopyForm, EventWizardFoundationForm,
|
||||
)
|
||||
from pretix.control.forms.filter import EventFilterForm
|
||||
from pretix.control.permissions import OrganizerPermissionRequiredMixin
|
||||
from pretix.control.views import PaginationMixin
|
||||
from pretix.control.views.utils import prepare_quotas_for_boxes
|
||||
|
||||
|
||||
class EventList(PaginationMixin, ListView):
|
||||
@@ -117,19 +117,7 @@ class EventList(PaginationMixin, ListView):
|
||||
s.first_quotas = s.first_quotas[:4]
|
||||
quotas += list(s.first_quotas)
|
||||
|
||||
qa = QuotaAvailability(early_out=False)
|
||||
for q in quotas:
|
||||
qa.queue(q)
|
||||
qa.compute()
|
||||
|
||||
for q in quotas:
|
||||
q.cached_avail = qa.results[q]
|
||||
q.cached_availability_paid_orders = qa.count_paid_orders.get(q, 0)
|
||||
if q.size is not None:
|
||||
q.percent_paid = min(
|
||||
100,
|
||||
round(q.cached_availability_paid_orders / q.size * 100) if q.size > 0 else 100
|
||||
)
|
||||
prepare_quotas_for_boxes(quotas)
|
||||
return ctx
|
||||
|
||||
@cached_property
|
||||
|
||||
@@ -84,6 +84,7 @@ from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.signals import subevent_forms
|
||||
from pretix.control.views import PaginationMixin
|
||||
from pretix.control.views.event import MetaDataEditorMixin
|
||||
from pretix.control.views.utils import prepare_quotas_for_boxes
|
||||
from pretix.helpers import GroupConcat
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.i18n import get_format_without_seconds
|
||||
@@ -145,19 +146,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM
|
||||
s.first_quotas = s.first_quotas[:4]
|
||||
quotas += list(s.first_quotas)
|
||||
|
||||
qa = QuotaAvailability(early_out=False)
|
||||
for q in quotas:
|
||||
qa.queue(q)
|
||||
qa.compute()
|
||||
|
||||
for q in quotas:
|
||||
q.cached_avail = qa.results[q]
|
||||
q.cached_availability_paid_orders = qa.count_paid_orders.get(q, 0)
|
||||
if q.size is not None:
|
||||
q.percent_paid = min(
|
||||
100,
|
||||
round(q.cached_availability_paid_orders / q.size * 100) if q.size > 0 else 100
|
||||
)
|
||||
prepare_quotas_for_boxes(quotas)
|
||||
return ctx
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
from pretix.base.services.quotas import QuotaAvailability
|
||||
|
||||
|
||||
def prepare_quotas_for_boxes(quotas):
|
||||
qa = QuotaAvailability(early_out=False)
|
||||
for q in quotas:
|
||||
qa.queue(q)
|
||||
qa.compute()
|
||||
|
||||
for q in quotas:
|
||||
q.cached_avail = qa.results[q]
|
||||
q.cached_availability_paid_orders = qa.count_paid_orders.get(q, 0)
|
||||
if q.size is not None:
|
||||
other_blocked = q.size - q.cached_availability_paid_orders - q.cached_avail[1]
|
||||
q.percent_paid = min(
|
||||
100,
|
||||
round(q.cached_availability_paid_orders / q.size * 100) if q.size > 0 else 100
|
||||
)
|
||||
q.percent_other = min(
|
||||
100,
|
||||
round(other_blocked / q.size * 100) if q.size > 0 else 100
|
||||
)
|
||||
@@ -20,10 +20,7 @@
|
||||
}
|
||||
|
||||
.loading-mock {
|
||||
display: inline-block;
|
||||
background: #eee;
|
||||
border-radius: $border-radius-base;
|
||||
height: 1em;
|
||||
animation: loading-mock-pulse 3s infinite;
|
||||
background-size: 200% 100%;
|
||||
background-image: linear-gradient(
|
||||
@@ -43,6 +40,11 @@
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
span.loading-mock {
|
||||
display: inline-block;
|
||||
border-radius: $border-radius-base;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
|
||||
.dashboard {
|
||||
|
||||
@@ -530,18 +530,45 @@ table td ul:last-child {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 50px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
strong {
|
||||
display: block;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.progress {
|
||||
height: 7px;
|
||||
height: 10px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.numbers {
|
||||
font-size: 10px;
|
||||
color: $text-muted;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
&.availability .progress-bar-success {
|
||||
background: var(--pretix-brand-success-lighten-20);
|
||||
.progress-bar-unconfirmed {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&.quotabox-full {
|
||||
width: 100px;
|
||||
padding: 0 2px;
|
||||
|
||||
strong {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 16px;
|
||||
width: 80px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.numbers {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.quotabox-more {
|
||||
|
||||
Reference in New Issue
Block a user