From c11f21ab3c64c6ef9d9cde8bfdcddf12f6663932 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Mon, 27 Jun 2011 23:39:40 +0200
Subject: [PATCH 1/8] Issue 362 - Add simple comments
* Added MediaComment database model
Holds `media_entry` (`ObjectId`), `author` (`ObjectId`), `created`, `content` and `content_html`.
---
mediagoblin/db/models.py | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 600b79ff..5d00aa34 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -147,8 +147,32 @@ class MediaEntry(Document):
def uploader(self):
return self.db.User.find_one({'_id': self['uploader']})
+class MediaComment(Document):
+ __collection__ = 'media_comments'
-REGISTER_MODELS = [MediaEntry, User]
+ structure = {
+ 'media_entry': ObjectId,
+ 'author': ObjectId,
+ 'created': datetime.datetime,
+ 'content': unicode,
+ 'content_html': unicode}
+
+ required_fields = [
+ 'author', 'created', 'content']
+
+ default_values = {
+ 'created': datetime.datetime.utcnow}
+
+ def media_entry(self):
+ pass
+
+ def author(self):
+ return self.db.User.find_one({'_id': self['author']})
+
+REGISTER_MODELS = [
+ MediaEntry,
+ User,
+ MediaComment]
def register_models(connection):
From 6a585e4c52f0c4efe47b33e70059303f24d68287 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 29 Jun 2011 01:14:52 +0200
Subject: [PATCH 2/8] Issue #362 - Added a route to MediaComment POST handler
---
mediagoblin/user_pages/routing.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 92998726..255b6f66 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -27,4 +27,7 @@ user_routes = [
Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
controller="mediagoblin.edit.views:edit_media"),
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
- controller="mediagoblin.user_pages.views:atom_feed")]
+ controller="mediagoblin.user_pages.views:atom_feed"),
+ Route('mediagoblin.user_pages.media_post_comment',
+ '/{user}/m/{media}/comment/add/',
+ controller="mediagoblin.user_pages.views:media_post_comment")]
From 7bd8197f32f17466f14d730546a06166ed6da67a Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 29 Jun 2011 01:16:51 +0200
Subject: [PATCH 3/8] Issue #362 - Updated the MediaComment model
* `MediaComment.get_comments()` now uses pagination
* `MediaComment.get_comments()` now sorts by `created` DESC
* `MediaComment.media_entry` is now **required**
* `MediaComment.media_entry()` now returns parent `MediaEntry`
---
mediagoblin/db/models.py | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 5d00aa34..5196dede 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -22,7 +22,8 @@ from mediagoblin import util
from mediagoblin.auth import lib as auth_lib
from mediagoblin import mg_globals
from mediagoblin.db import migrations
-from mediagoblin.db.util import ObjectId
+from mediagoblin.db.util import DESCENDING, ObjectId
+from mediagoblin.util import Pagination
###################
# Custom validators
@@ -115,7 +116,22 @@ class MediaEntry(Document):
def main_mediafile(self):
pass
-
+
+ def get_comments(self, page):
+ cursor = self.db.MediaComment.find({
+ 'media_entry': self['_id']}).sort('created', DESCENDING)
+
+ pagination = Pagination(page, cursor)
+ comments = pagination()
+
+ data = list()
+ for comment in comments:
+ comment['author'] = self.db.User.find_one({
+ '_id': comment['author']})
+ data.append(comment)
+
+ return (data, pagination)
+
def generate_slug(self):
self['slug'] = util.slugify(self['title'])
@@ -158,13 +174,13 @@ class MediaComment(Document):
'content_html': unicode}
required_fields = [
- 'author', 'created', 'content']
+ 'media_entry', 'author', 'created', 'content']
default_values = {
'created': datetime.datetime.utcnow}
def media_entry(self):
- pass
+ return self.db.MediaEntry.find_one({'_id': self['media_entry']})
def author(self):
return self.db.User.find_one({'_id': self['author']})
From aa7d1a2fb6148f6e899d7f8756e6c481dab3f532 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 29 Jun 2011 01:21:46 +0200
Subject: [PATCH 4/8] Issue #362 - Updated media.html with things necessary for
the simple comment feature
* `media.html` now imports `wtforms.html` for use in comment form rendering
* `media.html` now outputs a commenting form if `request.user` evals to `True`
* `media.html` now outputs `MediaComments` if `comments` evals to `True`
* `media.html` now includes `pagination.html` to handle comment pagination
---
.../mediagoblin/user_pages/media.html | 46 +++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 97ff8e51..cd0bb764 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -16,6 +16,9 @@
# along with this program. If not, see .
#}
{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
{% block mediagoblin_content %}
{# temporarily, an "image gallery" that isn't one really ;) #}
@@ -42,6 +45,49 @@
user= media.uploader().username,
media= media._id) }}">Edit
{% endif %}
+ {% if request.user %}
+
+ {% endif %}
+ {#
+ {{ wtforms_util.render_textarea_div(submit_form.description) }}
+ {{ wtforms_util.render_field_div(submit_form.file) }}
+ #}
+ {% if comments %}
+ Comments
+ {% for comment in comments %}
+
+ {% endfor %}
+ {% include "mediagoblin/utils/pagination.html" %}
+ {% endif %}
{% else %}
Sorry, no such media found.
{% endif %}
From 9074ee7c1df9cca8a250cc837c3e3efb8e359649 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 29 Jun 2011 01:29:39 +0200
Subject: [PATCH 5/8] Issue #362 - Updated `mediagoblin.user_pages.views` to
handle new "Simple comments" feature
* ADDED `media_post_comment(request)` which creates `MediaComments`
from POST requests
* UPDATED `media_home(request, media, **kwargs)` now passes `comments`,
`pagination` and `comments_form` to `media.html`
---
mediagoblin/user_pages/views.py | 51 ++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index d6cd6034..67a57d97 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -15,13 +15,18 @@
# along with this program. If not, see .
from webob import exc
-from mediagoblin.db.util import DESCENDING
-from mediagoblin.util import Pagination, render_to_response
+from mediagoblin.db.util import DESCENDING, ObjectId
+from mediagoblin.util import Pagination, render_to_response, redirect, \
+ clean_html
+from mediagoblin.user_pages import forms as user_forms
-from mediagoblin.decorators import uses_pagination, get_user_media_entry
+from mediagoblin.decorators import uses_pagination, get_user_media_entry, \
+ require_active_login
from werkzeug.contrib.atom import AtomFeed
+import markdown
+
@uses_pagination
def user_home(request, page):
"""'Homepage' of a User()"""
@@ -78,13 +83,45 @@ def user_gallery(request, page):
@get_user_media_entry
-def media_home(request, media):
- """'Homepage' of a MediaEntry()"""
+@uses_pagination
+def media_home(request, media, **kwargs):
+ """
+ 'Homepage' of a MediaEntry()
+ """
+
+ comment_form = user_forms.MediaCommentForm(request.POST)
+
+ (comments, pagination) = media.get_comments(kwargs.get('page'))
+
return render_to_response(
request,
'mediagoblin/user_pages/media.html',
- {'media': media})
+ {'media': media,
+ 'comments': comments,
+ 'pagination': pagination,
+ 'comment_form': comment_form})
+@require_active_login
+def media_post_comment(request):
+ """
+ recieves POST from a MediaEntry() comment form, saves the comment.
+ """
+ comment = request.db.MediaComment()
+ comment['media_entry'] = ObjectId(request.matchdict['media'])
+ comment['author'] = request.user['_id']
+ comment['content'] = request.POST['comment']
+
+ md = markdown.Markdown(
+ safe_mode = 'escape')
+ comment['content_html'] = clean_html(
+ md.convert(
+ comment['content']))
+
+ comment.save()
+
+ return redirect(request, 'mediagoblin.user_pages.media_home',
+ media = request.matchdict['media'],
+ user = request.matchdict['user'])
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
@@ -117,4 +154,4 @@ def atom_feed(request):
updated=entry.get('created'),
url=entry.url_for_self(request.urlgen))
- return feed.get_response()
+ return feed.get_response()
From 074ac832c3ccd22f58118d51606ede3a1e696b4c Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 29 Jun 2011 01:35:43 +0200
Subject: [PATCH 6/8] Issue #362 - Added new `wtforms.Form`;
`MediaCommentForm()`
* ADDED `MediaCommentForm` is a form for `MediaComment`
user entry and posting.
---
mediagoblin/user_pages/forms.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 mediagoblin/user_pages/forms.py
diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
new file mode 100644
index 00000000..9f7d2fbd
--- /dev/null
+++ b/mediagoblin/user_pages/forms.py
@@ -0,0 +1,21 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import wtforms
+
+class MediaCommentForm(wtforms.Form):
+ comment = wtforms.TextAreaField('Comment',
+ [wtforms.validators.Required()])
\ No newline at end of file
From 95e6da024d019c0f93d041aedc19b2bf6697a3fd Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 29 Jun 2011 20:41:52 -0500
Subject: [PATCH 7/8] Use the cleaned_markdown_conversion method instead of
doing that manually
---
mediagoblin/user_pages/views.py | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 67a57d97..d581f19c 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -16,8 +16,8 @@
from webob import exc
from mediagoblin.db.util import DESCENDING, ObjectId
-from mediagoblin.util import Pagination, render_to_response, redirect, \
- clean_html
+from mediagoblin.util import (
+ Pagination, render_to_response, redirect, cleaned_markdown_conversion)
from mediagoblin.user_pages import forms as user_forms
from mediagoblin.decorators import uses_pagination, get_user_media_entry, \
@@ -25,7 +25,6 @@ from mediagoblin.decorators import uses_pagination, get_user_media_entry, \
from werkzeug.contrib.atom import AtomFeed
-import markdown
@uses_pagination
def user_home(request, page):
@@ -101,6 +100,7 @@ def media_home(request, media, **kwargs):
'pagination': pagination,
'comment_form': comment_form})
+
@require_active_login
def media_post_comment(request):
"""
@@ -111,11 +111,7 @@ def media_post_comment(request):
comment['author'] = request.user['_id']
comment['content'] = request.POST['comment']
- md = markdown.Markdown(
- safe_mode = 'escape')
- comment['content_html'] = clean_html(
- md.convert(
- comment['content']))
+ comment['content_html'] = cleaned_markdown_conversion(comment['content'])
comment.save()
@@ -123,6 +119,7 @@ def media_post_comment(request):
media = request.matchdict['media'],
user = request.matchdict['user'])
+
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
def atom_feed(request):
From 52359e9103e85e153e3012332e59bd64abf83dbc Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 29 Jun 2011 20:51:17 -0500
Subject: [PATCH 8/8] Excitedly send a user a message that their comment was
posted.
---
mediagoblin/user_pages/views.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index d581f19c..399d2020 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -15,6 +15,8 @@
# along with this program. If not, see .
from webob import exc
+
+from mediagoblin import messages
from mediagoblin.db.util import DESCENDING, ObjectId
from mediagoblin.util import (
Pagination, render_to_response, redirect, cleaned_markdown_conversion)
@@ -115,6 +117,10 @@ def media_post_comment(request):
comment.save()
+ messages.add_message(
+ request, messages.SUCCESS,
+ 'Comment posted!')
+
return redirect(request, 'mediagoblin.user_pages.media_home',
media = request.matchdict['media'],
user = request.matchdict['user'])