Permalink
Browse files

WIP

  • Loading branch information...
0 parents commit 67c87618c26873c62f7f91cc87ff962d15047e81 @vdboor vdboor committed Mar 4, 2012
@@ -0,0 +1,10 @@
+*.pyc
+*.pyo
+*.mo
+*.db
+.project
+.pydevproject
+.idea/workspace.xml
+.DS_Store
+dist/
+docs/_build/
@@ -0,0 +1,9 @@
+# Make sure the monkey patching of django.contrib.comments is made,
+# even if ajaxcomments is not included in the installed apps
+# (only this feature is reused of it).
+#
+# it patches render_to_response() to:
+# - return JSON on Ajax requests
+# - makes request object accessable everywhere
+#
+import ajaxcomments.utils
@@ -0,0 +1,83 @@
+from django.conf import settings
+from django.contrib import admin
+from django.contrib.comments import get_model
+from django.contrib.admin.widgets import AdminTextInputWidget
+from django.core.exceptions import ImproperlyConfigured
+from django.utils.html import escape
+from django.utils.translation import ugettext_lazy as _
+from fluent_comments import appsettings
+
+USE_THREADEDCOMMENTS = 'threadedcomments' in settings.INSTALLED_APPS
+
+
+# Ensure the admin app is loaded,
+# so the model is unregistered here, and not loaded twice.
+if USE_THREADEDCOMMENTS:
+ # Avoid getting weird situations where both comment apps are loaded in the admin.
+ if not hasattr(settings, 'COMMENTS_APP') or settings.COMMENTS_APP == 'comments':
+ raise ImproperlyConfigured("To use 'threadedcomments', specify the COMMENTS_APP as well")
+
+ from threadedcomments.admin import ThreadedCommentsAdmin as CommentsAdminBase
+else:
+ from django.contrib.comments.admin import CommentsAdmin as CommentsAdminBase
+
+
+class FluentCommentsAdmin(CommentsAdminBase):
+ """
+ Updated admin screen for the comments model.
+
+ The ability to add a comment is removed here, the admin screen can only be used for managing comments.
+ Adding comments can happen at the frontend instead.
+
+ The fieldsets are more logically organized, and the generic relation is a readonly field instead of a massive pulldown + textarea.
+ The class supports both the standard ``django.contrib.comments`` and the ``threadedcomments`` applications.
+ """
+
+ fieldsets = [
+ (_('Content'),
+ {'fields': ('object_link', 'user_name', 'user_email', 'user_url', 'comment', 'submit_date',)}
+ ),
+ (_('Account information'),
+ {'fields': ('user', 'ip_address',)},
+ ),
+ (_('Moderation'),
+ {'fields': ('is_public', 'is_removed')}
+ ),
+ ]
+
+ list_display = ('user_name', 'object_link', 'ip_address', 'submit_date', 'is_public', 'is_removed')
+ readonly_fields = ('object_link', 'user', 'ip_address', 'submit_date',)
+
+ # Adjust the fieldsets for threaded comments
+ if USE_THREADEDCOMMENTS:
+ fieldsets[0][1]['fields'] = ('object_link', 'user_name', 'user_email', 'user_url', 'title', 'comment', 'submit_date',) # add title field.
+ fieldsets.insert(2, (_('Hierarchy'), {'fields': ('parent',)}))
+ raw_id_fields = ('parent',)
+
+
+ def object_link(self, comment):
+ object = comment.content_object
+ title = unicode(object)
+ return u'<a href="{0}">{1}</a>'.format(escape(object.get_absolute_url()), escape(title))
+
+ object_link.short_description = _("Page")
+ object_link.allow_tags = True
+
+ def has_add_permission(self, request):
+ return False
+
+ def formfield_for_dbfield(self, db_field, **kwargs):
+ if db_field.name == 'title':
+ kwargs['widget'] = AdminTextInputWidget
+ return super(FluentCommentsAdmin, self).formfield_for_dbfield(db_field, **kwargs)
+
+
+# Replace the old admin screen.
+if appsettings.FLUENT_COMMENTS_REPLACE_ADMIN:
+ CommentModel = get_model()
+ try:
+ admin.site.unregister(CommentModel)
+ except admin.sites.NotRegistered as e:
+ pass
+
+ admin.site.register(CommentModel, FluentCommentsAdmin)
@@ -0,0 +1,3 @@
+from django.conf import settings
+
+FLUENT_COMMENTS_REPLACE_ADMIN = getattr(settings, "FLUENT_COMMENTS_REPLACE_ADMIN", True)
No changes.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,101 @@
+(function($)
+{
+ var scrollElement = 'html, body';
+ var active_input = '';
+
+ // Parse script parameters!
+ var scripts = document.getElementsByTagName('script');
+ var myscript = scripts[ scripts.length - 1 ];
+ var cap = /[?&]STATIC_URL=([^&]+)/.exec(myscript.src);
+
+ var STATIC_URL = cap[1] || window.STATIC_URL || '/static/';
+ var ajaxmedia = STATIC_URL + 'fluent_comments/';
+
+
+ $.fn.ready(function()
+ {
+ var commentform = $('#comment-form > form');
+ if( commentform.length > 0 )
+ {
+ // Detect last active input.
+ // Submit if return is hit, or any button other then preview is hit.
+ commentform.find(':input').focus(setActiveInput).mousedown(setActiveInput);
+ commentform.submit(onCommentFormSubmit);
+ }
+
+
+ // Find the element to use for scrolling.
+ // This code is much shorter then jQuery.scrollTo()
+ $('html, body').each(function () {
+ var initScrollTop = $(this).attr('scrollTop');
+ $(this).attr('scrollTop', initScrollTop + 1);
+ if ($(this).attr('scrollTop') == initScrollTop + 1) {
+ scrollElement = this.nodeName.toLowerCase();
+ $(this).attr('scrollTop', initScrollTop); // Firefox 2 reset
+ return false;
+ }
+ });
+
+
+ // On load, scroll to proper comment.
+ var hash = window.location.hash;
+ if( hash.substring(0, 2) == "#c" )
+ {
+ var id = parseInt(hash.substring(2));
+ scrollToComment(id, 1000);
+ }
+ });
+
+
+ function setActiveInput()
+ {
+ active_input = this.name;
+ }
+
+ function onCommentFormSubmit(event)
+ {
+ if( active_input != 'preview' )
+ {
+ ajaxComment({
+ 'media': ajaxmedia,
+ 'complete': onCommentPosted
+ });
+ event.preventDefault(); // only after ajax call worked.
+ return false;
+ }
+ return true;
+ }
+
+
+ function scrollToComment(id, speed)
+ {
+ // Allow initialisation for scrolling.
+ if( window.on_scroll_to_comment && window.on_scroll_to_comment(id) === false )
+ return;
+
+ // Scroll to the comment.
+ var $comment = $("#c" + id);
+ if( $comment.length )
+ $(scrollElement).animate( {scrollTop: $comment.offset().top }, speed || 1000 );
+ }
+
+
+ function onCommentPosted($comment)
+ {
+ var id = $comment.attr('id');
+
+ if( id.substring(0, 1) == 'c' )
+ {
+ id = parseInt(id.substring(1));
+ $("#comment-added-message").fadeIn(200);
+
+ setTimeout(function(){
+ scrollToComment(id, 1000);
+ }, 1000);
+
+ setTimeout(function(){
+ $("#comment-added-message").fadeOut(500);
+ }, 4000);
+ }
+ }
+})(window.jQuery);
@@ -0,0 +1,88 @@
+/*
+ Based on django-ajaxcomments, BSD licensed.
+ Copyright (c) 2009 Brandon Konkle and individual contributors.
+
+ Updated to be more generic, more fancy, and usable with different templates.
+ */
+
+var ajaxComment = (function()
+{
+ var commentBusy = false;
+
+ function ajaxComment(args)
+ {
+ var media = args.media;
+ var oncomplete = args.complete;
+
+ $('div.comment-error').remove();
+ if (commentBusy) {
+ return false;
+ }
+
+ commentBusy = true;
+ var comment = $('div.comment-form form').serialize();
+ var url = $('div.comment-form form').attr('action');
+
+ // Add a wait animation
+ $('#comment-waiting').fadeIn(1000);
+
+ // Use AJAX to post the comment.
+ $.ajax({
+ type: 'POST',
+ url: url + 'ajax/',
+ data: comment,
+ success: function(data) {
+ commentBusy = false;
+ removeWaitAnimation();
+
+ if (data.success) {
+ commentSuccess(data);
+ var added = $("#comments > :last-child");
+ if( oncomplete ) oncomplete(added);
+ }
+ else {
+ commentFailure(data);
+ }
+ },
+ error: function(data) {
+ commentBusy = false;
+ removeWaitAnimation();
+
+ $('div.comment-form form').unbind('submit');
+ $('div.comment-form form').submit();
+ },
+ dataType: 'json'
+ });
+
+ return false;
+ }
+
+ function commentSuccess(data)
+ {
+ $('div.comment-form form textarea')[0].value = "";
+ $('#id_comment').val('');
+ $('#comments').append(data['html']);
+ $('div.comment:last').show('slow');
+ $('#comment-thanks').show().fadeOut(4000);
+ }
+
+ function commentFailure(data)
+ {
+ $('div.comment-form ul.errorlist').each(function() {
+ this.parentNode.removeChild(this);
+ });
+
+ for (var error in data.errors) {
+ $('#id_' + error).parent().before(data.errors[error])
+ }
+ }
+
+ function removeWaitAnimation()
+ {
+ // Remove the wait animation and message
+ $('.ajax-loader').remove();
+ $('div.comment-waiting').stop().remove();
+ }
+
+ return ajaxComment;
+})();
@@ -0,0 +1,32 @@
+{% comment %}
+ Something that django.contrib.comments does not provide:
+ An individual template for a single comment, to easily be reused.
+
+ This include is also used by django-ajaxcomments.
+ The div id should be "c{id}", because the comment.get_absolute_url() points to it.
+
+ Note, to override the displayed date format, don't replace this template.
+ Instead, define DATETIME_FORMAT in a locale file. Requires setting:
+
+ FORMAT_MODULE_PATH = 'settings.locale'
+
+ Then create 'settings/locale/XY/formats.py' with:
+
+ DATETIME_FORMAT = '...'
+
+ This should give you consistent dates across all views.
+{% endcomment %}
+{% load i18n %}
+
+ <div id="c{{ comment.id }}" class="comment-item">
+ {% spaceless %}
+ <h4>
+ {% if comment.url %}<a href="{{ comment.url }}" rel="nofollow">{% endif %}
+ {% if comment.name %}{{ comment.name }}{% else %}{% trans "Anonymous" %}{% endif %}
+ {% if comment.url %}</a>{% endif %}
+ <span class="comment-date">{% blocktrans with submit_date=comment.submit_date %}on {{ submit_date }}{% endblocktrans %}</span>
+ </h4>
+ {% endspaceless %}
+
+ <div class="comment-text">{{ comment.comment|linebreaks }}</div>
+ </div>
@@ -0,0 +1,18 @@
+{% load comments i18n crispy_forms_tags %}
+
+<form action="{% comment_form_target %}" method="post" class="form-horizontal">{% csrf_token %}
+ {% if next %}<div><input type="hidden" name="next" value="{{ next }}" /></div>{% endif %}
+
+ {{ form|crispy }}
+
+ <div class="form-actions">
+ <input type="submit" name="post" class="btn btn-submit" value="{% trans "Post" %}" />
+ <input type="submit" name="preview" class="btn btn-submit" value="{% trans "Preview" %}" />
+
+ <span id="comment-waiting" style="display: none;">
+ <img src="{{ STATIC_URL }}fluent_comments/img/ajax-wait.gif" alt="" class="ajax-loader" />{% trans "Please wait . . ." %}
+ </span>
+ <span id="comment-added-message" style="display: none;">{% trans "Your comment has been posted!" %}</span>
+ <span id="comment-thanks" style="display: none;">{% trans "Thank you for your comment!" %}</span>
+ </div>
+</form>
@@ -0,0 +1,10 @@
+{% comment %}
+ The normal list, spiced up.
+
+ The id="comments" is required for django-ajaxcomments,
+ the 'comments/comment.html template is also used by django-ajaxcomments.
+{% endcomment %}
+
+<div id="comments">
+ {% for comment in comment_list %}{% include "comments/comment.html" %}{% endfor %}
+</div>
@@ -0,0 +1,25 @@
+{% extends "comments/base.html" %}{% load i18n %}
+
+{% block title %}{% trans "Thanks for commenting" %}{% endblock %}
+
+{% block extrahead %}
+{{ block.super }}
+ <meta http-equiv="Refresh" content="5; url={{ comment.content_object.get_absolute_url }}#c{{ comment.id }}" />
+{% endblock %}
+
+{% block content %}
+ <h2>{% trans "Thanks for posting your comment" %}</h2>
+ <p>
+ {% blocktrans %}
+ We have received your comment, and posted it on the web site.<br/>
+ You will be sent back to the article...
+ {% endblocktrans %}
+ </p>
+
+ {# Use identical formatting to normal comment list #}
+ <div id="comments">
+ {% include "comments/comment.html" %}
+ </div>
+
+ <p><a href="{{ comment.content_object.get_absolute_url }}#c{{ comment.id }}">{% trans "Back to the article" %}</a></p>
+{% endblock %}
Oops, something went wrong.

0 comments on commit 67c8761

Please sign in to comment.