Free and open source ticket system written in python
at main 105 lines 3.9 kB view raw
1from django import forms 2from .models import Ticket, Template, Team, Category 3from django.utils.translation import gettext_lazy as _ 4import magic 5 6 7ATTACHMENT_CONTENT_TYPES = [ 8 'image/jpeg', 9 'image/png', 10 'application/pdf' 11] 12 13 14class MultipleFileInput(forms.ClearableFileInput): 15 allow_multiple_selected = True 16 17 18class MultipleFileField(forms.FileField): 19 def __init__(self, *args, **kwargs): 20 kwargs.setdefault("widget", MultipleFileInput( 21 attrs={'class': 'file-input w-full'})) 22 super().__init__(*args, **kwargs) 23 24 def clean(self, data, initial=None): 25 single_file_clean = super().clean 26 if isinstance(data, (list, tuple)): 27 result = [single_file_clean(d, initial) for d in data] 28 else: 29 result = single_file_clean(data, initial) 30 return result 31 32 33def clean_attachments(files): 34 if files: 35 for file in files: 36 # Check file size 37 if file.size > 1024 * 1024 * 5: 38 raise forms.ValidationError( 39 _('File size must be under 5MB.')) 40 41 # Check file type 42 uploaded_content_type = file.content_type 43 mg = magic.Magic(mime=True) 44 content_type = mg.from_buffer(file.read(1024)) 45 file.seek(0) 46 47 if content_type != uploaded_content_type: 48 uploaded_content_type = content_type 49 50 if uploaded_content_type not in ATTACHMENT_CONTENT_TYPES: 51 raise forms.ValidationError( 52 _('File type not supported. Supported types are: .jpg, .png, .pdf')) 53 return files 54 55 56class CommentForm(forms.Form): 57 text = forms.CharField(widget=forms.Textarea( 58 attrs={'class': 'textarea h-32 w-full', 'placeholder': 'Enter your comment here...'})) 59 hidden_from_client = forms.BooleanField(widget=forms.CheckboxInput( 60 attrs={'class': 'checkbox checkbox-secondary'}), required=False) 61 62 attachments = MultipleFileField(required=False) 63 64 def clean_attachments(self): 65 return clean_attachments(self.cleaned_data.get('attachments')) 66 67 68class TicketForm(forms.ModelForm): 69 class Meta: 70 model = Ticket 71 fields = ['title', 'description', 'category', 'follow_up_to'] 72 widgets = { 73 'title': forms.TextInput(attrs={'class': 'input w-full', 'placeholder': _('Please enter a title'), 'aria-label': _('Title')}), 74 'description': forms.Textarea(attrs={'class': 'textarea h-32 w-full', 'placeholder': _('Please describe your issue'), 'aria-label': _('Description')}), 75 'category': forms.Select(attrs={'class': 'select w-full'}), 76 'follow_up_to': forms.Select(attrs={'class': 'select w-full'}), 77 } 78 79 def __init__(self, user, *args, **kwargs): 80 super(TicketForm, self).__init__(*args, **kwargs) 81 self.fields['category'].empty_label = _('General') 82 self.fields['follow_up_to'].empty_label = _('No Follow-up') 83 self.fields['follow_up_to'].queryset = Ticket.objects.filter( 84 status=Ticket.Status.CLOSED, user=user) 85 86 attachments = MultipleFileField(required=False) 87 88 def clean_attachments(self): 89 return clean_attachments(self.cleaned_data.get('attachments')) 90 91 92class TemplateForm(forms.Form): 93 94 template_select = forms.ModelChoiceField(queryset=Template.objects.all(), widget=forms.Select( 95 attrs={'class': 'select select-sm w-full'})) 96 97 98class TeamAssignmentForm(forms.Form): 99 team_select = forms.ModelChoiceField(queryset=Team.objects.filter(readonly_access=False), empty_label=_('No Team'), required=False, widget=forms.Select( 100 attrs={'class': 'select select-sm w-full'})) 101 102 103class CategoryAssignmentForm(forms.Form): 104 category_select = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label=_('General'), required=False, widget=forms.Select( 105 attrs={'class': 'select select-sm w-full'}))