Commit fcc466d5 by benjaoming

Image management, revert, delete and restore

parent c1455967
...@@ -35,14 +35,13 @@ class ArticleQuerySet(QuerySet): ...@@ -35,14 +35,13 @@ class ArticleQuerySet(QuerySet):
def active(self): def active(self):
return self.filter(current_revision__deleted=False) return self.filter(current_revision__deleted=False)
class ArticleFkQuerySet(QuerySet): class ArticleFkQuerySet(QuerySet):
def can_read(self, user): def can_read(self, user):
"""Filter objects so only the ones with a user's reading access """Filter objects so only the ones with a user's reading access
are included""" are included"""
if user.has_perm('wiki.moderator'): if user.has_perm('wiki.moderator'):
return self.get_query_set() return self
if user.is_anonymous(): if user.is_anonymous():
q = self.filter(article__other_read=True) q = self.filter(article__other_read=True)
else: else:
...@@ -56,7 +55,7 @@ class ArticleFkQuerySet(QuerySet): ...@@ -56,7 +55,7 @@ class ArticleFkQuerySet(QuerySet):
"""Filter objects so only the ones with a user's writing access """Filter objects so only the ones with a user's writing access
are included""" are included"""
if user.has_perm('wiki.moderator'): if user.has_perm('wiki.moderator'):
return self.get_query_set() return self
if user.is_anonymous(): if user.is_anonymous():
q = self.filter(article__other_write=True) q = self.filter(article__other_write=True)
else: else:
......
...@@ -153,9 +153,9 @@ class RevisionPlugin(ArticlePlugin): ...@@ -153,9 +153,9 @@ class RevisionPlugin(ArticlePlugin):
# Permissions... overwrite if necessary # Permissions... overwrite if necessary
def can_read(self, **kwargs): def can_read(self, **kwargs):
return self.article.can_read(self, **kwargs) return self.article.can_read(**kwargs)
def can_write(self, **kwargs): def can_write(self, **kwargs):
return self.article.can_write(self, **kwargs) return self.article.can_write(**kwargs)
def add_revision(self, new_revision, save=True): def add_revision(self, new_revision, save=True):
""" """
...@@ -217,6 +217,7 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model): ...@@ -217,6 +217,7 @@ class RevisionPluginRevision(BaseRevisionMixin, models.Model):
class Meta: class Meta:
app_label = settings.APP_LABEL app_label = settings.APP_LABEL
get_latest_by = ('revision_number',) get_latest_by = ('revision_number',)
ordering = ('-created',)
###################################################### ######################################################
# SIGNAL HANDLERS # SIGNAL HANDLERS
...@@ -233,6 +234,6 @@ def update_simple_plugins(instance, *args, **kwargs): ...@@ -233,6 +234,6 @@ def update_simple_plugins(instance, *args, **kwargs):
if kwargs.get('created', False): if kwargs.get('created', False):
p_revisions = SimplePlugin.objects.filter(article=instance.article, deleted=False) p_revisions = SimplePlugin.objects.filter(article=instance.article, deleted=False)
# TODO: This was breaking things. SimplePlugin doesn't have a revision? # TODO: This was breaking things. SimplePlugin doesn't have a revision?
#p_revisions.update(revision=instance) p_revisions.update(article_revision=instance)
signals.post_save.connect(update_simple_plugins, ArticleRevision) signals.post_save.connect(update_simple_plugins, ArticleRevision)
\ No newline at end of file
...@@ -236,7 +236,7 @@ class AttachmentSearchView(ArticleMixin, ListView): ...@@ -236,7 +236,7 @@ class AttachmentSearchView(ArticleMixin, ListView):
def get_queryset(self): def get_queryset(self):
self.query = self.request.GET.get('query', None) self.query = self.request.GET.get('query', None)
if not self.query: if not self.query:
qs = models.Attachment.objects.active().get_empty_query_set() qs = models.Attachment.objects.get_empty_query_set()
else: else:
qs = models.Attachment.objects.active().can_read(self.request.user) qs = models.Attachment.objects.active().can_read(self.request.user)
qs = qs.filter(Q(original_filename__contains=self.query) | qs = qs.filter(Q(original_filename__contains=self.query) |
......
...@@ -15,7 +15,7 @@ def upload_path(instance, filename): ...@@ -15,7 +15,7 @@ def upload_path(instance, filename):
# Has to match original extension filename # Has to match original extension filename
upload_path = settings.UPLOAD_PATH upload_path = settings.UPLOAD_PATH
upload_path = upload_path.replace('%aid', str(instance.image.article.id)) upload_path = upload_path.replace('%aid', str(instance.plugin.image.article.id))
if settings.UPLOAD_PATH_OBSCURIFY: if settings.UPLOAD_PATH_OBSCURIFY:
import random, hashlib import random, hashlib
m=hashlib.md5(str(random.randint(0,100000000000000))) m=hashlib.md5(str(random.randint(0,100000000000000)))
...@@ -45,7 +45,11 @@ class Image(RevisionPlugin): ...@@ -45,7 +45,11 @@ class Image(RevisionPlugin):
class ImageRevision(RevisionPluginRevision): class ImageRevision(RevisionPluginRevision):
image = models.ImageField(upload_to=upload_path, image = models.ImageField(upload_to=upload_path,
max_length=2000) max_length=2000, height_field='height',
width_field='width')
width = models.SmallIntegerField(default=0)
height = models.SmallIntegerField(default=0)
def get_filename(self): def get_filename(self):
if self.image: if self.image:
...@@ -54,11 +58,25 @@ class ImageRevision(RevisionPluginRevision): ...@@ -54,11 +58,25 @@ class ImageRevision(RevisionPluginRevision):
def get_size(self): def get_size(self):
"""Used to retrieve the file size and not cause exceptions.""" """Used to retrieve the file size and not cause exceptions."""
try: try:
return self.file.size return self.image.size
except ValueError: except ValueError:
return None return None
def inherit_predecessor(self, image):
"""
Inherit certain properties from predecessor because it's very
convenient. Remember to always call this method before
setting properties :)"""
predecessor = image.current_revision.imagerevision
self.plugin = predecessor.plugin
self.image = predecessor.image
self.width = predecessor.width
self.height = predecessor.height
self.deleted = predecessor.deleted
self.locked = predecessor.locked
class Meta: class Meta:
verbose_name = _(u'image revision') verbose_name = _(u'image revision')
verbose_name_plural = _(u'image revisions') verbose_name_plural = _(u'image revisions')
app_label = settings.APP_LABEL app_label = settings.APP_LABEL
ordering = ('-created',)
{% extends "wiki/article.html" %} {% extends "wiki/article.html" %}
{% load wiki_tags i18n humanize %} {% load wiki_tags i18n humanize thumbnail %}
{% load url from future %} {% load url from future %}
{% block pagetitle %}{% trans "Images" %}: {{ article.current_revision.title }}{% endblock %} {% block pagetitle %}{% trans "Images" %}: {{ article.current_revision.title }}{% endblock %}
...@@ -7,26 +7,84 @@ ...@@ -7,26 +7,84 @@
{% block wiki_contents_tab %} {% block wiki_contents_tab %}
<p class="lead">{% trans "The following images are available for this article. Copy the markdown tag to directly refer to an image from the article text." %}</p> <p class="lead">{% trans "The following images are available for this article. Copy the markdown tag to directly refer to an image from the article text." %}</p>
<p> <p>
<a href="{% url 'wiki:edit' path=urlpath.path article_id=article.id %}" class="btn btn-large"> <a href="{% url 'wiki:edit' path=urlpath.path article_id=article.id %}">
<span class="icon-arrow-left"></span> <span class="icon-arrow-left"></span>
{% trans "Back to edit page" %} {% trans "Back to edit page" %}
</a> </a>
</p> </p>
<table class="table table-bordered table-striped" style="width: 100%;"> <table class="table table-bordered table-striped" style="width: 100%;">
{% for image in images %}
{% with image.current_revision.imagerevision as revision %}
<tr> <tr>
<th>{% trans "Image" %}</th> <th>{{ revision.get_filename }}</th>
<th>{% trans "Markdown tag" %}</th> <th>{% trans "Markdown tag" %}</th>
<th>{% trans "Uploaded by" %}</th> <th>{% trans "Uploaded by" %}</th>
<th>{% trans "Size" %}</th> <th>{% trans "Size" %}</th>
</tr> </tr>
{% for image in images %}
<tr> <tr>
<td rowspan="3">
{% thumbnail revision.image "250x150" crop="center" as thumb %}
<p class="thumbnail">
<img src="{{ thumb.url }}" alt="{{ revision.get_filename }}" />
</p>
{% endthumbnail %}
{% if image|can_write:user %}
<p>
<a href="#">
<span class="icon-upload"></span>
{% trans "Upload new file" %}
</a> <br />
{% if revision.deleted %}
<a href="{% url 'wiki:images_restore' path=urlpath.path article_id=article.id image_id=image.id %}">
<span class="icon-repeat"></span>
{% trans "Restore image" %}
</a>
{% else %}
<a href="{% url 'wiki:images_delete' path=urlpath.path article_id=article.id image_id=image.id %}">
<span class="icon-remove"></span>
{% trans "Remove image" %}
</a>
{% endif %}
</p>
{% endif %}
</td>
<td><code>[image:{{ image.id }}]</code></td> <td><code>[image:{{ image.id }}]</code></td>
<td> <td>
{% if image.current_revision.user %}{{ image.current_revision.user }}{% else %}{% if user|is_moderator %}{{ image.current_revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} <p>{% include "wiki/includes/revision_info.html" %}</p>
</td>
<td>{{ revision.get_size|filesizeformat }}<br />{{ revision.width }}x{{ revision.height }} pixels
</td> </td>
<td>{{ image.current_revision.get_size|filesizeformat }}</td>
</tr> </tr>
<tr>
<th colspan="100">{% trans "History" %}</th>
</tr>
<tr>
<td colspan="100">
<table class="table">
{% for old_revision in image.revision_set.all %}
<tr>
<td>
{% thumbnail revision.imagerevision.image "50x50" crop="center" as thumb %}
<img src="{{ thumb.url }}" alt="{{ revision.imagerevision.get_filename }}" />
{% endthumbnail %}
</td>
<td>{% include "wiki/includes/revision_info.html" with current_revision=image.current_revision revision=old_revision %}</td>
<td>{{ old_revision.imagerevision.get_size|filesizeformat }}</td>
<td>{{ old_revision.imagerevision.width }}x{{ old_revision.imagerevision.height }}</td>
<td>
{% if image|can_write:user and old_revision != image.current_revision %}
<a href="#">
<span class="icon-refresh"></span>
{% trans "Revert to this version" %}
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
{% endwith %}
{% empty %} {% empty %}
<tr> <tr>
<td colspan="100"> <td colspan="100">
...@@ -36,5 +94,7 @@ ...@@ -36,5 +94,7 @@
</table> </table>
{% include "wiki/includes/pagination.html" %}
{% endblock %} {% endblock %}
{% load i18n wiki_tags wiki_images_tags humanize thumbnail %} {% load i18n wiki_tags wiki_images_tags humanize thumbnail %}
{% load url from future %} {% load url from future %}
<h4>{% trans "Available images" %}</h4> {% with article|images_for_article as images %}
<style type="text/css">
<p>{% trans "Click on an image below to insert in your text. The format of the code inserted is:" %}<br /><code>[image:id alignment caption text]</code></p> #image-list tr:first-child td {border:0;}
</style>
<div style="max-height: 300px; overflow: auto;"> <div style="max-height: 300px; overflow: scroll-y;">
<table class="table table-striped"> <table class="table" style="margin-bottom: 0;" id="image-list">
{% for image in article|images_for_article %} {% for image in images %}
{% thumbnail image.image "150x50" crop="center" as thumb %} {% with image.current_revision.imagerevision as revision %}
{% thumbnail revision.image "50x50" crop="center" as thumb %}
<tr> <tr>
<td style="white-space: nowrap;">
<p>{{ revision.get_filename|truncatechars:30 }}</p>
<p>
<a href=""><span class="icon-edit"></span> {% trans "Insert" %}</a> <br />
<a href=""><span class="icon-edit"></span> {% trans "Replace" %}</a>
</p>
</td>
<td> <td>
<div class="thumbnail"> <div class="thumbnail">
<img src="{{ thumb.url }}" alt="{{ image.get_filename }}" /> <img src="{{ thumb.url }}" alt="{{ revision.get_filename }}" />
</div> </div>
</td> </td>
<td>
<span class="label">
{% trans "uploaded" %} {{ image.created|naturaltime }}
</span>
</td>
</tr> </tr>
{% endthumbnail %} {% endthumbnail %}
{% endwith %}
{% empty %} {% empty %}
<tr> <tr>
<td><em>{% trans "No images found for this article" %}</em></td> <td><em>{% trans "No images found for this article" %}</em></td>
...@@ -30,12 +34,13 @@ ...@@ -30,12 +34,13 @@
</table> </table>
</div> </div>
{% if images %}
<p> <p>
<a href="{% url 'wiki:images_index' path=urlpath.path article_id=article.id %}"> <a href="{% url 'wiki:images_index' path=urlpath.path article_id=article.id %}">
{% trans "Manage images" %} &raquo; {% trans "Manage images" %} &raquo;
</a> </a>
</p> </p>
{% endif %}
<hr /> <hr />
<h4>{% trans "Add new image" %}</h4> <h4>{% trans "Add new image" %}</h4>
...@@ -85,3 +90,14 @@ ...@@ -85,3 +90,14 @@
<p><em>{% trans "You do not have permissions to add images." %}</em></p> <p><em>{% trans "You do not have permissions to add images." %}</em></p>
{% endif %} {% endif %}
{% endif %} {% endif %}
<hr />
<h4>
{% trans "How to use images" %}
</h4>
<p>{% trans "After uploading an image, it is attached to this particular artice and can be used only here. Other users may replace the image, but older versions are kept. You probably want to show the image with a nice caption. To achieve this, press the Insert button and fill in the caption fields and possibly choose to have you image floating right or left of the content. You can use Markdown in the caption. The markdown code syntax for images looks like this:" %}<br /><code>[image:id alignment caption text]</code></p>
{% endwith %}
...@@ -7,7 +7,7 @@ register = template.Library() ...@@ -7,7 +7,7 @@ register = template.Library()
@register.filter @register.filter
def images_for_article(article): def images_for_article(article):
return models.ImageRevision.objects.filter(plugin__article=article).order_by('-created') return models.Image.objects.filter(article=article).order_by('-current_revision__created')
@register.filter @register.filter
def images_can_add(article, user): def images_can_add(article, user):
......
from django.views.generic.list import ListView from django.contrib import messages
from django.core.urlresolvers import reverse
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _
from django.views.generic.base import RedirectView
from django.views.generic.list import ListView
from wiki.decorators import get_article from wiki.decorators import get_article
from wiki.views.mixins import ArticleMixin
from wiki.plugins.images import models from wiki.plugins.images import models
from wiki.views.mixins import ArticleMixin
class ImageView(ArticleMixin, ListView): class ImageView(ArticleMixin, ListView):
...@@ -18,9 +22,66 @@ class ImageView(ArticleMixin, ListView): ...@@ -18,9 +22,66 @@ class ImageView(ArticleMixin, ListView):
return super(ImageView, self).dispatch(request, article, *args, **kwargs) return super(ImageView, self).dispatch(request, article, *args, **kwargs)
def get_queryset(self): def get_queryset(self):
return models.Image.objects.filter(article=self.article) if (self.request.user.has_perm('wiki.moderator') or
self.article.owner == self.request.user):
images = models.Image.objects.filter(article=self.article)
else:
images = models.Image.objects.filter(article=self.article,
current_revision__deleted=False)
images.select_related()
return images
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
kwargs.update(ArticleMixin.get_context_data(self, **kwargs)) kwargs.update(ArticleMixin.get_context_data(self, **kwargs))
return ListView.get_context_data(self, **kwargs) return ListView.get_context_data(self, **kwargs)
class DeleteView(ArticleMixin, RedirectView):
permanent = False
@method_decorator(get_article(can_write=True))
def dispatch(self, request, article, *args, **kwargs):
self.image = get_object_or_404(models.Image, article=article,
id=kwargs.get('image_id', None))
self.restore = kwargs.get('restore', False)
return ArticleMixin.dispatch(self, request, article, *args, **kwargs)
def get_redirect_url(self, **kwargs):
new_revision = models.ImageRevision()
new_revision.inherit_predecessor(self.image)
new_revision.set_from_request(self.request)
new_revision.deleted = not self.restore
new_revision.save()
self.image.current_revision = new_revision
self.image.save()
if self.restore:
messages.info(self.request, _('%s has been marked as deleted') % new_revision.get_filename())
else:
messages.info(self.request, _('%s has been restored') % new_revision.get_filename())
if self.urlpath:
return reverse('wiki:images_index', kwargs={'path': self.urlpath.path})
return reverse('wiki:images_index', kwargs={'article_id': self.article.id})
class RevisionChangeView(ArticleMixin, RedirectView):
permanent = False
@method_decorator(get_article(can_write=True))
def dispatch(self, request, article, *args, **kwargs):
self.image = get_object_or_404(models.Image, article=article,
id=kwargs.get('image_id', None))
self.revision = get_object_or_404(models.ImageRevision, plugin__article=article,
id=kwargs.get('rev_id', None))
return ArticleMixin.dispatch(self, request, article, *args, **kwargs)
def get_redirect_url(self, **kwargs):
self.image.current_revision = self.revision
self.image.save()
messages.info(self.request, _('%(file)s has been changed to revision #%(revision)d') %
{'file': self.image.current_revision.imagerevision.get_filename(),
'revision': self.revision.revision_number})
if self.urlpath:
return reverse('wiki:images_index', kwargs={'path': self.urlpath.path})
return reverse('wiki:images_index', kwargs={'article_id': self.article.id})
...@@ -25,7 +25,7 @@ class ImagePlugin(BasePlugin): ...@@ -25,7 +25,7 @@ class ImagePlugin(BasePlugin):
# List of notifications to construct signal handlers for. This # List of notifications to construct signal handlers for. This
# is handled inside the notifications plugin. # is handled inside the notifications plugin.
notifications = [{'model': models.Image, notifications = [{'model': models.Image,
'message': lambda obj: _(u"An image was added: %s") % obj.get_filename(), 'message': lambda obj: _(u"An image was added: %s") % obj.current_revision.get_filename(),
'key': ARTICLE_EDIT, 'key': ARTICLE_EDIT,
'created': True, 'created': True,
'get_article': lambda obj: obj.article} 'get_article': lambda obj: obj.article}
...@@ -33,6 +33,9 @@ class ImagePlugin(BasePlugin): ...@@ -33,6 +33,9 @@ class ImagePlugin(BasePlugin):
urlpatterns = patterns('', urlpatterns = patterns('',
url('^$', views.ImageView.as_view(), name='images_index'), url('^$', views.ImageView.as_view(), name='images_index'),
url('^delete/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_delete'),
url('^restore/(?P<image_id>\d+)/$', views.DeleteView.as_view(), name='images_restore', kwargs={'restore': True}),
url('^restore/(?P<image_id>\d+)/set-revision/(?P<rev_id>\d+)/$', views.RevisionChangeView.as_view(), name='images_restore'),
) )
#markdown_extensions = [AttachmentExtension()] #markdown_extensions = [AttachmentExtension()]
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#id_title {font-size: 20px; height: 30px; padding: 6px; width: 98%;} #id_title {font-size: 20px; height: 30px; padding: 6px; width: 98%;}
#id_summary {width: 98%; padding: 6px;} #id_summary {width: 98%; padding: 6px;}
#article_edit_form label {max-width: 120px;} #article_edit_form label {max-width: 100px;}
#article_edit_form .controls {margin-left: 140px;} #article_edit_form .controls {margin-left: 120px;}
.form-horizontal label { font-size: 18px; font-weight: bold; color: #777;} .form-horizontal label { font-size: 18px; font-weight: bold; color: #777;}
#settings_form label {font-size: inherit; font-weight: normal;} #settings_form label {font-size: inherit; font-weight: normal;}
......
...@@ -6,17 +6,32 @@ ...@@ -6,17 +6,32 @@
{% block wiki_contents_tab %} {% block wiki_contents_tab %}
<div style="width: 67%; min-width: 600px; float: left;"> <div class="row-fluid">
<div class="span8">
<form method="POST" class="form-horizontal" id="article_edit_form"> <form method="POST" class="form-horizontal" id="article_edit_form">
<input type="hidden" name="save" value="1" />
<input type="hidden" name="preview" value="1" />
{% with edit_form as form %} {% with edit_form as form %}
{% include "wiki/includes/editor.html" %} {% include "wiki/includes/editor.html" %}
{% endwith %} {% endwith %}
</form>
</div>
<div class="span4">
{% include "wiki/includes/editor_sidebar.html" %}
</div>
</div>
<div style="clear: both"></div>
<div class="form-actions"> <div class="form-actions">
<button type="submit" name="preview" value="1" class="btn btn-large" onclick="$('#previewModal').modal('show'); this.form.target='previewWindow'; this.form.action='{% url 'wiki:preview' path=urlpath.path article_id=article.id %}'"> <a class="btn btn-large" onclick="$('#previewModal').modal('show'); document.getElementById('article_edit_form').target='previewWindow'; document.getElementById('article_edit_form').action='{% url 'wiki:preview' path=urlpath.path article_id=article.id %}'; $('#article_edit_form').submit()" href="#">
<span class="icon-eye-open"></span> <span class="icon-eye-open"></span>
{% trans "Preview" %} {% trans "Preview" %}
</button> </a>
<button type="submit" name="save" value="1" class="btn btn-large btn-primary" onclick="this.form.target=''; this.form.action='{% url 'wiki:edit' path=urlpath.path article_id=article.id %}'"> <a class="btn btn-large btn-primary" onclick="document.getElementById('article_edit_form').target=''; document.getElementById('article_edit_form').action='{% url 'wiki:edit' path=urlpath.path article_id=article.id %}'; $('#article_edit_form').submit();" href="#">
<span class="icon-ok"></span> <span class="icon-ok"></span>
{% trans "Save changes" %} {% trans "Save changes" %}
</button> </button>
...@@ -36,23 +51,12 @@ ...@@ -36,23 +51,12 @@
<span class="icon-circle-arrow-left"></span> <span class="icon-circle-arrow-left"></span>
{% trans "Back to editor" %} {% trans "Back to editor" %}
</a> </a>
<button type="submit" name="save" value="1" class="btn btn-large btn-primary" onclick="this.form.target=''; this.form.action='{% url 'wiki:edit' path=urlpath.path article_id=article.id %}'"> <a class="btn btn-large btn-primary" onclick="document.getElementById('article_edit_form').target=''; document.getElementById('article_edit_form').action='{% url 'wiki:edit' path=urlpath.path article_id=article.id %}'; document.getElementById('article_edit_form').submit();" href="#">
<span class="icon-ok"></span> <span class="icon-ok"></span>
{% trans "Save changes" %} {% trans "Save changes" %}
</button> </a>
</div>
</div>
</form>
</div>
<div style="width: 33%; min-width: 300px; float: right;">
<div style="padding-left: 40px;">
{% include "wiki/includes/editor_sidebar.html" %}
</div> </div>
</div> </div>
<div style="clear: both"></div>
{% endblock %} {% endblock %}
...@@ -60,16 +60,7 @@ ...@@ -60,16 +60,7 @@
<div class="accordion-group"> <div class="accordion-group">
<div class="accordion-heading"> <div class="accordion-heading">
<a class="accordion-toggle" style="float: left;" href="#collapse{{ revision.revision_number }}" onclick="get_diff_json('{% url 'wiki:diff' revision.id %}', $('#collapse{{ revision.revision_number }}'))"> <a class="accordion-toggle" style="float: left;" href="#collapse{{ revision.revision_number }}" onclick="get_diff_json('{% url 'wiki:diff' revision.id %}', $('#collapse{{ revision.revision_number }}'))">
{{ revision.created }} (#{{ revision.revision_number }}) by {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} {% include "wiki/includes/revision_info.html" with current_revision=article.current_revision %}
{% if revision == article.current_revision %}
<strong>*</strong>
{% endif %}
{% if revision.deleted %}
<span class="badge badge-important">{% trans "deleted" %}</span>
{% endif %}
{% if revision.previous_revision.deleted and not revision.deleted %}
<span class="badge badge-success">{% trans "restored" %}</span>
{% endif %}
<div style="color: #CCC;"> <div style="color: #CCC;">
<small> <small>
{% if revision.user_message %} {% if revision.user_message %}
......
{% comment %}
This reusable code is shared between different templates and different inheritors of
BaseRevision.
{% endcomment %}
{% load wiki_tags i18n %}
{{ revision.created }} (#{{ revision.revision_number }}) {% trans "by" %} {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %}
{% if revision == current_revision %}
<strong>*</strong>
{% endif %}
{% if revision.deleted %}
<span class="badge badge-important">{% trans "deleted" %}</span>
{% endif %}
{% if revision.previous_revision.deleted and not revision.deleted %}
<span class="badge badge-success">{% trans "restored" %}</span>
{% endif %}
...@@ -5,16 +5,17 @@ ...@@ -5,16 +5,17 @@
{% if revision %} {% if revision %}
<div class="alert alert-info"> <div class="alert alert-info">
<strong>{% trans "Previewing revision" %}:</strong> {{ revision.created }} (#{{ revision.revision_number }}) by {% if revision.user %}{{ revision.user }}{% else %}{% if user|is_moderator %}{{ revision.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} <strong>{% trans "Previewing revision" %}:</strong>
{% include "wiki/includes/revision_info.html" %}
</div> </div>
{% endif %} {% endif %}
{% if merge %} {% if merge %}
<div class="alert alert-info"> <div class="alert alert-info">
<strong>{% trans "Previewing merge between" %}:</strong> <strong>{% trans "Previewing merge between" %}:</strong>
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} {% include "wiki/includes/revision_info.html" with revision=merge1 %}
<strong>{% trans "and" %}</strong> <strong>{% trans "and" %}</strong>
{{ merge1.created }} (#{{ merge1.revision_number }}) by {% if merge1.user %}{{ merge1.user }}{% else %}{% if user|is_moderator %}{{ merge1.ip_address|default:"anonymous (IP not logged)" }}{% else %}{% trans "anonymous (IP logged)" %}{% endif %}{% endif %} {% include "wiki/includes/revision_info.html" with revision=merge2 %}
</div> </div>
{% endif %} {% endif %}
......
...@@ -59,7 +59,7 @@ def can_read(obj, user): ...@@ -59,7 +59,7 @@ def can_read(obj, user):
@register.filter @register.filter
def can_write(obj, user): def can_write(obj, user):
"""Articles and plugins have a can_write method...""" """Articles and plugins have a can_write method..."""
return obj.can_write(user=user) return obj.can_write(**{'user': user})
@register.filter @register.filter
def is_moderator(user): def is_moderator(user):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment