forked from CGM_Public/pretix_original
Added a donut chart to the quota view
Moved morris.js out of the statistics plugin
This commit is contained in:
@@ -3,3 +3,4 @@ src/static/lightbox/* linguist-vendored
|
|||||||
src/static/typeahead/* linguist-vendored
|
src/static/typeahead/* linguist-vendored
|
||||||
src/static/moment/* linguist-vendored
|
src/static/moment/* linguist-vendored
|
||||||
src/static/datetimepicker/* linguist-vendored
|
src/static/datetimepicker/* linguist-vendored
|
||||||
|
src/static/charts/* linguist-vendored
|
||||||
|
|||||||
@@ -17,9 +17,12 @@
|
|||||||
<script type="text/javascript" src="{% static "bootstrap/js/bootstrap.js" %}"></script>
|
<script type="text/javascript" src="{% static "bootstrap/js/bootstrap.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "moment/moment-with-locales.js" %}"></script>
|
<script type="text/javascript" src="{% static "moment/moment-with-locales.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "datetimepicker/bootstrap-datetimepicker.js" %}"></script>
|
<script type="text/javascript" src="{% static "datetimepicker/bootstrap-datetimepicker.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static "charts/raphael-min.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static "charts/morris.min.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/metisMenu.min.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixcontrol/js/metisMenu.min.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/sb-admin-2.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixcontrol/js/sb-admin-2.js" %}"></script>
|
||||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/main.js" %}"></script>
|
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/main.js" %}"></script>
|
||||||
|
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/quota.js" %}"></script>
|
||||||
{% endcompress %}
|
{% endcompress %}
|
||||||
{{ html_head|safe }}
|
{{ html_head|safe }}
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|||||||
@@ -46,9 +46,13 @@
|
|||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
{% if quota.pk and quota.size != None %}
|
{% if quota.pk and quota.size != None %}
|
||||||
<div class="col-xs-12 col-lg-3">
|
<div class="col-xs-12 col-lg-3" id="quota-stats">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{% trans "Availability calculation" %}</legend>
|
<legend>{% trans "Availability calculation" %}</legend>
|
||||||
|
<div class="chart" id="quota_chart">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-9">{% trans "Total quota" %}</div>
|
<div class="col-xs-9">{% trans "Total quota" %}</div>
|
||||||
<div class="col-xs-3 text-right">{{ quota.size }}</div>
|
<div class="col-xs-3 text-right">{{ quota.size }}</div>
|
||||||
@@ -75,6 +79,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
|
<script type="application/json" id="quota-chart-data">{{ quota_chart_data|safe }}</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group submit-group">
|
<div class="form-group submit-group">
|
||||||
|
|||||||
@@ -26,3 +26,12 @@ class UpdateView(EventBasedFormMixin, edit.UpdateView):
|
|||||||
properly.
|
properly.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ChartContainingView:
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
resp = super().get(request, *args, **kwargs)
|
||||||
|
# required by raphael.js
|
||||||
|
resp['Content-Security-Policy'] = "script-src {static} 'unsafe-eval'; style-src {static} 'unsafe-inline'"
|
||||||
|
return resp
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.files import File
|
from django.core.files import File
|
||||||
from django.core.urlresolvers import resolve, reverse
|
from django.core.urlresolvers import resolve, reverse
|
||||||
@@ -6,7 +8,7 @@ from django.forms.models import ModelMultipleChoiceField, inlineformset_factory
|
|||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
from django.views.generic import ListView
|
from django.views.generic import ListView
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.detail import SingleObjectMixin
|
from django.views.generic.detail import SingleObjectMixin
|
||||||
@@ -24,7 +26,7 @@ from pretix.control.permissions import (
|
|||||||
EventPermissionRequiredMixin, event_permission_required,
|
EventPermissionRequiredMixin, event_permission_required,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import CreateView, UpdateView
|
from . import ChartContainingView, CreateView, UpdateView
|
||||||
|
|
||||||
|
|
||||||
class ItemList(ListView):
|
class ItemList(ListView):
|
||||||
@@ -525,13 +527,39 @@ class QuotaCreate(EventPermissionRequiredMixin, QuotaEditorMixin, CreateView):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class QuotaUpdate(EventPermissionRequiredMixin, QuotaEditorMixin, UpdateView):
|
class QuotaUpdate(EventPermissionRequiredMixin, QuotaEditorMixin, ChartContainingView, UpdateView):
|
||||||
model = Quota
|
model = Quota
|
||||||
form_class = QuotaForm
|
form_class = QuotaForm
|
||||||
template_name = 'pretixcontrol/items/quota.html'
|
template_name = 'pretixcontrol/items/quota.html'
|
||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'quota'
|
context_object_name = 'quota'
|
||||||
|
|
||||||
|
def get_context_data(self, *args, **kwargs):
|
||||||
|
ctx = super().get_context_data()
|
||||||
|
ctx['quota_chart_data'] = json.dumps([
|
||||||
|
{
|
||||||
|
'label': ugettext('Paid orders'),
|
||||||
|
'value': self.object.count_paid_orders()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': ugettext('Pending orders'),
|
||||||
|
'value': self.object.count_pending_orders()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': ugettext('Vouchers'),
|
||||||
|
'value': self.object.count_blocking_vouchers()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': ugettext('Current user\'s carts'),
|
||||||
|
'value': self.object.count_in_cart()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'label': ugettext('Current availability'),
|
||||||
|
'value': self.object.availability()[1]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
return ctx
|
||||||
|
|
||||||
def get_object(self, queryset=None) -> Quota:
|
def get_object(self, queryset=None) -> Quota:
|
||||||
try:
|
try:
|
||||||
return self.request.event.quotas.get(
|
return self.request.event.quotas.get(
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
from django.core.urlresolvers import resolve, reverse
|
from django.core.urlresolvers import resolve, reverse
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.template import Context
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from pretix.base.signals import order_paid, order_placed
|
from pretix.base.signals import order_paid, order_placed
|
||||||
from pretix.control.signals import html_head, nav_event
|
from pretix.control.signals import nav_event
|
||||||
|
|
||||||
|
|
||||||
@receiver(nav_event, dispatch_uid="statistics_nav")
|
@receiver(nav_event, dispatch_uid="statistics_nav")
|
||||||
@@ -26,17 +24,6 @@ def control_nav_import(sender, request=None, **kwargs):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@receiver(html_head, dispatch_uid="statistics_html_head")
|
|
||||||
def html_head_presale(sender, request=None, **kwargs):
|
|
||||||
url = resolve(request.path_info)
|
|
||||||
if url.namespace == 'plugins:statistics':
|
|
||||||
template = get_template('pretixplugins/statistics/control_head.html')
|
|
||||||
ctx = Context({})
|
|
||||||
return template.render(ctx)
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def clear_cache(sender, *args, **kwargs):
|
def clear_cache(sender, *args, **kwargs):
|
||||||
cache = sender.get_cache()
|
cache = sender.get_cache()
|
||||||
cache.delete('statistics_obd_data')
|
cache.delete('statistics_obd_data')
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
{% load staticfiles %}
|
|
||||||
{% load compress %}
|
|
||||||
|
|
||||||
{% compress css %}
|
|
||||||
<link type="text/css" rel="stylesheet" href="{% static "pretixplugins/statistics/morris.css" %}">
|
|
||||||
{% endcompress %}
|
|
||||||
<script type="text/javascript" src="{% static "pretixplugins/statistics/raphael-min.js" %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "pretixplugins/statistics/morris.min.js" %}"></script>
|
|
||||||
@@ -9,19 +9,14 @@ from django.views.generic import TemplateView
|
|||||||
|
|
||||||
from pretix.base.models import Item, Order, OrderPosition
|
from pretix.base.models import Item, Order, OrderPosition
|
||||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||||
|
from pretix.control.views import ChartContainingView
|
||||||
from pretix.plugins.statistics.signals import clear_cache
|
from pretix.plugins.statistics.signals import clear_cache
|
||||||
|
|
||||||
|
|
||||||
class IndexView(EventPermissionRequiredMixin, TemplateView):
|
class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView):
|
||||||
template_name = 'pretixplugins/statistics/index.html'
|
template_name = 'pretixplugins/statistics/index.html'
|
||||||
permission = 'can_view_orders'
|
permission = 'can_view_orders'
|
||||||
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
resp = super().get(request, *args, **kwargs)
|
|
||||||
# required by raphael.js
|
|
||||||
resp['Content-Security-Policy'] = "script-src {static} 'unsafe-eval'; style-src {static} 'unsafe-inline'"
|
|
||||||
return resp
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super().get_context_data(**kwargs)
|
ctx = super().get_context_data(**kwargs)
|
||||||
tz = timezone.get_current_timezone()
|
tz = timezone.get_current_timezone()
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*globals $, Morris, gettext*/
|
||||||
|
$(function () {
|
||||||
|
if (!$("#quota-stats").length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".chart").css("height", "250px");
|
||||||
|
new Morris.Donut({
|
||||||
|
element: 'quota_chart',
|
||||||
|
data: JSON.parse($("#quota-chart-data").html()),
|
||||||
|
resize: true,
|
||||||
|
colors: [
|
||||||
|
'#0044CC', // paid
|
||||||
|
'#0088CC', // pending
|
||||||
|
'#BD362F', // vouchers
|
||||||
|
'#F89406', // carts
|
||||||
|
'#51A351' // available
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,6 +4,7 @@ $fa-font-path: static("fontawesome/fonts");
|
|||||||
@import "../../fontawesome/scss/font-awesome.scss";
|
@import "../../fontawesome/scss/font-awesome.scss";
|
||||||
@import "../../typeahead/typeahead.css";
|
@import "../../typeahead/typeahead.css";
|
||||||
@import "../css/metisMenu.min.css";
|
@import "../css/metisMenu.min.css";
|
||||||
|
@import "../../charts/morris.css";
|
||||||
@import "../../datetimepicker/_bootstrap-datetimepicker.scss";
|
@import "../../datetimepicker/_bootstrap-datetimepicker.scss";
|
||||||
@import "_sb-admin-2.scss";
|
@import "_sb-admin-2.scss";
|
||||||
@import "_forms.scss";
|
@import "_forms.scss";
|
||||||
|
|||||||
Reference in New Issue
Block a user