1 # -*- coding: utf-8 -*-
 
   3 # This file is part of MIL/PEER, licensed under GNU Affero GPLv3 or later.
 
   4 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 
  11 from django.conf import settings
 
  12 from django import http
 
  13 from django.http import HttpResponseForbidden
 
  14 from django.middleware.gzip import GZipMiddleware
 
  15 from django.utils.decorators import decorator_from_middleware
 
  16 from django.utils.encoding import smart_unicode
 
  17 from django.utils.formats import localize
 
  18 from django.utils.html import escape
 
  19 from django.utils.translation import ugettext as _
 
  20 from django.views.decorators.http import require_POST
 
  21 from django.shortcuts import get_object_or_404, render
 
  23 from catalogue.models import Document, Template
 
  24 from dvcs.models import Revision
 
  26 from wiki import forms
 
  27 from wiki.helpers import JSONResponse, JSONFormInvalid
 
  30 # Quick hack around caching problems, TODO: use ETags
 
  32 from django.views.decorators.cache import never_cache
 
  34 logger = logging.getLogger("fnp.wiki")
 
  39 def get_history(document):
 
  41     for i, revision in enumerate(document.history()):
 
  44             "description": revision.description,
 
  45             "author": escape(revision.author_str()),
 
  46             "date": localize(revision.created_at),
 
  47             "revision": revision.pk,
 
  48             "published": _("Published") + ": " +
 
  49             localize(revision.publish_log.order_by('-timestamp')[0].timestamp)
 
  50             if revision.publish_log.exists() else "",
 
  56 def editor(request, pk, template_name='wiki/bootstrap.html'):
 
  57     doc = get_object_or_404(Document, pk=pk, deleted=False)
 
  59     save_form = forms.DocumentTextSaveForm(user=request.user, prefix="textsave")
 
  60     text = doc.materialize()
 
  61     revision = doc.revision
 
  62     history = get_history(doc)
 
  63     return render(request, template_name, {
 
  64         'serialized_document_data': json.dumps({
 
  66             'document_id': doc.pk,
 
  67             'title': doc.meta().get('title', ''),
 
  69             'version': len(history),
 
  70             'revision': revision.pk,
 
  72             'stage_name': doc.stage_name(),
 
  73             'assignment': doc.assigned_to.username if doc.assigned_to else None,
 
  75         'serialized_templates': json.dumps([
 
  76             {'id': t.id, 'name': t.name, 'content': t.content} for t in Template.objects.filter(is_partial=True)
 
  79             "text_save": save_form,
 
  80             "text_revert": forms.DocumentTextRevertForm(prefix="textrevert"),
 
  81             "text_publish": forms.DocumentTextPublishForm(prefix="textpublish"),
 
  88 @decorator_from_middleware(GZipMiddleware)
 
  89 def text(request, doc_id):
 
  90     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
  91     # if not doc.book.accessible(request):
 
  92     #     return HttpResponseForbidden("Not authorized.")
 
  94     if request.method == 'POST':
 
  95         form = forms.DocumentTextSaveForm(request.POST, user=request.user, prefix="textsave")
 
  97             if request.user.is_authenticated():
 
 101             text = form.cleaned_data['text']
 
 102             # parent_revision = form.cleaned_data['parent_revision']
 
 103             # if parent_revision is not None:
 
 104             #     parent = doc.at_revision(parent_revision)
 
 107             stage = form.cleaned_data['stage']
 
 108             # tags = [stage] if stage else []
 
 109             # publishable = (form.cleaned_data['publishable'] and
 
 110             #                request.user.has_perm('catalogue.can_pubmark'))
 
 115                     description=form.cleaned_data['comment'],
 
 116                     author_name=form.cleaned_data['author_name'],
 
 117                     author_email=form.cleaned_data['author_email'],
 
 121                 from traceback import print_exc
 
 124             return JSONResponse({
 
 125                 'text': None,  # doc.materialize() if parent_revision != revision else None,
 
 126                 'version': len(get_history(doc)),
 
 128                 'stage_name': doc.stage_name(),
 
 129                 'assignment': doc.assigned_to.username if doc.assigned_to else None
 
 132             return JSONFormInvalid(form)
 
 134         revision = request.GET.get("revision", None)
 
 137             revision = int(revision)
 
 138         except (ValueError, TypeError):
 
 139             revision = doc.revision()
 
 141         if revision is not None:
 
 142             text = doc.at_revision(revision).materialize()
 
 146         return JSONResponse({
 
 149             'revision': revision,
 
 155 def revert(request, doc_id):
 
 156     form = forms.DocumentTextRevertForm(request.POST, prefix="textrevert")
 
 158         doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 159         rev = get_object_or_404(Revision, pk=form.cleaned_data['revision'])
 
 161         comment = form.cleaned_data['comment']
 
 162         comment += "\n#revert to %s" % rev.pk
 
 164         if request.user.is_authenticated():
 
 165             author = request.user
 
 169         # before = doc.revision
 
 170         logger.info("Reverting %s to %s", doc_id, rev.pk)
 
 174             text=rev.materialize(),
 
 176             # author_name=form.cleaned_data['author_name'], #?
 
 177             # author_email=form.cleaned_data['author_email'], #?
 
 180         return JSONResponse({
 
 181             'document': doc.materialize(),
 
 182             'version': len(get_history(doc)),
 
 184             'stage_name': doc.stage_name(),
 
 185             'assignment': doc.assigned_to.username if doc.assigned_to else None,
 
 188         return JSONFormInvalid(form)
 
 192 def gallery(request, directory):
 
 193     if not request.user.is_authenticated():
 
 194         return HttpResponseForbidden("Not authorized.")
 
 198                         smart_unicode(settings.MEDIA_URL),
 
 199                         smart_unicode(settings.IMAGE_DIR),
 
 200                         smart_unicode(directory)))
 
 202         base_dir = os.path.join(
 
 203                     smart_unicode(settings.MEDIA_ROOT),
 
 204                     smart_unicode(settings.IMAGE_DIR),
 
 205                     smart_unicode(directory))
 
 207         def map_to_url(filename):
 
 208             return urllib.quote("%s/%s" % (base_url, smart_unicode(filename)))
 
 210         def is_image(filename):
 
 211             return os.path.splitext(f)[1].lower() in (u'.jpg', u'.jpeg', u'.png')
 
 213         images = [map_to_url(f) for f in map(smart_unicode, os.listdir(base_dir)) if is_image(f)]
 
 216         return JSONResponse(images)
 
 217     except (IndexError, OSError):
 
 218         logger.exception("Unable to fetch gallery")
 
 223 def diff(request, doc_id):
 
 224     revA = int(request.GET.get('from', 0))
 
 225     revB = int(request.GET.get('to', 0))
 
 228         revA, revB = revB, revA
 
 233     # TODO: check if revisions in line.
 
 235     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 237     # allow diff from the beginning
 
 239         docA = Revision.objects.get(pk=revA).materialize()
 
 242     docB = Revision.objects.get(pk=revB).materialize()
 
 244     return http.HttpResponse(nice_diff.html_diff_table(docA.splitlines(), docB.splitlines(), context=3))
 
 248 def history(request, doc_id):
 
 250     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 252     return JSONResponse(get_history(doc))