Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eventyay Common: Create an event dashboard #484

Open
wants to merge 9 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{% load i18n %}
<div class="navigation-button">
{% if request.organizer and request.event %}
<a href='{% url "eventyay_common:event.update" organizer=request.organizer.slug event=request.event.slug %}' class="header-nav btn btn-outline-success">
<a href='{% url "eventyay_common:event.index" organizer=request.organizer.slug event=request.event.slug %}' class="header-nav btn btn-outline-success">
<i class="fa fa-home"></i> {% trans "Home" %}
</a>
<a href="#" class="header-nav btn btn-outline-success active">
Expand Down
103 changes: 58 additions & 45 deletions src/pretix/eventyay_common/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

from django.conf import settings
from django.db.models import Q
from django.urls import Resolver404, get_script_prefix, resolve, reverse
from django.utils.translation import gettext_lazy as _
from django.urls import Resolver404, get_script_prefix, resolve
from django_scopes import scope

from pretix.base.models.auth import StaffSession
from pretix.base.settings import GlobalSettingsObject
from pretix.control.navigation import merge_in
from pretix.control.signals import nav_global
from pretix.eventyay_common.navigation import (
get_event_navigation, get_global_navigation,
)

from ..helpers.plugin_enable import is_video_enabled
from ..multidomain.urlreverse import get_event_domain
from .views.event import EventCreatedFor

SessionStore = import_module(settings.SESSION_ENGINE).SessionStore

Expand All @@ -28,16 +33,63 @@ def _default_context(request):
except Resolver404:
return {}

if not request.path.startswith(get_script_prefix() + 'common'):
if not request.path.startswith(f'{get_script_prefix()}common'):
return {}
ctx = {
'url_name': url.url_name,
'settings': settings,
'django_settings': settings,
'DEBUG': settings.DEBUG,
}

if hasattr(request, 'event') and request.user.is_authenticated:
ctx["talk_edit_url"] = (
settings.TALK_HOSTNAME + "/orga/event/" + request.event.slug
)
ctx['is_video_enabled'] = is_video_enabled(request.event)
ctx["is_talk_event_created"] = False
if (
request.event.settings.create_for == EventCreatedFor.BOTH.value
or request.event.settings.talk_schedule_public is not None
):
ctx["is_talk_event_created"] = True

if getattr(request, 'event', None) and hasattr(request, 'organizer') and request.user.is_authenticated:
ctx['nav_items'] = get_global_navigation(request)
ctx['is_video_enabled'] = is_video_enabled(request.event)
ctx["is_talk_event_created"] = False
if (
request.event.settings.create_for == EventCreatedFor.BOTH.value
or request.event.settings.talk_schedule_public is not None
):
ctx["is_talk_event_created"] = True

ctx['nav_items'] = get_event_navigation(request)
ctx['has_domain'] = get_event_domain(request.event, fallback=True) is not None
if not request.event.testmode:
with scope(organizer=request.organizer):
complain_testmode_orders = request.event.cache.get('complain_testmode_orders')
if complain_testmode_orders is None:
complain_testmode_orders = request.event.orders.filter(testmode=True).exists()
request.event.cache.set('complain_testmode_orders', complain_testmode_orders, 30)
ctx['complain_testmode_orders'] = complain_testmode_orders and request.user.has_event_permission(
request.organizer, request.event, 'can_view_orders', request=request
)
else:
ctx['complain_testmode_orders'] = False
if not request.event.live and ctx['has_domain']:
child_sess = request.session.get(f'child_session_{request.event.pk}')
s = SessionStore()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why you access the session this way, whereas the request is already available.

Note that, the documentation says that this way is for the code outside a view, like in Django commands, in background job, in unittest, etc...
But this code has request, meaning it is inside a view.

