Priviliged users can now add tags. Also, some minor cleanups in JS.
[redakcja.git] / apps / wiki / views.py
1 import os
2
3 from django.conf import settings
4
5 from django.views.generic.simple import direct_to_template
6 from django.views.decorators.http import require_POST
7 from wiki.helpers import JSONResponse, JSONFormInvalid, JSONServerError, ajax_require_permission
8 from django import http
9
10 from wiki.models import getstorage
11 from wiki.forms import DocumentTextSaveForm, DocumentTagForm
12 from datetime import datetime
13 from django.utils.encoding import smart_unicode
14 from django.utils.translation import ugettext_lazy as _
15
16 import wlapi
17
18 #
19 # Quick hack around caching problems, TODO: use ETags
20 #
21 from django.views.decorators.cache import never_cache
22
23 import logging
24 logger = logging.getLogger("fnp.peanut.api")
25
26 import nice_diff
27 import operator
28
29 MAX_LAST_DOCS = 10
30
31
32 @never_cache
33 def document_list(request, template_name='wiki/document_list.html'):
34     # TODO: find a way to cache "Storage All"
35     return direct_to_template(request, template_name, extra_context={
36         'document_list': getstorage().all(),
37         'last_docs': sorted(request.session.get("wiki_last_docs", {}).items(),
38                         key=operator.itemgetter(1), reverse=True),
39     })
40
41
42 @never_cache
43 def document_detail(request, name, template_name='wiki/document_details.html'):
44
45     document = getstorage().get_or_404(name)
46
47     access_time = datetime.now()
48     last_documents = request.session.get("wiki_last_docs", {})
49     last_documents[name] = access_time
50
51     if len(last_documents) > MAX_LAST_DOCS:
52         oldest_key = min(last_documents, key=last_documents.__getitem__)
53         del last_documents[oldest_key]
54     request.session['wiki_last_docs'] = last_documents
55
56     return direct_to_template(request, template_name, extra_context={
57         'document': document,
58         'document_info': document.info,
59         'document_meta': document.meta,
60         'forms': {"text_save": DocumentTextSaveForm(), "add_tag": DocumentTagForm()},
61     })
62
63
64 @never_cache
65 def document_text(request, name):
66     storage = getstorage()
67     document = storage.get_or_404(name)
68
69     if request.method == 'POST':
70         form = DocumentTextSaveForm(request.POST)
71
72         if form.is_valid():
73             revision = form.cleaned_data['parent_revision']
74             document.text = form.cleaned_data['text']
75
76             storage.put(document,
77                 author=form.cleaned_data['author'] or request.user.username,
78                 comment=form.cleaned_data['comment'],
79                 parent=revision,
80             )
81
82             return JSONResponse({
83                 'text': document.plain_text if revision != document.revision() else None,
84                 'meta': document.meta(),
85                 'revision': document.revision(),
86             })
87         else:
88             return JSONFormInvalid(form)
89     else:
90         return JSONResponse({
91             'text': document.plain_text,
92             'meta': document.meta(),
93             'revision': document.revision(),
94         })
95
96
97 @never_cache
98 def document_gallery(request, directory):
99     try:
100         base_url = ''.join((
101                         smart_unicode(settings.MEDIA_URL),
102                         smart_unicode(settings.FILEBROWSER_DIRECTORY),
103                         smart_unicode(directory)))
104
105         base_dir = os.path.join(
106                     smart_unicode(settings.MEDIA_ROOT),
107                     smart_unicode(settings.FILEBROWSER_DIRECTORY),
108                     smart_unicode(directory))
109
110         def map_to_url(filename):
111             return "%s/%s" % (base_url, smart_unicode(filename))
112
113         def is_image(filename):
114             return os.path.splitext(f)[1].lower() in (u'.jpg', u'.jpeg', u'.png')
115
116         images = [map_to_url(f) for f in map(smart_unicode, os.listdir(base_dir)) if is_image(f)]
117         images.sort()
118         return JSONResponse(images)
119     except (IndexError, OSError), exc:
120         import traceback
121         traceback.print_exc()
122         raise http.Http404
123
124
125 @never_cache
126 def document_diff(request, name):
127     storage = getstorage()
128
129     revA = int(request.GET.get('from', 0))
130     revB = int(request.GET.get('to', 0))
131
132     if revA > revB:
133         revA, revB = revB, revA
134
135     if revB == 0:
136         revB = None
137
138     docA = storage.get_or_404(name, int(revA))
139     docB = storage.get_or_404(name, int(revB))
140
141     return http.HttpResponse(nice_diff.html_diff_table(docA.plain_text.splitlines(),
142                                          docB.plain_text.splitlines(), context=3))
143
144
145 @never_cache
146 def document_history(request, name):
147     storage = getstorage()
148
149     # TODO: pagination
150     changesets = storage.history(name)
151
152     return JSONResponse(changesets)
153
154
155 @require_POST
156 @ajax_require_permission('wiki.can_change_tags')
157 def document_add_tag(request, name):
158     storage = getstorage()
159
160     form = DocumentTagForm(request.POST)
161     if form.is_valid():
162         doc = storage.get_or_404(form.cleaned_data['id'])
163         doc.add_tag(tag=form.cleaned_data['tag'],
164                     revision=form.cleaned_data['revision'],
165                     author=request.user.username)
166         return JSONResponse({"message": _("Tag added")})
167     else:
168         return JSONFormInvalid(form)
169
170
171 @require_POST
172 @ajax_require_permission('wiki.can_publish')
173 def document_publish(request, name, version):
174     storage = getstorage()
175
176     # get the document
177     document = storage.get_or_404(name, revision=int(version))
178
179     api = wlapi.WLAPI(settings.WL_API_CONFIG)
180     try:
181         return JSONResponse({"result": api.publish_book(document)})
182     except wlapi.APICallException, e:
183         return JSONServerError({"message": str(e)})