Skip to content

Commit

Permalink
participant register and kick
Browse files Browse the repository at this point in the history
  • Loading branch information
deawer234 committed Dec 6, 2023
1 parent 6f89205 commit 32fdbff
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 49 deletions.
4 changes: 2 additions & 2 deletions fiesta/apps/events/models/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Participant(BaseModel):

user = models.ForeignKey(
to="accounts.User",
related_name="participants",
related_name="event_participants",
on_delete=models.SET_NULL,
null=True,
db_index=True,
Expand All @@ -26,7 +26,7 @@ class Participant(BaseModel):
event = models.ForeignKey(
to="events.Event",
on_delete=models.SET_NULL,
related_name="participants",
related_name="event_participants",
null=True,
db_index=True,
verbose_name=_("event"),
Expand Down
47 changes: 29 additions & 18 deletions fiesta/apps/events/templates/events/event_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ <h1 class="card-title text-base-content"> Organizers </h1>

<div class="card-actions justify-end">

<select name="role" hx-post="{% url 'events:role-change' pk=event.pk pko=oc.pk %}" hx-trigger="change" hx-swap="none">
<select class="select select-bordered max-w-xs" name="role" hx-post="{% url 'events:role-change' pk=event.pk pko=oc.pk %}" hx-trigger="change" hx-swap="none">
{% for role_value, role_display in organizer_roles %}
<option value="{{ role_value }}" {% if oc.role == role_value %}selected{% endif %}>
{{ role_display }}
Expand All @@ -124,14 +124,13 @@ <h1 class="card-title text-base-content"> Organizers </h1>
{% endfor %}
</ul>
</div>

<div class="card-actions justify-end">
<a class="btn btn-primary btn-outline"
x-data="modal($el.href)"
x-bind="bind"
href="{% url "events:organizer-add" event.pk%}">{% trans "Add organizer" %}</a>
</div>
{% endif %}
<div class="card-actions justify-end">
<a class="btn btn-primary btn-outline"
x-data="modal($el.href)"
x-bind="bind"
href="{% url "events:organizer-add" event.pk%}">{% trans "Add organizer" %}</a>
</div>
</div>
</div>

Expand All @@ -142,7 +141,11 @@ <h1 class="card-title text-base-content"> Organizers </h1>
<h1 class="card-title text-base-content"> Event </h1>
<div class="card-actions justify-end">
<a href="{% url "events:participants" event.id %}" class="btn btn-primary btn-outline">{% translate "Show participants" %}</a>
<a href="{% url "events:event-update" event.id %}" class="btn btn-primary btn-outline">{% translate "Update event" %}</a>
<a href="{% url "events:event-update" event.id %}" class="btn btn-warning btn-outline">{% translate "Update event" %}</a>
<form action="{% url "events:event-delete" event.id %}" method="post" hx-confirm="Are you sure you want to delete the event ?">
{% csrf_token %}
<button type="submit" class="btn btn-danger btn-outline" >{% translate "Delete event" %}</button>
</form>
</div>
</div>
</div>
Expand Down Expand Up @@ -191,12 +194,16 @@ <h1 class="card-title text-base-content">{{ event.title }}</h1>


{% if request.membership.is_international %}
<form action="{% url "events:event-register" event.id %}", method="post">
{% csrf_token %}
<button type="submit">Register</button>
</form>

<a class="btn btn-primary btn-outline"
hx-post="{% url "events:event-register" event.pk %}"
hx-target="#response"
hx-indicator="#loading"
hx-swap="outerHTML">
{%translate "Register"%}
</a>
<div id="response"></div>
{% endif %}


</div>
</div>
Expand Down Expand Up @@ -249,10 +256,14 @@ <h1 class="card-title text-base-content">{{ event.title }}</h1>


{% if request.membership.is_international %}
<form action="{% url "events:event-register" event.id %}", method="post">
{% csrf_token %}
<button type="submit">Register</button>
</form>
<a class="btn btn-primary btn-outline"
hx-post="{% url "events:event-register" event.pk %}"
hx-target="#response"
hx-indicator="#loading"
hx-swap="outerHTML">
{%translate "Register"%}
</a>
<div id="response"></div>
{% endif %}


Expand Down
8 changes: 4 additions & 4 deletions fiesta/apps/events/templates/events/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<div class="container mx-auto p-6">
<h1 class="text-3xl font-semibold mb-4">Your events</h1>
<ul class="divide-y divide-gray-300">
{% for participating in participations %}
{% with event=participating.event %}
{% include "events/parts/event_item.html"%}
{% endwith %}
{% for event in users_events %}

{% include "events/parts/event_item.html"%}

{% endfor %}
</ul>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% load i18n %}

<a href="#"
class="btn btn-sm btn-outline btn-primary"
hx-post="{% url "events:event-kick" pk=event.pk pkp=record.pk %}"
hx-confirm="Are you sure you want to kick this participant ?"
hx-swap="outerHTML">
{% translate "Kick" %}
</a>
12 changes: 7 additions & 5 deletions fiesta/apps/events/templatetags/event_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def show_participants(context, event: Event):
return event.participants.filter(state='confirmed')
return None


@register.simple_tag(takes_context=True)
def get_price_variants(context, event: Event):
request: HttpRequest = context["request"]
Expand All @@ -29,11 +30,11 @@ def get_price_variants(context, event: Event):

@register.simple_tag(takes_context=True)
def get_event_fullness(context, event: Event):
if event.participants.all().count() <= event.capacity:
if event.event_participants.all().count() <= event.capacity:
return 0
elif event.participants.all().count() < event.capacity & event.participants.all().count() > event.capacity/2:
elif event.event_participants.all().count() < event.capacity & event.participants.all().count() > event.capacity/2:
return 1
elif event.participants.all().count() >= event.capacity:
elif event.event_participants.all().count() >= event.capacity:
return 2

@register.simple_tag(takes_context=True)
Expand All @@ -54,9 +55,10 @@ def is_participant(context, event: Event) -> bool:
@register.simple_tag(takes_context=True)
def can_edit(context, event: Event) -> bool:
request: HttpRequest = context["request"]
return is_moc(context, event) or event.author == request.membership.user or request.membership.user.has_perm("events.change_event")
return is_moc(context, event) or event.author == request.membership.user or request.membership.is_privileged or request.membership.user.has_perm('events.change_event')

@register.simple_tag(takes_context=True)
def can_see_participants(context, event: Event) -> bool:
request: HttpRequest = context["request"]
return is_moc(context, event) or event.author == request.membership.user or request.membership.user.has_perm("events.change_event")
return is_moc(context, event) or event.author == request.membership.user or request.membership.is_privileged or request.membership.user.has_perm('events.change_event')

6 changes: 4 additions & 2 deletions fiesta/apps/events/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.urls import path

from .views import EventsIndexView
from .views.event import AddEventView, EventDetailView, ParticipantsView, UpdateEventView, EventParticipantRegister
from .views.event import AddEventView, EventDetailView, ParticipantsView, UpdateEventView, EventParticipantRegister, DeleteEventView, EventParticipantKick
from .views.organizer import AddOrganizerView, UpdateOrganizerRole, DeleteOrganizerView
from .views.price import AddPriceView, UpdatePriceView, DeletePriceView
from .views.place import PlaceView, AddPlaceView, UpdatePlaceView, DeletePlaceView
Expand All @@ -15,8 +15,9 @@
urlpatterns = [
path('', EventsIndexView.as_view(), name="index"),
path('add-event', AddEventView.as_view(), name="add-event"),
path('event-update/<uuid:pk>', UpdateEventView.as_view(), name="event-update"),
path('event-detail/update/<uuid:pk>', UpdateEventView.as_view(), name="event-update"),
path('event-detail/<uuid:pk>', EventDetailView.as_view(), name="event-detail"),
path('event-detail/delete/<uuid:pk>', DeleteEventView.as_view(), name="event-delete"),
path("event-detail/<uuid:pk>/participants", ParticipantsView.as_view(), name="participants"), # event-detail/<uuid:pk>/
path("event-detail/<uuid:pk>/organizers/<uuid:pko>", UpdateOrganizerRole.as_view(), name="role-change"), # event-detail/<uuid:pk>/
path("event-detail/<uuid:pk>/organizers/delete/<uuid:pko>", DeleteOrganizerView.as_view(), name="organizer-delete"), # event-detail/<uuid:pk>/
Expand All @@ -30,4 +31,5 @@
path("place/update/<uuid:pk>", UpdatePlaceView.as_view(), name="place-update"),
path("place/delete/<uuid:pk>", DeletePlaceView.as_view(), name="place-delete"),
path("event-detail/<uuid:pk>/register", EventParticipantRegister.as_view(), name="event-register"),
path("event-detail/<uuid:pk>/kick/<uuid:pkp>", EventParticipantKick.as_view(), name="event-kick")
]
106 changes: 92 additions & 14 deletions fiesta/apps/events/views/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
import django_filters
from django.contrib.postgres.search import SearchVector
from django.forms import TextInput
from django.views.generic import CreateView, DetailView, UpdateView, View
from django.views.generic import CreateView, DetailView, UpdateView, DeleteView, View
import django_tables2 as tables

from django.utils.translation import gettext_lazy as _
from django.urls import reverse
from django_filters import CharFilter, ChoiceFilter

from ..models import Participant, Organizer
from ..models import Participant, Organizer, PriceVariant
from ..models.event import Event
from apps.utils.views import AjaxViewMixin
from apps.fiestaforms.views.htmx import HtmxFormViewMixin
Expand All @@ -38,6 +38,7 @@
from ...utils.breadcrumbs import with_breadcrumb, with_plugin_home_breadcrumb, with_object_breadcrumb
from allauth.account.utils import get_next_redirect_url
from django.contrib.auth import REDIRECT_FIELD_NAME
import datetime



Expand Down Expand Up @@ -88,7 +89,7 @@ class UpdateEventView(

form_class = AddEventForm
template_name = "fiestaforms/pages/card_page_for_ajax_form.html"
ajax_template_name = "events/templates/parts/update_event_form.html"
ajax_template_name = "events/parts/update_event_form.html"

success_message = _("Event updated")

Expand All @@ -99,6 +100,7 @@ def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpRespo
def get_initial(self):
return dict(
section=self.request.in_space_of_section,
author=self.event.author
)

def get_object(self, queryset=None):
Expand All @@ -117,7 +119,20 @@ def get_context_data(self, **kwargs):
def get_success_url(self):
return reverse("events:event-detail", args=[self.object.id])

class DeleteEventView(
EnsurePrivilegedUserViewMixin,
EnsureInSectionSpaceViewMixin,
DeleteView,
HtmxFormViewMixin,
AjaxViewMixin,
SuccessMessageMixin):

def get_object(self, queryset=None) -> Event:
return get_object_or_404(Event, pk=self.kwargs.get("pk"))

def get_success_url(self):
return reverse("events:index")

@with_plugin_home_breadcrumb
@with_breadcrumb(_("Detail"))
class EventDetailView(
Expand Down Expand Up @@ -163,7 +178,14 @@ def filter_search(self, queryset, name, value):
return queryset.annotate(search=SearchVector("user__last_name", "user__first_name", "state")).filter(
search=value
)

class EventKickButtonColumn(tables.TemplateColumn):
def __init__(self, event, *args, **kwargs):
self.event = event
super().__init__(*args, **kwargs)

def render(self, record, *args, **kwargs):
return super().render(record, extra_context={'event': self.event}, *args, **kwargs)

class EventParticipantsTable(tables.Table):
created = tables.DateTimeColumn(
Expand All @@ -182,9 +204,9 @@ class EventParticipantsTable(tables.Table):
accessor="event.title",
attrs={"th": {"class": "text-center"}},
)
price__name = tables.Column(
price__amount = tables.Column(
verbose_name=_("Price"),
accessor="price.name",
accessor="price.amount",
attrs={"th": {"class": "text-center"}},
)
state = tables.Column(
Expand All @@ -193,6 +215,11 @@ class EventParticipantsTable(tables.Table):
order_by="state",
attrs={"th": {"class": "text-center"}},
)
kick_button = EventKickButtonColumn(
event=None,
template_name="events/parts/kick_participant_button.html",
attrs={"th": {"class": "text-center"}},
)

class Meta:
model = Participant
Expand All @@ -202,8 +229,9 @@ class Meta:
sequence = (
"user__full_name",
"event__title",
"price__name",
"state"
"price__amount",
"state",
"kick_button"
)

empty_text = _("There are no participants")
Expand All @@ -213,6 +241,11 @@ def render_created(self, value):

def render_price__name(self, value):
return str(value)

def __init__(self, *args, **kwargs):
event = kwargs.pop('event', None)
super().__init__(*args, **kwargs)
self.columns['kick_button'].event = event


@with_plugin_home_breadcrumb
Expand All @@ -232,7 +265,17 @@ class ParticipantsView(
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
self.event = get_object_or_404(Event, pk=self.kwargs.get("pk"))
return super().dispatch(request, *args, **kwargs)


def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context ['event'] = self.event
return context

def get_table_kwargs(self):
kwargs = super().get_table_kwargs()
kwargs['event'] = self.event
return kwargs

def get_queryset(self):
return self.request.in_space_of_section.events.get(id=self.event.pk).participants.filter(
state__in=(
Expand All @@ -245,14 +288,49 @@ def get_queryset(self):

class EventParticipantRegister(
EnsureInSectionSpaceViewMixin,
CreateView):

model = Participant
View):

def form_valid(self, form: BaseModelForm) -> HttpResponse:
model = Participant

def dispatch(self, request, *args, **kwargs):
self.event = get_object_or_404(Event, pk=self.kwargs.get("pk"))
return super().dispatch(request, *args, **kwargs)

def choose_price(self):
if PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.FREE).exists():
return PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.FREE).get()
elif self.request.user.is_esn_card_holder & PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.WITH_ESN_CARD).exists():
return PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.WITH_ESN_CARD).get()
elif PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.STANDARD).exists():
return PriceVariant.objects.filter(event=self.event, type=EventPriceVariantType.STANDARD).get()
return None

def post(self, request, *args, **kwargs):
if Participant.objects.filter(user=self.request.user, event=self.event).exists():
return HttpResponse("You are already registered for this event.")
if self.choose_price() is None:
return HttpResponse("You can't register for this event yet.")
Participant.objects.create(
created=datetime.datetime.now(),
user=self.request.user,

event=self.event,
price=self.choose_price()
)
return super().form_valid(form)
return HttpResponse("Sucsessfully registered for this event.")

class EventParticipantKick(
EnsurePrivilegedUserViewMixin,
EnsureInSectionSpaceViewMixin,
DeleteView):

model = Participant

def get_object(self, queryset= None):
return get_object_or_404(Participant, pk=self.kwargs.get("pkp"))

def get_success_url(self) -> str:
return reverse("events:participants", args=[self.kwargs.get("pk")])




Loading

0 comments on commit 32fdbff

Please sign in to comment.