diff options
Diffstat (limited to 'mediagoblin')
-rw-r--r-- | mediagoblin/db/sql/base.py | 6 | ||||
-rw-r--r-- | mediagoblin/db/sql/migrations.py | 78 | ||||
-rw-r--r-- | mediagoblin/db/sql/util.py | 10 | ||||
-rw-r--r-- | mediagoblin/plugins/oauth/migrations.py | 92 | ||||
-rw-r--r-- | mediagoblin/static/css/base.css | 4 | ||||
-rw-r--r-- | mediagoblin/static/js/geolocation-map.js | 10 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/auth/register.html | 2 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/edit/attachments.html | 4 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/root.html | 30 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media.html | 4 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/utils/geolocation_map.html | 15 | ||||
-rw-r--r-- | mediagoblin/tools/text.py | 26 |
12 files changed, 203 insertions, 78 deletions
diff --git a/mediagoblin/db/sql/base.py b/mediagoblin/db/sql/base.py index 838080b0..e10e7739 100644 --- a/mediagoblin/db/sql/base.py +++ b/mediagoblin/db/sql/base.py @@ -79,11 +79,13 @@ class GMGTableBase(object): sess.add(self) sess.commit() - def delete(self): + def delete(self, commit=True): + """Delete the object and commit the change immediately by default""" sess = object_session(self) assert sess is not None, "Not going to delete detached %r" % self sess.delete(self) - sess.commit() + if commit: + sess.commit() Base = declarative_base(cls=GMGTableBase) diff --git a/mediagoblin/db/sql/migrations.py b/mediagoblin/db/sql/migrations.py index 1d822cd9..bc68caa3 100644 --- a/mediagoblin/db/sql/migrations.py +++ b/mediagoblin/db/sql/migrations.py @@ -17,11 +17,12 @@ import datetime from sqlalchemy import (MetaData, Table, Column, Boolean, SmallInteger, - Integer, Unicode, UnicodeText, DateTime, ForeignKey) + Integer, Unicode, UnicodeText, DateTime, + ForeignKey, UniqueConstraint) +from sqlalchemy.ext.declarative import declarative_base from mediagoblin.db.sql.util import RegisterMigration -from mediagoblin.db.sql.models import MediaEntry, Collection, User, \ - ProcessingMetaData +from mediagoblin.db.sql.models import MediaEntry, Collection, User MIGRATIONS = {} @@ -65,29 +66,40 @@ def add_transcoding_progress(db_conn): db_conn.commit() +class Collection_v0(declarative_base()): + __tablename__ = "core__collections" + + id = Column(Integer, primary_key=True) + title = Column(Unicode, nullable=False) + slug = Column(Unicode) + created = Column(DateTime, nullable=False, default=datetime.datetime.now, + index=True) + description = Column(UnicodeText) + creator = Column(Integer, ForeignKey(User.id), nullable=False) + items = Column(Integer, default=0) + +class CollectionItem_v0(declarative_base()): + __tablename__ = "core__collection_items" + + id = Column(Integer, primary_key=True) + media_entry = Column( + Integer, ForeignKey(MediaEntry.id), nullable=False, index=True) + collection = Column(Integer, ForeignKey(Collection.id), nullable=False) + note = Column(UnicodeText, nullable=True) + added = Column(DateTime, nullable=False, default=datetime.datetime.now) + position = Column(Integer) + + ## This should be activated, normally. + ## But this would change the way the next migration used to work. + ## So it's commented for now. + # __table_args__ = ( + # UniqueConstraint('collection', 'media_entry'), + # {}) + @RegisterMigration(4, MIGRATIONS) def add_collection_tables(db_conn): - metadata = MetaData(bind=db_conn.bind) - - collection = Table('core__collections', metadata, - Column('id', Integer, primary_key=True), - Column('title', Unicode, nullable=False), - Column('slug', Unicode), - Column('created', DateTime, nullable=False, default=datetime.datetime.now, index=True), - Column('description', UnicodeText), - Column('creator', Integer, ForeignKey(User.id), nullable=False), - Column('items', Integer, default=0)) - - collection_item = Table('core__collection_items', metadata, - Column('id', Integer, primary_key=True), - Column('media_entry', Integer, ForeignKey(MediaEntry.id), nullable=False, index=True), - Column('collection', Integer, ForeignKey(Collection.id), nullable=False), - Column('note', UnicodeText, nullable=True), - Column('added', DateTime, nullable=False, default=datetime.datetime.now), - Column('position', Integer)) - - collection.create() - collection_item.create() + Collection_v0.__table__.create(db_conn.bind) + CollectionItem_v0.__table__.create(db_conn.bind) db_conn.commit() @@ -104,15 +116,15 @@ def add_mediaentry_collected(db_conn): db_conn.commit() -@RegisterMigration(6, MIGRATIONS) -def create_processing_metadata_table(db): - metadata = MetaData(bind=db.bind) +class ProcessingMetaData_v0(declarative_base()): + __tablename__ = 'core__processing_metadata' - metadata_table = Table('core__processing_metadata', metadata, - Column('id', Integer, primary_key=True), - Column('media_entry_id', Integer, ForeignKey(MediaEntry.id), - nullable=False, index=True), - Column('callback_url', Unicode)) + id = Column(Integer, primary_key=True) + media_entry_id = Column(Integer, ForeignKey(MediaEntry.id), nullable=False, + index=True) + callback_url = Column(Unicode) - metadata_table.create() +@RegisterMigration(6, MIGRATIONS) +def create_processing_metadata_table(db): + ProcessingMetaData_v0.__table__.create(db.bind) db.commit() diff --git a/mediagoblin/db/sql/util.py b/mediagoblin/db/sql/util.py index 74b5d73e..c6d8562e 100644 --- a/mediagoblin/db/sql/util.py +++ b/mediagoblin/db/sql/util.py @@ -39,7 +39,7 @@ class MigrationManager(object): - migration_registry: where we should find all migrations to run """ - self.name = name + self.name = unicode(name) self.models = models self.session = session self.migration_registry = migration_registry @@ -297,17 +297,17 @@ def media_entries_for_tag_slug(dummy_db, tag_slug): & (Tag.slug == tag_slug)) -def clean_orphan_tags(): +def clean_orphan_tags(commit=True): + """Search for unused MediaTags and delete them""" q1 = Session.query(Tag).outerjoin(MediaTag).filter(MediaTag.id==None) for t in q1: Session.delete(t) - # The "let the db do all the work" version: # q1 = Session.query(Tag.id).outerjoin(MediaTag).filter(MediaTag.id==None) # q2 = Session.query(Tag).filter(Tag.id.in_(q1)) # q2.delete(synchronize_session = False) - - Session.commit() + if commit: + Session.commit() def check_collection_slug_used(dummy_db, creator_id, slug, ignore_c_id): diff --git a/mediagoblin/plugins/oauth/migrations.py b/mediagoblin/plugins/oauth/migrations.py index f2af3907..797e7585 100644 --- a/mediagoblin/plugins/oauth/migrations.py +++ b/mediagoblin/plugins/oauth/migrations.py @@ -14,16 +14,94 @@ # 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 sqlalchemy import MetaData, Table +from datetime import datetime, timedelta +from sqlalchemy import (MetaData, Table, Column, + Integer, Unicode, Enum, DateTime, ForeignKey) +from sqlalchemy.ext.declarative import declarative_base from mediagoblin.db.sql.util import RegisterMigration +from mediagoblin.db.sql.models import User -from mediagoblin.plugins.oauth.models import OAuthClient, OAuthToken, \ - OAuthUserClient, OAuthCode MIGRATIONS = {} +class OAuthClient_v0(declarative_base()): + __tablename__ = 'oauth__client' + + id = Column(Integer, primary_key=True) + created = Column(DateTime, nullable=False, + default=datetime.now) + + name = Column(Unicode) + description = Column(Unicode) + + identifier = Column(Unicode, unique=True, index=True) + secret = Column(Unicode, index=True) + + owner_id = Column(Integer, ForeignKey(User.id)) + redirect_uri = Column(Unicode) + + type = Column(Enum( + u'confidential', + u'public', + name=u'oauth__client_type')) + + +class OAuthUserClient_v0(declarative_base()): + __tablename__ = 'oauth__user_client' + id = Column(Integer, primary_key=True) + + user_id = Column(Integer, ForeignKey(User.id)) + client_id = Column(Integer, ForeignKey(OAuthClient_v0.id)) + + state = Column(Enum( + u'approved', + u'rejected', + name=u'oauth__relation_state')) + + +class OAuthToken_v0(declarative_base()): + __tablename__ = 'oauth__tokens' + + id = Column(Integer, primary_key=True) + created = Column(DateTime, nullable=False, + default=datetime.now) + expires = Column(DateTime, nullable=False, + default=lambda: datetime.now() + timedelta(days=30)) + token = Column(Unicode, index=True) + refresh_token = Column(Unicode, index=True) + + user_id = Column(Integer, ForeignKey(User.id), nullable=False, + index=True) + + client_id = Column(Integer, ForeignKey(OAuthClient_v0.id), nullable=False) + + def __repr__(self): + return '<{0} #{1} expires {2} [{3}, {4}]>'.format( + self.__class__.__name__, + self.id, + self.expires.isoformat(), + self.user, + self.client) + + +class OAuthCode_v0(declarative_base()): + __tablename__ = 'oauth__codes' + + id = Column(Integer, primary_key=True) + created = Column(DateTime, nullable=False, + default=datetime.now) + expires = Column(DateTime, nullable=False, + default=lambda: datetime.now() + timedelta(minutes=5)) + code = Column(Unicode, index=True) + + user_id = Column(Integer, ForeignKey(User.id), nullable=False, + index=True) + + client_id = Column(Integer, ForeignKey(OAuthClient_v0.id), nullable=False) + + @RegisterMigration(1, MIGRATIONS) def remove_and_replace_token_and_code(db): metadata = MetaData(bind=db.bind) @@ -38,9 +116,9 @@ def remove_and_replace_token_and_code(db): code_table.drop() - OAuthClient.__table__.create(db.bind) - OAuthUserClient.__table__.create(db.bind) - OAuthToken.__table__.create(db.bind) - OAuthCode.__table__.create(db.bind) + OAuthClient_v0.__table__.create(db.bind) + OAuthUserClient_v0.__table__.create(db.bind) + OAuthToken_v0.__table__.create(db.bind) + OAuthCode_v0.__table__.create(db.bind) db.commit() diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css index 4120f965..f8a9e014 100644 --- a/mediagoblin/static/css/base.css +++ b/mediagoblin/static/css/base.css @@ -259,6 +259,10 @@ text-align: center; height: 0; } +.hidden { + display: none; +} + .media_sidebar h3 { font-size: 1em; margin: 0 0 5px; diff --git a/mediagoblin/static/js/geolocation-map.js b/mediagoblin/static/js/geolocation-map.js index de49a37d..26d94c5d 100644 --- a/mediagoblin/static/js/geolocation-map.js +++ b/mediagoblin/static/js/geolocation-map.js @@ -31,19 +31,15 @@ $(document).ready(function () { var map = new L.Map('tile-map'); var mqtileUrl = 'http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg'; - var mqtileAttrib = 'Map data © ' - + String(new Date().getFullYear()) - + ' OpenStreetMap contributors, CC-BY-SA.' - + ' Imaging © ' - + String(new Date().getFullYear()) - + ' <a target="_blank" href="http://mapquest.com">MapQuest</a>.'; + var mqtileAttrib = '<a id="osm_license_link">see map license</a>'; var mqtile = new L.TileLayer( mqtileUrl, {maxZoom: 18, attribution: mqtileAttrib, subdomains: '1234'}); - var location = new L.LatLng(latitude, longitude); + map.attributionControl.setPrefix(''); + var location = new L.LatLng(latitude, longitude); map.setView(location, 13).addLayer(mqtile); var marker = new L.Marker(location); diff --git a/mediagoblin/templates/mediagoblin/auth/register.html b/mediagoblin/templates/mediagoblin/auth/register.html index a2505cb9..6dff0207 100644 --- a/mediagoblin/templates/mediagoblin/auth/register.html +++ b/mediagoblin/templates/mediagoblin/auth/register.html @@ -42,4 +42,6 @@ </div> </div> </form> +<!-- Focus the username field by default --> +<script>$(document).ready(function(){$("#username").focus();});</script> {% endblock %} diff --git a/mediagoblin/templates/mediagoblin/edit/attachments.html b/mediagoblin/templates/mediagoblin/edit/attachments.html index 976b1619..641306e8 100644 --- a/mediagoblin/templates/mediagoblin/edit/attachments.html +++ b/mediagoblin/templates/mediagoblin/edit/attachments.html @@ -40,7 +40,7 @@ </div> {% if media.attachment_files|count %} - <h2>Attachments</h2> + <h2>{% trans %}Attachments{% endtrans %}</h2> <ul> {% for attachment in media.attachment_files %} <li> @@ -53,7 +53,7 @@ </ul> {% endif %} - <h2>Add attachment</h2> + <h2>{% trans %]Add attachment{% endtrans %}</h2> {{ wtforms_util.render_divs(form) }} <div class="form_submit_buttons"> <a href="{{ media.url_for_self(request.urlgen) }}">Cancel</a> diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html index 99d3269f..047dd2bb 100644 --- a/mediagoblin/templates/mediagoblin/root.html +++ b/mediagoblin/templates/mediagoblin/root.html @@ -23,12 +23,30 @@ {% if request.user %} {% if request.user.status == 'active' %} <h1>{% trans %}Actions{% endtrans %}</h1> - <p><a href="{{ request.urlgen('mediagoblin.submit.collection') }}"> - {% trans %}Create new collection{% endtrans %} - </a></p> - <p><a href="{{ request.urlgen('mediagoblin.edit.account') }}"> - {%- trans %}Change account settings{% endtrans -%} - </a></p> + <ul> + <li><a href="{{ request.urlgen('mediagoblin.submit.start') }}"> + {%- trans %}Add media{% endtrans -%} + </a></li> + <li><a href="{{ request.urlgen('mediagoblin.submit.collection') }}"> + {%- trans %}Create new collection{% endtrans -%} + </a></li> + <li><a href="{{ request.urlgen('mediagoblin.edit.account') }}"> + {%- trans %}Change account settings{% endtrans -%} + </a></li> + <li><a href="{{ request.urlgen('mediagoblin.user_pages.processing_panel', + user=request.user.username) }}"> + {%- trans %}Media processing panel{% endtrans -%} + </a></li> + {% if request.user.is_admin %} + <li>Admin: + <ul> + <li><a href="{{ request.urlgen('mediagoblin.admin.panel') }}"> + {%- trans %}Media processing panel{% endtrans -%} + </a></li> + </ul> + </li> + {% endif %} + </ul> {% endif %} <h1>{% trans %}Explore{% endtrans %}</h1> {% else %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html index ac15dd2f..b870a8ae 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media.html @@ -197,7 +197,9 @@ <p> <a type="submit" href="{{ request.urlgen('mediagoblin.user_pages.media_collect', user=media.get_uploader.username, - media=media._id) }}" class="button_action button_collect" > + media=media._id) }}" + class="button_action button_collect" + title="{% trans %}Add media to collection{% endtrans %}"> </a> </p> {% endif %} diff --git a/mediagoblin/templates/mediagoblin/utils/geolocation_map.html b/mediagoblin/templates/mediagoblin/utils/geolocation_map.html index cd57d1f8..b48678bb 100644 --- a/mediagoblin/templates/mediagoblin/utils/geolocation_map.html +++ b/mediagoblin/templates/mediagoblin/utils/geolocation_map.html @@ -33,6 +33,21 @@ <input type="hidden" id="gps-latitude" value="{{ lat }}" /> </div> + <script> <!-- pop up full OSM license when clicked --> + $(document).ready(function(){ + $("#osm_license_link").click(function () { + $("#osm_attrib").slideToggle("slow"); + }); + }); + </script> + <div id="osm_attrib" class="hidden"><ul><li> + Data ©<a + href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> + contributors + </li><li>Imaging ©<a + href="http://mapquest.com">MapQuest</a></li><li>Maps powered by + <a href="http://leafletjs.com/"> Leaflet</a></li></ul> + </div> <p> <small> {% trans -%} diff --git a/mediagoblin/tools/text.py b/mediagoblin/tools/text.py index ea231244..96df49d2 100644 --- a/mediagoblin/tools/text.py +++ b/mediagoblin/tools/text.py @@ -38,13 +38,12 @@ HTML_CLEANER = Cleaner( allow_tags=[ 'div', 'b', 'i', 'em', 'strong', 'p', 'ul', 'ol', 'li', 'a', 'br', 'pre', 'code'], - remove_unknown_tags=False, # can't be used with allow_tags + remove_unknown_tags=False, # can't be used with allow_tags safe_attrs_only=True, - add_nofollow=True, # for now + add_nofollow=True, # for now host_whitelist=(), whitelist_tags=set([])) -TAGS_DELIMITER=','; def clean_html(html): # clean_html barfs on an empty string @@ -68,14 +67,12 @@ def convert_to_tag_list_of_dicts(tag_string): stripped_tag_string = u' '.join(tag_string.strip().split()) # Split the tag string into a list of tags - for tag in stripped_tag_string.split( - TAGS_DELIMITER): - + for tag in stripped_tag_string.split(','): + tag = tag.strip() # Ignore empty or duplicate tags - if tag.strip() and tag.strip() not in [t['name'] for t in taglist]: - - taglist.append({'name': tag.strip(), - 'slug': url.slugify(tag.strip())}) + if tag and tag not in [t['name'] for t in taglist]: + taglist.append({'name': tag, + 'slug': url.slugify(tag)}) return taglist @@ -85,11 +82,10 @@ def media_tags_as_string(media_entry_tags): This is the opposite of convert_to_tag_list_of_dicts """ - media_tag_string = '' + tags_string = '' if media_entry_tags: - media_tag_string = (TAGS_DELIMITER+u' ').join( - [tag['name'] for tag in media_entry_tags]) - return media_tag_string + tags_string = u', '.join([tag['name'] for tag in media_entry_tags]) + return tags_string TOO_LONG_TAG_WARNING = \ @@ -107,7 +103,7 @@ def tag_length_validator(form, field): if too_long_tags: raise wtforms.ValidationError( - TOO_LONG_TAG_WARNING % (mg_globals.app_config['tags_max_length'], \ + TOO_LONG_TAG_WARNING % (mg_globals.app_config['tags_max_length'], ', '.join(too_long_tags))) |