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