Skip to content

Commit

Permalink
Eventyay Common: Create an event dashboard (#505)
Browse files Browse the repository at this point in the history
* Add dashboard eventyay common

* Add custom css

* Change background

* Add component link for eventyay_common

* Update css style

* Fix isort

* Add custom style

* Add alert pop up, add line break

* Resolve conversation: update template url

* Refactor code eventyay_common

* Refactor context and navigation

* Add missing url return

* Fix css error

* Update tickets text

* Resolve conversations

* Fix isort warning

* Update modal

* Fix urljoin
  • Loading branch information
HungNgien authored Jan 20, 2025
1 parent 9efdd17 commit c361ed5
Show file tree
Hide file tree
Showing 16 changed files with 801 additions and 135 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{% 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">
<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">
<a href="{{ request.event.talk_dashboard_url }}" class="header-nav btn btn-outline-success">
<i class="fa fa-group"></i> {% trans "Talk" %}
</a>
{% endif %}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
{% load i18n %}
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Event organizer" %}
</h3>
</div>
<div class="panel-body timeline">
<div class="info-row">
{% trans "This event is organized by" %} <strong><a href="{% url 'control:organizer' request.organizer.slug %}">{{ request.organizer }}</a></strong>
<div class="panel panel-default items widget-container widget-small no-padding last-column">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Event organizer" %}
</h3>
</div>
<div class="info-row">
{% trans "Teams of the organizer are" %}
<span></span>
{% for id, name in organizer_teams %}
<strong><a href="{% url 'control:organizer.team' request.organizer.slug id %}">{{ name }}</a></strong>
{% if not forloop.last %}, {% endif %}
{% endfor %}
<div class="panel-body timeline overide-panel-body">
<div class="info-row">
{% trans "This event is organized by" %} <strong><a href="{% url 'control:organizer' request.organizer.slug %}">{{ request.organizer }}</a></strong>
</div>
<div class="info-row">
{% trans "Teams of the organizer are" %}
<span></span>
{% for id, name in organizer_teams %}
<strong><a href="{% url 'control:organizer.team' request.organizer.slug id %}">{{ name }}</a></strong>
{% if not forloop.last %}, {% endif %}
{% endfor %}
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
{% load i18n %}
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Your timeline" %}
</h3>
</div>
<div class="panel-body timeline">
{% regroup timeline by date as tl_list %}
{% for day in tl_list %}
<div class="row {% if day.grouper < today %}text-muted{% endif %}">
<div class="col-date">
<strong>{{ day.grouper|date:"SHORT_DATE_FORMAT" }}</strong>
</div>
<div class="col-event">
{% for e in day.list %}
<strong class="">{{ e.time|date:"TIME_FORMAT" }}</strong>
&nbsp;
<span class="{% if e.time < nearly_now %}text-muted{% endif %}">
{{ e.entry.description }}
</span>
{% if e.entry.edit_url %}
<div class="panel panel-default items widget-container widget-small no-padding column">
<div class="panel-heading">
<h3 class="panel-title">
{% trans "Your timeline" %}
</h3>
</div>
<div class="panel-body timeline overide-panel-body">
{% regroup timeline by date as tl_list %}
{% for day in tl_list %}
<div class="row {% if day.grouper < today %}text-muted{% endif %}">
<div class="col-date">
<strong>{{ day.grouper|date:"SHORT_DATE_FORMAT" }}</strong>
</div>
<div class="col-event">
{% for e in day.list %}
<strong class="">{{ e.time|date:"TIME_FORMAT" }}</strong>
&nbsp;
<a href="{{ e.entry.edit_url }}" class="text-muted">
<span class="fa fa-edit"></span>
</a>
{% endif %}
{% if forloop.revcounter > 1 %}
<br/>
{% endif %}
{% endfor %}
<span class="{% if e.time < nearly_now %}text-muted{% endif %}">
{{ e.entry.description }}
</span>
{% if e.entry.edit_url %}
&nbsp;
<a href="{{ e.entry.edit_url }}" class="text-muted">
<span class="fa fa-edit"></span>
</a>
{% endif %}
{% if forloop.revcounter > 1 %}
<br/>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
8 changes: 2 additions & 6 deletions src/pretix/control/templates/pretixcontrol/event/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,9 @@ <h3 class="panel-title">
{% endif %}
<div class="dashboard custom">
{% if not request.event.has_subevents or subevent %}
<div class="panel panel-default items widget-container widget-small no-padding column"">
{% include "pretixcontrol/event/fragment_timeline.html" %}
</div>
{% include "pretixcontrol/event/fragment_timeline.html" %}
{% endif %}
<div class="panel panel-default items widget-container widget-small no-padding last-column"">
{% include "pretixcontrol/event/fragment_info_box.html" %}
</div>
{% include "pretixcontrol/event/fragment_info_box.html" %}
</div>
<div class="dashboard">
{% for w in widgets %}
Expand Down
164 changes: 93 additions & 71 deletions src/pretix/eventyay_common/context.py
Original file line number Diff line number Diff line change
@@ -1,98 +1,120 @@
from importlib import import_module
import logging
from urllib.parse import urljoin

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.http import HttpRequest
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,
)

SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
from ..helpers.plugin_enable import is_video_enabled
from ..multidomain.urlreverse import get_event_domain
from .views.event import EventCreatedFor

logger = logging.getLogger(__name__)

def contextprocessor(request):
"""
Adds data to all template contexts
"""
if not hasattr(request, '_eventyay_common_default_context'):

def contextprocessor(request: HttpRequest):
if not hasattr(request, "_eventyay_common_default_context"):
request._eventyay_common_default_context = _default_context(request)
return request._eventyay_common_default_context


def _default_context(request):
def _default_context(request: HttpRequest):
try:
url = resolve(request.path_info)
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,
"url_name": url.url_name,
"settings": settings,
"django_settings": settings,
"DEBUG": settings.DEBUG,
"talk_hostname": settings.TALK_HOSTNAME,
}
if getattr(request, 'event', None) and hasattr(request, 'organizer') and request.user.is_authenticated:
ctx['nav_items'] = get_global_navigation(request)

