aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--docs/hackinghowto.rst2
-rwxr-xr-xlazyserver.sh19
-rw-r--r--mediagoblin/app.py7
-rw-r--r--mediagoblin/db/__init__.py46
-rw-r--r--mediagoblin/db/models.py50
-rw-r--r--mediagoblin/db/util.py2
-rw-r--r--mediagoblin/edit/views.py29
-rw-r--r--mediagoblin/init/__init__.py (renamed from mediagoblin/templates/mediagoblin/media_details.html)40
-rw-r--r--mediagoblin/init/celery/__init__.py (renamed from mediagoblin/celery_setup/__init__.py)2
-rw-r--r--mediagoblin/init/celery/dummy_settings_module.py (renamed from mediagoblin/celery_setup/dummy_settings_module.py)0
-rw-r--r--mediagoblin/init/celery/from_celery.py (renamed from mediagoblin/celery_setup/from_celery.py)2
-rw-r--r--mediagoblin/init/celery/from_tests.py (renamed from mediagoblin/celery_setup/from_tests.py)2
-rw-r--r--mediagoblin/init/config.py (renamed from mediagoblin/config.py)0
-rw-r--r--mediagoblin/process_media/__init__.py36
-rw-r--r--mediagoblin/static/css/base.css31
-rw-r--r--mediagoblin/static/images/icon_delete.pngbin0 -> 472 bytes
-rw-r--r--mediagoblin/static/images/icon_edit.pngbin0 -> 297 bytes
-rw-r--r--mediagoblin/static/images/icon_feed.pngbin0 -> 522 bytes
-rw-r--r--mediagoblin/templates/mediagoblin/edit/edit_profile.html4
-rw-r--r--mediagoblin/templates/mediagoblin/root.html1
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html104
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/user.html11
-rw-r--r--mediagoblin/templates/mediagoblin/utils/object_gallery.html12
-rw-r--r--mediagoblin/templates/mediagoblin/utils/pagination.html62
-rw-r--r--mediagoblin/templates/mediagoblin/utils/prev_next.html45
-rw-r--r--mediagoblin/templates/mediagoblin/utils/profile.html16
-rw-r--r--mediagoblin/tests/test_celery_setup.py4
-rw-r--r--mediagoblin/tests/test_config.py2
-rw-r--r--mediagoblin/tests/test_mgoblin_app.ini2
-rw-r--r--mediagoblin/tests/tools.py10
-rw-r--r--mediagoblin/user_pages/views.py13
-rw-r--r--mediagoblin/util.py16
-rwxr-xr-xruntests.sh2
34 files changed, 388 insertions, 185 deletions
diff --git a/.gitignore b/.gitignore
index 9187e738..f5c2ba31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@ mediagoblin.egg-info
*.pyo
docs/_build/
user_dev/
+mediagoblin_user.ini
server-log.txt
*~
*.swp
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 911f2340..08b228f1 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -150,7 +150,7 @@ celeryd in another window.
Run::
- CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
+ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_celery ./bin/celeryd
Running the test suite
diff --git a/lazyserver.sh b/lazyserver.sh
index fdb03ba0..4f10f771 100755
--- a/lazyserver.sh
+++ b/lazyserver.sh
@@ -16,6 +16,22 @@
# 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/>.
+if [ "$1" = "-h" ]
+then
+ echo "$0 [-h] [-c paste.ini] ARGS_to_paster"
+ echo " For example:"
+ echo " $0 -c fcgi.ini port_number=23371"
+ exit 1
+fi
+
+PASTE_INI=paste.ini
+if [ "$1" = "-c" ]
+then
+ PASTE_INI="$2"
+ shift
+ shift
+fi
+
if [ -f ./bin/paster ]; then
echo "Using ./bin/paster";
export PASTER="./bin/paster";
@@ -27,4 +43,5 @@ else
exit 1
fi
-CELERY_ALWAYS_EAGER=true $PASTER serve paste.ini --reload
+set -x
+CELERY_ALWAYS_EAGER=true $PASTER serve $PASTE_INI "$@" --reload
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index b27b5761..9454b403 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -21,11 +21,12 @@ import routes
from webob import Request, exc
from mediagoblin import routing, util, storage, staticdirect
-from mediagoblin.config import (
+from mediagoblin.init.config import (
read_mediagoblin_config, generate_validation_report)
from mediagoblin.db.open import setup_connection_and_db_from_config
from mediagoblin.mg_globals import setup_globals
-from mediagoblin.celery_setup import setup_celery_from_config
+from mediagoblin.init.celery import setup_celery_from_config
+from mediagoblin.init import get_jinja_loader
from mediagoblin.workbench import WorkbenchManager
@@ -71,7 +72,7 @@ class MediaGoblinApp(object):
app_config)
# Get the template environment
- self.template_loader = util.get_jinja_loader(
+ self.template_loader = get_jinja_loader(
app_config.get('user_template_path'))
# Set up storage systems
diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py
index c129cbf8..776025ca 100644
--- a/mediagoblin/db/__init__.py
+++ b/mediagoblin/db/__init__.py
@@ -13,3 +13,49 @@
#
# 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/>.
+
+"""
+Database Abstraction/Wrapper Layer
+==================================
+
+ **NOTE from Chris Webber:** I asked Elrond to explain why he put
+ ASCENDING and DESCENDING in db/util.py when we could just import from
+ pymongo. Read beow for why, but note that nobody is actually doing
+ this and there's no proof that we'll ever support more than
+ MongoDB... it would be a huge amount of work to do so.
+
+ If you really want to prove that possible, jump on IRC and talk to
+ us about making such a branch. In the meanwhile, it doesn't hurt to
+ have things as they are... if it ever makes it hard for us to
+ actually do things, we might revisit or remove this. But for more
+ information, read below.
+
+This submodule is for most of the db specific stuff.
+
+There are two main ideas here:
+
+1. Open up a small possibility to replace mongo by another
+ db. This means, that all direct mongo accesses should
+ happen in the db submodule. While all the rest uses an
+ API defined by this submodule.
+
+ Currently this API happens to be basicly mongo.
+ Which means, that the abstraction/wrapper layer is
+ extremely thin.
+
+2. Give the rest of the app a simple and easy way to get most of
+ their db needs. Which often means some simple import
+ from db.util.
+
+What does that mean?
+
+* Never import mongo directly outside of this submodule.
+
+* Inside this submodule you can do whatever is needed. The
+ API border is exactly at the submodule layer. Nowhere
+ else.
+
+* helper functions can be moved in here. They become part
+ of the db.* API
+
+"""
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index bf825a23..8aa35ca9 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -22,8 +22,7 @@ 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 DESCENDING, ObjectId
-from mediagoblin.util import Pagination
+from mediagoblin.db.util import ASCENDING, DESCENDING, ObjectId
###################
# Custom validators
@@ -109,24 +108,13 @@ class MediaEntry(Document):
migration_handler = migrations.MediaEntryMigration
+ def get_comments(self):
+ return self.db.MediaComment.find({
+ 'media_entry': self['_id']}).sort('created', DESCENDING)
+
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'])
@@ -154,6 +142,32 @@ class MediaEntry(Document):
'mediagoblin.user_pages.media_home',
user=uploader['username'],
media=unicode(self['_id']))
+
+ def url_to_prev(self, urlgen):
+ """
+ Provide a url to the previous entry from this user, if there is one
+ """
+ cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']},
+ 'uploader': self['uploader']}).sort(
+ '_id', DESCENDING).limit(1)
+
+ if cursor.count():
+ return urlgen('mediagoblin.user_pages.media_home',
+ user=self.uploader()['username'],
+ media=unicode(cursor[0]['_id']))
+
+ def url_to_next(self, urlgen):
+ """
+ Provide a url to the next entry from this user, if there is one
+ """
+ cursor = self.db.MediaEntry.find({'_id' : {"$gt": self['_id']},
+ 'uploader': self['uploader']}).sort(
+ '_id', ASCENDING).limit(1)
+
+ if cursor.count():
+ return urlgen('mediagoblin.user_pages.media_home',
+ user=self.uploader()['username'],
+ media=unicode(cursor[0]['_id']))
def uploader(self):
return self.db.User.find_one({'_id': self['uploader']})
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 46f899f7..70c37945 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -30,7 +30,7 @@ document relevant to here:
import copy
# Imports that other modules might use
-from pymongo import DESCENDING
+from pymongo import ASCENDING, DESCENDING
from pymongo.errors import InvalidId
from mongokit import ObjectId
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index a9071495..e064a9c3 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -17,6 +17,7 @@
from webob import exc
+from mediagoblin import messages
from mediagoblin.util import render_to_response, redirect, clean_html
from mediagoblin.edit import forms
from mediagoblin.edit.lib import may_edit_media
@@ -63,6 +64,14 @@ def edit_media(request, media):
return redirect(request, "mediagoblin.user_pages.media_home",
user=media.uploader()['username'], media=media['slug'])
+ if request.user['is_admin'] \
+ and media['uploader'] != request.user['_id'] \
+ and request.method != 'POST':
+ messages.add_message(
+ request, messages.WARNING,
+ "You are editing another user's media. Proceed with caution.")
+
+
return render_to_response(
request,
'mediagoblin/edit/edit.html',
@@ -73,7 +82,18 @@ def edit_media(request, media):
@require_active_login
def edit_profile(request):
- user = request.user
+ # admins may edit any user profile given a username in the querystring
+ edit_username = request.GET.get('username')
+ if request.user['is_admin'] and request.user['username'] != edit_username:
+ user = request.db.User.find_one({'username': edit_username})
+ # No need to warn again if admin just submitted an edited profile
+ if request.method != 'POST':
+ messages.add_message(
+ request, messages.WARNING,
+ "You are editing a user's profile. Proceed with caution.")
+ else:
+ user = request.user
+
form = forms.EditProfileForm(request.POST,
url = user.get('url'),
bio = user.get('bio'))
@@ -83,7 +103,12 @@ def edit_profile(request):
user['bio'] = request.POST['bio']
user.save()
- return redirect(request, "index", user=user['username'])
+ messages.add_message(request,
+ messages.SUCCESS,
+ 'Profile edited!')
+ return redirect(request,
+ "mediagoblin.edit.profile",
+ username=edit_username)
return render_to_response(
request,
diff --git a/mediagoblin/templates/mediagoblin/media_details.html b/mediagoblin/init/__init__.py
index 0e907616..b8ed2456 100644
--- a/mediagoblin/templates/mediagoblin/media_details.html
+++ b/mediagoblin/init/__init__.py
@@ -1,4 +1,3 @@
-{#
# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
@@ -14,24 +13,21 @@
#
# 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/>.
-#}
-{% extends "mediagoblin/base.html" %}
-{% 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) }}" />
- <h1>Media details for {{media.title}}</h1>
- <p>
- <br/>Uploaded: {{ media.created}}
- <br/>Description: {{media.description}}
- </p>
- </div>
- <div class="grid_4 omega sidebar">
- <p>Uploaded: {{ media.created}}</p>
- </div>
- {% else %}
- <p>Sorry, no such media found.<p/>
- {% endif %}
-{% endblock %}
+
+import jinja2
+
+
+def get_jinja_loader(user_template_path=None):
+ """
+ Set up the Jinja template loaders, possibly allowing for user
+ overridden templates.
+
+ (In the future we may have another system for providing theming;
+ for now this is good enough.)
+ """
+ if user_template_path:
+ return jinja2.ChoiceLoader(
+ [jinja2.FileSystemLoader(user_template_path),
+ jinja2.PackageLoader('mediagoblin', 'templates')])
+ else:
+ return jinja2.PackageLoader('mediagoblin', 'templates')
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/init/celery/__init__.py
index e35dbce2..67c3dfa0 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/init/celery/__init__.py
@@ -20,7 +20,7 @@ import sys
MANDATORY_CELERY_IMPORTS = ['mediagoblin.process_media']
-DEFAULT_SETTINGS_MODULE = 'mediagoblin.celery_setup.dummy_settings_module'
+DEFAULT_SETTINGS_MODULE = 'mediagoblin.init.celery.dummy_settings_module'
def setup_celery_from_config(app_config, global_config,
diff --git a/mediagoblin/celery_setup/dummy_settings_module.py b/mediagoblin/init/celery/dummy_settings_module.py
index e69de29b..e69de29b 100644
--- a/mediagoblin/celery_setup/dummy_settings_module.py
+++ b/mediagoblin/init/celery/dummy_settings_module.py
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/init/celery/from_celery.py
index ed0a409e..c053591b 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/init/celery/from_celery.py
@@ -17,7 +17,7 @@
import os
from mediagoblin import app, mg_globals
-from mediagoblin.celery_setup import setup_celery_from_config
+from mediagoblin.init.celery import setup_celery_from_config
OUR_MODULENAME = __name__
diff --git a/mediagoblin/celery_setup/from_tests.py b/mediagoblin/init/celery/from_tests.py
index 779ecd65..b2293e2c 100644
--- a/mediagoblin/celery_setup/from_tests.py
+++ b/mediagoblin/init/celery/from_tests.py
@@ -17,7 +17,7 @@
import os
from mediagoblin.tests.tools import TEST_APP_CONFIG
-from mediagoblin.celery_setup.from_celery import setup_self
+from mediagoblin.init.celery.from_celery import setup_self
OUR_MODULENAME = __name__
diff --git a/mediagoblin/config.py b/mediagoblin/init/config.py
index 2f93d32c..2f93d32c 100644
--- a/mediagoblin/config.py
+++ b/mediagoblin/init/config.py
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 0dce1418..0d1abcb3 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -22,6 +22,7 @@ from mediagoblin import mg_globals as mgg
THUMB_SIZE = 200, 200
+MEDIUM_SIZE = 640, 640
def create_pub_filepath(entry, filename):
@@ -43,20 +44,32 @@ def process_media_initial(media_id):
mgg.queue_store, queued_filepath,
'source')
- queued_file = file(queued_filename, 'r')
+ thumb = Image.open(queued_filename)
+ thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
+ # ensure color mode is compatible with jpg
+ if thumb.mode != "RGB":
+ thumb = thumb.convert("RGB")
- with queued_file:
- thumb = Image.open(queued_file)
- thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
- # ensure color mode is compatible with jpg
- if thumb.mode != "RGB":
- thumb = thumb.convert("RGB")
+ thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg')
+
+ thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
+ with thumb_file:
+ thumb.save(thumb_file, "JPEG")
+
+ """
+ Create medium file, used in `media.html`
+ """
+ medium = Image.open(queued_filename)
+ medium.thumbnail(MEDIUM_SIZE, Image.ANTIALIAS)
+
+ if medium.mode != "RGB":
+ medium = medium.convert("RGB")
- thumb_filepath = create_pub_filepath(entry, 'thumbnail.jpg')
+ medium_filepath = create_pub_filepath(entry, 'medium.jpg')
- thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
- with thumb_file:
- thumb.save(thumb_file, "JPEG")
+ medium_file = mgg.public_store.get_file(medium_filepath, 'w')
+ with medium_file:
+ medium.save(medium_file, "JPEG")
# we have to re-read because unlike PIL, not everything reads
# things in string representation :)
@@ -73,6 +86,7 @@ def process_media_initial(media_id):
media_files_dict = entry.setdefault('media_files', {})
media_files_dict['thumb'] = thumb_filepath
media_files_dict['main'] = main_filepath
+ media_files_dict['medium'] = medium_filepath
entry['state'] = u'processed'
entry.save()
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 31573820..3b2a9a50 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -133,15 +133,6 @@ a.mediagoblin_logo:hover {
/* common website elements */
-.dotted_line {
- width:100%;
- height:0px;
- border-bottom: dotted 1px #5f5f5f;
- position:absolute;
- left:0px;
- margin-top:-20px;
-}
-
.button {
font-family:'Carter One', arial, serif;
height:32px;
@@ -164,6 +155,10 @@ a.mediagoblin_logo:hover {
padding-right:11px;
}
+.pagination{
+text-align:center;
+}
+
/* forms */
.form_box {
@@ -223,6 +218,17 @@ a.mediagoblin_logo:hover {
width:280px;
}
+/* comments */
+
+.comment_author {
+ margin-bottom:40px;
+ padding-top:4px;
+}
+
+.comment_content p {
+ margin-bottom:4px;
+}
+
/* media galleries */
ul.media_thumbnail {
@@ -240,3 +246,10 @@ li.media_thumbnail {
zoom:1;
. *display:inline;
}
+
+/* icons */
+
+img.media_icon{
+ margin:0 4px;
+ vertical-align:sub;
+}
diff --git a/mediagoblin/static/images/icon_delete.png b/mediagoblin/static/images/icon_delete.png
new file mode 100644
index 00000000..9d76a5db
--- /dev/null
+++ b/mediagoblin/static/images/icon_delete.png
Binary files differ
diff --git a/mediagoblin/static/images/icon_edit.png b/mediagoblin/static/images/icon_edit.png
new file mode 100644
index 00000000..480c73ad
--- /dev/null
+++ b/mediagoblin/static/images/icon_edit.png
Binary files differ
diff --git a/mediagoblin/static/images/icon_feed.png b/mediagoblin/static/images/icon_feed.png
new file mode 100644
index 00000000..11e5b1e7
--- /dev/null
+++ b/mediagoblin/static/images/icon_feed.png
Binary files differ
diff --git a/mediagoblin/templates/mediagoblin/edit/edit_profile.html b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
index 7efd0ee3..cf228977 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit_profile.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit_profile.html
@@ -21,8 +21,8 @@
{% block mediagoblin_content %}
- <form action="{{ request.urlgen('mediagoblin.edit.profile',
- user=user.username) }}"
+ <form action="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
+ user['username'] }}"
method="POST" enctype="multipart/form-data">
<div class="grid_6 prefix_1 suffix_1 edit_box form_box">
<h1>Editing {{ user['username'] }}'s profile</h1>
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index e29abd51..5b744999 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -23,7 +23,6 @@
{% if request.user %}
<p>
<a href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit an item</a>
- <a href="{{ request.urlgen('mediagoblin.edit.profile') }}">Edit profile</a>
</p>
{% else %}
<p>
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 3cebe2f9..ca2ec5d6 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -18,86 +18,100 @@
{% extends "mediagoblin/base.html" %}
{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+{% from "mediagoblin/utils/pagination.html" import render_pagination %}
{% block mediagoblin_content %}
- {# temporarily, an "image gallery" that isn't one really ;) #}
{% if media %}
<div class="grid_8 alpha media_image">
- <h1>
+ {% if media.media_files.medium %}
+ <img src="{{ request.app.public_store.file_url(
+ media.media_files.medium) }}" />
+ {% else %}
+ <img src="{{ request.app.public_store.file_url(
+ media.media_files.main) }}" />
+ {% endif %}
+
+ <h2>
{{media.title}}
- </h1>
- <img class="media_image" src="{{ request.app.public_store.file_url(
- media.media_files.main) }}" />
+ </h2>
+
+ {% autoescape False %}
+ <p>{{ media.description_html }}</p>
+ {% endautoescape %}
+
<p>
- Uploaded on
+ &mdash;&nbsp;uploaded on
{{ "%4d-%02d-%02d"|format(media.created.year,
media.created.month, media.created.day) }}
by
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
user= media.uploader().username) }}">
{{- media.uploader().username }}</a>
- </p>
+ </p>
+ <br /><br />
- {% 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 %}
+ <h3>Comments</h3>
{% 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" />
+ <input type="submit" value="Post comment!" 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 %}
+ {% set comment_author = comment.author() %}
<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>
+ </div>
+ <div class="comment_author">&mdash;
+ <a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
+ user = comment_author['username']) }}">
+ {{ comment_author['username'] }}</a> at
+ <!--</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>
{% endfor %}
- {% include "mediagoblin/utils/pagination.html" %}
+
+ {{ render_pagination(request, pagination) }}
</div>
{% endif %}
-
<div class="grid_4 omega media_sidebar">
- <p>This is a sidebar! Yay!</p>
+ {% include "mediagoblin/utils/prev_next.html" %}
+ <h3>Sidebar content here!</h3>
+ <p>
+ {% if media['uploader'] == request.user['_id'] or
+ request.user['is_admin'] %}
+ <p>
+ <a href="{{ request.urlgen('mediagoblin.edit.edit_media',
+ user= media.uploader().username,
+ media= media._id) }}"
+ ><img src="{{ request.staticdirect('/images/icon_edit.png') }}"
+ class="media_icon" />edit</a>
+ </p>
+ <p>
+ <img src="{{ request.staticdirect('/images/icon_delete.png') }}"
+ class="media_icon" />delete
+ </p>
+ {% endif %}
+ </p>
</div>
{% else %}
- <p>Sorry, no such media found.<p/>
+ <p>Sorry, no such media found.<p/>
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index 99e46a72..d23daccd 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -27,18 +27,21 @@
{% block mediagoblin_content -%}
{% if user %}
<h1>{{ user.username }}'s profile</h1>
+ {% if request.user == user.username or request.user['is_admin'] %}
+ <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
+ user.username }}"> Edit</a>
+ {% endif %}
{% include "mediagoblin/utils/profile.html" %}
+ {% set pagination_base_url = user_gallery_url %}
{% include "mediagoblin/utils/object_gallery.html" %}
- <p><a href="{{ request.urlgen('mediagoblin.user_pages.user_gallery',
- user= request.user['username']) }}">View all of {{ user.username }}'s media</a></p>
-
+ <p><a href="{{ user_gallery_url }}">View all of {{ user.username }}'s media</a></p>
<a href={{ request.urlgen(
'mediagoblin.user_pages.atom_feed',
- user=user.username) }}> atom feed</a>
+ user=user.username) }}>atom feed</a>
{% else %}
{# This *should* not occur as the view makes sure we pass in a user. #}
<p>Sorry, no such user found.<p/>
diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
index 8c88c174..4e2886f8 100644
--- a/mediagoblin/templates/mediagoblin/utils/object_gallery.html
+++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
@@ -16,6 +16,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
+{% from "mediagoblin/utils/pagination.html" import render_pagination %}
+
{% block object_gallery_content -%}
<div>
{% if media_entries %}
@@ -28,8 +30,12 @@
</li>
{% endfor %}
</ul>
- {% include "mediagoblin/utils/pagination.html" %}
- {% endif %}
-
+ {% if pagination_base_url %}
+ {# different url, so set that and don't keep the get params #}
+ {{ render_pagination(request, pagination, pagination_base_url, False) }}
+ {% else %}
+ {{ render_pagination(request, pagination) }}
+ {% endif %}
+ {% endif %}
</div>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index 2be0b92e..aae50d22 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -15,30 +15,48 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#}
-{# only display if {{pagination}} is defined #}
+{% macro render_pagination(request, pagination,
+ base_url=None, preserve_get_params=True) %}
+ {# only display if {{pagination}} is defined #}
+ {% if pagination and pagination.pages > 1 %}
+ {% if not base_url %}
+ {% set base_url = request.path_info %}
+ {% endif %}
-{% if pagination %}
- <div class="pagination">
+ {% if preserve_get_params %}
+ {% set get_params = request.GET %}
+ {% else %}
+ {% set get_params = {} %}
+ {% endif %}
- {% if pagination.has_prev %}
- <a href="{{ pagination.get_page_url(request, pagination.page-1) }}">&laquo; Prev</>
- {% endif %}
-
- {%- for page in pagination.iter_pages() %}
- {% if page %}
- {% if page != pagination.page %}
- <a href="{{ pagination.get_page_url(request, page) }}">{{ page }}</a>
+ <div class="pagination">
+ <p>
+ {% if pagination.has_prev %}
+ <a href="{{ pagination.get_page_url_explicit(
+ base_url, get_params,
+ pagination.page - 1) }}">&laquo; Prev</a>
+ {% endif %}
+
+ {%- for page in pagination.iter_pages() %}
+ {% if page %}
+ {% if page != pagination.page %}
+ <a href="{{ pagination.get_page_url_explicit(
+ base_url, get_params,
+ page) }}">{{ page }}</a>
+ {% else %}
+ {{ page }}
+ {% endif %}
{% else %}
- <strong>{{ page }}</strong>
+ <span class="ellipsis">…</span>
{% endif %}
- {% else %}
- <span class="ellipsis">…</span>
+ {%- endfor %}
+
+ {% if pagination.has_next %}
+ <a href="{{ pagination.get_page_url_explicit(
+ base_url, get_params,
+ pagination.page + 1) }}">Next &raquo;</a>
{% endif %}
- {%- endfor %}
-
- {% if pagination.has_next %}
- <a href="{{ pagination.get_page_url(request, pagination.page + 1) }}">Next &raquo;</a>
- {% endif %}
- </div>
-{% endif %}
-
+ </p>
+ </div>
+ {% endif %}
+{% endmacro %}
diff --git a/mediagoblin/templates/mediagoblin/utils/prev_next.html b/mediagoblin/templates/mediagoblin/utils/prev_next.html
new file mode 100644
index 00000000..e054ed23
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/utils/prev_next.html
@@ -0,0 +1,45 @@
+{#
+# 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/>.
+#}
+
+{# Provide navigation links to neighboring media entries, if possible #}
+{% set prev_entry_url = media.url_to_prev(request.urlgen) %}
+{% set next_entry_url = media.url_to_next(request.urlgen) %}
+
+<div>
+ {# There are no previous entries for the very first media entry #}
+ {% if prev_entry_url %}
+ <a href="{{ prev_entry_url }}">
+ {# TODO - insert 'Previous' and 'X' image sources #}
+ Previous
+ </a>
+ {% else %}
+ {# This is the first entry. display greyed-out 'previous' image #}
+ X
+ {% endif %}
+
+ {# Likewise, this could be the very last media entry #}
+ {% if next_entry_url %}
+ <a href="{{ next_entry_url }}">
+ {# TODO - insert 'Next' and 'X' image sources #}
+ Next
+ </a>
+ {% else %}
+ {# This is the last entry. display greyed-out 'next' image #}
+ X
+ {% endif %}
+</div>
diff --git a/mediagoblin/templates/mediagoblin/utils/profile.html b/mediagoblin/templates/mediagoblin/utils/profile.html
index b3f5f0f8..21468033 100644
--- a/mediagoblin/templates/mediagoblin/utils/profile.html
+++ b/mediagoblin/templates/mediagoblin/utils/profile.html
@@ -20,16 +20,16 @@
<div>
<ul>
{% if user.url %}
- <li>
- <a href="{{ user.url }}">homepage</a>
- </li>
- {% endif %}
+ <li>
+ <a href="{{ user.url }}">homepage</a>
+ </li>
+ {% endif %}
{% if user.bio %}
- <li>
- {{ user.bio }}
- </li>
- {% endif %}
+ <li>
+ {{ user.bio }}
+ </li>
+ {% endif %}
</ul>
</div>
{% endblock %}
diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py
index 8bf97ae4..b80cab49 100644
--- a/mediagoblin/tests/test_celery_setup.py
+++ b/mediagoblin/tests/test_celery_setup.py
@@ -16,8 +16,8 @@
import pkg_resources
-from mediagoblin import celery_setup
-from mediagoblin.config import read_mediagoblin_config
+from mediagoblin.init import celery as celery_setup
+from mediagoblin.init.config import read_mediagoblin_config
TEST_CELERY_CONF_NOSPECIALDB = pkg_resources.resource_filename(
diff --git a/mediagoblin/tests/test_config.py b/mediagoblin/tests/test_config.py
index 244f05e5..f9f12072 100644
--- a/mediagoblin/tests/test_config.py
+++ b/mediagoblin/tests/test_config.py
@@ -16,7 +16,7 @@
import pkg_resources
-from mediagoblin import config
+from mediagoblin.init import config
CARROT_CONF_GOOD = pkg_resources.resource_filename(
diff --git a/mediagoblin/tests/test_mgoblin_app.ini b/mediagoblin/tests/test_mgoblin_app.ini
index e022d47b..fd0f87a4 100644
--- a/mediagoblin/tests/test_mgoblin_app.ini
+++ b/mediagoblin/tests/test_mgoblin_app.ini
@@ -8,7 +8,7 @@ email_debug_mode = true
db_name = __mediagoblin_tests__
# Celery shouldn't be set up by the application as it's setup via
-# mediagoblin.celery_setup.from_celery
+# mediagoblin.init.celery.from_celery
celery_setup_elsewhere = true
[celery]
diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py
index 64f773f0..e56af4de 100644
--- a/mediagoblin/tests/tools.py
+++ b/mediagoblin/tests/tools.py
@@ -22,7 +22,7 @@ from paste.deploy import loadapp
from webtest import TestApp
from mediagoblin import util
-from mediagoblin.config import read_mediagoblin_config
+from mediagoblin.init.config import read_mediagoblin_config
from mediagoblin.decorators import _make_safe
from mediagoblin.db.open import setup_connection_and_db_from_config
@@ -42,8 +42,8 @@ USER_DEV_DIRECTORIES_TO_SETUP = [
BAD_CELERY_MESSAGE = """\
Sorry, you *absolutely* must run nosetests with the
-mediagoblin.celery_setup.from_tests module. Like so:
-$ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests"""
+mediagoblin.init.celery.from_tests module. Like so:
+$ CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests ./bin/nosetests"""
class BadCeleryEnviron(Exception): pass
@@ -51,7 +51,7 @@ class BadCeleryEnviron(Exception): pass
def suicide_if_bad_celery_environ():
if not os.environ.get('CELERY_CONFIG_MODULE') == \
- 'mediagoblin.celery_setup.from_tests':
+ 'mediagoblin.init.celery.from_tests':
raise BadCeleryEnviron(BAD_CELERY_MESSAGE)
@@ -59,7 +59,7 @@ def get_test_app(dump_old_app=True):
suicide_if_bad_celery_environ()
# Leave this imported as it sets up celery.
- from mediagoblin.celery_setup import from_tests
+ from mediagoblin.init.celery import from_tests
global MGOBLIN_APP
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 399d2020..3a8684d3 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -48,10 +48,15 @@ def user_home(request, page):
if media_entries == None:
return exc.HTTPNotFound()
+ user_gallery_url = request.urlgen(
+ 'mediagoblin.user_pages.user_gallery',
+ user=user['username'])
+
return render_to_response(
request,
'mediagoblin/user_pages/user.html',
{'user': user,
+ 'user_gallery_url': user_gallery_url,
'media_entries': media_entries,
'pagination': pagination})
@@ -82,17 +87,19 @@ def user_gallery(request, page):
'media_entries': media_entries,
'pagination': pagination})
+MEDIA_COMMENTS_PER_PAGE = 50
@get_user_media_entry
@uses_pagination
-def media_home(request, media, **kwargs):
+def media_home(request, media, page, **kwargs):
"""
'Homepage' of a MediaEntry()
"""
- comment_form = user_forms.MediaCommentForm(request.POST)
+ pagination = Pagination(page, media.get_comments(), MEDIA_COMMENTS_PER_PAGE)
+ comments = pagination()
- (comments, pagination) = media.get_comments(kwargs.get('page'))
+ comment_form = user_forms.MediaCommentForm(request.POST)
return render_to_response(
request,
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index a20e87c4..ab219df0 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -64,22 +64,6 @@ def clear_test_buckets():
clear_test_template_context()
-def get_jinja_loader(user_template_path=None):
- """
- Set up the Jinja template loaders, possibly allowing for user
- overridden templates.
-
- (In the future we may have another system for providing theming;
- for now this is good enough.)
- """
- if user_template_path:
- return jinja2.ChoiceLoader(
- [jinja2.FileSystemLoader(user_template_path),
- jinja2.PackageLoader('mediagoblin', 'templates')])
- else:
- return jinja2.PackageLoader('mediagoblin', 'templates')
-
-
SETUP_JINJA_ENVS = {}
diff --git a/runtests.sh b/runtests.sh
index 9b96b17c..1dfbf093 100755
--- a/runtests.sh
+++ b/runtests.sh
@@ -27,4 +27,4 @@ else
exit 1
fi
-CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests $NOSETESTS $@
+CELERY_CONFIG_MODULE=mediagoblin.init.celery.from_tests $NOSETESTS $@