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