comments admin management improved

remotes/origin/stage6
Alexander Burdeinyi 9 years ago
parent ef8c9717ba
commit 4ce7d412b2
  1. 75
      comments/admin.py
  2. 1
      comments/forms.py
  3. 6
      static/admin/css/comments_manage.css
  4. 24
      static/admin/js/comments_manage.js
  5. 98
      static/js/jquery.truncator.js

@ -1,14 +1,32 @@
# -*- coding: utf-8 -*-
from functools import update_wrapper, partial
from django.contrib import admin
from django.contrib.admin.util import unquote
from django.conf.urls import patterns, url
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy, reverse
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
from django.utils.html import escape
from django.utils.encoding import force_text
from functions.admin import DefaultAdmin
from functions.http import JsonResponse
from .models import Comment
class CommentAdmin(DefaultAdmin):
list_display = ['text', 'ip', 'user', 'hidden',]
class Media:
js = (
"js/jquery.truncator.js",
"admin/js/comments_manage.js",
)
# css = {
# 'all': ("admin/css/comments_manage.css",),
# }
list_display = ['text', 'ip', 'user', 'hide']
list_select_related = True
list_filter = ('hidden', )
date_hierarchy = 'created'
@ -21,4 +39,59 @@ class CommentAdmin(DefaultAdmin):
'text', )}),
)
def hide(self, obj):
body = u'<img src="{url}" alt={alt}>' \
u'&nbsp;<a class="action" href="{href}">{label}</a>' \
u'&nbsp;|&nbsp;<a class="action" href="{href2}">{label2}</a>'\
.format(**self.get_yesno_image_data(obj))
return body
hide.short_description = _(u'Модерирование')
hide.allow_tags = True
def urls(self):
urlpatterns = self.get_urls()
def wrap(view):
def wrapper(*args, **kwargs):
return self.admin_site.admin_view(view)(*args, **kwargs)
return update_wrapper(wrapper, view)
info = self.model._meta.app_label, self.model._meta.module_name
_urlpatterns = patterns('',
url(r'^(?P<object_id>\d+)/ajax/(?P<action>hide|show|banro|unbanro)/$',
wrap(self.ajax_view),
name='%s_%s_ajax' % info),
)
return _urlpatterns + urlpatterns
urls = property(urls)
def get_yesno_image_data(self, obj):
return {
'url': '/static/admin/img/icon-{0}.gif'.format('no' if obj.hidden else 'yes'),
'alt': str(not obj.hidden),
'href': reverse('admin:comments_comment_ajax', args=[obj.id, 'hide' if not obj.hidden else 'show']),
'label': unicode(_(u'Опубликовать') if obj.hidden else _(u'Скрыть')),
'href2': reverse('admin:comments_comment_ajax', args=[obj.id, 'banro' if not obj.user.readonly else 'unbanro']),
'label2': unicode(_(u'Снять RO') if obj.user.readonly else _(u'Наложить RO')),
}
def ajax_view(self, request, object_id, extra_context=None, *args, **kwargs):
"The 'change' admin view for this model."
action = kwargs.get('action')
model = self.model
opts = model._meta
obj = self.get_object(request, unquote(object_id))
if not self.has_change_permission(request, obj) or not request.is_ajax():
raise PermissionDenied
if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)})
if action in ['hide', 'show']:
obj.hidden = True if action == 'hide' else False
obj.save()
else:
obj.user.readonly = True if action == 'banro' else False
obj.user.save()
return JsonResponse(dict({'success': True}, **self.get_yesno_image_data(obj)))
ajax_view.csrf_exempt = True
admin.site.register(Comment, CommentAdmin)

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from django import forms
from django.utils.translation import ugettext as _
from functions.forms import EmptySelect
from .models import Comment

@ -0,0 +1,6 @@
div.results tr div.moderation {
display: none;
}
div.results tr:hover div.moderation {
display: inline;
}

@ -0,0 +1,24 @@
$(document).ready(function () {
$('div.results a.action').on('click', function (e) {
e.preventDefault();
_this = $(this);
$.ajax({
url: _this.attr('href'),
type: 'post',
success: function (data) {
if (data.success==true) {
img = _this.siblings('img');
img.attr({
src: data.url,
alt: data.alt
});
img.next().attr('href', data.href).html(data.label).next().attr('href', data.href2).html(data.label2);
}
}
});
});
$('div.results tbody th a').truncate({
max_length: 50,
});
});

@ -0,0 +1,98 @@
// HTML Truncator for jQuery
// by Henrik Nyh <http://henrik.nyh.se> 2008-02-28.
// Free to modify and redistribute with credit.
(function($) {
var trailing_whitespace = true;
$.fn.truncate = function(options) {
var opts = $.extend({}, $.fn.truncate.defaults, options);
$(this).each(function() {
var content_length = $.trim(squeeze($(this).text())).length;
if (content_length <= opts.max_length)
return; // bail early if not overlong
var actual_max_length = opts.max_length - opts.more.length - 3; // 3 for " ()"
var truncated_node = recursivelyTruncate(this, actual_max_length);
var full_node = $(this).hide();
truncated_node.insertAfter(full_node);
findNodeForMore(truncated_node).append(' (<a href="#show more content">'+opts.more+'</a>)');
findNodeForLess(full_node).append(' (<a href="#show less content">'+opts.less+'</a>)');
truncated_node.find('a:last').click(function() {
truncated_node.hide(); full_node.show(); return false;
});
full_node.find('a:last').click(function() {
truncated_node.show(); full_node.hide(); return false;
});
});
}
// Note that the " (…more)" bit counts towards the max length – so a max
// length of 10 would truncate "1234567890" to "12 (…more)".
$.fn.truncate.defaults = {
max_length: 100,
more: '…more',
less: 'less'
};
function recursivelyTruncate(node, max_length) {
return (node.nodeType == 3) ? truncateText(node, max_length) : truncateNode(node, max_length);
}
function truncateNode(node, max_length) {
var node = $(node);
var new_node = node.clone().empty();
var truncatedChild;
node.contents().each(function() {
var remaining_length = max_length - new_node.text().length;
if (remaining_length == 0) return; // breaks the loop
truncatedChild = recursivelyTruncate(this, remaining_length);
if (truncatedChild) new_node.append(truncatedChild);
});
return new_node;
}
function truncateText(node, max_length) {
var text = squeeze(node.data);
if (trailing_whitespace) // remove initial whitespace if last text
text = text.replace(/^ /, ''); // node had trailing whitespace.
trailing_whitespace = !!text.match(/ $/);
var text = text.slice(0, max_length);
// Ensure HTML entities are encoded
// http://debuggable.com/posts/encode-html-entities-with-jquery:480f4dd6-13cc-4ce9-8071-4710cbdd56cb
text = $('<div/>').text(text).html();
return text;
}
// Collapses a sequence of whitespace into a single space.
function squeeze(string) {
return string.replace(/\s+/g, ' ');
}
// Finds the last, innermost block-level element
function findNodeForMore(node) {
var $node = $(node);
var last_child = $node.children(":last");
if (!last_child) return node;
var display = last_child.css('display');
if (!display || display=='inline') return $node;
return findNodeForMore(last_child);
};
// Finds the last child if it's a p; otherwise the parent
function findNodeForLess(node) {
var $node = $(node);
var last_child = $node.children(":last");
if (last_child && last_child.is('p')) return last_child;
return node;
};
})(jQuery);
Loading…
Cancel
Save