2021-07-08 17:23:06 +02:00
"""
Author : Michel Peltriaux
Organization : Struktur - und Genehmigungsdirektion Nord , Rhineland - Palatinate , Germany
Contact : michel . peltriaux @sgdnord.rlp.de
Created on : 08.07 .21
"""
2022-02-17 13:13:32 +01:00
from dal import autocomplete
2021-07-08 17:23:06 +02:00
from django import forms
2022-08-10 08:03:18 +02:00
from django . db import transaction
2022-01-27 11:37:38 +01:00
from django . urls import reverse , reverse_lazy
2021-07-08 17:23:06 +02:00
from django . utils . translation import gettext_lazy as _
2022-01-27 11:37:38 +01:00
from api . models import APIUserToken
from intervention . inputs import GenerateInput
2022-02-17 13:13:32 +01:00
from user . models import User , UserNotification , Team
2021-07-08 17:23:06 +02:00
2022-08-15 10:50:01 +02:00
from konova . forms . modals import BaseModalForm , RemoveModalForm
from konova . forms import BaseForm
2021-07-08 17:23:06 +02:00
class UserNotificationForm ( BaseForm ) :
""" Form for changing the notification settings of a user
"""
notifications = forms . MultipleChoiceField (
label_suffix = " " ,
label = _ ( " Notifications " ) ,
required = False , # allow total disabling of all notifications
help_text = _ ( " Select the situations when you want to receive a notification " ) ,
widget = forms . CheckboxSelectMultiple (
attrs = {
2021-07-09 07:46:20 +02:00
" class " : " list-unstyled " ,
2021-07-08 17:23:06 +02:00
}
) ,
choices = [ ]
)
def __init__ ( self , user : User , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . user = user
self . form_title = _ ( " Edit notifications " )
2021-07-09 07:46:20 +02:00
self . form_caption = _ ( " " )
2021-07-08 17:23:06 +02:00
self . action_url = reverse ( " user:notifications " )
self . cancel_redirect = reverse ( " user:index " )
# Insert all notifications into form field by creating choices as tuples
notifications = UserNotification . objects . filter (
is_active = True ,
)
choices = [ ]
for n in notifications :
choices . append (
( n . id , _ ( n . name ) )
)
self . fields [ " notifications " ] . choices = choices
2022-01-12 12:56:22 +01:00
users_current_notifications = self . user . notifications . all ( )
2021-07-08 17:23:06 +02:00
users_current_notifications = [ str ( n . id ) for n in users_current_notifications ]
self . fields [ " notifications " ] . initial = users_current_notifications
def save ( self ) :
""" Stores the changes in the user konova_extension
Returns :
"""
selected_notification_ids = self . cleaned_data . get ( " notifications " , [ ] )
notifications = UserNotification . objects . filter (
id__in = selected_notification_ids ,
)
2022-01-12 12:56:22 +01:00
self . user . notifications . set ( notifications )
2021-08-02 14:10:57 +02:00
class UserContactForm ( BaseModalForm ) :
name = forms . CharField (
label = _ ( " Username " ) ,
label_suffix = " " ,
required = False ,
widget = forms . TextInput (
attrs = {
" readonly " : True ,
2021-10-25 08:51:06 +02:00
" class " : " form-control " ,
2021-08-02 14:10:57 +02:00
}
) ,
)
person_name = forms . CharField (
label = _ ( " Person name " ) ,
label_suffix = " " ,
required = False ,
widget = forms . TextInput (
attrs = {
" readonly " : True ,
2021-10-25 08:51:06 +02:00
" class " : " form-control " ,
2021-08-02 14:10:57 +02:00
}
) ,
)
mail = forms . EmailField (
label = _ ( " E-Mail " ) ,
label_suffix = " " ,
required = False ,
widget = forms . TextInput (
attrs = {
" readonly " : True ,
2021-10-25 08:51:06 +02:00
" class " : " form-control " ,
2021-08-02 14:10:57 +02:00
}
) ,
)
def __init__ ( self , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . render_submit = False
self . form_title = _ ( " User contact data " )
self . form_caption = " "
self . initialize_form_field ( " name " , self . instance . username )
self . initialize_form_field ( " person_name " , " {} {} " . format ( self . instance . first_name , self . instance . last_name ) )
self . initialize_form_field ( " mail " , self . instance . email )
2022-01-27 11:37:38 +01:00
class UserAPITokenForm ( BaseForm ) :
token = forms . CharField (
label = _ ( " Token " ) ,
label_suffix = " " ,
max_length = 255 ,
required = True ,
help_text = _ ( " Generated automatically " ) ,
widget = GenerateInput (
attrs = {
" class " : " form-control " ,
" url " : reverse_lazy ( " api:generate-new-token " ) ,
}
)
)
def __init__ ( self , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . form_title = _ ( " Create new token " )
self . form_caption = _ ( " A new token needs to be validated by an administrator! " )
self . action_url = reverse ( " user:api-token " )
self . cancel_redirect = reverse ( " user:index " )
# Make direct token editing by user impossible. Instead set the proper url for generating a new token
self . initialize_form_field ( " token " , None )
self . fields [ " token " ] . widget . attrs [ " readonly " ] = True
def save ( self ) :
""" Saves the form data
Returns :
api_token ( APIUserToken )
"""
user = self . instance
new_token = self . cleaned_data [ " token " ]
2022-01-27 14:48:42 +01:00
if user . api_token is not None :
user . api_token . delete ( )
2022-01-27 11:37:38 +01:00
new_token = APIUserToken . objects . create (
token = new_token
)
user . api_token = new_token
user . save ( )
return new_token
2022-02-17 13:13:32 +01:00
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 = " 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 " )
2022-02-18 11:02:40 +01:00
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
2022-02-17 13:13:32 +01:00
def save ( self ) :
with transaction . atomic ( ) :
team = Team . objects . create (
name = self . cleaned_data . get ( " name " , None ) ,
description = self . cleaned_data . get ( " description " , None ) ,
)
2022-05-30 15:38:16 +02:00
team . admins . add ( self . user )
2022-02-17 13:13:32 +01:00
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 ) :
2022-05-30 14:35:31 +02:00
admins = forms . ModelMultipleChoiceField (
label = _ ( " Admins " ) ,
2022-02-17 13:13:32 +01:00
label_suffix = " " ,
help_text = _ ( " Administrators manage team details and members " ) ,
2022-05-30 14:35:31 +02:00
required = True ,
queryset = User . objects . all ( ) ,
widget = autocomplete . ModelSelect2Multiple (
url = " team-admin-autocomplete " ,
forward = [
" members " ,
" admins " ,
] ,
attrs = {
" data-placeholder " : _ ( " Click for selection " ) ,
} ,
) ,
2022-02-17 13:13:32 +01:00
)
2022-05-30 14:35:31 +02:00
def __is_admins_valid ( self ) :
admins = set ( self . cleaned_data . get ( " admins " , { } ) )
members = set ( self . cleaned_data . get ( " members " , { } ) )
_is_valid = admins . issubset ( members )
2022-02-17 13:44:32 +01:00
if not _is_valid :
self . add_error (
2022-05-30 14:35:31 +02:00
" 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. " )
2022-02-17 13:44:32 +01:00
)
return _is_valid
2022-02-18 11:02:40 +01:00
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
2022-02-17 13:44:32 +01:00
def is_valid ( self ) :
super_valid = super ( ) . is_valid ( )
2022-05-30 14:35:31 +02:00
admin_valid = self . __is_admins_valid ( )
2022-02-17 13:44:32 +01:00
return super_valid and admin_valid
2022-02-17 13:13:32 +01:00
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 ,
2022-05-30 14:35:31 +02:00
" admins " : self . instance . admins . all ( ) ,
2022-02-17 13:13:32 +01:00
}
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 " , [ ] ) )
2022-05-30 14:35:31 +02:00
self . instance . admins . set ( self . cleaned_data . get ( " admins " , [ ] ) )
2022-02-17 13:13:32 +01:00
return self . instance
class RemoveTeamModalForm ( RemoveModalForm ) :
2022-05-30 14:35:31 +02:00
def __init__ ( self , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . form_caption = _ ( " ATTENTION! \n \n Removing the team means all members will lose their access to data, based on this team! \n \n Are you sure to remove this team? " )
2022-02-18 14:06:51 +01:00
2022-05-30 15:38:16 +02:00
def save ( self ) :
self . instance . mark_as_deleted ( self . user )
return self . instance
2022-02-18 14:06:51 +01:00
2022-04-13 15:52:41 +02:00
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 )
2022-02-18 14:06:51 +01:00
class TeamDataForm ( BaseModalForm ) :
name = forms . CharField (
label_suffix = " " ,
label = _ ( " Team name " ) ,
max_length = 500 ,
required = False ,
widget = forms . TextInput (
attrs = {
" placeholder " : _ ( " Team name " ) ,
" class " : " form-control " ,
}
)
)
description = forms . CharField (
label_suffix = " " ,
required = False ,
label = _ ( " Description " ) ,
widget = forms . Textarea (
attrs = {
" rows " : 5 ,
" class " : " form-control "
}
)
)
def __init__ ( self , * args , * * kwargs ) :
super ( ) . __init__ ( * args , * * kwargs )
self . form_title = _ ( " Team " )
self . form_caption = " "
self . render_submit = False
form_data = {
" name " : self . instance . name ,
" description " : self . instance . description ,
}
self . load_initial_data (
form_data ,
[
" name " ,
" description "
]
)