aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/conf.py4
-rw-r--r--docs/hackinghowto.rst5
-rwxr-xr-xmaketarball.sh57
-rw-r--r--mediagoblin.ini3
-rw-r--r--mediagoblin/auth/views.py33
-rw-r--r--mediagoblin/config_spec.ini5
-rw-r--r--mediagoblin/db/indexes.py10
-rw-r--r--mediagoblin/db/models.py20
-rw-r--r--mediagoblin/db/util.py13
-rw-r--r--mediagoblin/edit/forms.py3
-rw-r--r--mediagoblin/edit/views.py6
-rw-r--r--mediagoblin/process_media/__init__.py4
-rw-r--r--mediagoblin/static/css/base.css82
-rw-r--r--mediagoblin/static/images/icon.pngbin1670 -> 0 bytes
-rw-r--r--mediagoblin/static/images/logo.pngbin0 -> 839 bytes
-rw-r--r--mediagoblin/static/images/navigation_end.pngbin0 -> 718 bytes
-rw-r--r--mediagoblin/static/images/navigation_left.pngbin0 -> 406 bytes
-rw-r--r--mediagoblin/static/images/navigation_right.pngbin0 -> 383 bytes
-rw-r--r--mediagoblin/static/images/pagination_left.pngbin0 -> 252 bytes
-rw-r--r--mediagoblin/static/images/pagination_right.pngbin0 -> 249 bytes
-rw-r--r--mediagoblin/submit/routing.py5
-rw-r--r--mediagoblin/submit/views.py5
-rw-r--r--mediagoblin/templates/mediagoblin/auth/login.html4
-rw-r--r--mediagoblin/templates/mediagoblin/auth/verify_email.html28
-rw-r--r--mediagoblin/templates/mediagoblin/base.html8
-rw-r--r--mediagoblin/templates/mediagoblin/root.html10
-rw-r--r--mediagoblin/templates/mediagoblin/submit/success.html22
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media.html21
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/user.html48
-rw-r--r--mediagoblin/templates/mediagoblin/utils/pagination.html17
-rw-r--r--mediagoblin/templates/mediagoblin/utils/prev_next.html13
-rw-r--r--mediagoblin/templates/mediagoblin/utils/profile.html25
-rw-r--r--mediagoblin/tests/test_auth.py4
-rw-r--r--mediagoblin/user_pages/forms.py43
-rw-r--r--mediagoblin/user_pages/routing.py3
-rw-r--r--mediagoblin/user_pages/views.py10
-rw-r--r--mediagoblin/util.py36
-rw-r--r--mediagoblin/views.py4
-rw-r--r--setup.py2
39 files changed, 322 insertions, 231 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 0e75a617..6c64cdda 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -48,9 +48,9 @@ copyright = u'2011, Free Software Foundation, Inc and contributors'
# built documents.
#
# The short X.Y version.
-version = '0.0.2'
+version = '0.0.3'
# The full version, including alpha/beta/rc tags.
-release = '0.0.2'
+release = '0.0.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 08b228f1..914a5135 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -57,6 +57,11 @@ requirements::
sudo apt-get install mongodb git-core python python-dev \
python-lxml
+On Fedora::
+
+ yum install mongodb-server python-paste-deploy python-paste-script \
+ git-core python python-devel
+
.. YouCanHelp::
If you have instructions for other GNU/Linux distributions to set
diff --git a/maketarball.sh b/maketarball.sh
new file mode 100755
index 00000000..2ee78016
--- /dev/null
+++ b/maketarball.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+# usage: maketarball
+# maketarball <tag>
+#
+# With no arguments, this creates a source tarball from git master with a
+# filename based on today's date.
+#
+# With a <tag> argument, this creates a tarball of the tag.
+#
+# Examples:
+#
+# ./maketarball
+# ./maketarball v0.0.2
+
+NOWDATE=`date "+%Y-%m-%d"`
+
+if [ -z "$1" ]
+then
+ REVISH=master
+ PREFIX="$NOWDATE-$REVISH"
+else
+ REVISH=$1
+ PREFIX="$REVISH"
+fi
+
+# convert PREFIX to all lowercase.
+# nix the v from tag names.
+PREFIX=`echo "$PREFIX" | tr '[A-Z]' '[a-z]' | sed s/v//`
+
+echo "== REVISH $REVISH"
+echo "== PREFIX $PREFIX"
+
+echo ""
+
+echo "generating archive...."
+git archive \
+ --format=tar \
+ --prefix=mediagoblin-$PREFIX/ \
+ $REVISH > mediagoblin-$PREFIX.tar
+
+if [[ $? -ne 0 ]]
+then
+ echo "git archive command failed. See above text for reason."
+ if [[ -e mediagoblin-$PREFIX.tar ]]
+ then
+ rm mediagoblin-$PREFIX.tar
+ fi
+ exit 1;
+fi
+
+echo "compressing...."
+gzip mediagoblin-$PREFIX.tar
+
+echo "archive at mediagoblin-$PREFIX.tar.gz"
+
+echo "done." \ No newline at end of file
diff --git a/mediagoblin.ini b/mediagoblin.ini
index 596107dc..e889646a 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -8,6 +8,9 @@ email_sender_address = "notice@mediagoblin.example.org"
# set to false to enable sending notices
email_debug_mode = true
+# Set to false to disable registrations
+allow_registration = true
+
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 1d00f382..7fe507b1 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -18,6 +18,8 @@ import uuid
from webob import exc
+from mediagoblin import messages
+from mediagoblin import mg_globals
from mediagoblin.util import render_to_response, redirect
from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib
@@ -29,6 +31,14 @@ def register(request):
"""
Your classic registration view!
"""
+ # Redirects to indexpage if registrations are disabled
+ if not mg_globals.app_config["allow_registration"]:
+ messages.add_message(
+ request,
+ messages.WARNING,
+ ('Sorry, registration is disabled on this instance.'))
+ return redirect(request, "index")
+
register_form = auth_forms.RegistrationForm(request.POST)
if request.method == 'POST' and register_form.validate():
@@ -51,7 +61,7 @@ def register(request):
entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
request.POST['password'])
entry.save(validate=True)
-
+
send_verification_email(entry, request)
return redirect(request, "mediagoblin.auth.register_success")
@@ -97,13 +107,14 @@ def login(request):
'mediagoblin/auth/login.html',
{'login_form': login_form,
'next': request.GET.get('next') or request.POST.get('next'),
- 'login_failed': login_failed})
+ 'login_failed': login_failed,
+ 'allow_registration': mg_globals.app_config["allow_registration"]})
def logout(request):
# Maybe deleting the user_id parameter would be enough?
request.session.delete()
-
+
return redirect(request, "index")
@@ -124,16 +135,24 @@ def verify_email(request):
if user and user['verification_key'] == unicode(request.GET['token']):
user['status'] = u'active'
user['email_verified'] = True
- verification_successful = True
user.save()
+ verification_successful = True
+ messages.add_message(
+ request,
+ messages.SUCCESS,
+ ('Your email address has been verified. '
+ 'You may now login, edit your profile, and submit images!'))
else:
verification_successful = False
-
+ messages.add_message(request,
+ messages.ERROR,
+ 'The verification key or user id is incorrect')
+
return render_to_response(
request,
- 'mediagoblin/auth/verify_email.html',
+ 'mediagoblin/user_pages/user.html',
{'user': user,
- 'verification_successful': verification_successful})
+ 'verification_successful' : verification_successful})
def resend_activation(request):
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
index aadf5c21..b6356b0e 100644
--- a/mediagoblin/config_spec.ini
+++ b/mediagoblin/config_spec.ini
@@ -21,6 +21,9 @@ direct_remote_path = string(default="/mgoblin_static/")
email_debug_mode = boolean(default=True)
email_sender_address = string(default="notice@mediagoblin.example.org")
+# Set to false to disable registrations
+allow_registration = boolean(default=True)
+
# By default not set, but you might want something like:
# "%(here)s/user_dev/templates/"
local_templates = string()
@@ -73,4 +76,4 @@ celeryd_eta_scheduler_precision = float()
# known lists
celery_routes = string_list()
-celery_imports = string_list() \ No newline at end of file
+celery_imports = string_list()
diff --git a/mediagoblin/db/indexes.py b/mediagoblin/db/indexes.py
index d379a52b..a832e013 100644
--- a/mediagoblin/db/indexes.py
+++ b/mediagoblin/db/indexes.py
@@ -45,11 +45,13 @@ REQUIRED READING:
To remove deprecated indexes
----------------------------
-Removing deprecated indexes is easier, just do:
+Removing deprecated indexes is the same, just move the index into the
+deprecated indexes mapping.
-INACTIVE_INDEXES = {
- 'collection_name': [
- 'deprecated_index_identifier1', 'deprecated_index_identifier2']}
+DEPRECATED_INDEXES = {
+ 'collection_name': {
+ 'deprecated_index_identifier1': {
+ 'index': [index_foo_goes_here]}}
... etc.
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 8aa35ca9..279cb9f2 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -147,31 +147,33 @@ class MediaEntry(Document):
"""
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)
-
+ cursor = self.db.MediaEntry.find({'_id' : {"$gt": self['_id']},
+ 'uploader': self['uploader'],
+ 'state': 'processed'}).sort(
+ '_id', ASCENDING).limit(1)
if cursor.count():
return urlgen('mediagoblin.user_pages.media_home',
user=self.uploader()['username'],
- media=unicode(cursor[0]['_id']))
+ media=unicode(cursor[0]['slug']))
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)
+ cursor = self.db.MediaEntry.find({'_id' : {"$lt": self['_id']},
+ 'uploader': self['uploader'],
+ 'state': 'processed'}).sort(
+ '_id', DESCENDING).limit(1)
if cursor.count():
return urlgen('mediagoblin.user_pages.media_home',
user=self.uploader()['username'],
- media=unicode(cursor[0]['_id']))
+ media=unicode(cursor[0]['slug']))
def uploader(self):
return self.db.User.find_one({'_id': self['uploader']})
+
class MediaComment(Document):
__collection__ = 'media_comments'
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 70c37945..37e6586f 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -81,18 +81,25 @@ def remove_deprecated_indexes(database, deprecated_indexes=DEPRECATED_INDEXES):
Args:
- database: pymongo or mongokit database instance.
- deprecated_indexes: the indexes to deprecate in the pattern of:
- {'collection': ['index_identifier1', 'index_identifier2']}
+ {'collection_name': {
+ 'identifier': {
+ 'index': [index_foo_goes_here],
+ 'unique': True}}
+
+ (... although we really only need the 'identifier' here, as the
+ rest of the information isn't used in this case. But it's kept
+ around so we can remember what it was)
Returns:
A list of indexes removed in form ('collection', 'index_name')
"""
indexes_removed = []
- for collection_name, index_names in deprecated_indexes.iteritems():
+ for collection_name, indexes in deprecated_indexes.iteritems():
collection = database[collection_name]
collection_indexes = collection.index_information().keys()
- for index_name in index_names:
+ for index_name, index_data in indexes.iteritems():
if index_name in collection_indexes:
collection.drop_index(index_name)
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py
index d5e7f0a9..0ed52af1 100644
--- a/mediagoblin/edit/forms.py
+++ b/mediagoblin/edit/forms.py
@@ -23,7 +23,8 @@ class EditForm(wtforms.Form):
'Title',
[wtforms.validators.Length(min=0, max=500)])
slug = wtforms.TextField(
- 'Slug')
+ 'Slug',
+ [wtforms.validators.Required(message="The slug can't be empty")])
description = wtforms.TextAreaField('Description of this work')
class EditProfileForm(wtforms.Form):
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index e064a9c3..3bcf788b 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -106,9 +106,9 @@ def edit_profile(request):
messages.add_message(request,
messages.SUCCESS,
'Profile edited!')
- return redirect(request,
- "mediagoblin.edit.profile",
- username=edit_username)
+ return redirect(request,
+ 'mediagoblin.user_pages.user_home',
+ user=edit_username)
return render_to_response(
request,
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 27f72b65..da3e887e 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -54,7 +54,7 @@ def process_media_initial(media_id):
thumb_file = mgg.public_store.get_file(thumb_filepath, 'w')
with thumb_file:
- thumb.save(thumb_file, "JPEG")
+ thumb.save(thumb_file, "JPEG", quality=90)
"""
Create medium file, used in `media.html`
@@ -69,7 +69,7 @@ def process_media_initial(media_id):
medium_file = mgg.public_store.get_file(medium_filepath, 'w')
with medium_file:
- medium.save(medium_file, "JPEG")
+ medium.save(medium_file, "JPEG", quality=90)
# we have to re-read because unlike PIL, not everything reads
# things in string representation :)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 10dbc98b..31b8ebc2 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -1,6 +1,6 @@
body {
- background-color: #272727;
- color: #f7f7f7;
+ background-color: #1F1F1F;
+ color: #aaa;
font-family: sans-serif;
padding:none;
margin:0px;
@@ -18,28 +18,23 @@ form {
font-family: 'Carter One';
font-style: normal;
font-weight: normal;
- src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=VjW2qt1pkqVtO22ObxgEBRsxEYwM7FgeyaSgU71cLG0') format('woff');
+ src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=FWNn6ITYqL6or7ZTmBxRhq3fkYX5z1QtDUdIWoaaD_k') format('woff');
}
/* text styles */
h1{
font-family: 'Carter One', arial, serif;
- margin-bottom: 20px;
- margin-top:40px;
+ margin-bottom: 15px;
+ margin-top:15px;
}
h2{
margin-top:20px;
}
-p {
- font-family: sans-serif;
- font-size:16px;
-}
-
a {
- color: #86D4B1;
+ color: #fff;
}
label {
@@ -56,15 +51,33 @@ label {
.mediagoblin_header {
width:100%;
height:36px;
- background-color:#393939;
+ background-color:#2F2F2F;
padding-top:14px;
margin-bottom:40px;
}
+.header_submit{
+ color:#272727;
+ background-color:#aaa;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(##D2D2D2), to(#aaa));
+ background-image: -webkit-linear-gradient(top, #D2D2D2, #aaa);
+ background-image: -moz-linear-gradient(top, #D2D2D2, #aaa);
+ background-image: -ms-linear-gradient(top, #D2D2D2, #aaa);
+ background-image: -o-linear-gradient(top, #D2D2D2, #aaa);
+ background-image: linear-gradient(top, #D2D2D2, #aaa);
+ box-shadow:0px 0px 4px #000;
+ border-radius:5px 5px 5px 5px;
+ margin:8px;
+ padding:3px 8px;
+ text-decoration:none;
+ border:medium none;
+ font-family:'Carter One',arial,serif;
+}
+
.mediagoblin_footer {
width:100%;
- height:26px;
- background-color:#393939;
+ height:30px;
+ background-color:#2F2F2F;
bottom:0px;
padding-top:8px;
position:absolute;
@@ -77,19 +90,6 @@ label {
padding-bottom:74px;
}
-a.mediagoblin_logo {
- width:34px;
- height:25px;
- margin-right:10px;
- background-image:url('../images/icon.png');
- background-position:0px 0px;
- display:inline-block;
-}
-
-a.mediagoblin_logo:hover {
- background-position:0px -28px;
-}
-
.mediagoblin_header_right {
float:right;
}
@@ -122,6 +122,10 @@ a.mediagoblin_logo:hover {
text-align:center;
}
+.pagination_arrow{
+ margin:5px;
+}
+
/* forms */
.form_box {
@@ -130,7 +134,7 @@ text-align:center;
background-repeat:repeat-x;
font-size:18px;
padding-bottom:30px;
- padding-top:1px;
+ padding-top:30px;
margin-left:auto;
margin-right:auto;
display:block;
@@ -160,6 +164,7 @@ text-align:center;
.form_field_error {
background-color:#87453b;
+ color:#fff;
border:none;
font-size:16px;
padding:9px;
@@ -190,7 +195,7 @@ text-align:center;
height:180px;
overflow:hidden;
float:left;
- margin:0px 10px 10px 0px;
+ margin:0px 4px 10px 4px;
text-align:center;
}
@@ -204,14 +209,14 @@ img.media_icon{
/* navigation */
.navigation_button{
- width: 139px;
+ width:139px;
display:block;
float:left;
- text-align: center;
- background-color: #393939;
- text-decoration: none;
- padding: 6px 0pt;
- font-family: 'Carter One', arial, serif;
+ text-align:center;
+ background-color:#393939;
+ text-decoration:none;
+ padding:12px 0pt;
+ font-family:'Carter One', arial, serif;
font-size:2em;
margin:0 0 20px
}
@@ -257,10 +262,3 @@ ul.mediagoblin_messages {
background-color: #f7f7f7;
color:#272727;
}
-
-/* profile stuff */
-
-.profile_content p, .profile_bio {
- padding: 6px;
- background-color: #393939;
-}
diff --git a/mediagoblin/static/images/icon.png b/mediagoblin/static/images/icon.png
deleted file mode 100644
index 4f4f3e9c..00000000
--- a/mediagoblin/static/images/icon.png
+++ /dev/null
Binary files differ
diff --git a/mediagoblin/static/images/logo.png b/mediagoblin/static/images/logo.png
new file mode 100644
index 00000000..cf28a6d4
--- /dev/null
+++ b/mediagoblin/static/images/logo.png
Binary files differ
diff --git a/mediagoblin/static/images/navigation_end.png b/mediagoblin/static/images/navigation_end.png
new file mode 100644
index 00000000..b2f27296
--- /dev/null
+++ b/mediagoblin/static/images/navigation_end.png
Binary files differ
diff --git a/mediagoblin/static/images/navigation_left.png b/mediagoblin/static/images/navigation_left.png
new file mode 100644
index 00000000..d1645120
--- /dev/null
+++ b/mediagoblin/static/images/navigation_left.png
Binary files differ
diff --git a/mediagoblin/static/images/navigation_right.png b/mediagoblin/static/images/navigation_right.png
new file mode 100644
index 00000000..d4caa7b8
--- /dev/null
+++ b/mediagoblin/static/images/navigation_right.png
Binary files differ
diff --git a/mediagoblin/static/images/pagination_left.png b/mediagoblin/static/images/pagination_left.png
new file mode 100644
index 00000000..56a26596
--- /dev/null
+++ b/mediagoblin/static/images/pagination_left.png
Binary files differ
diff --git a/mediagoblin/static/images/pagination_right.png b/mediagoblin/static/images/pagination_right.png
new file mode 100644
index 00000000..84f8abba
--- /dev/null
+++ b/mediagoblin/static/images/pagination_right.png
Binary files differ
diff --git a/mediagoblin/submit/routing.py b/mediagoblin/submit/routing.py
index 3edbab70..5585ecb0 100644
--- a/mediagoblin/submit/routing.py
+++ b/mediagoblin/submit/routing.py
@@ -18,7 +18,4 @@ from routes.route import Route
submit_routes = [
Route('mediagoblin.submit.start', '/',
- controller='mediagoblin.submit.views:submit_start'),
- Route('mediagoblin.submit.success', '/success/',
- template='mediagoblin/submit/success.html',
- controller='mediagoblin.views:simple_template_render')]
+ controller='mediagoblin.submit.views:submit_start')]
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 4c7476b0..1848f5e5 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -95,8 +95,3 @@ def submit_start(request):
request,
'mediagoblin/submit/start.html',
{'submit_form': submit_form})
-
-
-def submit_success(request):
- return render_to_response(
- request, 'mediagoblin/submit/success.html', {})
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index 2303ce5c..e25783ea 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -35,7 +35,9 @@
<input type="hidden" name="next" value="{{ next }}" class="button"
style="display: none;"/>
{% endif %}
- <p>Don't have an account yet?<br /><a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
+ {% if allow_registration %}
+ <p>Don't have an account yet?<br /><a href="{{ request.urlgen('mediagoblin.auth.register') }}">Create one here!</a></p>
+ {% endif %}
</div>
</form>
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/verify_email.html b/mediagoblin/templates/mediagoblin/auth/verify_email.html
deleted file mode 100644
index b6e6d1f8..00000000
--- a/mediagoblin/templates/mediagoblin/auth/verify_email.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{#
-# 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/>.
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% block mediagoblin_content %}
-<p>
- {% if verification_successful %}
- Your email address has been verified!
- {% else %}
- The verification key or user id is incorrect
- {% endif %}
-</p>
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index b71fca24..40bb085e 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -38,8 +38,12 @@
<div class="container_16">
<div class="grid_16">
{% block mediagoblin_logo %}
- <a class="mediagoblin_logo" href="{{ request.urlgen('index') }}"></a>
- {% endblock %}{% block mediagoblin_header_title %}{% endblock %}
+ <a class="mediagoblin_logo" href="{{ request.urlgen('index') }}"><img src="{{ request.staticdirect('/images/logo.png') }}" alt="Mediagoblin logo" /></a>
+ {% endblock %}
+ {% if request.user %}
+ <a class="header_submit" href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit media</a>
+ {% endif %}
+ {% block mediagoblin_header_title %}{% endblock %}
<div class="mediagoblin_header_right">
{% if request.user %}
<a href="{{ request.urlgen('mediagoblin.user_pages.user_home',
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 5b744999..bae033c4 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -29,10 +29,12 @@
If you have an account, you can
<a href="{{ request.urlgen('mediagoblin.auth.login') }}">Login</a>.
</p>
- <p>
- If you don't have an account, please
- <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Register</a>.
- </p>
+ {% if allow_registration %}
+ <p>
+ If you don't have an account, please
+ <a href="{{ request.urlgen('mediagoblin.auth.register') }}">Register</a>.
+ </p>
+ {% endif %}
{% endif %}
{# temporarily, an "image gallery" that isn't one really ;) #}
diff --git a/mediagoblin/templates/mediagoblin/submit/success.html b/mediagoblin/templates/mediagoblin/submit/success.html
deleted file mode 100644
index afc9f9d1..00000000
--- a/mediagoblin/templates/mediagoblin/submit/success.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{#
-# 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/>.
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% block mediagoblin_content %}
- Woohoo! Submitted!
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 0383277b..3f4dce3b 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -48,14 +48,14 @@
user= media.uploader().username) }}">
{{- media.uploader().username }}</a>
</p>
- <br /><br />
+ <br />
<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">
- {{ wtforms_util.render_field_div(comment_form.comment) }}
+ {{ wtforms_util.render_field_div(comment_form.comment_content) }}
<div class="form_submit_buttons">
<input type="submit" value="Post comment!" class="button" />
</div>
@@ -65,7 +65,12 @@
{% if comments %}
{% for comment in comments %}
{% set comment_author = comment.author() %}
- <div class="comment_wrapper" id="comment-{{ comment['_id'] }}">
+ {% 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'] }}">
+ {% endif %}
<div class="comment_content">
{% autoescape False %}
{{ comment.content_html }}
@@ -77,7 +82,10 @@
{{ comment_author['username'] }}</a> at
<!--</div>
<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,
comment.created.month,
comment.created.day,
@@ -88,7 +96,10 @@
</div>
{% endfor %}
- {{ render_pagination(request, pagination) }}
+ {{ render_pagination(request, pagination,
+ request.urlgen('mediagoblin.user_pages.media_home',
+ user = media.uploader().username,
+ media = media._id)) }}
</div>
{% endif %}
<div class="grid_5 omega">
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index aed330c8..9d99ac53 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -26,33 +26,25 @@
{% block mediagoblin_content -%}
{% if user %}
- <h1>{{ user.username }}'s profile</h1>
-
- {% include "mediagoblin/utils/profile.html" %}
-
- {% if request.user['_id'] == user['_id'] or request.user['is_admin'] %}
- <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
- user.username }}">Edit profile</a>
- {% endif %}
-
- {% if request.user['_id'] == user['_id'] %}
- <p>
- <a href="{{ request.urlgen('mediagoblin.submit.start') }}">Submit an item</a>
- </p>
- {% endif %}
-
- {% set pagination_base_url = user_gallery_url %}
- {% include "mediagoblin/utils/object_gallery.html" %}
-
- <div class="clear"></div>
-
- <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>
- {% else %}
- {# This *should* not occur as the view makes sure we pass in a user. #}
- <p>Sorry, no such user found.<p/>
+ <h1>{{ user.username }}'s profile</h1>
+ <div class="grid_6 alpha">
+ {% include "mediagoblin/utils/profile.html" %}
+ {% if request.user['_id'] == user['_id'] or request.user['is_admin'] %}
+ <a href="{{ request.urlgen('mediagoblin.edit.profile') }}?username={{
+ user.username }}">Edit profile</a>
+ {% endif %}
+ </div>
+ <div class="grid_10 omega">
+ {% set pagination_base_url = user_gallery_url %}
+ {% include "mediagoblin/utils/object_gallery.html" %}
+ <div class="clear"></div>
+ <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>
+ {% else %}
+ {# This *should* not occur as the view makes sure we pass in a user. #}
+ <p>Sorry, no such user found.<p/>
+ </div>
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index aae50d22..23d49463 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -34,9 +34,16 @@
{% if pagination.has_prev %}
<a href="{{ pagination.get_page_url_explicit(
base_url, get_params,
- pagination.page - 1) }}">&laquo; Prev</a>
+ pagination.page - 1) }}"><img class="pagination_arrow" src="/mgoblin_static/images/pagination_left.png" alt="Previous page" />Newer</a>
{% endif %}
-
+ {% if pagination.has_next %}
+ <a href="{{ pagination.get_page_url_explicit(
+ base_url, get_params,
+ pagination.page + 1) }}">Older<img class="pagination_arrow" src="/mgoblin_static/images/pagination_right.png" alt="Next page" />
+ </a>
+ {% endif %}
+ <br />
+ Go to page:
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page != pagination.page %}
@@ -50,12 +57,6 @@
<span class="ellipsis">…</span>
{% endif %}
{%- endfor %}
-
- {% if pagination.has_next %}
- <a href="{{ pagination.get_page_url_explicit(
- base_url, get_params,
- pagination.page + 1) }}">Next &raquo;</a>
- {% endif %}
</p>
</div>
{% endif %}
diff --git a/mediagoblin/templates/mediagoblin/utils/prev_next.html b/mediagoblin/templates/mediagoblin/utils/prev_next.html
index 8908c298..7cf8d2a4 100644
--- a/mediagoblin/templates/mediagoblin/utils/prev_next.html
+++ b/mediagoblin/templates/mediagoblin/utils/prev_next.html
@@ -24,20 +24,23 @@
{# There are no previous entries for the very first media entry #}
{% if prev_entry_url %}
<a class="navigation_button navigation_left" href="{{ prev_entry_url }}">
- &lt;
+ <img src="/mgoblin_static/images/navigation_left.png" alt="Previous image" />
</a>
{% else %}
{# This is the first entry. display greyed-out 'previous' image #}
- <p class="navigation_button">X</p>
+ <p class="navigation_button navigation_left">
+ <img src="/mgoblin_static/images/navigation_end.png" alt="No previous images" />
+ </p>
{% endif %}
-
{# Likewise, this could be the very last media entry #}
{% if next_entry_url %}
<a class="navigation_button" href="{{ next_entry_url }}">
- &gt;
+ <img src="/mgoblin_static/images/navigation_right.png" alt="Next image" />
</a>
{% else %}
{# This is the last entry. display greyed-out 'next' image #}
- <p class="navigation_button">X</p>
+ <p class="navigation_button">
+ <img src="/mgoblin_static/images/navigation_end.png" alt="No following images" />
+ </p>
{% endif %}
</div>
diff --git a/mediagoblin/templates/mediagoblin/utils/profile.html b/mediagoblin/templates/mediagoblin/utils/profile.html
index 72a285d2..f44defa5 100644
--- a/mediagoblin/templates/mediagoblin/utils/profile.html
+++ b/mediagoblin/templates/mediagoblin/utils/profile.html
@@ -17,17 +17,14 @@
#}
{% block profile_content -%}
- <div class="profile_content">
- {% if user.url %}
- <p class="profile_homepage">
- <a href="{{ user.url }}">homepage</a>
- </p>
- {% endif %}
-
- {% if user.bio %}
- <p class="profile_bio">
- {{ user.bio }}
- </p>
- {% endif %}
- </div>
-{% endblock %}
+ {% if user.bio %}
+ <p>
+ {{ user.bio }}
+ </p>
+ {% endif %}
+ {% if user.url %}
+ <p>
+ <a href="{{ user.url }}">{{ user.url }}</a>
+ </p>
+ {% endif %}
+{% endblock %}
diff --git a/mediagoblin/tests/test_auth.py b/mediagoblin/tests/test_auth.py
index 3a13cbb1..ad9dd35b 100644
--- a/mediagoblin/tests/test_auth.py
+++ b/mediagoblin/tests/test_auth.py
@@ -189,7 +189,7 @@ def test_register_views(test_app):
"/auth/verify_email/?userid=%s&token=total_bs" % unicode(
new_user['_id']))
context = util.TEMPLATE_TEST_CONTEXT[
- 'mediagoblin/auth/verify_email.html']
+ 'mediagoblin/user_pages/user.html']
assert context['verification_successful'] == False
new_user = mg_globals.database.User.find_one(
{'username': 'happygirl'})
@@ -201,7 +201,7 @@ def test_register_views(test_app):
util.clear_test_template_context()
test_app.get("%s?%s" % (path, get_params))
context = util.TEMPLATE_TEST_CONTEXT[
- 'mediagoblin/auth/verify_email.html']
+ 'mediagoblin/user_pages/user.html']
assert context['verification_successful'] == True
new_user = mg_globals.database.User.find_one(
{'username': 'happygirl'})
diff --git a/mediagoblin/user_pages/forms.py b/mediagoblin/user_pages/forms.py
index 9f7d2fbd..8829b674 100644
--- a/mediagoblin/user_pages/forms.py
+++ b/mediagoblin/user_pages/forms.py
@@ -1,21 +1,22 @@
-# 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
+# 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_content = wtforms.TextAreaField(
+ 'Comment',
+ [wtforms.validators.Required()])
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 255b6f66..3be0617d 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -24,6 +24,9 @@ user_routes = [
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
requirements=dict(m_id="[0-9a-fA-F]{24}"),
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/",
controller="mediagoblin.edit.views:edit_media"),
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 3a8684d3..a3172ebd 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -95,8 +95,14 @@ def media_home(request, media, page, **kwargs):
"""
'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()
comment_form = user_forms.MediaCommentForm(request.POST)
@@ -118,7 +124,7 @@ def media_post_comment(request):
comment = request.db.MediaComment()
comment['media_entry'] = ObjectId(request.matchdict['media'])
comment['author'] = request.user['_id']
- comment['content'] = request.POST['comment']
+ comment['content'] = request.POST['comment_content']
comment['content_html'] = cleaned_markdown_conversion(comment['content'])
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index ab219df0..7b1e4a2a 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -14,6 +14,8 @@
# 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/>.
+from __future__ import division
+
from email.MIMEText import MIMEText
import gettext
import pkg_resources
@@ -21,7 +23,7 @@ import smtplib
import sys
import re
import urllib
-from math import ceil
+from math import ceil, floor
import copy
from babel.localedata import exists
@@ -35,6 +37,8 @@ from mediagoblin import mg_globals
from mediagoblin import messages
from mediagoblin.db.util import ObjectId
+from itertools import izip, count
+
TESTS_ENABLED = False
def _activate_testing():
"""
@@ -133,7 +137,16 @@ def render_to_response(request, template, context):
def redirect(request, *args, **kwargs):
"""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):
@@ -418,7 +431,8 @@ class Pagination(object):
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
@@ -426,11 +440,25 @@ class Pagination(object):
- page: requested page
- per_page: number of objects per page
- 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.cursor = cursor
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):
"""
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 5b6d9773..e7d9dbdd 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -14,6 +14,7 @@
# 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/>.
+from mediagoblin import mg_globals
from mediagoblin.util import render_to_response
from mediagoblin.db.util import DESCENDING
@@ -23,7 +24,8 @@ def root_view(request):
return render_to_response(
request, 'mediagoblin/root.html',
- {'media_entries': media_entries})
+ {'media_entries': media_entries,
+ 'allow_registration': mg_globals.app_config["allow_registration"]})
def simple_template_render(request):
diff --git a/setup.py b/setup.py
index 2a007f4e..799f00d8 100644
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@ from setuptools import setup, find_packages
setup(
name = "mediagoblin",
- version = "0.0.2",
+ version = "0.0.3",
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
zip_safe=False,
# scripts and dependencies