document stages on import,
[redakcja.git] / apps / wiki / forms.py
1 # -*- coding: utf-8 -*-
2 #
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.
5 #
6 from django.contrib.auth.models import User
7 from django.db.models import Count
8 from django import forms
9 from django.utils.translation import ugettext_lazy as _
10
11 from dvcs.models import Tag
12 from wiki.constants import MASTERS
13 from wiki.models import Book, Chunk
14
15 class DocumentTagForm(forms.Form):
16     """
17         Form for tagging revisions.
18     """
19
20     id = forms.CharField(widget=forms.HiddenInput)
21     tag = forms.ModelChoiceField(queryset=Tag.objects.all())
22     revision = forms.IntegerField(widget=forms.HiddenInput)
23
24
25 class DocumentPubmarkForm(forms.Form):
26     """
27         Form for marking revisions for publishing.
28     """
29
30     id = forms.CharField(widget=forms.HiddenInput)
31     publishable = forms.BooleanField(required=False, initial=True,
32             label=_('Publishable'))
33     revision = forms.IntegerField(widget=forms.HiddenInput)
34
35
36 class DocumentCreateForm(forms.ModelForm):
37     """
38         Form used for creating new documents.
39     """
40     file = forms.FileField(required=False)
41     text = forms.CharField(required=False, widget=forms.Textarea)
42
43     class Meta:
44         model = Book
45         exclude = ['gallery', 'parent', 'parent_number']
46         prepopulated_fields = {'slug': ['title']}
47
48     def clean(self):
49         super(DocumentCreateForm, self).clean()
50         file = self.cleaned_data['file']
51
52         if file is not None:
53             try:
54                 self.cleaned_data['text'] = file.read().decode('utf-8')
55             except UnicodeDecodeError:
56                 raise forms.ValidationError("Text file must be UTF-8 encoded.")
57
58         if not self.cleaned_data["text"]:
59             raise forms.ValidationError("You must either enter text or upload a file")
60
61         return self.cleaned_data
62
63
64 class DocumentsUploadForm(forms.Form):
65     """
66         Form used for uploading new documents.
67     """
68     file = forms.FileField(required=True, label=_('ZIP file'))
69
70     def clean(self):
71         file = self.cleaned_data['file']
72
73         import zipfile
74         try:
75             z = self.cleaned_data['zip'] = zipfile.ZipFile(file)
76         except zipfile.BadZipfile:
77             raise forms.ValidationError("Should be a ZIP file.")
78         if z.testzip():
79             raise forms.ValidationError("ZIP file corrupt.")
80
81         return self.cleaned_data
82
83
84 class DocumentTextSaveForm(forms.Form):
85     """
86     Form for saving document's text:
87
88         * parent_revision - revision which the modified text originated from.
89         * comment - user's verbose comment; will be used in commit.
90         * stage_completed - mark this change as end of given stage.
91
92     """
93
94     parent_revision = forms.IntegerField(widget=forms.HiddenInput)
95     text = forms.CharField(widget=forms.HiddenInput)
96
97     author_name = forms.CharField(
98         required=False,
99         label=_(u"Author"),
100         help_text=_(u"Your name"),
101     )
102
103     author_email = forms.EmailField(
104         required=False,
105         label=_(u"Author's email"),
106         help_text=_(u"Your email address, so we can show a gravatar :)"),
107     )
108
109     comment = forms.CharField(
110         required=True,
111         widget=forms.Textarea,
112         label=_(u"Your comments"),
113         help_text=_(u"Describe changes you made."),
114     )
115
116     stage_completed = forms.ModelChoiceField(
117         queryset=Tag.objects.all(),
118         required=False,
119         label=_(u"Completed"),
120         help_text=_(u"If you completed a life cycle stage, select it."),
121     )
122
123
124 class DocumentTextRevertForm(forms.Form):
125     """
126     Form for reverting document's text:
127
128         * revision - revision to revert to.
129         * comment - user's verbose comment; will be used in commit.
130
131     """
132
133     revision = forms.IntegerField(widget=forms.HiddenInput)
134
135     author_name = forms.CharField(
136         required=False,
137         label=_(u"Author"),
138         help_text=_(u"Your name"),
139     )
140
141     author_email = forms.EmailField(
142         required=False,
143         label=_(u"Author's email"),
144         help_text=_(u"Your email address, so we can show a gravatar :)"),
145     )
146
147     comment = forms.CharField(
148         required=True,
149         widget=forms.Textarea,
150         label=_(u"Your comments"),
151         help_text=_(u"Describe the reason for reverting."),
152     )
153
154
155 class ChunkForm(forms.ModelForm):
156     """
157         Form used for editing a chunk.
158     """
159     user = forms.ModelChoiceField(queryset=
160         User.objects.annotate(count=Count('document')).
161         order_by('-count', 'last_name', 'first_name'))
162
163
164     class Meta:
165         model = Chunk
166         exclude = ['number']
167
168     def clean_slug(self):
169         slug = self.cleaned_data['slug']
170         try:
171             chunk = Chunk.objects.get(book=self.instance.book, slug=slug)
172         except Chunk.DoesNotExist:
173             return slug
174         if chunk == self.instance:
175             return slug
176         raise forms.ValidationError(_('Chunk with this slug already exists'))
177
178
179 class ChunkAddForm(ChunkForm):
180     """
181         Form used for adding a chunk to a document.
182     """
183
184     def clean_slug(self):
185         slug = self.cleaned_data['slug']
186         try:
187             user = Chunk.objects.get(book=self.instance.book, slug=slug)
188         except Chunk.DoesNotExist:
189             return slug
190         raise forms.ValidationError(_('Chunk with this slug already exists'))
191
192
193
194
195 class BookAppendForm(forms.Form):
196     """
197         Form for appending a book to another book.
198         It means moving all chunks from book A to book B and deleting A.
199     """
200
201     append_to = forms.ModelChoiceField(queryset=Book.objects.all(),
202         label=_("Append to"))
203
204
205 class BookForm(forms.ModelForm):
206     """
207         Form used for editing a Book.
208     """
209
210     class Meta:
211         model = Book
212
213
214 class ChooseMasterForm(forms.Form):
215     """
216         Form used for fixing the chunks in a book.
217     """
218
219     master = forms.ChoiceField(choices=((m, m) for m in MASTERS))