diff --git a/src/pretix/control/templates/pretixcontrol/event/new_index.html b/src/pretix/control/templates/pretixcontrol/event/new_index.html index 9a2bfe6a4..8c77c1488 100644 --- a/src/pretix/control/templates/pretixcontrol/event/new_index.html +++ b/src/pretix/control/templates/pretixcontrol/event/new_index.html @@ -30,9 +30,14 @@ {% include "pretixcontrol/event/fragment_qr_dropdown.html" with url=0 %} - +
+ + {{ shop_state.content|safe }} - {{ shop_state.content|safe }} +
@@ -88,6 +93,26 @@ {% endif %} + +
+ {% trans "Internal comment" %} +
+ {% csrf_token %} +
+ {% bootstrap_field comment_form.comment layout="horizontal" show_help=True show_label=False horizontal_field_class="col-md-12" %} +
+ {% if not comment_form.readonly %} +

+
+ +

+ {% endif %} +
+
+ {% eventsignal request.event "pretix.control.signals.event_dashboard_top" request=request %} @@ -102,7 +127,7 @@
-
+ + -
+ + + + + {% trans "Name" %} + + + {% trans "Begin" %} + + + + + {% trans "Paid tickets per quota" %} + + + + + {% for s in subevents %} + + + {{ s.name }}
+ + #{{ s.pk }} + + + + {{ s.get_date_from_display }}
+ + {{ s.date_from|date:"l" }} + + + + {% for q in s.first_quotas|slice:":3" %} + {% include "pretixcontrol/fragment_quota_box_paid.html" with quota=q %} + {% endfor %} + {% if s.first_quotas|length > 3 %} + + ··· + + {% endif %} + + {% endfor %} + -
- -
-
-
-

- {% trans "Internal comment" %} -

-
-
-
- {% csrf_token %} -
- {% bootstrap_field comment_form.comment layout="horizontal" show_help=True show_label=False horizontal_field_class="col-md-12" %} -
- {% if not comment_form.readonly %} -

-
- -

- {% endif %} -
-
-
-
- -
-
-
-

- {% trans "Event logs" %} -

-
-
    -
    - -
    -
