diff --git a/apps/comments/__init__.py b/apps/comments/__init__.py new file mode 100644 index 0000000000..69f70938bb --- /dev/null +++ b/apps/comments/__init__.py @@ -0,0 +1,40 @@ +from django.utils.translation import ugettext_lazy as _ + +from navigation.api import register_links, \ + register_model_list_columns +from permissions.api import register_permissions + +from django.contrib.comments.models import Comment + +from documents.models import Document + +PERMISSION_COMMENT_CREATE = 'comment_create' +PERMISSION_COMMENT_DELETE = 'comment_delete' +PERMISSION_COMMENT_EDIT = 'comment_edit' + +register_permissions('comments', [ + {'name': PERMISSION_COMMENT_CREATE, 'label': _(u'Create new comments')}, + {'name': PERMISSION_COMMENT_DELETE, 'label': _(u'Delete comments')}, + {'name': PERMISSION_COMMENT_EDIT, 'label': _(u'Edit comments')}, +]) + +comment_delete = {'text': _('delete'), 'view': 'comment_delete', 'args': 'object.id', 'famfam': 'comment_delete', 'permissions': {'namespace': 'comments', 'permissions': [PERMISSION_COMMENT_DELETE]}} +comment_multiple_delete = {'text': _('delete'), 'view': 'comment_multiple_delete', 'args': 'object.id', 'famfam': 'comments_delete', 'permissions': {'namespace': 'comments', 'permissions': [PERMISSION_COMMENT_DELETE]}} +comment_add = {'text': _('add comment'), 'view': 'comment_add', 'args': 'document.id', 'famfam': 'comment_add', 'permissions': {'namespace': 'comments', 'permissions': [PERMISSION_COMMENT_CREATE]}} + +register_model_list_columns(Comment, [ + { + 'name': _(u'date'), + 'attribute': 'submit_date' + }, + { + 'name': _(u'user'), + 'attribute': lambda x: x.user.get_full_name() if x.user.get_full_name() else x.user + }, + { + 'name': _(u'comment'), + 'attribute': 'comment' + } +]) + +register_links(Document, [comment_add]) diff --git a/apps/comments/forms.py b/apps/comments/forms.py new file mode 100644 index 0000000000..9c75121b2e --- /dev/null +++ b/apps/comments/forms.py @@ -0,0 +1,11 @@ +from django import forms +from django.contrib.comments.models import Comment + + +class CommentForm(forms.ModelForm): + """ + A standard model form to allow users to post a comment + """ + class Meta: + model = Comment + fields = ('comment',) diff --git a/apps/comments/locale/es/LC_MESSAGES/django.mo b/apps/comments/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..cdc8e07e39 Binary files /dev/null and b/apps/comments/locale/es/LC_MESSAGES/django.mo differ diff --git a/apps/comments/locale/es/LC_MESSAGES/django.po b/apps/comments/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000000..e60297767d --- /dev/null +++ b/apps/comments/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,89 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-05-01 04:21-0400\n" +"PO-Revision-Date: 2011-05-01 04:25\n" +"Last-Translator: Roberto Rosario \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: \n" +"X-Translated-Using: django-rosetta 0.5.6\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: __init__.py:16 +msgid "Create new comments" +msgstr "Crear nuevos comentarios" + +#: __init__.py:17 +msgid "Delete comments" +msgstr "Eliminar comentarios" + +#: __init__.py:18 +msgid "Edit comments" +msgstr "Editar los comentarios" + +#: __init__.py:21 __init__.py:22 +msgid "delete" +msgstr "eliminar" + +#: __init__.py:23 +msgid "add comment" +msgstr "añadir comentario" + +#: __init__.py:27 +msgid "date" +msgstr "fecha" + +#: __init__.py:31 +msgid "user" +msgstr "usuario" + +#: __init__.py:35 views.py:45 +msgid "comment" +msgstr "comentario" + +#: utils.py:17 +msgid "comments" +msgstr "comentarios" + +#: views.py:26 +msgid "Must provide at least one comment." +msgstr "Debe proveer al menos un comentario." + +#: views.py:36 +#, python-format +msgid "Comment \"%s\" deleted successfully." +msgstr "Comentario \"%s\" eliminado exitosamente." + +#: views.py:38 +#, python-format +msgid "Error deleting comment \"%(comment)s\": %(error)s" +msgstr "Error al eliminar el comentario \" %(comment)s\": %(error)s " + +#: views.py:52 +#, python-format +msgid "Are you sure you wish to delete the comment: %s?" +msgstr "¿Está seguro que desea eliminar el comentario:% s?" + +#: views.py:54 +#, python-format +msgid "Are you sure you wish to delete the comments: %s?" +msgstr "¿Está seguro que desea eliminar los comentarios:% s?" + +#: views.py:84 +msgid "Comment added successfully." +msgstr "Comentario añadido exitosamente." + +#: views.py:91 +#, python-format +msgid "Add comment to document: %s" +msgstr "Añadir comentario al documento: %s" diff --git a/apps/comments/models.py b/apps/comments/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/apps/comments/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/comments/tests.py b/apps/comments/tests.py new file mode 100644 index 0000000000..2247054b35 --- /dev/null +++ b/apps/comments/tests.py @@ -0,0 +1,23 @@ +""" +This file demonstrates two different styles of tests (one doctest and one +unittest). These will both pass when you run "manage.py test". + +Replace these with more appropriate tests for your application. +""" + +from django.test import TestCase + +class SimpleTest(TestCase): + def test_basic_addition(self): + """ + Tests that 1 + 1 always equals 2. + """ + self.failUnlessEqual(1 + 1, 2) + +__test__ = {"doctest": """ +Another way to test that 1 + 1 is equal to 2. + +>>> 1 + 1 == 2 +True +"""} + diff --git a/apps/comments/urls.py b/apps/comments/urls.py new file mode 100644 index 0000000000..680051c84f --- /dev/null +++ b/apps/comments/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls.defaults import patterns, url + +urlpatterns = patterns('comments.views', + url(r'^(?P\d+)/delete/$', 'comment_delete', (), 'comment_delete'), + url(r'^multiple/delete/$', 'comment_multiple_delete', (), 'comment_multiple_delete'), + url(r'^add_to_document(?P\d+)/$', 'comment_add', (), 'comment_add'), +) diff --git a/apps/comments/utils.py b/apps/comments/utils.py new file mode 100644 index 0000000000..cb2873e612 --- /dev/null +++ b/apps/comments/utils.py @@ -0,0 +1,20 @@ +from django.utils.translation import ugettext_lazy as _ +from django.contrib.comments.models import Comment +from comments import comment_delete + + +def get_comments_subtemplate(obj): + """ + Return all the settings to render a subtemplate containing an + object's comments + """ + return { + 'name': 'generic_list_subtemplate.html', + 'context': { + 'title': _(u'comments'), + 'object_list': Comment.objects.for_model(obj), + 'hide_link': True, + 'hide_object': True, + 'navigation_object_links': [comment_delete], + } + } diff --git a/apps/comments/views.py b/apps/comments/views.py new file mode 100644 index 0000000000..1efd1ea6cf --- /dev/null +++ b/apps/comments/views.py @@ -0,0 +1,93 @@ +from django.shortcuts import render_to_response, get_object_or_404 +from django.utils.translation import ugettext_lazy as _ +from django.contrib.comments.models import Comment +from django.http import HttpResponseRedirect +from django.template import RequestContext +from django.contrib import messages +from django.contrib.contenttypes.models import ContentType +from django.contrib.sites.models import Site + +from permissions.api import check_permissions +from documents.models import Document + +from comments import PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_CREATE +from comments.forms import CommentForm + + +def comment_delete(request, comment_id=None, comment_id_list=None): + check_permissions(request.user, 'comments', [PERMISSION_COMMENT_DELETE]) + post_action_redirect = None + + if comment_id: + comments = [get_object_or_404(Comment, pk=comment_id)] + elif comment_id_list: + comments = [get_object_or_404(Comment, pk=comment_id) for comment_id in comment_id_list.split(',')] + else: + messages.error(request, _(u'Must provide at least one comment.')) + return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) + + previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) + next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) + + if request.method == 'POST': + for comment in comments: + try: + comment.delete() + messages.success(request, _(u'Comment "%s" deleted successfully.') % comment) + except Exception, e: + messages.error(request, _(u'Error deleting comment "%(comment)s": %(error)s') % { + 'comment': comment, 'error': e + }) + + return HttpResponseRedirect(next) + + context = { + 'object_name': _(u'comment'), + 'delete_view': True, + 'previous': previous, + 'next': next, + } + if len(comments) == 1: + context['object'] = comments[0] + context['title'] = _(u'Are you sure you wish to delete the comment: %s?') % ', '.join([unicode(d) for d in comments]) + elif len(comments) > 1: + context['title'] = _(u'Are you sure you wish to delete the comments: %s?') % ', '.join([unicode(d) for d in comments]) + + return render_to_response('generic_confirm.html', context, + context_instance=RequestContext(request)) + + +def comment_multiple_delete(request): + return comment_delete( + request, comment_id_list=request.GET.get('id_list', []) + ) + + +def comment_add(request, document_id): + check_permissions(request.user, 'comments', [PERMISSION_COMMENT_CREATE]) + + document = get_object_or_404(Document, pk=document_id) + post_action_redirect = None + + next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) + + if request.method == 'POST': + form = CommentForm(request.POST) + if form.is_valid(): + comment = form.save(commit=False) + comment.user = request.user + comment.content_type = ContentType.objects.get_for_model(document) + comment.object_pk = document.pk + comment.site = Site.objects.get_current() + comment.save() + + messages.success(request, _(u'Comment added successfully.')) + return HttpResponseRedirect(next) + else: + form = CommentForm() + + return render_to_response('generic_form.html', { + 'form': form, + 'title': _(u'Add comment to document: %s') % document, + 'next': next, + }, context_instance=RequestContext(request)) diff --git a/apps/documents/views.py b/apps/documents/views.py index d222b2ac80..fc7ab0b0fa 100644 --- a/apps/documents/views.py +++ b/apps/documents/views.py @@ -3,7 +3,7 @@ import zipfile import urlparse import urllib -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.http import HttpResponseRedirect from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext @@ -14,6 +14,7 @@ from django.views.generic.create_update import delete_object, update_object from django.conf import settings from django.utils.http import urlencode from django.core.files.uploadedfile import SimpleUploadedFile +from django.contrib.comments.models import Comment import sendfile from common.utils import pretty_size @@ -25,6 +26,7 @@ from filesystem_serving.conf.settings import FILESERVING_ENABLE from permissions.api import check_permissions from navigation.utils import resolve_to_name from tags.utils import get_tags_subtemplate +from comments.utils import get_comments_subtemplate from documents.conf.settings import DELETE_STAGING_FILE_AFTER_UPLOAD from documents.conf.settings import USE_STAGING_DIRECTORY @@ -291,6 +293,9 @@ def document_view(request, document_id): if document.tags.count(): subtemplates_list.append(get_tags_subtemplate(document)) + if Comment.objects.for_model(document).count(): + subtemplates_list.append(get_comments_subtemplate(document)) + subtemplates_list.append( { 'name': 'generic_list_subtemplate.html', @@ -845,6 +850,9 @@ def document_view_simple(request, document_id): subtemplates_list = [] if document.tags.count(): subtemplates_list.append(get_tags_subtemplate(document)) + + if Comment.objects.for_model(document).count(): + subtemplates_list.append(get_comments_subtemplate(document)) subtemplates_list.append( { diff --git a/settings.py b/settings.py index 3d4372edd2..699400892a 100644 --- a/settings.py +++ b/settings.py @@ -142,6 +142,7 @@ INSTALLED_APPS = ( 'folders', 'taggit', 'tags', + 'comments', ) TEMPLATE_CONTEXT_PROCESSORS = ( diff --git a/urls.py b/urls.py index 87ae2ab05c..5f34cfcae1 100644 --- a/urls.py +++ b/urls.py @@ -18,7 +18,7 @@ urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), (r'^grappelli/', include('grappelli.urls')), (r'^sentry/', include('sentry.urls')), - (r'^comments/', include('django.contrib.comments.urls')), + (r'^comments/', include('comments.urls')), )