aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mediagoblin/db/indexes.py10
-rw-r--r--mediagoblin/db/models.py46
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html63
-rw-r--r--mediagoblin/user_pages/forms.py21
-rw-r--r--mediagoblin/user_pages/routing.py5
-rw-r--r--mediagoblin/user_pages/views.py54
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()