- {% endblock %} diff --git a/src/pretix/control/views/new_dashboard.py b/src/pretix/control/views/new_dashboard.py index 018155a53..2526f33e5 100644 --- a/src/pretix/control/views/new_dashboard.py +++ b/src/pretix/control/views/new_dashboard.py @@ -1,5 +1,5 @@ import json -from datetime import datetime, timedelta +import datetime from decimal import Decimal import dateutil @@ -20,7 +20,10 @@ from pretix.base.timeline import timeline_for_event from pretix.control.forms.event import CommentForm from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views import ChartContainingView -from pretix.control.views.dashboards import NUM_WIDGET + +NUM_WIDGET = str('
{num}' + '{text}' + '{text_add}
') class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView): @@ -54,15 +57,11 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) else: opqs = OrderPosition.objects - tickc = opqs.filter( - order__event=self.request.event, item__admission=True, - order__status__in=(Order.STATUS_PAID, Order.STATUS_PENDING), - ).count() - ctx['shop_state'] = { 'display_size': 'small', 'priority': 1000, - 'content': '
{state}
'.format( + 'content': '{t1} {state} '.format( + t1=_('Your ticket shop is'), state=_('live') if self.request.event.live and not self.request.event.testmode else ( _('live and in test mode') if self.request.event.live else ( _('not yet public') if not self.request.event.testmode else ( @@ -73,7 +72,7 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) icon='fa-check-circle' if self.request.event.live and not self.request.event.testmode else ( 'fa-warning' if self.request.event.live else ( 'fa-times-circle' if not self.request.event.testmode else ( - 'fa-times-circle' + 'fa-lock' ) ) ), @@ -93,22 +92,38 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) cl.auto_checkin_sales_channels = [sales_channels[channel] for channel in cl.auto_checkin_sales_channels] ctx['checkinlists'] = qs + tickc = opqs.filter( + order__event=self.request.event, item__admission=True, + order__status__in=(Order.STATUS_PAID, Order.STATUS_PENDING), + ).count() ctx['attendees_ordered'] = { - 'content': NUM_WIDGET.format(num=tickc, text=_('Attendees (ordered)')), + 'content': NUM_WIDGET.format(num=f'{tickc} ', + text=_('Attendees (ordered)'), + text_add=''), 'priority': 100, 'url': reverse('control:event.orders', kwargs={ 'event': self.request.event.slug, 'organizer': self.request.event.organizer.slug }) + ('?subevent={}'.format(subevent.pk) if subevent else '') } - paidc = opqs.filter( order__event=self.request.event, item__admission=True, order__status=Order.STATUS_PAID, ).count() - ctx['attendees_paid'] = { - 'content': NUM_WIDGET.format(num=paidc, text=_('Attendees (paid)')), + 'content': NUM_WIDGET.format(num=f'{paidc} ', text=_('Attendees (paid)'), + text_add=''), + 'priority': 100, + 'url': reverse('control:event.orders.overview', kwargs={ + 'event': self.request.event.slug, + 'organizer': self.request.event.organizer.slug + }) + ('?subevent={}'.format(subevent.pk) if subevent else '') + } + ctx['attendees_paid_ordered'] = { + 'content': NUM_WIDGET.format( + num=f' {tickc}', + text=_('Attendees'), + text_add=_(f'{paidc} paid, {tickc - paidc} pending')), 'priority': 100, 'url': reverse('control:event.orders.overview', kwargs={ 'event': self.request.event.slug, @@ -131,8 +146,8 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) ctx['total_revenue'] = { 'content': NUM_WIDGET.format( num=formats.localize(round_decimal(rev, self.request.event.currency)), - text=_('Total revenue ({currency})').format(currency=self.request.event.currency) - ), + text=_('Total revenue ({currency})').format(currency=self.request.event.currency), + text_add=''), 'priority': 100, 'url': reverse('control:event.orders.overview', kwargs={ 'event': self.request.event.slug, @@ -143,15 +158,15 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) cache = self.request.event.cache ckey = str(subevent.pk) if subevent else 'all' tz = timezone.get_current_timezone() - # op_date = OrderPayment.objects.filter( - # order=OuterRef('order'), - # state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED), - # payment_date__isnull=False - # ).values('order').annotate( - # m=Max('payment_date') - # ).values( - # 'm' - # ).order_by() + op_date = OrderPayment.objects.filter( + order=OuterRef('order'), + state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED), + payment_date__isnull=False + ).values('order').annotate( + m=Max('payment_date') + ).values( + 'm' + ).order_by() p_date = OrderPayment.objects.filter( order=OuterRef('pk'), state__in=(OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED), @@ -164,23 +179,23 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) ctx['rev_data'] = cache.get('statistics_rev_data' + ckey) if not ctx['rev_data']: rev_by_day = {} - # if subevent: - # for o in OrderPosition.objects.annotate( - # payment_date=Subquery(op_date, output_field=DateTimeField()) - # ).filter(order__event=self.request.event, - # subevent=subevent, - # order__status=Order.STATUS_PAID, - # payment_date__isnull=False).values('payment_date', 'price'): - # day = o['payment_date'].astimezone(tz).date() - # rev_by_day[day] = rev_by_day.get(day, 0) + o['price'] - # else: - for o in Order.objects.annotate( - payment_date=Subquery(p_date, output_field=DateTimeField()) - ).filter(event=self.request.event, - status=Order.STATUS_PAID, - payment_date__isnull=False).values('payment_date', 'total'): - day = o['payment_date'].astimezone(tz).date() - rev_by_day[day] = rev_by_day.get(day, 0) + o['total'] + if subevent: + for o in OrderPosition.objects.annotate( + payment_date=Subquery(op_date, output_field=DateTimeField()) + ).filter(order__event=self.request.event, + subevent=subevent, + order__status=Order.STATUS_PAID, + payment_date__isnull=False).values('payment_date', 'price'): + day = o['payment_date'].astimezone(tz).date() + rev_by_day[day] = rev_by_day.get(day, 0) + o['price'] + else: + for o in Order.objects.annotate( + payment_date=Subquery(p_date, output_field=DateTimeField()) + ).filter(event=self.request.event, + status=Order.STATUS_PAID, + payment_date__isnull=False).values('payment_date', 'total'): + day = o['payment_date'].astimezone(tz).date() + rev_by_day[day] = rev_by_day.get(day, 0) + o['total'] data = [] total = 0 @@ -189,11 +204,13 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) dtstart=min(rev_by_day.keys() if rev_by_day else [datetime.date.today()]), until=max(rev_by_day.keys() if rev_by_day else [datetime.date.today()])): d = d.date() - total += float(rev_by_day.get(d, 0)) - data.append({ - 'date': d.strftime('%Y-%m-%d'), - 'revenue': round(total, 2), - }) + rev = float(rev_by_day.get(d, 0)) + if True: # rev != 0: + total += rev + data.append({ + 'date': d.strftime('%Y-%m-%d'), + 'revenue': round(total, 2), + }) ctx['rev_data'] = json.dumps(data) cache.set('statistics_rev_data' + ckey, ctx['rev_data']) # ctx = ctx | statistics.get_context_data(IndexView(request=request)) @@ -228,6 +245,6 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView) for t in timeline_for_event(self.request.event, subevent) ] ctx['today'] = now().astimezone(self.request.event.timezone).date() - ctx['nearly_now'] = now().astimezone(self.request.event.timezone) - timedelta(seconds=20) + ctx['nearly_now'] = now().astimezone(self.request.event.timezone) - datetime.timedelta(seconds=20) # resp['Content-Security-Policy'] = "style-src 'unsafe-inline'" return ctx diff --git a/src/pretix/static/pretixcontrol/scss/_dashboard.scss b/src/pretix/static/pretixcontrol/scss/_dashboard.scss index 973660ddb..22f8ff0b5 100644 --- a/src/pretix/static/pretixcontrol/scss/_dashboard.scss +++ b/src/pretix/static/pretixcontrol/scss/_dashboard.scss @@ -11,6 +11,10 @@ margin-right: -15px; } +.no-background { + background: none !important; +} + .dashboard .widget-container { flex: 1 0 auto; align-self: stretch; @@ -57,23 +61,27 @@ .dashboard .numwidget { .num { display: block; - padding: 10px 0 10px; text-align: center; font-size: 40px; } + .text { display: block; text-align: center; font-size: 20px; } + + .text-add { + display: block; + padding: 10px 0; + text-align: center; + font-size: 20px; + } } -.shopstate { - text-align: center; - +.shop_state { span.live, span.off { - display: block; - font-size: 18px; + font-size: 16px; } span.live { @@ -83,6 +91,10 @@ span.off { color: $brand-danger; } + + a { + vertical-align: top; + } } .widget-container.widget-container-event {