diff options
-rw-r--r-- | mediagoblin/db/indexes.py | 10 | ||||
-rw-r--r-- | mediagoblin/db/models.py | 46 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media.html | 63 | ||||
-rw-r--r-- | mediagoblin/user_pages/forms.py | 21 | ||||
-rw-r--r-- | mediagoblin/user_pages/routing.py | 5 | ||||
-rw-r--r-- | mediagoblin/user_pages/views.py | 54 |
6 files changed, 182 insertions, 17 deletions
diff --git a/mediagoblin/db/indexes.py b/mediagoblin/db/indexes.py index bbcceb6d..d379a52b 100644 --- a/mediagoblin/db/indexes.py +++ b/mediagoblin/db/indexes.py @@ -111,6 +111,16 @@ USER_INDEXES = { ACTIVE_INDEXES['users'] = USER_INDEXES +# MediaComment indexes + +MEDIA_COMMENT_INDEXES = { + 'mediaentry_created': { + 'index': [('media_entry', ASCENDING), + ('created', DESCENDING)]}} + +ACTIVE_INDEXES['media_comments'] = MEDIA_COMMENT_INDEXES + + #################### # Deprecated indexes #################### diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 8d06ae49..bf825a23 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 @@ -110,7 +111,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']) @@ -142,8 +158,32 @@ class MediaEntry(Document): def uploader(self): return self.db.User.find_one({'_id': self['uploader']}) +class MediaComment(Document): + __collection__ = 'media_comments' + + structure = { + 'media_entry': ObjectId, + 'author': ObjectId, + 'created': datetime.datetime, + 'content': unicode, + 'content_html': unicode} + + required_fields = [ + 'media_entry', 'author', 'created', 'content'] + + default_values = { + 'created': datetime.datetime.utcnow} + + def media_entry(self): + return self.db.MediaEntry.find_one({'_id': self['media_entry']}) + + def author(self): + return self.db.User.find_one({'_id': self['author']}) -REGISTER_MODELS = [MediaEntry, User] +REGISTER_MODELS = [ + MediaEntry, + User, + MediaComment] def register_models(connection): diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index 90c5a231..3cebe2f9 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -16,15 +16,18 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. #} {% extends "mediagoblin/base.html" %} + +{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %} + {% block mediagoblin_content %} {# temporarily, an "image gallery" that isn't one really ;) #} {% if media %} <div class="grid_8 alpha media_image"> - <img src="{{ request.app.public_store.file_url( - media.media_files.main) }}" /> - <h2> + <h1> {{media.title}} - </h2> + </h1> + <img class="media_image" src="{{ request.app.public_store.file_url( + media.media_files.main) }}" /> <p> Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year, @@ -33,16 +36,64 @@ <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', user= media.uploader().username) }}"> {{- media.uploader().username }}</a> - </p> + </p> + {% autoescape False %} <p>{{ media.description_html }}</p> {% endautoescape %} + {% if media['uploader'] == request.user['_id'] %} <p><a href="{{ request.urlgen('mediagoblin.edit.edit_media', user= media.uploader().username, media= media._id) }}">Edit</a></p> {% endif %} - </div> + {% if request.user %} + <form action="{{ request.urlgen('mediagoblin.user_pages.media_post_comment', + user= media.uploader().username, + media=media._id) }}" method="POST"> + <h3>Post a comment!</h3> + {{ wtforms_util.render_field_div(comment_form.comment) }} + <div class="form_submit_buttons"> + <input type="submit" value="Submit" class="button" /> + </div> + </form> + {% endif %} + + {# + {{ wtforms_util.render_textarea_div(submit_form.description) }} + {{ wtforms_util.render_field_div(submit_form.file) }} + #} + + {% if comments %} + <h3>Comments</h3> + {% for comment in comments %} + <div class="comment_wrapper" id="comment-{{ comment['_id'] }}"> + <div class="comment_author">By: + <a href="{{ request.urlgen('mediagoblin.user_pages.user_home', + user = comment['author']['username']) }}"> + {{ comment['author']['username'] }} + </a> + </div> + <div class="comment_datetime"> + <a href="#comment-{{ comment['_id'] }}"> + {{ "%4d-%02d-%02d %02d:%02d"|format(comment.created.year, + comment.created.month, + comment.created.day, + comment.created.hour, + comment.created.minute) }} + </a> + </div> + <div class="comment_content"> + {% autoescape False %} + {{ comment.content_html }} + {% endautoescape %} + </div> + </div> + {% endfor %} + {% include "mediagoblin/utils/pagination.html" %} + </div> + {% endif %} + <div class="grid_4 omega media_sidebar"> <p>This is a sidebar! Yay!</p> </div> 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 <http://www.gnu.org/licenses/>.
+
+import wtforms
+
+class MediaCommentForm(wtforms.Form):
+ comment = wtforms.TextAreaField('Comment',
+ [wtforms.validators.Required()])
\ No newline at end of file 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")] diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index d6cd6034..399d2020 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -15,13 +15,19 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from webob import exc -from mediagoblin.db.util import DESCENDING -from mediagoblin.util import Pagination, render_to_response -from mediagoblin.decorators import uses_pagination, get_user_media_entry +from mediagoblin import messages +from mediagoblin.db.util import DESCENDING, ObjectId +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, \ + require_active_login from werkzeug.contrib.atom import AtomFeed + @uses_pagination def user_home(request, page): """'Homepage' of a User()""" @@ -78,12 +84,46 @@ 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'] + + comment['content_html'] = cleaned_markdown_conversion(comment['content']) + + 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']) ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5 @@ -117,4 +157,4 @@ def atom_feed(request): updated=entry.get('created'), url=entry.url_for_self(request.urlgen)) - return feed.get_response() + return feed.get_response() |