Skip to content
Snippets Groups Projects
Forked from Lloyd Meins / AlekSIS-App-Abi
101 commits behind the upstream repository.
views.py 12.35 KiB
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.db.models import Count
from django.forms import modelformset_factory
from django.http import HttpResponse
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache
from django.views.generic import FormView

from django_tables2 import SingleTableView
from extra_views import ModelFormSetView
from guardian.shortcuts import assign_perm
from material import Layout, Row, Span2, Span3, Span7
from reversion.views import RevisionMixin
from rules.contrib.views import PermissionRequiredMixin

from aleksis.core.mixins import (
    AdvancedCreateView,
    AdvancedDeleteView,
    AdvancedEditView,
    SuccessMessageMixin,
)

from .forms import (
    AbiGroupForm,
    AbiPersonForm,
    ImportForm,
    ProfileFieldValueForm,
    QuoteForm,
    RankingCategoryForm,
    ranking_form_factory,
)
from .models import (
    AbiGroup,
    AbiPerson,
    AdditionalProfileField,
    Profile,
    ProfileFieldValue,
    Quote,
    RankingCategory,
)
from .tables import AbiGroupTable, AbiPersonTable, MyQuotesTable, QuotesTable, RankingCategoryTable


class AbiPersonListView(PermissionRequiredMixin, SingleTableView):
    """Table of all abi persons."""

    model = AbiPerson
    table_class = AbiPersonTable
    permission_required = "abi.view_abipersons_rule"
    template_name = "abi/abi_person/list.html"

    def get_queryset(self):
        return AbiPerson.objects.annotate_progress()


@method_decorator(never_cache, name="dispatch")
class AbiPersonCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for abi persons."""

    model = AbiPerson
    form_class = AbiPersonForm
    permission_required = "abi.add_abiperson_rule"
    template_name = "abi/abi_person/create.html"
    success_url = reverse_lazy("abi_persons")
    success_message = _("The person has been created.")


@method_decorator(never_cache, name="dispatch")
class AbiPersonEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for abi persons."""

    model = AbiPerson
    form_class = AbiPersonForm
    permission_required = "abi.edit_abiperson_rule"
    template_name = "abi/abi_person/edit.html"
    success_url = reverse_lazy("abi_persons")
    success_message = _("The person has been saved.")


@method_decorator(never_cache, name="dispatch")
class AbiPersonDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
    """Delete view for abi persons."""

    model = AbiPerson
    permission_required = "abi.delete_abiperson_rule"
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("abi_persons")
    success_message = _("The person has been deleted.")


class AbiGroupListView(PermissionRequiredMixin, SingleTableView):
    """Table of all abi groups."""

    model = AbiGroup
    table_class = AbiGroupTable
    permission_required = "abi.view_abigroups_rule"
    template_name = "abi/abi_group/list.html"

    def get_queryset(self):
        return AbiGroup.objects.annotate(members_count=Count("members"))


@method_decorator(never_cache, name="dispatch")
class AbiGroupCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for abi groups."""

    model = AbiGroup
    form_class = AbiGroupForm
    permission_required = "abi.add_abiaroup_rule"
    template_name = "abi/abi_group/create.html"
    success_url = reverse_lazy("abi_groups")
    success_message = _("The group has been created.")


@method_decorator(never_cache, name="dispatch")
class AbiGroupEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for abi groups."""

    model = AbiGroup
    form_class = AbiGroupForm
    permission_required = "abi.edit_abigroup_rule"
    template_name = "abi/abi_group/edit.html"
    success_url = reverse_lazy("abi_groups")
    success_message = _("The group has been saved.")


@method_decorator(never_cache, name="dispatch")
class AbiGroupDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
    """Delete view for abi groups."""

    model = AbiGroup
    permission_required = "abi.delete_abigroup_rule"
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("abi_groups")
    success_message = _("The group has been deleted.")


@method_decorator(never_cache, name="dispatch")
class AbiGroupImportView(PermissionRequiredMixin, FormView):
    """Import view for abi groups."""

    form_class = ImportForm
    permission_required = "abi.import_abigroup_rule"
    template_name = "abi/abi_group/import.html"
    success_url = reverse_lazy("abi_groups")

    def form_valid(self, form):
        form.save()
        messages.success(self.request, _("The group has been imported."))
        return super().form_valid(form)


class RankingCategoryListView(PermissionRequiredMixin, SingleTableView):
    """Table of all ranking categories."""

    model = RankingCategory
    table_class = RankingCategoryTable
    permission_required = "abi.view_rankingcategories_rule"
    template_name = "abi/ranking/ranking_category/list.html"

    def get_queryset(self):
        return RankingCategory.objects.annotate(
            number_of_votes=Count("rankings__ranked_by", distinct=True)
        )


@method_decorator(never_cache, name="dispatch")
class RankingCategoryCreateView(PermissionRequiredMixin, AdvancedCreateView):
    """Create view for ranking categories."""

    model = RankingCategory
    form_class = RankingCategoryForm
    permission_required = "abi.add_abiaroup_rule"
    template_name = "abi/ranking/ranking_category/create.html"
    success_url = reverse_lazy("ranking_categories")
    success_message = _("The ranking category has been created.")


