bornhack-website/src/backoffice/views/facilities.py

321 lines
10 KiB
Python

import logging
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.forms import modelformset_factory
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.views.generic import DetailView, ListView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from leaflet.forms.widgets import LeafletWidget
from camps.mixins import CampViewMixin
from facilities.models import (
Facility,
FacilityFeedback,
FacilityOpeningHours,
FacilityType,
)
from teams.models import Team
from ..mixins import OrgaTeamPermissionMixin, RaisePermissionRequiredMixin
logger = logging.getLogger("bornhack.%s" % __name__)
class FacilityTypeListView(CampViewMixin, OrgaTeamPermissionMixin, ListView):
model = FacilityType
template_name = "facility_type_list_backoffice.html"
context_object_name = "facility_type_list"
class FacilityTypeCreateView(CampViewMixin, OrgaTeamPermissionMixin, CreateView):
model = FacilityType
template_name = "facility_type_form.html"
fields = [
"name",
"description",
"icon",
"marker",
"responsible_team",
"quickfeedback_options",
]
def get_context_data(self, **kwargs):
"""
Do not show teams that are not part of the current camp in the dropdown
"""
context = super().get_context_data(**kwargs)
context["form"].fields["responsible_team"].queryset = Team.objects.filter(
camp=self.camp
)
return context
def get_success_url(self):
return reverse(
"backoffice:facility_type_list", kwargs={"camp_slug": self.camp.slug}
)
class FacilityTypeUpdateView(CampViewMixin, OrgaTeamPermissionMixin, UpdateView):
model = FacilityType
template_name = "facility_type_form.html"
fields = [
"name",
"description",
"icon",
"marker",
"responsible_team",
"quickfeedback_options",
]
def get_context_data(self, **kwargs):
"""
Do not show teams that are not part of the current camp in the dropdown
"""
context = super().get_context_data(**kwargs)
context["form"].fields["responsible_team"].queryset = Team.objects.filter(
camp=self.camp
)
return context
def get_success_url(self):
return reverse(
"backoffice:facility_type_list", kwargs={"camp_slug": self.camp.slug}
)
class FacilityTypeDeleteView(CampViewMixin, OrgaTeamPermissionMixin, DeleteView):
model = FacilityType
template_name = "facility_type_delete.html"
context_object_name = "facility_type"
def delete(self, *args, **kwargs):
for facility in self.get_object().facilities.all():
facility.feedbacks.all().delete()
facility.opening_hours.all().delete()
facility.delete()
return super().delete(*args, **kwargs)
def get_success_url(self):
messages.success(self.request, "The FacilityType has been deleted")
return reverse(
"backoffice:facility_type_list", kwargs={"camp_slug": self.camp.slug}
)
class FacilityListView(CampViewMixin, OrgaTeamPermissionMixin, ListView):
model = Facility
template_name = "facility_list_backoffice.html"
class FacilityDetailView(CampViewMixin, OrgaTeamPermissionMixin, DetailView):
model = Facility
template_name = "facility_detail_backoffice.html"
pk_url_kwarg = "facility_uuid"
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
return qs.prefetch_related("opening_hours")
class FacilityCreateView(CampViewMixin, OrgaTeamPermissionMixin, CreateView):
model = Facility
template_name = "facility_form.html"
fields = ["facility_type", "name", "description", "location"]
def get_form(self, *args, **kwargs):
form = super().get_form(*args, **kwargs)
form.fields["location"].widget = LeafletWidget(
attrs={
"display_raw": "true",
}
)
return form
def get_context_data(self, **kwargs):
"""
Do not show types that are not part of the current camp in the dropdown
"""
context = super().get_context_data(**kwargs)
context["form"].fields["facility_type"].queryset = FacilityType.objects.filter(
responsible_team__camp=self.camp
)
return context
def get_success_url(self):
messages.success(self.request, "The Facility has been created")
return reverse("backoffice:facility_list", kwargs={"camp_slug": self.camp.slug})
class FacilityUpdateView(CampViewMixin, OrgaTeamPermissionMixin, UpdateView):
model = Facility
template_name = "facility_form.html"
pk_url_kwarg = "facility_uuid"
fields = ["facility_type", "name", "description", "location"]
def get_form(self, *args, **kwargs):
form = super().get_form(*args, **kwargs)
form.fields["location"].widget = LeafletWidget(
attrs={
"display_raw": "true",
}
)
return form
def get_success_url(self):
messages.success(self.request, "The Facility has been updated")
return reverse(
"backoffice:facility_detail",
kwargs={
"camp_slug": self.camp.slug,
"facility_uuid": self.get_object().uuid,
},
)
class FacilityDeleteView(CampViewMixin, OrgaTeamPermissionMixin, DeleteView):
model = Facility
template_name = "facility_delete.html"
pk_url_kwarg = "facility_uuid"
def delete(self, *args, **kwargs):
self.get_object().feedbacks.all().delete()
self.get_object().opening_hours.all().delete()
return super().delete(*args, **kwargs)
def get_success_url(self):
messages.success(self.request, "The Facility has been deleted")
return reverse("backoffice:facility_list", kwargs={"camp_slug": self.camp.slug})
class FacilityFeedbackView(CampViewMixin, RaisePermissionRequiredMixin, FormView):
template_name = "facilityfeedback_backoffice.html"
def get_permission_required(self):
"""
This view requires two permissions, camps.backoffice_permission and
the permission_set for the team in question.
"""
if not self.team.permission_set:
raise PermissionDenied("No permissions set defined for this team")
return ["camps.backoffice_permission", self.team.permission_set]
def setup(self, *args, **kwargs):
super().setup(*args, **kwargs)
self.team = get_object_or_404(
Team, camp=self.camp, slug=self.kwargs["team_slug"]
)
self.queryset = FacilityFeedback.objects.filter(
facility__facility_type__responsible_team=self.team, handled=False
)
self.form_class = modelformset_factory(
FacilityFeedback,
fields=("handled",),
min_num=self.queryset.count(),
validate_min=True,
max_num=self.queryset.count(),
validate_max=True,
extra=0,
)
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context["team"] = self.team
context["feedback_list"] = self.queryset
context["formset"] = self.form_class(queryset=self.queryset)
return context
def form_valid(self, form):
form.save()
if form.changed_objects:
messages.success(
self.request,
f"Marked {len(form.changed_objects)} FacilityFeedbacks as handled!",
)
return redirect(self.get_success_url())
def get_success_url(self, *args, **kwargs):
return reverse(
"backoffice:facilityfeedback",
kwargs={"camp_slug": self.camp.slug, "team_slug": self.team.slug},
)
class FacilityMixin(CampViewMixin):
def setup(self, *args, **kwargs):
super().setup(*args, **kwargs)
self.facility = get_object_or_404(Facility, uuid=kwargs["facility_uuid"])
def get_form(self, *args, **kwargs):
"""
The default range widgets are a bit shit because they eat the help_text and
have no indication of which field is for what. So we add a nice placeholder.
"""
form = super().get_form(*args, **kwargs)
form.fields["when"].widget.widgets[0].attrs = {
"placeholder": f"Open Date and Time (YYYY-MM-DD HH:MM). Active time zone is {settings.TIME_ZONE}.",
}
form.fields["when"].widget.widgets[1].attrs = {
"placeholder": f"Close Date and Time (YYYY-MM-DD HH:MM). Active time zone is {settings.TIME_ZONE}.",
}
return form
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["facility"] = self.facility
return context
class FacilityOpeningHoursCreateView(
FacilityMixin, OrgaTeamPermissionMixin, CreateView
):
model = FacilityOpeningHours
template_name = "facility_opening_hours_form.html"
fields = ["when", "notes"]
def form_valid(self, form):
"""
Set facility before saving
"""
hours = form.save(commit=False)
hours.facility = self.facility
hours.save()
messages.success(self.request, "New opening hours created successfully!")
return redirect(
reverse(
"backoffice:facility_detail",
kwargs={"camp_slug": self.camp.slug, "facility_uuid": self.facility.pk},
)
)
class FacilityOpeningHoursUpdateView(
FacilityMixin, OrgaTeamPermissionMixin, UpdateView
):
model = FacilityOpeningHours
template_name = "facility_opening_hours_form.html"
fields = ["when", "notes"]
def get_success_url(self):
messages.success(self.request, "Opening hours have been updated successfully")
return reverse(
"backoffice:facility_detail",
kwargs={"camp_slug": self.camp.slug, "facility_uuid": self.facility.pk},
)
class FacilityOpeningHoursDeleteView(
FacilityMixin, OrgaTeamPermissionMixin, DeleteView
):
model = FacilityOpeningHours
template_name = "facility_opening_hours_delete.html"
def get_success_url(self):
messages.success(self.request, "Opening hours have been deleted successfully")
return reverse(
"backoffice:facility_detail",
kwargs={"camp_slug": self.camp.slug, "facility_uuid": self.facility.pk},
)