1 # -*- coding: utf-8 -*-
3 # This file is part of FNP-Redakcja, licensed under GNU Affero GPLv3 or later.
4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
6 from django.utils.encoding import force_text
7 from django.utils.html import format_html
8 from django.utils.safestring import mark_safe
10 from catalogue.models import Category
11 from catalogue.models import Tag
12 from django import forms
13 from django.utils.translation import ugettext_lazy as _
15 from catalogue.constants import MASTERS
18 def tag_field(category_tag, required=True):
19 category = Category.objects.get(dc_tag=category_tag)
20 return forms.ModelMultipleChoiceField(queryset=category.tag_set.all(), required=required)
23 class DocumentCreateForm(forms.Form):
25 Form used for creating new documents.
27 owner_organization = forms.CharField(required=False)
28 title = forms.CharField()
29 publisher = forms.CharField(required=False)
30 description = forms.CharField(required=False)
31 cover = forms.FileField(required=False)
33 def clean_cover(self):
34 cover = self.cleaned_data['cover']
35 if cover and cover.name.rsplit('.', 1)[-1].lower() not in ('jpg', 'jpeg', 'png', 'gif', 'svg'):
36 raise forms.ValidationError(_('The cover should be an image file (jpg/png/gif)'))
40 class TagForm(forms.Form):
41 def __init__(self, category, instance=None, tutorial_no=None, *args, **kwargs):
42 super(TagForm, self).__init__(*args, **kwargs)
43 self.category = category
44 self.instance = instance
45 self.field().queryset = Tag.objects.filter(category=self.category)
46 self.field().label = self.category.label.capitalize()
47 if tutorial_no and category.tutorial:
48 self.field().widget.attrs.update({
49 'data-toggle': 'tutorial',
50 'data-tutorial': str(tutorial_no),
51 'data-placement': 'bottom',
52 'data-content': category.tutorial,
55 self.field().initial = self.get_initial()
57 def save(self, instance=None):
58 instance = instance or self.instance
59 assert instance, 'No instance provided'
60 self.category.set_tags_for(instance, self.cleaned_tags())
63 raise NotImplementedError
65 def get_initial(self):
66 raise NotImplementedError
68 def cleaned_tags(self):
69 raise NotImplementedError
71 def metadata_rows(self):
73 '<dc:%(name)s>%(value)s</dc:%(name)s>' % {'name': tag.category.dc_tag, 'value': tag.dc_value}
74 for tag in self.cleaned_tags())
77 class TagSelect(forms.Select):
78 def render_option(self, selected_choices, option_value, option_label):
79 if option_value is None:
83 tag = Tag.objects.get(id=int(option_value))
85 help_html = mark_safe(' data-help="%s"' % tag.help_text)
86 option_value = force_text(option_value)
87 if option_value in selected_choices:
88 selected_html = mark_safe(' selected="selected"')
89 if not self.allow_multiple_selected:
90 # Only allow for a single selection.
91 selected_choices.remove(option_value)
95 u'<option value="{}"{}{}>{}</option>',
96 option_value, selected_html, help_html, force_text(option_label))
99 class TagSingleForm(TagForm):
100 tag = forms.ModelChoiceField(
102 widget=TagSelect(attrs={
103 'class': 'form-control',
108 return self.fields['tag']
110 def get_initial(self):
111 return self.instance.tags.get(category=self.category)
113 def cleaned_tags(self):
114 return [self.cleaned_data['tag']]
117 class TagMultipleForm(TagForm):
118 tags = forms.ModelMultipleChoiceField(
119 Tag.objects.none(), required=False,
120 widget=forms.SelectMultiple(attrs={
121 'class': 'chosen-select',
122 'data-placeholder': _('Choose'),
126 return self.fields['tags']
128 def get_initial(self):
129 return self.instance.tags.filter(category=self.category)
131 def cleaned_tags(self):
132 return self.cleaned_data['tags']
135 class DocumentsUploadForm(forms.Form):
137 Form used for uploading new documents.
139 file = forms.FileField(required=True, label=_('ZIP file'))
140 dirs = forms.BooleanField(
141 label=_('Directories are documents in chunks'),
142 widget=forms.CheckboxInput(attrs={'disabled': 'disabled'}))
145 file = self.cleaned_data['file']
149 z = self.cleaned_data['zip'] = zipfile.ZipFile(file)
150 except zipfile.BadZipfile:
151 raise forms.ValidationError("Should be a ZIP file.")
153 raise forms.ValidationError("ZIP file corrupt.")
155 return self.cleaned_data
158 class ChooseMasterForm(forms.Form):
160 Form used for fixing the chunks in a book.
163 master = forms.ChoiceField(choices=((m, m) for m in MASTERS))
166 class DocumentForkForm(forms.Form):
168 Form used for forking documents.
170 owner_organization = forms.CharField(required=False)