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.translation import ugettext as _
 
  19 from django.views.decorators.http import require_POST
 
  20 from django.shortcuts import get_object_or_404, render
 
  22 from catalogue.models import Document, Template
 
  23 from dvcs.models import Revision
 
  25 from wiki import forms
 
  26 from wiki.helpers import JSONResponse, JSONFormInvalid
 
  29 # Quick hack around caching problems, TODO: use ETags
 
  31 from django.views.decorators.cache import never_cache
 
  33 logger = logging.getLogger("fnp.wiki")
 
  38 def get_history(document):
 
  40     for i, revision in enumerate(document.history()):
 
  43             "description": revision.description,
 
  44             "author": revision.author_str(),
 
  45             "date": localize(revision.created_at),
 
  46             "revision": revision.pk,
 
  47             "published": _("Published") + ": " +
 
  48             localize(revision.publish_log.order_by('-timestamp')[0].timestamp)
 
  49             if revision.publish_log.exists() else "",
 
  55 def editor(request, pk, template_name='wiki/bootstrap.html'):
 
  56     doc = get_object_or_404(Document, pk=pk, deleted=False)
 
  58     save_form = forms.DocumentTextSaveForm(user=request.user, prefix="textsave")
 
  59     text = doc.materialize()
 
  60     revision = doc.revision
 
  61     history = get_history(doc)
 
  62     return render(request, template_name, {
 
  63         'serialized_document_data': json.dumps({
 
  65             'document_id': doc.pk,
 
  66             'title': doc.meta().get('title', ''),
 
  68             'version': len(history),
 
  69             'revision': revision.pk,
 
  71             'assignment': str(doc.assigned_to),
 
  73         'serialized_templates': json.dumps([
 
  74             {'id': t.id, 'name': t.name, 'content': t.content} for t in Template.objects.filter(is_partial=True)
 
  77             "text_save": save_form,
 
  78             "text_revert": forms.DocumentTextRevertForm(prefix="textrevert"),
 
  79             "text_publish": forms.DocumentTextPublishForm(prefix="textpublish"),
 
  86 @decorator_from_middleware(GZipMiddleware)
 
  87 def text(request, doc_id):
 
  88     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
  89     # if not doc.book.accessible(request):
 
  90     #     return HttpResponseForbidden("Not authorized.")
 
  92     if request.method == 'POST':
 
  93         form = forms.DocumentTextSaveForm(request.POST, user=request.user, prefix="textsave")
 
  95             if request.user.is_authenticated():
 
  99             text = form.cleaned_data['text']
 
 100             # parent_revision = form.cleaned_data['parent_revision']
 
 101             # if parent_revision is not None:
 
 102             #     parent = doc.at_revision(parent_revision)
 
 105             stage = form.cleaned_data['stage']
 
 106             # tags = [stage] if stage else []
 
 107             # publishable = (form.cleaned_data['publishable'] and
 
 108             #                request.user.has_perm('catalogue.can_pubmark'))
 
 113                     description=form.cleaned_data['comment'],
 
 114                     author_name=form.cleaned_data['author_name'],
 
 115                     author_email=form.cleaned_data['author_email'],
 
 119                 from traceback import print_exc
 
 122             # revision = doc.revision()
 
 123             return JSONResponse({
 
 124                 'text': None,  # doc.materialize() if parent_revision != revision else None,
 
 125                 # 'version': revision,
 
 126                 # 'stage': doc.stage.name if doc.stage else None,
 
 127                 'assignment': doc.assigned_to.username if doc.assigned_to else None
 
 130             return JSONFormInvalid(form)
 
 132         revision = request.GET.get("revision", None)
 
 135             revision = int(revision)
 
 136         except (ValueError, TypeError):
 
 137             revision = doc.revision()
 
 139         if revision is not None:
 
 140             text = doc.at_revision(revision).materialize()
 
 144         return JSONResponse({
 
 147             'revision': revision,
 
 153 def revert(request, doc_id):
 
 154     form = forms.DocumentTextRevertForm(request.POST, prefix="textrevert")
 
 156         doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 157         rev = get_object_or_404(Revision, pk=form.cleaned_data['revision'])
 
 159         comment = form.cleaned_data['comment']
 
 160         comment += "\n#revert to %s" % rev.pk
 
 162         if request.user.is_authenticated():
 
 163             author = request.user
 
 167         # before = doc.revision
 
 168         logger.info("Reverting %s to %s", doc_id, rev.pk)
 
 172             text=rev.materialize(),
 
 174             # author_name=form.cleaned_data['author_name'], #?
 
 175             # author_email=form.cleaned_data['author_email'], #?
 
 178         return JSONResponse({
 
 179             # 'document': None, #doc.materialize() if before != doc.revision else None,
 
 180             # 'version': doc.revision(),
 
 183         return JSONFormInvalid(form)
 
 187 def gallery(request, directory):
 
 188     if not request.user.is_authenticated():
 
 189         return HttpResponseForbidden("Not authorized.")
 
 193                         smart_unicode(settings.MEDIA_URL),
 
 194                         smart_unicode(settings.IMAGE_DIR),
 
 195                         smart_unicode(directory)))
 
 197         base_dir = os.path.join(
 
 198                     smart_unicode(settings.MEDIA_ROOT),
 
 199                     smart_unicode(settings.IMAGE_DIR),
 
 200                     smart_unicode(directory))
 
 202         def map_to_url(filename):
 
 203             return urllib.quote("%s/%s" % (base_url, smart_unicode(filename)))
 
 205         def is_image(filename):
 
 206             return os.path.splitext(f)[1].lower() in (u'.jpg', u'.jpeg', u'.png')
 
 208         images = [map_to_url(f) for f in map(smart_unicode, os.listdir(base_dir)) if is_image(f)]
 
 211         return JSONResponse(images)
 
 212     except (IndexError, OSError):
 
 213         logger.exception("Unable to fetch gallery")
 
 218 def diff(request, doc_id):
 
 219     revA = int(request.GET.get('from', 0))
 
 220     revB = int(request.GET.get('to', 0))
 
 223         revA, revB = revB, revA
 
 228     # TODO: check if revisions in line.
 
 230     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 232     # allow diff from the beginning
 
 234         docA = Revision.objects.get(pk=revA).materialize()
 
 237     docB = Revision.objects.get(pk=revB).materialize()
 
 239     return http.HttpResponse(nice_diff.html_diff_table(docA.splitlines(), docB.splitlines(), context=3))
 
 243 def history(request, doc_id):
 
 245     doc = get_object_or_404(Document, pk=doc_id, deleted=False)
 
 247     return JSONResponse(get_history(doc))