if not child_sess or not s.exists(child_sess):
s[f'pretix_event_access_{request.event.pk}'] = request.session.session_key
s.create()
ctx['new_session'] = s.session_key
request.session[f'child_session_{request.event.pk}'] = s.session_key
else:
ctx['new_session'] = child_sess
request.session['event_access'] = True
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 request.user.is_authenticated:
ctx['nav_items'] = get_global_navigation(request)
Expand All @@ -57,42 +109,3 @@ def _default_context(request):
ctx['talk_hostname'] = settings.TALK_HOSTNAME

return ctx


def get_global_navigation(request):
url = request.resolver_match
if not url:
return []
nav = [
{
'label': _('Dashboard'),
'url': reverse('eventyay_common:dashboard'),
'active': (url.url_name == 'dashboard'),
'icon': 'dashboard',
},
{
'label': _('My Events'),
'url': reverse('eventyay_common:events'),
'active': 'events' in url.url_name,
'icon': 'calendar',
},
{
'label': _('Organizers'),
'url': reverse('eventyay_common:organizers'),
'active': 'organizers' in url.url_name,
'icon': 'group',
},
{
'label': _('Account'),
'url': reverse('eventyay_common:account'),
'active': 'account' in url.url_name,
'icon': 'user',
}

]

merge_in(nav, sorted(
sum((list(a[1]) for a in nav_global.send(request, request=request)), []),
key=lambda r: (1 if r.get('parent') else 0, r['label'])
))
return nav
80 changes: 80 additions & 0 deletions src/pretix/eventyay_common/navigation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from django.http import HttpRequest
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from pretix.control.navigation import merge_in
from pretix.control.signals import nav_event, nav_global


def get_global_navigation(request):
url = request.resolver_match
if not url:
return []
request.user.has_active_staff_session(request.session.session_key)
nav = [
{
'label': _('Dashboard'),
'url': reverse('eventyay_common:dashboard'),
'active': (url.url_name == 'dashboard'),
'icon': 'dashboard',
},
{
'label': _('My Events'),
'url': reverse('eventyay_common:events'),
'active': 'events' in url.url_name,
'icon': 'calendar',
},
{
'label': _('Organizers'),
'url': reverse('eventyay_common:organizers'),
'active': 'organizers' in url.url_name,
'icon': 'group',
},
{
'label': _('Account'),
'url': reverse('eventyay_common:account'),
'active': 'account' in url.url_name,
'icon': 'user',
}

]

merge_in(nav, sorted(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this code tested? It looks weird because:

  • sorted() requires the 1st argument to be iterable, but you pass a scalar value.
  • sum() accepts only one positional parameter, the 2nd parameter must be keyword one, but you pass two positional ones.

sum((list(a[1]) for a in nav_global.send(request, request=request)), []),
key=lambda r: (1 if r.get('parent') else 0, r['label'])
))
return nav


def get_event_navigation(request: HttpRequest):
url = request.resolver_match
if not url:
return []
request.user.has_active_staff_session(request.session.session_key)
nav = [
{
'label': _('Dashboard'),
'url': reverse('eventyay_common:event.index', kwargs={
'event': request.event.slug,
'organizer': request.event.organizer.slug,
}),
'active': (url.url_name == 'event.index'),
'icon': 'dashboard',
},
{
'label': _('Settings'),
'url': reverse('eventyay_common:event.update', kwargs={
'event': request.event.slug,
'organizer': request.event.organizer.slug,
}),
'active': (url.url_name == 'event.update'),
'icon': 'wrench',
}
]

merge_in(nav, sorted(
sum((list(a[1]) for a in nav_event.send(request.event, request=request)), []),
key=lambda r: (1 if r.get('parent') else 0, r['label'])
))

