Issue #431 - Prevent comment link expiry - Added functionality for comment linking

*   `media.html`
    *   Changed comment textarea handle from `comment` => `field_comment`
    *   Active comment is hilighted with the CSS class name `comment_active`
    	and also with the hyperlink anchor #comment
    *   Changed media.html so that pagination always uses
    	Route('mediagoblin.user_pages.media_home') as base_url
*   `user_pages/forms.py`
    *   Renamed MediaComment form field `comment` => `field_comment`
*   `user_pages/routing.py`
    *   Added route for `/u/joar/m/123..456/c/234..567/`, points to `media_home`
*   `user_pages/views.py`
    *   `media_home` now checks if the request contains a comment id parameter
        then acts accordingly with pagination whether to call it with a
        `jump_to_id` or not.
    *	`media_post_comment` - Updated MediaCommentForm field name
        `comment` => `field_comment`
*   `util.py`
    *   `redirect` now supports querystring arguments. - NOT USED (should we
        keep it? I think so, it might be useful, sometime [don't call me a
        code hoarder]).
    *   `Pagination.__init__` now accepts one further argument, the `jump_to_id`.
        It assist the comment linking functionality in finding and returning the
        proper page for a comment.
        This feature will work for all kinds of objects. It might not be
        optimal, but it is well functional :)
This commit is contained in:
Joar Wandborg 2011-07-07 18:04:19 +02:00
parent 5ed4722de8
commit af2fcba5c4
5 changed files with 60 additions and 12 deletions

View File

