Automatically search for the next match after single replace, fixes #3384
[redakcja.git] / apps / wiki_img / views.py
index c4d32b7..08a0a03 100644 (file)
@@ -1,17 +1,23 @@
 import os
 import functools
 import logging
-logger = logging.getLogger("fnp.wiki")
+logger = logging.getLogger("fnp.wiki_img")
 
-from django.views.generic.simple import direct_to_template
 from django.core.urlresolvers import reverse
-from wiki.helpers import JSONResponse
+from wiki.helpers import (JSONResponse, JSONFormInvalid, JSONServerError,
+                ajax_require_permission)
+
 from django import http
-from django.shortcuts import get_object_or_404
+from django.shortcuts import get_object_or_404, render
+from django.views.decorators.http import require_GET, require_POST
 from django.conf import settings
+from django.utils.formats import localize
+from django.utils.translation import ugettext as _
 
-from wiki_img.models import ImageDocument
-from wiki_img.forms import DocumentTextSaveForm
+from catalogue.models import Image
+from wiki import forms
+from wiki import nice_diff
+from wiki_img.forms import ImageSaveForm
 
 #
 # Quick hack around caching problems, TODO: use ETags
@@ -21,50 +27,187 @@ from django.views.decorators.cache import never_cache
 
 @never_cache
 def editor(request, slug, template_name='wiki_img/document_details.html'):
-    doc = get_object_or_404(ImageDocument, slug=slug)
+    doc = get_object_or_404(Image, slug=slug)
 