@method_decorator(never_cache, name="dispatch")
class RankingCategoryEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for ranking categories."""

    model = RankingCategory
    form_class = RankingCategoryForm
    permission_required = "abi.edit_rankingcategory_rule"
    template_name = "abi/ranking/ranking_category/edit.html"
    success_url = reverse_lazy("ranking_categories")
    success_message = _("The ranking category has been saved.")


@method_decorator(never_cache, name="dispatch")
class RankingCategoryDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
    """Delete view for ranking categories."""

    model = RankingCategory
    permission_required = "abi.delete_rankingcategory_rule"
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("ranking_categories")
    success_message = _("The ranking category has been deleted.")


@method_decorator(never_cache, name="dispatch")
class RankingFormView(PermissionRequiredMixin, FormView):
    """Form view for rankings."""

    permission_required = "abi.rank_persons_rule"
    template_name = "abi/ranking/ranking/form.html"
    success_url = reverse_lazy("ranking_form")

    def get_form_class(self):
        return ranking_form_factory(self.request)

    def form_valid(self, form) -> HttpResponse:
        form.save(self.request)
        return super().form_valid(form)


@method_decorator(never_cache, name="dispatch")
class ProfileView(PermissionRequiredMixin, AdvancedEditView):
    model = Profile
    queryset = Profile.objects.all()
    fields = "__all__"
    value_fields_formset = None
    object = None  # noqa
    success_message = _("The profile has been updated successfully!")
    permission_required = "abi.use_profile_rule"

    def get_success_url(self):
        return reverse("update_profile")

    def get_object(self, queryset=None):
        qs = queryset or self.get_queryset()
        try:
            abi_person = AbiPerson.objects.get(person=self.request.user.person)
        except AbiPerson.DoesNotExist:
            raise PermissionDenied()
        obj = qs.get_or_create(person=abi_person)[0]
        self.object = obj
        objs = ProfileFieldValue.objects.filter(profile=obj)
        fields = list(objs.values_list("field", flat=True))
        fields_to_create = AdditionalProfileField.objects.all().exclude(pk__in=fields)
        ProfileFieldValue.objects.bulk_create(
            [ProfileFieldValue(profile=obj, field=field) for field in fields_to_create]
        )
        self.value_fields_formset = modelformset_factory(
            model=ProfileFieldValue, fields=("value",), form=ProfileFieldValueForm, extra=0,
        )
        return obj

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            context["additional_fields"] = self.value_fields_formset(
                self.request.POST,
                self.request.FILES,
                queryset=ProfileFieldValue.objects.filter(profile=self.object),
            )
        else:
            context["additional_fields"] = self.value_fields_formset(
                queryset=ProfileFieldValue.objects.filter(profile=self.object)
            )
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        value_fields = context["additional_fields"]

        if value_fields.is_valid():
            value_fields.save()
            return super().form_valid(form)
        else:
            return self.form_invalid(form)


class MyQuotesListView(PermissionRequiredMixin, SingleTableView):
    """Table of all submitted quotes."""

    model = Quote
    table_class = MyQuotesTable
    permission_required = "abi.view_suggested_quotes_rule"
    template_name = "abi/quotes/my.html"

    def get_queryset(self):
        return Quote.objects.filter(submitted_by=self.request.user.person.abi_person)


@method_decorator(never_cache, name="dispatch")
class SuggestQuoteView(PermissionRequiredMixin, AdvancedCreateView):
    """Suggest a quote."""

    model = Quote
    form_class = QuoteForm
    success_message = _("The quote has been sent successfully!")
    permission_required = "abi.suggest_quote"
    template_name = "abi/quotes/suggest.html"

    def get_success_url(self):
        return reverse("my_quotes")

    def form_valid(self, form):
        form.instance.submitted_by = self.request.user.person.abi_person
        r = super().form_valid(form)
        assign_perm("abi.view_quote", self.request.user, self.object)
        return r


@method_decorator(never_cache, name="dispatch")
class CreateQuoteView(PermissionRequiredMixin, AdvancedCreateView):
    """Insertion of quotes."""

    model = Quote
    form_class = QuoteForm
    success_message = _("The quote has been saved successfully!")
    permission_required = "abi.create_quote_rule"
    template_name = "abi/quotes/create.html"

    def get_success_url(self):
        return reverse("quotes")


class QuotesListView(PermissionRequiredMixin, SingleTableView):
    """Table of all added quotes."""

    model = Quote
    table_class = QuotesTable
    permission_required = "abi.view_quotes_rule"
    template_name = "abi/quotes/list.html"


@method_decorator(never_cache, name="dispatch")
class QuoteEditView(PermissionRequiredMixin, AdvancedEditView):
    """Edit view for quotes."""

    model = Quote
    form_class = QuoteForm
    permission_required = "abi.edit_quote_rule"
    template_name = "abi/quotes/edit.html"
    success_url = reverse_lazy("quotes")
    success_message = _("The quote has been saved.")


@method_decorator(never_cache, name="dispatch")
class QuoteDeleteView(PermissionRequiredMixin, RevisionMixin, AdvancedDeleteView):
    """Delete view for quotes."""

    model = Quote
    permission_required = "abi.delete_quote_rule"
    template_name = "core/pages/delete.html"
    success_url = reverse_lazy("quotes")
    success_message = _("The quote has been deleted.")


@method_decorator(never_cache, name="dispatch")
class ConfigureProfileView(PermissionRequiredMixin, SuccessMessageMixin, ModelFormSetView):
    model = AdditionalProfileField
    fields = ("name", "limit")
    factory_kwargs = {"can_delete": True, "can_delete_extra": False}
    success_message = _("The profile questions have been updated successfully.")
    permission_required = "abi.edit_profile_questions_rule"

    def get_object(self, queryset=None):
        self.object = None
        return None

    def get_success_url(self):
        return reverse("configure_profile")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["layout"] = Layout(Row(Span7("name"), Span3("limit"), Span2("DELETE")))
        return context