@ -55,7 +55,7 @@
<form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment',
user= media.uploader().username, user= media.uploader().username,
media=media._id) }}" method="POST"> media=media._id) }}" method="POST">
{{ wtforms_util.render_field_div(comment_form.comment) }} {{ wtforms_util.render_field_div(comment_form.field_comment) }}
<div class="form_submit_buttons"> <div class="form_submit_buttons">
<input type="submit" value="Post comment!" class="button" /> <input type="submit" value="Post comment!" class="button" />
</div> </div>
@ -65,7 +65,12 @@
{% if comments %} {% if comments %}
{% for comment in comments %} {% for comment in comments %}
{% set comment_author = comment.author() %} {% set comment_author = comment.author() %}
{% if pagination.active_id == comment._id %}
<div class="comment_wrapper comment_active" id="comment-{{ comment['_id'] }}">
<a name="comment" id="comment"></a>
{% else %}
<div class="comment_wrapper" id="comment-{{ comment['_id'] }}"> <div class="comment_wrapper" id="comment-{{ comment['_id'] }}">
{% endif %}
<div class="comment_content"> <div class="comment_content">
{% autoescape False %} {% autoescape False %}
{{ comment.content_html }} {{ comment.content_html }}
@ -77,7 +82,10 @@
{{ comment_author['username'] }}</a> at {{ comment_author['username'] }}</a> at
<!--</div> <!--</div>
<div class="comment_datetime">--> <div class="comment_datetime">-->
<a href="#comment-{{ comment['_id'] }}"> <a href="{{ request.urlgen('mediagoblin.user_pages.media_home.view_comment',
comment = comment['_id'],
user = media.uploader().username,
media = media._id) }}#comment">
{{ "%4d-%02d-%02d %02d:%02d"|format(comment.created.year, {{ "%4d-%02d-%02d %02d:%02d"|format(comment.created.year,
comment.created.month, comment.created.month,
comment.created.day, comment.created.day,
@ -88,7 +96,10 @@
</div> </div>
{% endfor %} {% endfor %}
{{ render_pagination(request, pagination) }} {{ render_pagination(request, pagination,
request.urlgen('mediagoblin.user_pages.media_home',
user = media.uploader().username,
media = media._id)) }}
</div> </div>
{% endif %} {% endif %}
<div class="grid_5 omega"> <div class="grid_5 omega">

View File

@ -17,5 +17,5 @@
import wtforms import wtforms
class MediaCommentForm(wtforms.Form): class MediaCommentForm(wtforms.Form):
comment = wtforms.TextAreaField('Comment', field_comment = wtforms.TextAreaField('Comment',
[wtforms.validators.Required()]) [wtforms.validators.Required()])

View File

@ -24,6 +24,9 @@ user_routes = [
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/', Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
requirements=dict(m_id="[0-9a-fA-F]{24}"), requirements=dict(m_id="[0-9a-fA-F]{24}"),
controller="mediagoblin.user_pages.views:media_home"), controller="mediagoblin.user_pages.views:media_home"),
Route('mediagoblin.user_pages.media_home.view_comment',
'/{user}/m/{media}/c/{comment}/',
controller="mediagoblin.user_pages.views:media_home"),
Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/", Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
controller="mediagoblin.edit.views:edit_media"), controller="mediagoblin.edit.views:edit_media"),
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/', Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',

View File

@ -95,8 +95,14 @@ def media_home(request, media, page, **kwargs):
""" """
'Homepage' of a MediaEntry() 'Homepage' of a MediaEntry()
""" """
if ObjectId(request.matchdict.get('comment')):
pagination = Pagination(
page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE,
ObjectId(request.matchdict.get('comment')))
else:
pagination = Pagination(
page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE)
pagination = Pagination(page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE)
comments = pagination() comments = pagination()
comment_form = user_forms.MediaCommentForm(request.POST) comment_form = user_forms.MediaCommentForm(request.POST)
@ -118,7 +124,7 @@ def media_post_comment(request):
comment = request.db.MediaComment() comment = request.db.MediaComment()
comment['media_entry'] = ObjectId(request.matchdict['media']) comment['media_entry'] = ObjectId(request.matchdict['media'])
comment['author'] = request.user['_id'] comment['author'] = request.user['_id']
comment['content'] = request.POST['comment'] comment['content'] = request.POST['field_comment']
comment['content_html'] = cleaned_markdown_conversion(comment['content']) comment['content_html'] = cleaned_markdown_conversion(comment['content'])

View File

@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import division
from email.MIMEText import MIMEText from email.MIMEText import MIMEText
import gettext import gettext
import pkg_resources import pkg_resources
@ -21,7 +23,7 @@ import smtplib
import sys import sys
import re import re
import urllib import urllib
from math import ceil from math import ceil, floor
import copy import copy
from babel.localedata import exists from babel.localedata import exists
@ -35,6 +37,8 @@ from mediagoblin import mg_globals
from mediagoblin import messages from mediagoblin import messages
from mediagoblin.db.util import ObjectId from mediagoblin.db.util import ObjectId
from itertools import izip, count
TESTS_ENABLED = False TESTS_ENABLED = False
def _activate_testing(): def _activate_testing():
""" """
@ -133,7 +137,16 @@ def render_to_response(request, template, context):
def redirect(request, *args, **kwargs): def redirect(request, *args, **kwargs):
"""Returns a HTTPFound(), takes a request and then urlgen params""" """Returns a HTTPFound(), takes a request and then urlgen params"""
return exc.HTTPFound(location=request.urlgen(*args, **kwargs))
querystring = None
if kwargs.get('querystring'):
querystring = kwargs.get('querystring')
del kwargs['querystring']
return exc.HTTPFound(
location=''.join([
request.urlgen(*args, **kwargs),
querystring if querystring else '']))
def setup_user_in_request(request): def setup_user_in_request(request):
@ -418,7 +431,8 @@ class Pagination(object):
get actual data slice through __call__(). get actual data slice through __call__().
""" """
def __init__(self, page, cursor, per_page=PAGINATION_DEFAULT_PER_PAGE): def __init__(self, page, cursor, per_page=PAGINATION_DEFAULT_PER_PAGE,
jump_to_id=False):
""" """
Initializes Pagination Initializes Pagination
@ -426,11 +440,25 @@ class Pagination(object):
- page: requested page - page: requested page
- per_page: number of objects per page - per_page: number of objects per page
- cursor: db cursor - cursor: db cursor
- jump_to_id: ObjectId, sets the page to the page containing the object
with _id == jump_to_id.
""" """
self.page = page self.page = page
self.per_page = per_page self.per_page = per_page
self.cursor = cursor self.cursor = cursor
self.total_count = self.cursor.count() self.total_count = self.cursor.count()
self.active_id = None
if jump_to_id:
cursor = copy.copy(self.cursor)
for (doc, increment) in izip(cursor, count(0)):
if doc['_id'] == jump_to_id:
self.page = 1 + int(floor(increment / self.per_page))
self.active_id = jump_to_id
break
def __call__(self): def __call__(self):
""" """