elif request.user.is_authenticated:
ctx['nav_items'] = get_global_navigation(request)

gs = GlobalSettingsObject()
ctx['global_settings'] = gs.settings

if request.user.is_authenticated:
ctx['staff_session'] = request.user.has_active_staff_session(request.session.session_key)
ctx['staff_need_to_explain'] = (
StaffSession.objects.filter(user=request.user, date_end__isnull=False).filter(
Q(comment__isnull=True) | Q(comment="")
ctx["global_settings"] = gs.settings

if not request.user.is_authenticated:
return ctx

ctx["nav_items"] = get_global_navigation(request)
ctx["staff_session"] = request.user.has_active_staff_session(
request.session.session_key
)
ctx["staff_need_to_explain"] = (
StaffSession.objects.filter(user=request.user, date_end__isnull=False).filter(
Q(comment__isnull=True) | Q(comment="")
)
if request.user.is_staff and settings.PRETIX_ADMIN_AUDIT_COMMENTS
else StaffSession.objects.none()
)

# Verify if the request includes an event
event = getattr(request, "event", None)
if not event:
return ctx

ctx["talk_edit_url"] = urljoin(settings.TALK_HOSTNAME, f"orga/event/{event.slug}")
ctx["is_video_enabled"] = is_video_enabled(event)
ctx["is_talk_event_created"] = False
if (
event.settings.create_for == EventCreatedFor.BOTH.value
or event.settings.talk_schedule_public is not None
):
ctx["is_talk_event_created"] = True

# Verify if the request includes an organizer
organizer = getattr(request, "organizer", None)
if not organizer:
return ctx

ctx["nav_items"] = get_event_navigation(request, event)
ctx["has_domain"] = get_event_domain(event, fallback=True) is not None
if not event.testmode:
with scope(organizer=organizer):
complain_testmode_orders = event.cache.get("complain_testmode_orders")
if complain_testmode_orders is None:
complain_testmode_orders = event.orders.filter(testmode=True).exists()
event.cache.set(
"complain_testmode_orders", complain_testmode_orders, 30
)
ctx["complain_testmode_orders"] = (
complain_testmode_orders
and request.user.has_event_permission(
organizer, event, "can_view_orders", request=request
)
if request.user.is_staff and settings.PRETIX_ADMIN_AUDIT_COMMENTS else StaffSession.objects.none()
)

ctx['talk_hostname'] = settings.TALK_HOSTNAME
else:
ctx["complain_testmode_orders"] = False

if not event.live and ctx["has_domain"]:
child_sess_key = f"child_session_{event.pk}"
child_sess = request.session.get(child_sess_key)

if not child_sess:
request.session[child_sess_key] = request.session.session_key
else:
ctx["new_session"] = child_sess
request.session["event_access"] = True

if request.GET.get("subevent", ""):
subevent_id = request.GET.get("subevent", "").strip()
try:
pk = int(subevent_id)
# Do not use .get() for lazy evaluation
ctx["selected_subevents"] = event.subevents.filter(pk=pk)
except ValueError as e:
logger.error("Error parsing subevent ID: %s", e)

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
Loading

0 comments on commit c361ed5

Please sign in to comment.