""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: ksp-servicestelle@sgdnord.rlp.de Created on: 18.08.22 """ from dal import autocomplete from django import forms from django.db import transaction from django.urls import reverse from django.utils.translation import gettext_lazy as _ from konova.forms.modals import BaseModalForm, RemoveModalForm from user.models import User, Team class NewTeamModalForm(BaseModalForm): name = forms.CharField( label_suffix="", label=_("Team name"), max_length=500, widget=forms.TextInput( attrs={ "placeholder": _("Team name"), "class": "form-control", } ) ) description = forms.CharField( label_suffix="", label=_("Description"), widget=forms.Textarea( attrs={ "rows": 5, "class": "form-control" } ) ) members = forms.ModelMultipleChoiceField( label=_("Manage team members"), label_suffix="", help_text=_("Multiple selection possible - You can only select users which are not already a team member. Enter the full username or e-mail."), required=True, queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user:share-user-autocomplete", attrs={ "data-placeholder": _("Click for selection"), "data-minimum-input-length": 3, }, ), ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("Create new team") self.form_caption = _("You will become the administrator for this group by default. You do not need to add yourself to the list of members.") self.action_url = reverse("user:team-new") self.cancel_redirect = reverse("user:team-index") def _is_name_valid(self): name = self.cleaned_data.get("name", None) teams_with_same_name = Team.objects.filter( name=name ) name_valid = not teams_with_same_name.exists() if not name_valid: self.add_error( "name", _("Name already taken. Try another.") ) return name_valid def is_valid(self): super_valid = super().is_valid() name_valid = self._is_name_valid() return super_valid and name_valid def save(self): with transaction.atomic(): team = Team.objects.create( name=self.cleaned_data.get("name", None), description=self.cleaned_data.get("description", None), ) team.admins.add(self.user) members = self.cleaned_data.get("members", User.objects.none()) if self.user.id not in members: members = members.union( User.objects.filter( id=self.user.id ) ) team.users.set(members) return team class EditTeamModalForm(NewTeamModalForm): admins = forms.ModelMultipleChoiceField( label=_("Admins"), label_suffix="", help_text=_("Administrators manage team details and members"), required=True, queryset=User.objects.all(), widget=autocomplete.ModelSelect2Multiple( url="user:team-admin-autocomplete", forward=[ "members", "admins", ], attrs={ "data-placeholder": _("Click for selection"), }, ), ) def __is_admins_valid(self): admins = set(self.cleaned_data.get("admins", {})) members = set(self.cleaned_data.get("members", {})) _is_valid = admins.issubset(members) if not _is_valid: self.add_error( "admins", _("Selected admins need to be members of this team.") ) _is_admin_length_valid = len(admins) > 0 if not _is_admin_length_valid: self.add_error( "admins", _("There must be at least one admin on this team.") ) return _is_valid def _is_name_valid(self): name = self.cleaned_data.get("name", None) teams_with_same_name = Team.objects.filter( name=name ).exclude( id=self.instance.id ) name_valid = not teams_with_same_name.exists() if not name_valid: self.add_error( "name", _("Name already taken. Try another.") ) return name_valid def is_valid(self): super_valid = super().is_valid() admin_valid = self.__is_admins_valid() return super_valid and admin_valid def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("Edit team") self.action_url = reverse("user:team-edit", args=(self.instance.id,)) self.cancel_redirect = reverse("user:team-index") members = self.instance.users.all() form_data = { "members": members, "name": self.instance.name, "description": self.instance.description, "admins": self.instance.admins.all(), } self.load_initial_data(form_data) def save(self): with transaction.atomic(): self.instance.name = self.cleaned_data.get("name", None) self.instance.description = self.cleaned_data.get("description", None) self.instance.save() self.instance.users.set(self.cleaned_data.get("members", [])) self.instance.admins.set(self.cleaned_data.get("admins", [])) return self.instance class RemoveTeamModalForm(RemoveModalForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_caption = _("ATTENTION!\n\nRemoving the team means all members will lose their access to data, based on this team! \n\nAre you sure to remove this team?") def save(self): self.instance.mark_as_deleted(self.user) return self.instance class LeaveTeamModalForm(RemoveModalForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("Leave team") def save(self): self.instance.remove_user(self.user)