forked from CGM_Public/pretix_original
Make navigation structure more approachable to new users (#1083)
* Move event selector to sidebar * Unify navigation * Fix confusing icons
This commit is contained in:
@@ -8,11 +8,14 @@ from django.utils.translation import get_language
|
||||
|
||||
from pretix.base.models.auth import StaffSession
|
||||
from pretix.base.settings import GlobalSettingsObject
|
||||
from pretix.control.navigation import (
|
||||
get_event_navigation, get_global_navigation, get_organizer_navigation,
|
||||
)
|
||||
|
||||
from ..helpers.i18n import (
|
||||
get_javascript_format, get_javascript_output_format, get_moment_locale,
|
||||
)
|
||||
from .signals import html_head, nav_event, nav_global, nav_topbar
|
||||
from .signals import html_head, nav_topbar
|
||||
|
||||
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
|
||||
|
||||
@@ -40,10 +43,9 @@ def contextprocessor(request):
|
||||
ctx['html_head'] = "".join(_html_head)
|
||||
|
||||
_js_payment_weekdays_disabled = '[]'
|
||||
_nav_event = []
|
||||
if getattr(request, 'event', None) and hasattr(request, 'organizer') and request.user.is_authenticated:
|
||||
for receiver, response in nav_event.send(request.event, request=request):
|
||||
_nav_event += response
|
||||
ctx['nav_items'] = get_event_navigation(request)
|
||||
|
||||
if request.event.settings.get('payment_term_weekdays'):
|
||||
_js_payment_weekdays_disabled = '[0,6]'
|
||||
|
||||
@@ -65,17 +67,13 @@ def contextprocessor(request):
|
||||
if request.GET.get('subevent', ''):
|
||||
# Do not use .get() for lazy evaluation
|
||||
ctx['selected_subevents'] = request.event.subevents.filter(pk=request.GET.get('subevent'))
|
||||
elif getattr(request, 'organizer', None) and request.user.is_authenticated:
|
||||
ctx['nav_items'] = get_organizer_navigation(request)
|
||||
elif request.user.is_authenticated:
|
||||
ctx['nav_items'] = get_global_navigation(request)
|
||||
|
||||
ctx['nav_event'] = _nav_event
|
||||
ctx['js_payment_weekdays_disabled'] = _js_payment_weekdays_disabled
|
||||
|
||||
_nav_global = []
|
||||
if not hasattr(request, 'event') and request.user.is_authenticated:
|
||||
for receiver, response in nav_global.send(request, request=request):
|
||||
_nav_global += response
|
||||
|
||||
ctx['nav_global'] = sorted(_nav_global, key=lambda n: n['label'])
|
||||
|
||||
_nav_topbar = []
|
||||
if request.user.is_authenticated:
|
||||
for receiver, response in nav_topbar.send(request, request=request):
|
||||
|
||||
471
src/pretix/control/navigation.py
Normal file
471
src/pretix/control/navigation.py
Normal file
@@ -0,0 +1,471 @@
|
||||
from django.http import HttpRequest
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import pgettext_lazy, ugettext_lazy as _
|
||||
|
||||
from pretix.control.signals import (
|
||||
nav_event, nav_event_settings, nav_global, nav_organizer,
|
||||
)
|
||||
|
||||
|
||||
def get_event_navigation(request: HttpRequest):
|
||||
url = request.resolver_match
|
||||
if not url:
|
||||
return []
|
||||
nav = [
|
||||
{
|
||||
'label': _('Dashboard'),
|
||||
'url': reverse('control:event.index', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': (url.url_name == 'event.index'),
|
||||
'icon': 'dashboard',
|
||||
}
|
||||
]
|
||||
if 'can_change_event_settings' in request.eventpermset:
|
||||
event_settings = [
|
||||
{
|
||||
'label': _('General'),
|
||||
'url': reverse('control:event.settings', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings',
|
||||
},
|
||||
{
|
||||
'label': _('Payment'),
|
||||
'url': reverse('control:event.settings.payment', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.payment',
|
||||
},
|
||||
{
|
||||
'label': _('Plugins'),
|
||||
'url': reverse('control:event.settings.plugins', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.plugins',
|
||||
},
|
||||
{
|
||||
'label': _('Display'),
|
||||
'url': reverse('control:event.settings.display', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.display',
|
||||
},
|
||||
{
|
||||
'label': _('Tickets'),
|
||||
'url': reverse('control:event.settings.tickets', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.tickets',
|
||||
},
|
||||
{
|
||||
'label': _('E-mail'),
|
||||
'url': reverse('control:event.settings.mail', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.mail',
|
||||
},
|
||||
{
|
||||
'label': _('Tax rules'),
|
||||
'url': reverse('control:event.settings.tax', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.tax',
|
||||
},
|
||||
{
|
||||
'label': _('Invoicing'),
|
||||
'url': reverse('control:event.settings.invoice', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.invoice',
|
||||
},
|
||||
{
|
||||
'label': _('Widget'),
|
||||
'url': reverse('control:event.settings.widget', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name == 'event.settings.widget',
|
||||
},
|
||||
]
|
||||
event_settings += sorted(
|
||||
sum((list(a[1]) for a in nav_event_settings.send(request.event, request=request)), []),
|
||||
key=lambda r: r['label']
|
||||
)
|
||||
nav.append({
|
||||
'label': _('Settings'),
|
||||
'url': reverse('control:event.settings', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': False,
|
||||
'icon': 'wrench',
|
||||
'children': event_settings
|
||||
})
|
||||
if request.event.has_subevents:
|
||||
nav.append({
|
||||
'label': pgettext_lazy('subevent', 'Dates'),
|
||||
'url': reverse('control:event.subevents', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': ('event.subevent' in url.url_name),
|
||||
'icon': 'calendar',
|
||||
})
|
||||
|
||||
if 'can_change_items' in request.eventpermset:
|
||||
nav.append({
|
||||
'label': _('Products'),
|
||||
'url': reverse('control:event.items', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': False,
|
||||
'icon': 'ticket',
|
||||
'children': [
|
||||
{
|
||||
'label': _('Products'),
|
||||
'url': reverse('control:event.items', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name in (
|
||||
'event.item', 'event.items.add', 'event.items') or "event.item." in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Quotas'),
|
||||
'url': reverse('control:event.items.quotas', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.items.quota' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Categories'),
|
||||
'url': reverse('control:event.items.categories', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.items.categories' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Questions'),
|
||||
'url': reverse('control:event.items.questions', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.items.questions' in url.url_name,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
if 'can_view_orders' in request.eventpermset:
|
||||
nav.append({
|
||||
'label': _('Orders'),
|
||||
'url': reverse('control:event.orders', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': False,
|
||||
'icon': 'shopping-cart',
|
||||
'children': [
|
||||
{
|
||||
'label': _('All orders'),
|
||||
'url': reverse('control:event.orders', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name in ('event.orders', 'event.order') or "event.order." in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Overview'),
|
||||
'url': reverse('control:event.orders.overview', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.orders.overview' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Refunds'),
|
||||
'url': reverse('control:event.orders.refunds', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.orders.refunds' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Export'),
|
||||
'url': reverse('control:event.orders.export', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.orders.export' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Waiting list'),
|
||||
'url': reverse('control:event.orders.waitinglist', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.orders.waitinglist' in url.url_name,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
if 'can_view_vouchers' in request.eventpermset:
|
||||
nav.append({
|
||||
'label': _('Vouchers'),
|
||||
'url': reverse('control:event.vouchers', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': False,
|
||||
'icon': 'tags',
|
||||
'children': [
|
||||
{
|
||||
'label': _('All vouchers'),
|
||||
'url': reverse('control:event.vouchers', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': url.url_name != 'event.vouchers.tags' and "event.vouchers" in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Tags'),
|
||||
'url': reverse('control:event.vouchers.tags', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.vouchers.tags' in url.url_name,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
if 'can_view_orders' in request.eventpermset:
|
||||
nav.append({
|
||||
'label': pgettext_lazy('navigation', 'Check-in'),
|
||||
'url': reverse('control:event.orders.checkinlists', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': False,
|
||||
'icon': 'check-square-o',
|
||||
'children': [
|
||||
{
|
||||
'label': _('Check-in lists'),
|
||||
'url': reverse('control:event.orders.checkinlists', kwargs={
|
||||
'event': request.event.slug,
|
||||
'organizer': request.event.organizer.slug,
|
||||
}),
|
||||
'active': 'event.orders.checkin' in url.url_name,
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
merge_in(nav, sorted(
|
||||
sum((list(a[1]) for a in nav_event.send(request.event, request=request)), []),
|
||||
key=lambda r: r['label']
|
||||
))
|
||||
|
||||
return nav
|
||||
|
||||
|
||||
def get_global_navigation(request):
|
||||
url = request.resolver_match
|
||||
if not url:
|
||||
return []
|
||||
has_staff_session = request.user.has_active_staff_session(request.session.session_key)
|
||||
nav = [
|
||||
{
|
||||
'label': _('Dashboard'),
|
||||
'url': reverse('control:index'),
|
||||
'active': (url.url_name == 'index'),
|
||||
'icon': 'dashboard',
|
||||
},
|
||||
{
|
||||
'label': _('Events'),
|
||||
'url': reverse('control:events'),
|
||||
'active': 'events' in url.url_name,
|
||||
'icon': 'calendar',
|
||||
},
|
||||
{
|
||||
'label': _('Organizers'),
|
||||
'url': reverse('control:organizers'),
|
||||
'active': 'organizers' in url.url_name,
|
||||
'icon': 'group',
|
||||
},
|
||||
{
|
||||
'label': _('Order search'),
|
||||
'url': reverse('control:search.orders'),
|
||||
'active': 'search.orders' in url.url_name,
|
||||
'icon': 'search',
|
||||
},
|
||||
{
|
||||
'label': _('User settings'),
|
||||
'url': reverse('control:user.settings'),
|
||||
'active': False,
|
||||
'icon': 'user',
|
||||
'children': [
|
||||
{
|
||||
'label': _('General'),
|
||||
'url': reverse('control:user.settings'),
|
||||
'active': 'user.settings' == url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Notifications'),
|
||||
'url': reverse('control:user.settings.notifications'),
|
||||
'active': 'user.settings.notifications' == url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('2FA'),
|
||||
'url': reverse('control:user.settings.2fa'),
|
||||
'active': 'user.settings.2fa' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Authorized apps'),
|
||||
'url': reverse('control:user.settings.oauth.list'),
|
||||
'active': 'user.settings.oauth' in url.url_name,
|
||||
},
|
||||
{
|
||||
'label': _('Account history'),
|
||||
'url': reverse('control:user.settings.history'),
|
||||
'active': 'user.settings.history' in url.url_name,
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
if has_staff_session:
|
||||
nav.append({
|
||||
'label': _('Users'),
|
||||
'url': reverse('control:users'),
|
||||
'active': False,
|
||||
'icon': 'user',
|
||||
'children': [
|
||||
{
|
||||
'label': _('All users'),
|
||||
'url': reverse('control:users'),
|
||||
'active': ('users' in url.url_name),
|
||||
},
|
||||
{
|
||||
'label': _('Admin sessions'),
|
||||
'url': reverse('control:user.sudo.list'),
|
||||
'active': ('sudo' in url.url_name),
|
||||
},
|
||||
]
|
||||
})
|
||||
nav.append({
|
||||
'label': _('Global settings'),
|
||||
'url': reverse('control:global.settings'),
|
||||
'active': False,
|
||||
'icon': 'wrench',
|
||||
'children': [
|
||||
{
|
||||
'label': _('Settings'),
|
||||
'url': reverse('control:global.settings'),
|
||||
'active': (url.url_name == 'global.settings'),
|
||||
},
|
||||
{
|
||||
'label': _('Update check'),
|
||||
'url': reverse('control:global.update'),
|
||||
'active': (url.url_name == 'global.update'),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
merge_in(nav, sorted(
|
||||
sum((list(a[1]) for a in nav_global.send(request, request=request)), []),
|
||||
key=lambda r: r['label']
|
||||
))
|
||||
return nav
|
||||
|
||||
|
||||
def get_organizer_navigation(request):
|
||||
url = request.resolver_match
|
||||
if not url:
|
||||
return []
|
||||
nav = [
|
||||
{
|
||||
'label': _('Events'),
|
||||
'url': reverse('control:organizer', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': url.url_name == 'organizer',
|
||||
'icon': 'calendar',
|
||||
},
|
||||
]
|
||||
if 'can_change_organizer_settings' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Settings'),
|
||||
'url': reverse('control:organizer.edit', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'icon': 'wrench',
|
||||
'children': [
|
||||
{
|
||||
'label': _('General'),
|
||||
'url': reverse('control:organizer.edit', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': url.url_name == 'organizer.edit',
|
||||
},
|
||||
{
|
||||
'label': _('Display'),
|
||||
'url': reverse('control:organizer.display', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': url.url_name == 'organizer.display',
|
||||
},
|
||||
]
|
||||
})
|
||||
if 'can_change_teams' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Teams'),
|
||||
'url': reverse('control:organizer.teams', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.team' in url.url_name,
|
||||
'icon': 'group',
|
||||
})
|
||||
if 'can_change_organizer_settings' in request.orgapermset:
|
||||
nav.append({
|
||||
'label': _('Devices'),
|
||||
'url': reverse('control:organizer.devices', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.device' in url.url_name,
|
||||
'icon': 'tablet',
|
||||
})
|
||||
nav.append({
|
||||
'label': _('Webhooks'),
|
||||
'url': reverse('control:organizer.webhooks', kwargs={
|
||||
'organizer': request.organizer.slug
|
||||
}),
|
||||
'active': 'organizer.webhook' in url.url_name,
|
||||
'icon': 'bolt',
|
||||
})
|
||||
|
||||
merge_in(nav, sorted(
|
||||
sum((list(a[1]) for a in nav_organizer.send(request.organizer, request=request, organizer=request.organizer)),
|
||||
[]),
|
||||
key=lambda r: r['label']
|
||||
))
|
||||
return nav
|
||||
|
||||
|
||||
def merge_in(nav, newnav):
|
||||
for item in newnav:
|
||||
if 'parent' in item:
|
||||
parents = [n for n in nav if n['url'] == item['parent']]
|
||||
if parents:
|
||||
parents[0]['children'].append(item)
|
||||
else:
|
||||
nav.append(item)
|
||||
@@ -82,10 +82,6 @@
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<button type="button" class="navbar-toggle navbar-events"
|
||||
data-toggle="collapse" data-target=".navbar-events-collapse">
|
||||
<i class="fa fa-calendar"></i><span class="caret"></span>
|
||||
</button>
|
||||
{% if request.event %}
|
||||
{% if has_domain and not request.event.live %}
|
||||
<form action="{% eventurl request.event "presale:event.auth" %}" method="post"
|
||||
@@ -108,24 +104,6 @@
|
||||
</a>
|
||||
</div>
|
||||
<ul class="nav navbar-nav navbar-top-links navbar-left hidden-xs">
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle event-dropdown-toggle" data-toggle="dropdown"><i class="fa fa-calendar"></i>
|
||||
<div class="event-indicator">
|
||||
<span class="event-name">{{ request.event }}</span>
|
||||
<span class="event-daterange">{{ request.event.get_date_range_display }}</span>
|
||||
</div>
|
||||
<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu event-dropdown" role="menu" data-event-typeahead
|
||||
data-source="{% url "control:events.typeahead" %}">
|
||||
<li class="query-holder">
|
||||
<div class="form-box">
|
||||
<input type="text" class="form-control"
|
||||
placeholder="{% trans "Search for events" %}"
|
||||
data-typeahead-query>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% if request.event %}
|
||||
<li>
|
||||
{% if has_domain and not request.event.live %}
|
||||
@@ -209,71 +187,56 @@
|
||||
</li>
|
||||
</ul>
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="sidebar-nav navbar-events-collapse navbar-collapse hidden-sm hidden-md hidden-lg mobile-event-dropdown">
|
||||
<ul class="nav" data-event-typeahead data-source="{% url "control:events.typeahead" %}">
|
||||
<li class="query-holder">
|
||||
<div class="form-box">
|
||||
<input type="text" class="form-control"
|
||||
placeholder="{% trans "Search for events" %}"
|
||||
data-typeahead-query>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sidebar-nav navbar-nav-collapse navbar-collapse">
|
||||
<div class="dropdown context-selector">
|
||||
{% if request.event %}
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa-stack fa-lg">
|
||||
<i class="fa fa-circle fa-stack-2x"></i>
|
||||
<i class="fa fa-calendar fa-stack-1x fa-inverse"></i>
|
||||
</span>
|
||||
<div class="context-indicator">
|
||||
<span class="context-name">{{ request.event }}</span>
|
||||
<span class="context-meta">{{ request.event.get_date_range_display }}</span>
|
||||
</div>
|
||||
<span class="caret"></span></a>
|
||||
{% elif request.organizer %}
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa-stack fa-lg">
|
||||
<i class="fa fa-circle fa-stack-2x"></i>
|
||||
<i class="fa fa-group fa-stack-1x fa-inverse"></i>
|
||||
</span>
|
||||
<div class="context-indicator">
|
||||
<span class="context-name">{{ request.organizer }}</span>
|
||||
<span class="context-meta">{% trans "Organizer account" %}</span>
|
||||
</div>
|
||||
<span class="caret"></span></a>
|
||||
{% else %}
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<span class="fa-stack fa-lg">
|
||||
<i class="fa fa-circle fa-stack-2x"></i>
|
||||
<i class="fa fa-user fa-stack-1x fa-inverse"></i>
|
||||
</span>
|
||||
|
||||
<div class="context-indicator">
|
||||
<span class="context-name">{{ request.user }}</span>
|
||||
</div>
|
||||
<span class="caret"></span></a>
|
||||
{% endif %}
|
||||
<ul class="dropdown-menu event-dropdown" role="menu" data-event-typeahead
|
||||
data-source="{% url "control:nav.typeahead" %}">
|
||||
<li class="query-holder">
|
||||
<div class="form-box">
|
||||
<input type="text" class="form-control" id="event-dropdown-field"
|
||||
placeholder="{% trans "Search for events" %}"
|
||||
data-typeahead-query>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul class="nav" id="side-menu">
|
||||
{% block nav %}
|
||||
<li>
|
||||
<a href="{% url 'control:index' %}" {% if url_name == "index" %}class="active"{% endif %}>
|
||||
<i class="fa fa-dashboard fa-fw"></i>
|
||||
{% trans "Dashboard" %}
|
||||
</a>
|
||||
</li>
|
||||
{% if staff_session %}
|
||||
<li>
|
||||
<a href="{% url 'control:global.settings' %}"
|
||||
{% if "global.settings" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-wrench fa-fw"></i>
|
||||
{% trans "Global settings" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{% url 'control:events' %}" {% if "events" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-calendar fa-fw"></i>
|
||||
{% trans "Events" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:organizers' %}" {% if "organizer" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-users fa-fw"></i>
|
||||
{% trans "Organizers" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:search.orders' %}"
|
||||
{% if url_name == "search.orders" %}class="active"{% endif %}>
|
||||
<i class="fa fa-search fa-fw"></i>
|
||||
{% trans "Order search" %}
|
||||
</a>
|
||||
</li>
|
||||
{% if staff_session %}
|
||||
<li>
|
||||
<a href="{% url 'control:users' %}"
|
||||
{% if "users" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-user fa-fw"></i>
|
||||
{% trans "Users" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:user.sudo.list' %}"
|
||||
{% if "sudo" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-id-card fa-fw"></i>
|
||||
{% trans "Admin sessions" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for nav in nav_global %}
|
||||
{% for nav in nav_items %}
|
||||
<li>
|
||||
<a href="{{ nav.url }}" {% if nav.active %}class="active"{% endif %}
|
||||
{% if nav.children %}class="has-children"{% endif %}>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<input type="text" class="form-control" id="dashboard_query"
|
||||
placeholder="{% trans "Go to event" %}"
|
||||
data-typeahead-query autofocus>
|
||||
<ul data-event-typeahead data-source="{% url "control:events.typeahead" %}" data-typeahead-field="#dashboard_query"
|
||||
<ul data-event-typeahead data-source="{% url "control:nav.typeahead" %}" data-typeahead-field="#dashboard_query"
|
||||
class="event-dropdown dropdown-menu">
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -2,158 +2,3 @@
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% block title %}{{ request.event.name }}{% endblock %}
|
||||
|
||||
{% block nav %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.index' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.index" %}class="active"{% endif %}>
|
||||
<i class="fa fa-dashboard fa-fw"></i>
|
||||
{% trans "Event dashboard" %}
|
||||
</a>
|
||||
</li>
|
||||
{% if 'can_change_event_settings' in request.eventpermset %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.settings' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if is_event_settings or "event.settings" == url_name or "event.settings." in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-wrench fa-fw"></i>
|
||||
{% trans "Settings" %}
|
||||
</a>
|
||||
</li>
|
||||
{% if request.event.has_subevents %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.subevents' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.subevent" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-calendar fa-fw"></i>
|
||||
{% trans "Dates" context "subevent" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if 'can_change_items' in request.eventpermset %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.items' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="has-children">
|
||||
<i class="fa fa-ticket fa-fw"></i>
|
||||
{% trans "Products" %}
|
||||
</a>
|
||||
<a href="#" class="arrow">
|
||||
<span class="fa arrow"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a href="{% url 'control:event.items' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.items" == url_name or "event.item." in url_name or "event.items.add" == url_name or url_name == "event.item" %}class="active"{% endif %}>
|
||||
{% trans "Products" %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.items.quotas' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.items.quotas" in url_name %}class="active"{% endif %}>
|
||||
{% trans "Quotas" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.items.categories' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.items.categories" in url_name %}class="active"{% endif %}>
|
||||
{% trans "Categories" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.items.questions' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.items.questions" in url_name %}class="active"{% endif %}>
|
||||
{% trans "Questions" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_view_orders' in request.eventpermset %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
class="has-children">
|
||||
<i class="fa fa-shopping-cart fa-fw"></i>
|
||||
{% trans "Orders" %}
|
||||
</a>
|
||||
<a href="#" class="arrow">
|
||||
<span class="fa arrow"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.orders" or "event.order." in url_name or url_name == "event.order" %}class="active"{% endif %}>
|
||||
{% trans "All orders" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders.overview' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.orders.overview" %}class="active"{% endif %}>
|
||||
{% trans "Overview" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders.refunds' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.orders.refunds" %}class="active"{% endif %}>
|
||||
{% trans "Refunds" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders.export' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.orders.export" %}class="active"{% endif %}>
|
||||
{% trans "Export" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders.waitinglist' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.orders.waitinglist" %}class="active"{% endif %}>
|
||||
{% trans "Waiting list" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_view_vouchers' in request.eventpermset %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.vouchers' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if url_name == "event.voucher" %}class="active"{% endif %}>
|
||||
<i class="fa fa-tags fa-fw"></i>
|
||||
{% trans "Vouchers" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_view_orders' in request.eventpermset %}
|
||||
<li>
|
||||
<a href="{% url 'control:event.orders.checkinlists' organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
{% if "event.orders.checkin" in url_name %}class="active"{% endif %}>
|
||||
<i class="fa fa-check-square-o fa-fw"></i>
|
||||
{% trans "Check-in lists" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for nav in nav_event %}
|
||||
<li>
|
||||
<a href="{{ nav.url }}" {% if nav.active %}class="active"{% endif %}
|
||||
{% if nav.children %}class="has-children"{% endif %}>
|
||||
{% if nav.icon and "." in nav.icon %}
|
||||
<img src="{% static nav.icon %}" class="fa-img">
|
||||
{% elif nav.icon %}
|
||||
<i class="fa fa-{{ nav.icon }} fa-fw"></i>
|
||||
{% endif %}
|
||||
{{ nav.label }}
|
||||
</a>
|
||||
{% if nav.children %}
|
||||
<a href="#" class="arrow">
|
||||
<span class="fa arrow"></span>
|
||||
</a>
|
||||
<ul class="nav nav-second-level">
|
||||
{% for item in nav.children %}
|
||||
<li>
|
||||
<a href="{{ item.url }}"
|
||||
{% if item.active %}class="active"{% endif %}>
|
||||
{{ item.label }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% load hierarkey_form %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Display settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Invoice settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Invoice settings" %}</legend>
|
||||
<legend>{% trans "General settings" %}</legend>
|
||||
{% bootstrap_field form.invoice_generate layout="control" %}
|
||||
{% bootstrap_field form.invoice_email_attachment layout="control" %}
|
||||
{% bootstrap_field form.invoice_numbers_prefix layout="control" %}
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
{% load bootstrap3 %}
|
||||
{% load static %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "E-mail settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data"
|
||||
mail-preview-url="{% url "control:event.settings.mail.preview" event=request.event.slug organizer=request.event.organizer.slug %}">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<fieldset>
|
||||
<legend>{% trans "E-mail settings" %}</legend>
|
||||
<legend>{% trans "General settings" %}</legend>
|
||||
{% bootstrap_field form.mail_prefix layout="control" %}
|
||||
{% bootstrap_field form.mail_from layout="control" %}
|
||||
{% bootstrap_field form.mail_text_signature layout="control" %}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Payment settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal form-plugins">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Installed plugins" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal form-plugins">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
<legend>{% trans "Installed plugins" %}</legend>
|
||||
{% if "success" in request.GET %}
|
||||
<div class="alert alert-success">
|
||||
{% trans "Your changes have been saved." %}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "General settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
|
||||
@@ -27,68 +27,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<h1>{% trans "Settings" %}</h1>
|
||||
<ul class="nav nav-pills">
|
||||
{% if 'can_change_event_settings' in request.eventpermset %}
|
||||
<li {% if "event.settings" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "General" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.payment" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.payment' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Payment" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.plugins" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.plugins' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Plugins" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.display" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.display' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Display" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.tickets" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.tickets' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Tickets" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.mail" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.mail' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "E-mail" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.tax" in url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.tax' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Tax rules" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.invoice" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.invoice' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Invoicing" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.permissions" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.permissions' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Permissions" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.settings.widget" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.settings.widget' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Widget" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for nav in nav_event_settings %}
|
||||
<li {% if nav.active %}class="active"{% endif %}>
|
||||
<a href="{{ nav.url }}">
|
||||
{{ nav.label }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% block inside %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Delete tax rule" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<legend>{% trans "Delete tax rule" %}</legend>
|
||||
<h1>{% trans "Delete tax rule" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% if possible %}
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
{% endblock %}
|
||||
{% block inside %}
|
||||
{% if rule %}
|
||||
<legend>{% blocktrans with name=rule.name %}Tax rule: {{ name }}{% endblocktrans %}</legend>
|
||||
<h1>{% blocktrans with name=rule.name %}Tax rule: {{ name }}{% endblocktrans %}</h1>
|
||||
{% else %}
|
||||
<legend>{% trans "Tax rule" %}</legend>
|
||||
<h1>{% trans "Tax rule" %}</h1>
|
||||
{% endif %}
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Tax rules" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<legend>{% trans "Tax rules" %}</legend>
|
||||
<h1>{% trans "Tax rules" %}</h1>
|
||||
{% if taxrules|length == 0 %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
{% block inside %}
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<h1>{% trans "Ticket download" %}</h1>
|
||||
<fieldset>
|
||||
<legend>{% trans "Ticket download" %}</legend>
|
||||
{% if request.event.settings.ticket_download and not any_enabled %}
|
||||
<div class="alert alert-warning">
|
||||
{% blocktrans trimmed %}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% load eventurl %}
|
||||
{% load eventsignal %}
|
||||
{% block inside %}
|
||||
<legend>{% trans "Widget" %}</legend>
|
||||
<h1>{% trans "Widget" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
The pretix widget is a way to embed your ticket shop into your event website. This way, your visitors can
|
||||
|
||||
@@ -5,18 +5,6 @@
|
||||
{% block title %}{% trans "Global settings" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Global settings" %}</h1>
|
||||
<ul class="nav nav-pills">
|
||||
<li {% if "global.settings" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:global.settings' %}">
|
||||
{% trans "General" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "global.update" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:global.update' %}">
|
||||
{% trans "Update check" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% block inner %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,65 +3,6 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Organizer" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>
|
||||
{% blocktrans with name=organizer.name %}Organizer: {{ name }}{% endblocktrans %}
|
||||
{% if 'can_change_organizer_settings' in request.orgapermset %}
|
||||
<a href="{% url "control:organizer.edit" organizer=organizer.slug %}"
|
||||
class="btn btn-default hidden-print">
|
||||
<span class="fa fa-edit"></span>
|
||||
{% trans "Edit" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if request.user.is_staff and staff_session %}
|
||||
<a href="{% url "control:organizer.delete" organizer=organizer.slug %}"
|
||||
class="btn btn-danger hidden-print">
|
||||
<span class="fa fa-trash"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</h1>
|
||||
<ul class="nav nav-pills hidden-print">
|
||||
<li {% if "organizer" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url "control:organizer" organizer=organizer.slug %}">
|
||||
{% trans "Events" %}
|
||||
</a>
|
||||
</li>
|
||||
{% if 'can_change_teams' in request.orgapermset %}
|
||||
<li {% if "organizer.team" in url_name %}class="active"{% endif %}>
|
||||
<a href="{% url "control:organizer.teams" organizer=organizer.slug %}">
|
||||
{% trans "Teams" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_change_organizer_settings' in request.orgapermset %}
|
||||
<li {% if "organizer.display" in url_name %}class="active"{% endif %}>
|
||||
<a href="{% url "control:organizer.display" organizer=organizer.slug %}">
|
||||
{% trans "Display" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_change_organizer_settings' in request.orgapermset %}
|
||||
<li {% if "organizer.device" in url_name %}class="active"{% endif %}>
|
||||
<a href="{% url "control:organizer.devices" organizer=organizer.slug %}">
|
||||
{% trans "Devices" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if 'can_change_organizer_settings' in request.orgapermset %}
|
||||
<li {% if "organizer.webhook" in url_name %}class="active"{% endif %}>
|
||||
<a href="{% url "control:organizer.webhooks" organizer=organizer.slug %}">
|
||||
{% trans "Webhooks" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% for nav in nav_organizer %}
|
||||
<li {% if nav.active %}class="active"{% endif %}>
|
||||
<a href="{{ nav.url }}">
|
||||
{{ nav.label }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
{% block inner %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% blocktrans with name=organizer.name %}Organizer: {{ name }}{% endblocktrans %}
|
||||
</h1>
|
||||
{% if events|length == 0 %}
|
||||
<p>
|
||||
<em>{% trans "You currently do not have access to any events." %}</em>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<legend>{% trans "Connect to device:" %} {{ device.name }}</legend>
|
||||
<h1>{% trans "Connect to device:" %} {{ device.name }}</h1>
|
||||
|
||||
<div>
|
||||
<ol>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
{% if device %}
|
||||
<legend>{% trans "Device:" %} {{ device.name }}</legend>
|
||||
<h1>{% trans "Device:" %} {{ device.name }}</h1>
|
||||
{% else %}
|
||||
<legend>{% trans "Connect a new device" %}</legend>
|
||||
<h1>{% trans "Connect a new device" %}</h1>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% if device %}
|
||||
|
||||
@@ -2,20 +2,20 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h2>{% trans "Revoke device access:" %} {{ device.name }}</h2>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<strong>{% blocktrans %}Are you sure you want remove access for this device?{% endblocktrans %}</strong>
|
||||
{% trans "All data of this device will stay available, but you can't use the device any more." %}
|
||||
</p>
|
||||
<div class="form-group submit-group">
|
||||
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug%}" class="btn btn-default btn-cancel">
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger btn-save">
|
||||
{% trans "Revoke" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<h1>{% trans "Revoke device access:" %} {{ device.name }}</h1>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
<p>
|
||||
<strong>{% blocktrans %}Are you sure you want remove access for this device?{% endblocktrans %}</strong>
|
||||
{% trans "All data of this device will stay available, but you can't use the device any more." %}
|
||||
</p>
|
||||
<div class="form-group submit-group">
|
||||
<a href="{% url "control:organizer.devices" organizer=request.organizer.slug %}" class="btn btn-default btn-cancel">
|
||||
{% trans "Cancel" %}
|
||||
</a>
|
||||
<button type="submit" class="btn btn-danger btn-save">
|
||||
{% trans "Revoke" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<legend>
|
||||
<h1>
|
||||
{% trans "Connected devices" %}
|
||||
</legend>
|
||||
</h1>
|
||||
<div class="alert alert-info">
|
||||
{% blocktrans trimmed %}
|
||||
This menu allows you to connect hardware devices such as box office terminals or scanning terminals to
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "Display settings" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
{% load formset_tags %}
|
||||
{% block title %}{% trans "Organizer" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Organizer" %}</h1>
|
||||
<h1>
|
||||
{% blocktrans with name=organizer.name %}Organizer settings{% endblocktrans %}
|
||||
{% if request.user.is_staff and staff_session %}
|
||||
<a href="{% url "control:organizer.delete" organizer=organizer.slug %}"
|
||||
class="btn btn-danger hidden-print">
|
||||
<span class="fa fa-trash"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h2>{% trans "Delete team:" %} {{ team.name }}</h2>
|
||||
<h1>{% trans "Delete team:" %} {{ team.name }}</h1>
|
||||
{% if not possible %}
|
||||
<p>{% blocktrans %}You cannot delete the team because there would be no one left who could change team permissions afterwards.{% endblocktrans %}</p>
|
||||
<div class="form-group submit-group">
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
{% if team %}
|
||||
<h2>{% trans "Team:" %} {{ team.name }}</h2>
|
||||
<h1>{% trans "Team:" %} {{ team.name }}</h1>
|
||||
{% else %}
|
||||
<h2>{% trans "Create a new team" %}</h2>
|
||||
<h1>{% trans "Create a new team" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You will be able to add team members in the next step.
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h2>
|
||||
<h1>
|
||||
{% trans "Team:" %} {{ team.name }}
|
||||
<a href="{% url "control:organizer.team.edit" organizer=organizer.slug team=team.pk %}"
|
||||
class="btn btn-default">
|
||||
<span class="fa fa-edit"></span>
|
||||
{% trans "Edit" %}
|
||||
</a>
|
||||
</h2>
|
||||
</h1>
|
||||
<h3>{% trans "Team members" %}</h3>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<h1>{% trans "Teams" %}</h1>
|
||||
<p>
|
||||
{% trans "The list below shows all teams that exist within this organizer." %}
|
||||
</p>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
{% if webhook %}
|
||||
<legend>{% trans "Modify webhook" %}</legend>
|
||||
<h1>{% trans "Modify webhook" %}</h1>
|
||||
{% else %}
|
||||
<legend>{% trans "Create a new webhook" %}</legend>
|
||||
<h1>{% trans "Create a new webhook" %}</h1>
|
||||
{% endif %}
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<legend>{% blocktrans with url=webhook.target_url %}Logs for webhook {{ url }}{% endblocktrans %}</legend>
|
||||
<h1>{% blocktrans with url=webhook.target_url %}Logs for webhook {{ url }}{% endblocktrans %}</h1>
|
||||
<p>
|
||||
{% trans "This page shows all calls to your webhook in the past 30 days." %}
|
||||
</p>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inner %}
|
||||
<legend>
|
||||
<h1>
|
||||
{% trans "Webhooks" %}
|
||||
</legend>
|
||||
</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
This menu allows you to create webhooks to connect pretix to other online services.
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Vouchers" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Vouchers" %}</h1>
|
||||
<ul class="nav nav-pills">
|
||||
<li {% if "event.vouchers" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.vouchers' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "All vouchers" %}
|
||||
</a>
|
||||
</li>
|
||||
<li {% if "event.vouchers.tags" == url_name %}class="active"{% endif %}>
|
||||
<a href="{% url 'control:event.vouchers.tags' organizer=request.event.organizer.slug event=request.event.slug %}">
|
||||
{% trans "Tags" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% block inside %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@@ -4,7 +4,7 @@
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Voucher" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Create multiple voucher" %}</h1>
|
||||
<h1>{% trans "Create multiple vouchers" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{% extends "pretixcontrol/vouchers/base.html" %}
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load urlreplace %}
|
||||
{% block title %}{% trans "Vouchers" %}{% endblock %}
|
||||
{% block inside %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Vouchers" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Vouchers allow you to assign tickets to specific persons for a lower price. They also enable you to
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{% extends "pretixcontrol/vouchers/base.html" %}
|
||||
{% extends "pretixcontrol/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block inside %}
|
||||
{% block title %}{% trans "Voucher tags" %}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>{% trans "Voucher tags" %}</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
If you add a "tag" to a voucher, you can here see statistics on their usage.
|
||||
|
||||
@@ -96,6 +96,7 @@ urlpatterns = [
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/delete$', organizer.TeamDeleteView.as_view(),
|
||||
name='organizer.team.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/slugrng', main.SlugRNG.as_view(), name='events.add.slugrng'),
|
||||
url(r'^nav/typeahead/$', typeahead.nav_context_list, name='nav.typeahead'),
|
||||
url(r'^events/$', main.EventList.as_view(), name='events'),
|
||||
url(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||
url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),
|
||||
|
||||
@@ -46,7 +46,6 @@ from pretix.control.forms.event import (
|
||||
TicketSettingsForm, WidgetCodeForm,
|
||||
)
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.signals import nav_event_settings
|
||||
from pretix.helpers.database import rolledback_transaction
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
from pretix.multidomain.urlreverse import get_domain
|
||||
@@ -60,12 +59,7 @@ from ..logdisplay import OVERVIEW_BLACKLIST
|
||||
class EventSettingsViewMixin:
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['nav_event_settings'] = []
|
||||
ctx['is_event_settings'] = True
|
||||
|
||||
for recv, retv in nav_event_settings.send(sender=self.request.event, request=self.request):
|
||||
ctx['nav_event_settings'] += retv
|
||||
ctx['nav_event_settings'].sort(key=lambda n: n['label'])
|
||||
return ctx
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,55 @@ from pretix.helpers.daterange import daterange
|
||||
from pretix.helpers.i18n import i18ncomp
|
||||
|
||||
|
||||
def serialize_user(u):
|
||||
return {
|
||||
'id': u.pk,
|
||||
'type': 'user',
|
||||
'name': str(u),
|
||||
'text': str(u),
|
||||
'url': reverse('control:index')
|
||||
}
|
||||
|
||||
|
||||
def serialize_orga(o):
|
||||
return {
|
||||
'id': o.pk,
|
||||
'slug': o.slug,
|
||||
'type': 'organizer',
|
||||
'name': str(o.name),
|
||||
'text': str(o.name),
|
||||
'url': reverse('control:organizer', kwargs={
|
||||
'organizer': o.slug
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
def serialize_event(e):
|
||||
dr = e.get_date_range_display()
|
||||
if e.has_subevents:
|
||||
if e.min_from is None:
|
||||
dr = pgettext('subevent', 'No dates')
|
||||
else:
|
||||
tz = pytz.timezone(e.settings.timezone)
|
||||
dr = _('Series:') + ' ' + daterange(
|
||||
e.min_from.astimezone(tz),
|
||||
(e.max_fromto or e.max_to or e.max_from).astimezone(tz)
|
||||
)
|
||||
return {
|
||||
'id': e.pk,
|
||||
'slug': e.slug,
|
||||
'type': 'event',
|
||||
'organizer': str(e.organizer.name),
|
||||
'name': str(e.name),
|
||||
'text': str(e.name),
|
||||
'date_range': dr,
|
||||
'url': reverse('control:event.index', kwargs={
|
||||
'event': e.slug,
|
||||
'organizer': e.organizer.slug
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
def event_list(request):
|
||||
query = request.GET.get('query', '')
|
||||
try:
|
||||
@@ -35,37 +84,12 @@ def event_list(request):
|
||||
order_from=Coalesce('min_from', 'date_from'),
|
||||
).order_by('-order_from')
|
||||
|
||||
def serialize(e):
|
||||
|
||||
dr = e.get_date_range_display()
|
||||
if e.has_subevents:
|
||||
if e.min_from is None:
|
||||
dr = pgettext('subevent', 'No dates')
|
||||
else:
|
||||
tz = pytz.timezone(e.settings.timezone)
|
||||
dr = _('Series:') + ' ' + daterange(
|
||||
e.min_from.astimezone(tz),
|
||||
(e.max_fromto or e.max_to or e.max_from).astimezone(tz)
|
||||
)
|
||||
return {
|
||||
'id': e.pk,
|
||||
'slug': e.slug,
|
||||
'organizer': str(e.organizer.name),
|
||||
'name': str(e.name),
|
||||
'text': str(e.name),
|
||||
'date_range': dr,
|
||||
'url': reverse('control:event.index', kwargs={
|
||||
'event': e.slug,
|
||||
'organizer': e.organizer.slug
|
||||
})
|
||||
}
|
||||
|
||||
total = qs.count()
|
||||
pagesize = 20
|
||||
offset = (page - 1) * pagesize
|
||||
doc = {
|
||||
'results': [
|
||||
serialize(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
||||
serialize_event(e) for e in qs.select_related('organizer')[offset:offset + pagesize]
|
||||
],
|
||||
'pagination': {
|
||||
"more": total >= (offset + pagesize)
|
||||
@@ -74,6 +98,51 @@ def event_list(request):
|
||||
return JsonResponse(doc)
|
||||
|
||||
|
||||
def nav_context_list(request):
|
||||
query = request.GET.get('query', '')
|
||||
try:
|
||||
page = int(request.GET.get('page', '1'))
|
||||
except ValueError:
|
||||
page = 1
|
||||
|
||||
qs_events = request.user.get_events_with_any_permission(request).filter(
|
||||
Q(name__icontains=i18ncomp(query)) | Q(slug__icontains=query)
|
||||
).annotate(
|
||||
min_from=Min('subevents__date_from'),
|
||||
max_from=Max('subevents__date_from'),
|
||||
max_to=Max('subevents__date_to'),
|
||||
max_fromto=Greatest(Max('subevents__date_to'), Max('subevents__date_from'))
|
||||
).annotate(
|
||||
order_from=Coalesce('min_from', 'date_from'),
|
||||
).order_by('-order_from')
|
||||
|
||||
if request.user.has_active_staff_session(request.session.session_key):
|
||||
qs_orga = Organizer.objects.all()
|
||||
else:
|
||||
qs_orga = Organizer.objects.filter(pk__in=request.user.teams.values_list('organizer', flat=True))
|
||||
if query:
|
||||
qs_orga = qs_orga.filter(Q(name__icontains=query) | Q(slug__icontains=query))
|
||||
|
||||
show_user = not query or query.lower() in request.user.email.lower() or query.lower() in request.user.fullname.lower()
|
||||
total = qs_events.count() + qs_orga.count()
|
||||
pagesize = 20
|
||||
offset = (page - 1) * pagesize
|
||||
results = ([
|
||||
serialize_user(request.user)
|
||||
] if show_user else []) + [
|
||||
serialize_orga(e) for e in qs_orga[offset:offset + (pagesize if query else 5)]
|
||||
] + [
|
||||
serialize_event(e) for e in qs_events.select_related('organizer')[offset:offset + (pagesize if query else 5)]
|
||||
]
|
||||
doc = {
|
||||
'results': results,
|
||||
'pagination': {
|
||||
"more": total >= (offset + pagesize)
|
||||
}
|
||||
}
|
||||
return JsonResponse(doc)
|
||||
|
||||
|
||||
@event_permission_required(None)
|
||||
def subevent_select2(request, **kwargs):
|
||||
query = request.GET.get('query', '')
|
||||
|
||||
Reference in New Issue
Block a user