Free and open source ticket system written in python
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'}))