-    return direct_to_template(request, template_name, extra_context={
+    return render(request, template_name, {
         'document': doc,
         'forms': {
-            "text_save": DocumentTextSaveForm(prefix="textsave"),
+            "text_save": ImageSaveForm(user=request.user, prefix="textsave"),
+            "text_revert": forms.DocumentTextRevertForm(prefix="textrevert"),
+            "pubmark": forms.DocumentPubmarkForm(prefix="pubmark"),
         },
+        'can_pubmark': request.user.has_perm('catalogue.can_pubmark_image'),
+        'REDMINE_URL': settings.REDMINE_URL,
+    })
+
+
+@require_GET
+def editor_readonly(request, slug, template_name='wiki_img/document_details_readonly.html'):
+    doc = get_object_or_404(Image, slug=slug)
+    try:
+        revision = request.GET['revision']
+    except (KeyError):
+        raise Http404
+
+    return render(request, template_name, {
+        'document': doc,
+        'revision': revision,
+        'readonly': True,
         'REDMINE_URL': settings.REDMINE_URL,
     })
 
 
 @never_cache
-def text(request, slug):
+def text(request, image_id):
+    doc = get_object_or_404(Image, pk=image_id)
     if request.method == 'POST':
-        form = DocumentTextSaveForm(request.POST, prefix="textsave")
+        form = ImageSaveForm(request.POST, user=request.user, prefix="textsave")
         if form.is_valid():
-            document = get_object_or_404(ImageDocument, slug=slug)
-            commit = form.cleaned_data['parent_commit']
-
-            comment = form.cleaned_data['comment']
-
             if request.user.is_authenticated():
-                user = request.user
+                author = request.user
             else:
-                user = None
-
-            document.doc.commit(
-                parent=commit,
-                text=form.cleaned_data['text'],
-                author=user,
-                description=comment
-            )
-
+                author = None
+            text = form.cleaned_data['text']
+            parent_revision = form.cleaned_data['parent_revision']
+            if parent_revision is not None:
+                parent = doc.at_revision(parent_revision)
+            else:
+                parent = None
+            stage = form.cleaned_data['stage_completed']
+            tags = [stage] if stage else []
+            publishable = (form.cleaned_data['publishable'] and
+                    request.user.has_perm('catalogue.can_pubmark_image'))
+            doc.commit(author=author,
+                   text=text,
+                   parent=parent,
+                   description=form.cleaned_data['comment'],
+                   tags=tags,
+                   author_name=form.cleaned_data['author_name'],
+                   author_email=form.cleaned_data['author_email'],
+                   publishable=publishable,
+                )
+            revision = doc.revision()
             return JSONResponse({
-                'text': document.doc.materialize(),
-                'revision': document.doc.change_set.count(),
+                'text': doc.materialize() if parent_revision != revision else None,
+                'meta': {},
+                'revision': revision,
             })
         else:
             return JSONFormInvalid(form)
     else:
-        doc = get_object_or_404(ImageDocument, slug=slug).doc
+        revision = request.GET.get("revision", None)
+        
+        try:
+            revision = int(revision)
+        except (ValueError, TypeError):
+            revision = doc.revision()
+
+        if revision is not None:
+            text = doc.at_revision(revision).materialize()
+        else:
+            text = ''
+
         return JSONResponse({
-            'text': doc.materialize(),
-            'revision': doc.change_set.count(),
-            'commit': doc.head.id,
+            'text': text,
+            'meta': {},
+            'revision': revision,
         })
 
+
+@never_cache
+def history(request, object_id):
+    # TODO: pagination
+    doc = get_object_or_404(Image, pk=object_id)
+    if not doc.accessible(request):
+        return HttpResponseForbidden("Not authorized.")
+
+    changes = []
+    for change in doc.history().reverse():
+        changes.append({
+                "version": change.revision,
+                "description": change.description,
+                "author": change.author_str(),
+                "date": localize(change.created_at),
+                "publishable": _("Publishable") + "\n" if change.publishable else "",
+                "tag": ',\n'.join(unicode(tag) for tag in change.tags.all()),
+            })
+    return JSONResponse(changes)
+
+
+@never_cache
+@require_POST
+def revert(request, object_id):
+    form = forms.DocumentTextRevertForm(request.POST, prefix="textrevert")
+    if form.is_valid():
+        doc = get_object_or_404(Image, pk=object_id)
+        if not doc.accessible(request):
+            return HttpResponseForbidden("Not authorized.")
+
+        revision = form.cleaned_data['revision']
+
+        comment = form.cleaned_data['comment']
+        comment += "\n#revert to %s" % revision
+
+        if request.user.is_authenticated():
+            author = request.user
+        else:
+            author = None
+
+        before = doc.revision()
+        logger.info("Reverting %s to %s", object_id, revision)
+        doc.at_revision(revision).revert(author=author, description=comment)
+
+        return JSONResponse({
+            'text': doc.materialize() if before != doc.revision() else None,
+            'meta': {},
+            'revision': doc.revision(),
+        })
+    else:
+        return JSONFormInvalid(form)
+
+
+@never_cache
+def diff(request, object_id):
+    revA = int(request.GET.get('from', 0))
+    revB = int(request.GET.get('to', 0))
+
+    if revA > revB:
+        revA, revB = revB, revA
+
+    if revB == 0:
+        revB = None
+
+    doc = get_object_or_404(Image, pk=object_id)
+    if not doc.accessible(request):
+        return HttpResponseForbidden("Not authorized.")
+
+    # allow diff from the beginning
+    if revA:
+        docA = doc.at_revision(revA).materialize()
+    else:
+        docA = ""
+    docB = doc.at_revision(revB).materialize()
+
+    return http.HttpResponse(nice_diff.html_diff_table(docA.splitlines(),
+                                         docB.splitlines(), context=3))
+
+
+@require_POST
+@ajax_require_permission('catalogue.can_pubmark_image')
+def pubmark(request, object_id):
+    form = forms.DocumentPubmarkForm(request.POST, prefix="pubmark")
+    if form.is_valid():
+        doc = get_object_or_404(Image, pk=object_id)
+        if not doc.accessible(request):
+            return HttpResponseForbidden("Not authorized.")
+
+        revision = form.cleaned_data['revision']
+        publishable = form.cleaned_data['publishable']
+        change = doc.at_revision(revision)
+        if publishable != change.publishable:
+            change.set_publishable(publishable)
+            return JSONResponse({"message": _("Revision marked")})
+        else:
+            return JSONResponse({"message": _("Nothing changed")})
+    else:
+        return JSONFormInvalid(form)