return nav
37 changes: 37 additions & 0 deletions src/pretix/eventyay_common/templates/eventyay_common/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,43 @@
</ul>
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-nav-collapse navbar-collapse">
<div class="dropdown context-selector">
{% block nav_top_header %}
{% if request.event %}
<a href="#" class="dropdown-toggle">
<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>
</a>
{% elif request.organizer %}
<a href="#" class="dropdown-toggle">
<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>
</a>
{% else %}
<a href="#" class="dropdown-toggle">
<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>
</a>
{% endif %}
{% endblock %}
</div>
<ul class="nav" id="side-menu">
{% block nav %}
{% for nav in nav_items %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% load i18n %}
<div class="navigation-button">
{% if request.organizer and request.event %}
<a href="#" class="header-nav btn btn-outline-success active">
<i class="fa fa-home"></i> {% trans "Home" %}
</a>
<a href='{% url "control:event.index" organizer=request.organizer.slug event=request.event.slug %}' class="header-nav btn btn-outline-success">
<i class="fa fa-ticket"></i> {% trans "Tickets" %}
</a>
{% if is_talk_event_created %}
<a href="{{ talk_edit_url }}" class="header-nav btn btn-outline-success">
<i class="fa fa-group"></i> {% trans "Talk" %}
</a>
{% endif %}
{% if is_video_enabled %}
<a class="header-nav btn btn-outline-success"
href='{% url "eventyay_common:event.create_access_to_video" organizer=request.organizer.slug event=request.event.slug %}'
title="{% trans 'Access videos related to this event' %}">
<i class="fa fa-video-camera"></i> {% trans "Videos" %}
</a>
{% endif %}
{% endif %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{% load i18n %}
<div class="dashboard custom">
<div class="panel panel-default items widget-container widget-full no-padding">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Your Dashboard" %}
</h3>
</div>
<div class="panel-body">
<p>
{% trans "Your event dashboard offers an overview of three seamlessly integrated components, each customizable to meet your needs: Tickets for sales and registration management, Talks and Speakers for organizing content and creating schedules, and Video for hosting engaging and interactive virtual events with live interpretation." %}
</p>
</div>
</div>

<div class="panel panel-default widget-container widget-small no-padding column">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Tickets" %}
</h3>
</div>
<div class="panel-body">
<p>
{% trans "Set up and configure ticketing for your event and sell add-ons such as premium access or Swag Manage attendees and exhibitors, design custom badges, and streamline your event marketing by sending targeted emails." %}
</p>
<p>
{% trans "Go to" %} <a href="{% url 'control:event.index' organizer=request.organizer.slug event=request.event.slug %}">{% trans "Tickets Dashboard" %}</a>
</p>
</div>
</div>
<div class="panel panel-default widget-container widget-small no-padding column">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Talks and Speakers" %}
</h3>
</div>
<div class="panel-body">
<p>
{% trans "Setup and configure content for your event, create calls for proposals and speakers and build a schedule. Manage the submission and review process, and select speakers." %}
</p>
{% if is_talk_event_created %}
<p>
{% trans "Go to" %} <a href="{{ talk_edit_url }}">{% trans "Talks Dashboard" %}</a>
</p>
{% else %}
<p>
{% trans "Go to" %} <a href="#" data-toggle="modal" data-target="#alert-modal">{% trans "Talks Dashboard" %}</a>
</p>
{% endif %}
</div>
</div>
<div class="panel panel-default widget-container widget-small no-padding last-column">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Video" %}
</h3>
</div>
<div class="panel-body">
<p>
{% trans "Setup and configure live video streams, online workshops with live-audio interpretation and chats. Offer virtual exhibitor booths with rich content and social media integration." %}
</p>
{% if is_video_enabled %}
<p>
{% trans "Go to" %} <a href="{% url 'eventyay_common:event.create_access_to_video' organizer=request.organizer.slug event=request.event.slug %}">{% trans "Video Configuration" %}</a>
</p>
{% else %}
<p>
{% trans "Go to" %} <a href="#" data-toggle="modal" data-target="#alert-modal">{% trans "Video Configuration" %}</a>
</p>
{% endif %}
</div>
</div>
<div class="modal fade" id="alert-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header bg-danger">
<h3 class="modal-title text-center text-danger">{% trans "Alert" %}</h3>
</div>
<div class="modal-body">
<div class="text-center">
<p>
You need to enable this component first.
</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{% trans "Close" %}</button>
</div>
</div>
</div>
</div>
</div>
Loading
Loading