diff --git a/spa/api/v1/MixResource.py b/spa/api/v1/MixResource.py index ab8dd4e..94260fd 100644 --- a/spa/api/v1/MixResource.py +++ b/spa/api/v1/MixResource.py @@ -23,7 +23,7 @@ class MixResource(BackboneCompatibleResource): queryset = Mix.objects.filter(is_active=True) always_return_data = True detail_uri_name = 'slug' - excludes = ['download_url', 'is_active', 'local_file', 'upload_date'] + excludes = ['download_url', 'is_active', 'local_file', 'upload_date', 'waveform-generated'] filtering = { 'comments': ALL_WITH_RELATIONS } @@ -34,7 +34,7 @@ class MixResource(BackboneCompatibleResource): ret = [] for genre in genres: if genre['id'] == genre['text']: - new_item = genre(description=genre['text']) + new_item = Genre(description=genre['text']) new_item.save() ret.append(new_item) else: @@ -49,7 +49,8 @@ class MixResource(BackboneCompatibleResource): def prepend_urls(self): return [ - url(r"^(?P%s)/(?P[\w\d_.-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), + url(r"^(?P%s)/(?P[\d]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), + url(r"^(?P%s)/(?P[\w\d-]+)/$" % self._meta.resource_name, self.wrap_view('dispatch_detail'), name="api_dispatch_detail"), url(r"^(?P%s)/(?P\w[\w/-]*)/comments%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_comments'), name="api_get_comments"), url(r"^(?P%s)/(?P\w[\w/-]*)/activity%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('get_activity'), name="api_get_activity"), ] @@ -92,6 +93,8 @@ class MixResource(BackboneCompatibleResource): return ret def obj_update(self, bundle, **kwargs): + bundle.obj.update_favourite(bundle.request.user, bundle.data['favourited']) + bundle.obj.update_liked(bundle.request.user, bundle.data['liked']) ret = super(MixResource, self).obj_update(bundle, bundle.request) self._unpackGenreList(ret, bundle.data['genre-list']) return ret @@ -106,6 +109,9 @@ class MixResource(BackboneCompatibleResource): return Mix.get_listing('latest', bundle.request.user) + def hydrate_favourited(self, bundle): + return bundle + def dehydrate_mix_image(self, bundle): return bundle.obj.get_image_url() @@ -114,12 +120,11 @@ class MixResource(BackboneCompatibleResource): bundle.data['user_name'] = bundle.obj.user.get_nice_name() bundle.data['user_profile_url'] = bundle.obj.user.get_absolute_url() bundle.data['user_profile_image'] = bundle.obj.user.get_small_profile_image() - bundle.data['item_url'] = 'mix/%s' % bundle.obj.slug + bundle.data['item_url'] = '/mix/%s' % bundle.obj.slug bundle.data['play_count'] = bundle.obj.plays.count() bundle.data['download_count'] = bundle.obj.downloads.count() bundle.data['like_count'] = bundle.obj.likes.count() - bundle.data['mode'] = 'mix' bundle.data['tooltip'] = render_to_string('inc/player_tooltip.html', {'item': bundle.obj}) bundle.data['comment_count'] = bundle.obj.comments.count() diff --git a/spa/migrations/0010_auto.py b/spa/migrations/0010_auto.py new file mode 100644 index 0000000..5953117 --- /dev/null +++ b/spa/migrations/0010_auto.py @@ -0,0 +1,221 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding M2M table for field favourites on 'UserProfile' + db.create_table(u'spa_userprofile_favourites', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('from_userprofile', models.ForeignKey(orm['spa.userprofile'], null=False)), + ('to_userprofile', models.ForeignKey(orm['spa.userprofile'], null=False)) + )) + db.create_unique(u'spa_userprofile_favourites', ['from_userprofile_id', 'to_userprofile_id']) + + + def backwards(self, orm): + # Removing M2M table for field favourites on 'UserProfile' + db.delete_table('spa_userprofile_favourites') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0011_auto__del_field__activity_user.py b/spa/migrations/0011_auto__del_field__activity_user.py new file mode 100644 index 0000000..ca86ec9 --- /dev/null +++ b/spa/migrations/0011_auto__del_field__activity_user.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting field '_Activity.user' + db.delete_column(u'spa__activity', 'user_id') + + + def backwards(self, orm): + # Adding field '_Activity.user' + db.add_column(u'spa__activity', 'user', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', null=True, to=orm['auth.User']), + keep_default=False) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0012_auto__add_field__activity_user.py b/spa/migrations/0012_auto__add_field__activity_user.py new file mode 100644 index 0000000..4db157f --- /dev/null +++ b/spa/migrations/0012_auto__add_field__activity_user.py @@ -0,0 +1,228 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field '_Activity.user' + db.add_column(u'spa__activity', 'user', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='activity', null=True, to=orm['auth.User']), + keep_default=False) + + # Removing M2M table for field favourites on 'UserProfile' + db.delete_table('spa_userprofile_favourites') + + + def backwards(self, orm): + # Deleting field '_Activity.user' + db.delete_column(u'spa__activity', 'user_id') + + # Adding M2M table for field favourites on 'UserProfile' + db.create_table(u'spa_userprofile_favourites', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('from_userprofile', models.ForeignKey(orm['spa.userprofile'], null=False)), + ('to_userprofile', models.ForeignKey(orm['spa.userprofile'], null=False)) + )) + db.create_unique(u'spa_userprofile_favourites', ['from_userprofile_id', 'to_userprofile_id']) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0013_auto__del_mixfavourite__add_usermixfavourite.py b/spa/migrations/0013_auto__del_mixfavourite__add_usermixfavourite.py new file mode 100644 index 0000000..734a816 --- /dev/null +++ b/spa/migrations/0013_auto__del_mixfavourite__add_usermixfavourite.py @@ -0,0 +1,233 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'MixFavourite' + db.delete_table(u'spa_mixfavourite') + + # Adding model 'UserMixFavourite' + db.create_table(u'spa_usermixfavourite', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['spa.Mix'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='users', to=orm['spa.UserProfile'])), + ('date', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('spa', ['UserMixFavourite']) + + + def backwards(self, orm): + # Adding model 'MixFavourite' + db.create_table(u'spa_mixfavourite', ( + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['spa.Mix'])), + (u'_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)), + )) + db.send_create_signal('spa', ['MixFavourite']) + + # Deleting model 'UserMixFavourite' + db.delete_table(u'spa_usermixfavourite') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.usermixfavourite': { + 'Meta': {'object_name': 'UserMixFavourite'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'users'", 'to': "orm['spa.UserProfile']"}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0014_auto__del_usermixfavourite__add_mixfavourite.py b/spa/migrations/0014_auto__del_usermixfavourite__add_mixfavourite.py new file mode 100644 index 0000000..7a8efbc --- /dev/null +++ b/spa/migrations/0014_auto__del_usermixfavourite__add_mixfavourite.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'UserMixFavourite' + db.delete_table(u'spa_usermixfavourite') + + # Adding model 'MixFavourite' + db.create_table(u'spa_mixfavourite', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['spa.Mix'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='users', to=orm['spa.UserProfile'])), + ('date', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('spa', ['MixFavourite']) + + + def backwards(self, orm): + # Adding model 'UserMixFavourite' + db.create_table(u'spa_usermixfavourite', ( + ('date', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='favourites', to=orm['spa.Mix'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='users', to=orm['spa.UserProfile'])), + )) + db.send_create_signal('spa', ['UserMixFavourite']) + + # Deleting model 'MixFavourite' + db.delete_table(u'spa_mixfavourite') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'users'", 'to': "orm['spa.UserProfile']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0015_auto__chg_field_mixfavourite_user.py b/spa/migrations/0015_auto__chg_field_mixfavourite_user.py new file mode 100644 index 0000000..2aaf23a --- /dev/null +++ b/spa/migrations/0015_auto__chg_field_mixfavourite_user.py @@ -0,0 +1,217 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Changing field 'MixFavourite.user' + db.alter_column(u'spa_mixfavourite', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])) + + def backwards(self, orm): + + # Changing field 'MixFavourite.user' + db.alter_column(u'spa_mixfavourite', 'user_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['spa.UserProfile'])) + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'users'", 'to': u"orm['auth.User']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0016_auto__del_mixlike.py b/spa/migrations/0016_auto__del_mixlike.py new file mode 100644 index 0000000..ceda5f3 --- /dev/null +++ b/spa/migrations/0016_auto__del_mixlike.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'MixLike' + db.delete_table(u'spa_mixlike') + + + def backwards(self, orm): + # Adding model 'MixLike' + db.create_table(u'spa_mixlike', ( + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='likes', to=orm['spa.Mix'])), + (u'_activity_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['spa._Activity'], unique=True, primary_key=True)), + )) + db.send_create_signal('spa', ['MixLike']) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': u"orm['auth.User']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/migrations/0017_auto__add_mixlike.py b/spa/migrations/0017_auto__add_mixlike.py new file mode 100644 index 0000000..45b1dd8 --- /dev/null +++ b/spa/migrations/0017_auto__add_mixlike.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'MixLike' + db.create_table(u'spa_mixlike', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('mix', self.gf('django.db.models.fields.related.ForeignKey')(related_name='likes', to=orm['spa.Mix'])), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='likes', to=orm['auth.User'])), + ('date', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('spa', ['MixLike']) + + + def backwards(self, orm): + # Deleting model 'MixLike' + db.delete_table(u'spa_mixlike') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa._activity': { + 'Meta': {'object_name': '_Activity'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'uid': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity'", 'null': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa._lookup': { + 'Meta': {'object_name': '_Lookup'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.chatmessage': { + 'Meta': {'object_name': 'ChatMessage'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.TextField', [], {}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'chat_messages'", 'null': 'True', 'to': "orm['spa.UserProfile']"}) + }, + 'spa.comment': { + 'Meta': {'object_name': 'Comment'}, + 'comment': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comments'", 'null': 'True', 'to': "orm['spa.Mix']"}), + 'time_index': ('django.db.models.fields.IntegerField', [], {}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) + }, + 'spa.event': { + 'Meta': {'object_name': 'Event'}, + 'attendees': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'attendees'", 'symmetrical': 'False', 'to': u"orm['auth.User']"}), + 'date_created': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_description': ('tinymce.models.HTMLField', [], {}), + 'event_recurrence': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Recurrence']"}), + 'event_time': ('django.db.models.fields.TimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'event_title': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'event_venue': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Venue']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'spa.genre': { + 'Meta': {'object_name': 'Genre'}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) + }, + 'spa.label': { + 'Meta': {'object_name': 'Label'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'spa.mix': { + 'Meta': {'object_name': 'Mix'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'download_allowed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'download_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'genres': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['spa.Genre']", 'symmetrical': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_featured': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100', 'blank': 'True'}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'stream_url': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'uid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '38', 'blank': 'True'}), + 'upload_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.mixdownload': { + 'Meta': {'object_name': 'MixDownload', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.mixfavourite': { + 'Meta': {'object_name': 'MixFavourite'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'favourites'", 'to': u"orm['auth.User']"}) + }, + 'spa.mixlike': { + 'Meta': {'object_name': 'MixLike'}, + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': "orm['spa.Mix']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'likes'", 'to': u"orm['auth.User']"}) + }, + 'spa.mixplay': { + 'Meta': {'object_name': 'MixPlay', '_ormbases': ['spa._Activity']}, + u'_activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'plays'", 'to': "orm['spa.Mix']"}) + }, + 'spa.purchaselink': { + 'Meta': {'object_name': 'PurchaseLink'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'track': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'purchase_link'", 'to': "orm['spa.Tracklist']"}), + 'url': ('django.db.models.fields.URLField', [], {'max_length': '200'}) + }, + 'spa.recurrence': { + 'Meta': {'object_name': 'Recurrence', '_ormbases': ['spa._Lookup']}, + u'_lookup_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa._Lookup']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'spa.release': { + 'Meta': {'object_name': 'Release'}, + 'embed_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'release_artist': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'release_date': ('django.db.models.fields.DateField', [], {'default': 'datetime.datetime(2013, 5, 25, 0, 0)'}), + 'release_description': ('django.db.models.fields.TextField', [], {}), + 'release_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'release_label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.Label']"}), + 'release_title': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']"}) + }, + 'spa.releaseaudio': { + 'Meta': {'object_name': 'ReleaseAudio'}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'local_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.tracklist': { + 'Meta': {'object_name': 'Tracklist'}, + 'artist': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'index': ('django.db.models.fields.SmallIntegerField', [], {}), + 'label': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tracklist'", 'to': "orm['spa.Mix']"}), + 'remixer': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'timeindex': ('django.db.models.fields.TimeField', [], {'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'spa.userprofile': { + 'Meta': {'object_name': 'UserProfile'}, + 'activity_sharing': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'activity_sharing_networks': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'avatar_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'followers': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'following_rel_+'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'default': 'None', 'max_length': '50', 'null': 'True', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'userprofile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'spa.venue': { + 'Meta': {'object_name': 'Venue'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), + 'venue_address': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'venue_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '100', 'blank': 'True'}), + 'venue_name': ('django.db.models.fields.CharField', [], {'max_length': '250'}) + } + } + + complete_apps = ['spa'] \ No newline at end of file diff --git a/spa/models/_basemodel.py b/spa/models/_basemodel.py index a30502a..eaebb8f 100644 --- a/spa/models/_basemodel.py +++ b/spa/models/_basemodel.py @@ -7,8 +7,10 @@ from django.utils import simplejson from core.utils import url from dss import localsettings, settings +from immutablefield.models import ImmutableModel -class _BaseModel(models.Model): + +class _BaseModel(ImmutableModel): logger = logging.getLogger(__name__) class Meta: diff --git a/spa/models/activity.py b/spa/models/activity.py index 4ce6fec..aba70cf 100644 --- a/spa/models/activity.py +++ b/spa/models/activity.py @@ -10,7 +10,7 @@ from spa.models.managers.QueuedActivityModelManager import QueuedActivityModelMa class _Activity(_BaseModel): - user = models.ForeignKey(User, null=True) + user = models.ForeignKey(User, null=True, related_name='activity') uid = models.CharField(max_length=50, blank=True, null=True) date = models.DateTimeField(auto_now=True) objects = InheritanceManager() diff --git a/spa/models/comment.py b/spa/models/comment.py index be218d5..85ccb3c 100644 --- a/spa/models/comment.py +++ b/spa/models/comment.py @@ -3,6 +3,7 @@ from django.db import models from spa.models._basemodel import _BaseModel from spa.models.mix import Mix + class Comment(_BaseModel): class Meta: app_label = 'spa' @@ -16,5 +17,3 @@ class Comment(_BaseModel): def get_absolute_url(self): return '/comment/%i' % self.id - def save(self, force_insert=False, force_update=False, using=None): - super(Comment, self).save(force_insert, force_update, using) \ No newline at end of file diff --git a/spa/models/genre.py b/spa/models/genre.py index 2961b3b..ba9df1e 100644 --- a/spa/models/genre.py +++ b/spa/models/genre.py @@ -12,7 +12,7 @@ class Genre(_BaseModel): def save(self, force_insert=False, force_update=False, using=None): if not self.slug: - self.description = unique_slugify(self, self.description, slug_separator='_') + self.slug = unique_slugify(self, self.description, slug_separator='_') super(Genre, self).save(force_insert, force_update, using) diff --git a/spa/models/mix.py b/spa/models/mix.py index 2599721..276edfa 100644 --- a/spa/models/mix.py +++ b/spa/models/mix.py @@ -11,15 +11,16 @@ from django.db.models import Count from core.utils import url from core.utils.audio.mp3 import mp3_length from core.utils.url import unique_slugify +from spa.models.mixlike import MixLike from spa.models.genre import Genre from spa.models.mixplay import MixPlay from spa.models.mixdownload import MixDownload from dss import settings, localsettings from spa.models.userprofile import UserProfile from spa.models._basemodel import _BaseModel +from spa.models.mixfavourite import MixFavourite from core.utils.file import generate_save_file_name -from core.utils.audio.mp3 import mp3_length - +from immutablefield.models import ImmutableModel def mix_file_name(instance, filename): return generate_save_file_name(instance.uid, 'mixes', filename) @@ -52,6 +53,9 @@ class Mix(_BaseModel): genres = models.ManyToManyField(Genre) + class ImmutableMeta: + immutable = ['user'] + def __unicode__(self): return self.title @@ -195,6 +199,32 @@ class Mix(_BaseModel): return False + def update_favourite(self, user, value): + try: + if user is None: + return + if user.is_authenticated(): + if value: + if self.favourites.filter(user=user).count() == 0: + self.favourites.add(MixFavourite(mix=self, user=user)) + else: + self.favourites.filter(user=user).delete() + except Exception, ex: + self.logger.error("Exception updating favourite: %s" % ex.message) + + def update_liked(self, user, value): + try: + if user is None: + return + if user.is_authenticated(): + if value: + if self.likes.filter(user=user).count() == 0: + self.likes.add(MixLike(mix=self, user=user)) + else: + self.likes.filter(user=user).delete() + except Exception, ex: + self.logger.error("Exception updating like: %s" % ex.message) + def is_favourited(self, user): if user is None: return False diff --git a/spa/models/mixfavourite.py b/spa/models/mixfavourite.py index 3685bf2..fd56d1a 100644 --- a/spa/models/mixfavourite.py +++ b/spa/models/mixfavourite.py @@ -1,17 +1,10 @@ -from spa.models import _basemodel, UserProfile, Mix, _Activity +from django.contrib.auth.models import User +from spa.models._basemodel import _BaseModel from django.db import models -class MixFavourite(_Activity): - mix = models.ForeignKey(Mix, related_name='favourites') - def get_verb_passed(self): - return "favourited" +class MixFavourite(_BaseModel): + mix = models.ForeignKey('spa.Mix', related_name='favourites') + user = models.ForeignKey(User, related_name='favourites') + date = models.DateTimeField(auto_now=True) - def get_object_singular(self): - return "mix" - - def get_object_name(self): - return self.mix.title - - def get_object_url(self): - return self.mix.get_absolute_url() \ No newline at end of file diff --git a/spa/models/mixlike.py b/spa/models/mixlike.py index 93eee6d..2edfd83 100644 --- a/spa/models/mixlike.py +++ b/spa/models/mixlike.py @@ -1,20 +1,9 @@ +from django.contrib.auth.models import User from django.db import models -from spa.models.activity import _Activity +from spa.models._basemodel import _BaseModel -class MixLike(_Activity): + +class MixLike(_BaseModel): mix = models.ForeignKey('spa.Mix', related_name='likes') - - def __unicode__(self): - return "%s on %s" % (self.user.get_full_name(), self.mix.title) - - def get_verb_passed(self): - return "liked" - - def get_object_singular(self): - return "mix" - - def get_object_name(self): - return self.mix.title - - def get_object_url(self): - return self.mix.get_absolute_url() \ No newline at end of file + user = models.ForeignKey(User, related_name='likes') + date = models.DateTimeField(auto_now=True) diff --git a/spa/models/userprofile.py b/spa/models/userprofile.py index e929223..3349277 100644 --- a/spa/models/userprofile.py +++ b/spa/models/userprofile.py @@ -86,6 +86,17 @@ class UserProfile(_BaseModel): except Exception, e: self.logger.error("Unable to create profile slug: %s", e.message) + def toggle_favourite(self, mix, value): + try: + if value: + if self.activity.filter(mix=mix).count() == 0: + self.activity.model.add(mix=mix, user=self) + self.favourites.model.save() + else: + self.favourites.model.delete(mix=mix) + except Exception, ex: + self.logger.error("Exception updating favourite: %s" % ex.message) + def add_follower(self, user): self.followers.add(user) try: diff --git a/static/css/com.podnoms.player.css b/static/css/com.podnoms.player.css index 90ebb5c..00f6485 100644 --- a/static/css/com.podnoms.player.css +++ b/static/css/com.podnoms.player.css @@ -134,7 +134,9 @@ div.player-body ul.player-controls a { /* Listing CSS */ .audio-listing { list-style: none; - margin: 0; +} +.audio-listing-single{ + margin-left: 32px; } img.mix-listing-image { diff --git a/static/css/deepsouthsounds.css b/static/css/deepsouthsounds.css index 21621c1..889f62d 100644 --- a/static/css/deepsouthsounds.css +++ b/static/css/deepsouthsounds.css @@ -49,9 +49,8 @@ img.event-content { -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; - border-color: -moz-use-text-color -moz-use-text-color #E5E5E5; - border-style: none none solid; - border-width: 0 0 1px; + border: 0 none -moz-use-text-color; + border-bottom: 1px solid #E5E5E5; color: #333333; display: block; font-size: 19.5px; @@ -61,6 +60,9 @@ img.event-content { width: 100%; } +.mix-listing { +} + #mix-comments-list ul { list-style-type: none; } @@ -391,39 +393,29 @@ div.event-content td { position: relative; top: 1px; } -.dss-option-table td{ + +.dss-option-table td { text-align: center; vertical-align: middle; } -#div_avatar_image_upload{ + +#div_avatar_image_upload { width: 100%; text-align: center; } -#div_avatar_image{ + +#div_avatar_image { display: inline-block; } -.mix-image-container img{ + +.mix-image-container img { height: 120px; width: 180px; } .btn.loading { - background-image: -webkit-gradient(linear, 0 0, 100% 100%, - color-stop(.25, rgba(0, 0, 0, .10)), - color-stop(.25, transparent), - color-stop(.5, transparent), - color-stop(.5, rgba(0, 0, 0, .10)), - color-stop(.75, rgba(0, 0, 0, .10)), - color-stop(.75, transparent), - to(transparent)); - background-image: - -moz-linear-gradient(-45deg, - rgba(0, 0, 0, .10) 25%, - transparent 25%, - transparent 50%, rgba(0, 0, 0, .10) 50%, - rgba(0, 0, 0, .10) 75%, - transparent 75%, transparent - ); + background-image: -webkit-gradient(linear, 0 0, 100% 100%, color-stop(.25, rgba(0, 0, 0, .10)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(0, 0, 0, .10)), color-stop(.75, rgba(0, 0, 0, .10)), color-stop(.75, transparent), to(transparent)); + background-image: -moz-linear-gradient(-45deg, rgba(0, 0, 0, .10) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, .10) 50%, rgba(0, 0, 0, .10) 75%, transparent 75%, transparent); background-size: 50px 50px; -moz-background-size: 50px 50px; -webkit-background-size: 50px 50px; @@ -435,6 +427,6 @@ div.event-content td { background-position: 0 0; } to { - background-position: -50px 0; + background-position: -50px 0; } } \ No newline at end of file diff --git a/static/js/app/app.js b/static/js/_old/app.js similarity index 87% rename from static/js/app/app.js rename to static/js/_old/app.js index 25a6a0e..bcf2bbe 100644 --- a/static/js/app/app.js +++ b/static/js/_old/app.js @@ -6,7 +6,7 @@ Code provided under the BSD License: */ -var AppRouter = Backbone.Router.extend({ +var AppRouter = Marionette.AppRouter.extend({ root: '/', routes: { "debug": "debug", @@ -39,6 +39,7 @@ var AppRouter = Backbone.Router.extend({ $('#header').html(this.headerView.el); $('#site-content-fill').html(''); this.bind('all', this.trackPageView); + console.log("App router intialized"); }, trackPageView: function () { var url; @@ -46,6 +47,7 @@ var AppRouter = Backbone.Router.extend({ return com.podnoms.utils.trackPageView(url); }, defaultRoute: function (path) { + console.log("Default route"); if (path == undefined || path == "" || path == "/") this.mixList('latest'); else { @@ -60,8 +62,8 @@ var AppRouter = Backbone.Router.extend({ id: 'fergalmoran' }); model.fetch({ - success: function(){ - var content= new SidebarViewUser({ + success: function () { + var content = new SidebarViewUser({ model: model }); $('#content').html(content.render().el); @@ -74,15 +76,15 @@ var AppRouter = Backbone.Router.extend({ id: user }); model.fetch({ - success: function(){ - var content= new SidebarViewUser({ + success: function () { + var content = new SidebarViewUser({ model: model }); $('#sidebar').html(content.render().el); } }); }, - users: function(){ + users: function () { console.log("Loading users"); }, editUser: function () { @@ -100,6 +102,7 @@ var AppRouter = Backbone.Router.extend({ }); }, mixList: function (type) { + console.log("Rendering mix list"); this._renderMixList(type); this.sidebarView = new SidebarView(); $('#sidebar').html(this.sidebarView.el); @@ -257,16 +260,23 @@ var AppRouter = Backbone.Router.extend({ alert("Connecting accounts"); } }); - +/* com.podnoms.utils.loadTemplate(['HeaderView', 'SidebarView', 'SidebarViewUser', 'UserEditView', 'MixListView', 'MixListItemView', 'MixView', 'MixCreateView', 'CommentListView', 'CommentListItemView', 'ActivityListView', 'ActivityListItemView', 'ReleaseListView', 'ReleaseListItemView', 'ReleaseItemView', 'ReleaseView', 'ReleaseCreateView', 'ReleaseAudioListView', 'ReleaseAudioItemView', 'EventCreateView', 'EventListView', 'EventListItemView', 'EventView', 'EventItemView'], function () { - window.app = new AppRouter(); - // Trigger the initial route and enable HTML5 History API support, set the - // root folder to '/' by default. Change in app.js. - var enablePushState = true; - // Disable for older browsers - var pushState = !!(enablePushState && window.history && window.history.pushState); - Backbone.history.start({ pushState: pushState, root: app.root, hashChange: true }); - + window.app = new Marionette.Application(); + window.app.addInitializer(function (options) { + new AppRouter(); + // Trigger the initial route and enable HTML5 History API support, set the + // root folder to '/' by default. Change in app.js. + var enablePushState = true; + // Disable for older browsers + var pushState = !!(enablePushState && window.history && window.history.pushState); + Backbone.history.start({ + pushState: pushState, + hashChange: true + }); + console.log("Backbone history initialized"); + }); + window.app.start(); // All navigation that is relative should be passed through the navigate // method, to be processed by the router. If the link has a `data-bypass` // attribute, bypass the delegation completely. @@ -289,4 +299,4 @@ com.podnoms.utils.loadTemplate(['HeaderView', 'SidebarView', 'SidebarViewUser', } }); }); -var _eventAggregator = _.extend({}, Backbone.Events); +*/ \ No newline at end of file diff --git a/static/js/app/appv2.coffee b/static/js/app/appv2.coffee new file mode 100644 index 0000000..4c7cf02 --- /dev/null +++ b/static/js/app/appv2.coffee @@ -0,0 +1,73 @@ +define ['backbone', 'marionette', 'app.lib/router', 'app.lib/panningRegion', 'views/header', 'views/sidebar/sidebar', + 'models/mix/collection'], +(Backbone, Marionette, DssRouter, PanningRegion, HeaderView, SidebarView, MixCollection) -> + Marionette.Region.prototype.open = (view) -> + @.$el.hide(); + @.$el.html(view.el); + @.$el.slideDown("fast"); + true + + App = new Marionette.Application(); + + App.vent.on "mix:favourite", (model) -> + console.log "App(vent): mix:favourite" + model.save 'favourited', !model.get('favourited'), patch: true + true + + App.vent.on "mix:like", (model) -> + console.log "App(vent): mix:like" + model.save 'liked', !model.get('liked'), patch: true + true + + App.vent.on "mix:share", (mode, model) -> + console.log "App(vent): mix:share" + if (mode == "facebook") + social.sharePageToFacebook(model); + else if (mode == "twitter") + social.sharePageToTwitter(model); + true + + App.vent.on "routing:started", -> + console.log "App(vent): routing:started" + enablePushState = true; + #Disable for older browsers + pushState = !!(enablePushState && window.history && window.history.pushState) + Backbone.history.start({ + pushState: pushState, + hashChange: true + }) + true + + App.addRegions { + headerRegion: "#header", + contentRegion: { + selector: "#content" + #regionType: PanningRegion + } + sidebarRegion: "#sidebar" + } + + App.addInitializer -> + console.log("App: routing starting"); + App.Router = new DssRouter(); + return App.vent.trigger("routing:started"); + + App.addInitializer -> + console.log("App: gobbling links"); + $(document).on("click", "a[href]:not([data-bypass])", (evt) -> + href = { prop: $(this).prop("href"), attr: $(this).attr("href") }; + root = location.protocol + "//" + location.host + (App.root || '/'); + if (href.prop.slice(0, root.length) == root) + evt.preventDefault(); + App.Router.navigate(href.attr, true); + true + ) + true + + console.warn("Creating event aggregator shim") + window._eventAggregator = _.extend({}, Backbone.Events); + App.headerRegion.show(new HeaderView()); + sidebarView = new SidebarView(); + App.sidebarRegion.show(sidebarView) + + App; diff --git a/static/js/app/appv2.js b/static/js/app/appv2.js new file mode 100644 index 0000000..d235522 --- /dev/null +++ b/static/js/app/appv2.js @@ -0,0 +1,84 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + + define(['backbone', 'marionette', 'app.lib/router', 'app.lib/panningRegion', 'views/header', 'views/sidebar/sidebar', 'models/mix/collection'], function(Backbone, Marionette, DssRouter, PanningRegion, HeaderView, SidebarView, MixCollection) { + var App, sidebarView; + Marionette.Region.prototype.open = function(view) { + this.$el.hide(); + this.$el.html(view.el); + this.$el.slideDown("fast"); + return true; + }; + App = new Marionette.Application(); + App.vent.on("mix:favourite", function(model) { + console.log("App(vent): mix:favourite"); + model.save('favourited', !model.get('favourited'), { + patch: true + }); + return true; + }); + App.vent.on("mix:like", function(model) { + console.log("App(vent): mix:like"); + model.save('liked', !model.get('liked'), { + patch: true + }); + return true; + }); + App.vent.on("mix:share", function(mode, model) { + console.log("App(vent): mix:share"); + if (mode === "facebook") { + social.sharePageToFacebook(model); + } else if (mode === "twitter") { + social.sharePageToTwitter(model); + } + return true; + }); + App.vent.on("routing:started", function() { + var enablePushState, pushState; + console.log("App(vent): routing:started"); + enablePushState = true; + pushState = !!(enablePushState && window.history && window.history.pushState); + Backbone.history.start({ + pushState: pushState, + hashChange: true + }); + return true; + }); + App.addRegions({ + headerRegion: "#header", + contentRegion: { + selector: "#content" + }, + sidebarRegion: "#sidebar" + }); + App.addInitializer(function() { + console.log("App: routing starting"); + App.Router = new DssRouter(); + return App.vent.trigger("routing:started"); + }); + App.addInitializer(function() { + console.log("App: gobbling links"); + $(document).on("click", "a[href]:not([data-bypass])", function(evt) { + var href, root; + href = { + prop: $(this).prop("href"), + attr: $(this).attr("href") + }; + root = location.protocol + "//" + location.host + (App.root || '/'); + if (href.prop.slice(0, root.length) === root) { + evt.preventDefault(); + App.Router.navigate(href.attr, true); + return true; + } + }); + return true; + }); + console.warn("Creating event aggregator shim"); + window._eventAggregator = _.extend({}, Backbone.Events); + App.headerRegion.show(new HeaderView()); + sidebarView = new SidebarView(); + App.sidebarRegion.show(sidebarView); + return App; + }); + +}).call(this); diff --git a/static/js/app/dss.bootstrapper.js b/static/js/app/dss.bootstrapper.js index dddb93a..8a12b14 100644 --- a/static/js/app/dss.bootstrapper.js +++ b/static/js/app/dss.bootstrapper.js @@ -1,27 +1,35 @@ requirejs.config({ baseUrl: "static/js", paths: { + jquery: 'libs/jquery', backbone: 'libs/backbone/backbone', marionette: 'libs/backbone/backbone.marionette', + ich: 'libs/ICanHaz', underscore: 'libs/backbone/underscore', - jquery: 'libs/jquery', + text: 'libs/text', templates: '/templates', views: 'app/views', models: 'app/models', + app: 'app/appv2', + 'app.lib': 'app/lib', moment: 'libs/moment' }, shim: { backbone: { exports: 'Backbone', - deps: ['jquery', 'underscore'] + deps: ['underscore'] }, marionette: { - exports: 'Backbone.Marionette', + exports: 'Marionette', deps: ['backbone'] + }, + underscore: { + exports: '_' } } }); -requirejs(['backbone'], function(Backbone){ - console.log("RequireJS primed"); -}); \ No newline at end of file +requirejs(['backbone', 'app'], function (Backbone, App) { + console.log("Dss.Bootstrapper: primed"); + App.start(); +}); diff --git a/static/js/app/lib/backbone.dss.model.collection.js b/static/js/app/lib/backbone.dss.model.collection.js new file mode 100644 index 0000000..2883bea --- /dev/null +++ b/static/js/app/lib/backbone.dss.model.collection.js @@ -0,0 +1,8 @@ +define(['backbone'], function (Backbone) { + return Backbone.Collection.extend({ + parse: function (response) { + this.recent_meta = response.meta || {}; + return response.objects || response; + } + }); +}); diff --git a/static/js/app/lib/backbone.dss.model.js b/static/js/app/lib/backbone.dss.model.js new file mode 100644 index 0000000..b1a4a01 --- /dev/null +++ b/static/js/app/lib/backbone.dss.model.js @@ -0,0 +1,29 @@ +define(['backbone'], function (Backbone) { + + var TastypieModel = Backbone.Model.extend({ + base_url: function () { + var temp_url = Backbone.Model.prototype.url.call(this); + return (temp_url.charAt(temp_url.length - 1) == '/' ? temp_url : temp_url + '/'); + }, + url: function () { + return this.base_url(); + } + }); + + var TastypieCollection = Backbone.Collection.extend({ + parse: function (response) { + this.recent_meta = response.meta || {}; + return response.objects || response; + } + }); + + return TastypieModel.extend({ + addError: function (field, message) { + if (_.isUndefined(this.errors[field])) { + this.errors[field] = []; + } + this.errors[field].push(message); + return field; + } + }); +}); diff --git a/static/js/app/lib/controller.coffee b/static/js/app/lib/controller.coffee new file mode 100644 index 0000000..f27b109 --- /dev/null +++ b/static/js/app/lib/controller.coffee @@ -0,0 +1,41 @@ +define ['app', 'marionette', 'models/mix/item', 'views/mix/list', 'views/mix/detail', 'views/mix/edit'], +(App, Marionette, MixItem, MixListView, MixDetailView, MixEditView)-> + class DssController extends Marionette.Controller + home: -> + console.log "Controller: home" + @showMixList() + true + + showMixList: (type, options) -> + console.log "Controller: showMixList" + type = type or "latest" + app = require('app') + + app.contentRegion.show(new MixListView($.extend({type: type}, options)), 'drop'); + true + + showMix: (slug)-> + console.log "Controller: showMix" + app = require('app') + mix = new MixItem({id: slug}) + mix.fetch( + success: -> + app.contentRegion.show(new MixDetailView({model: mix})) + true + ) + true + + editMix: (slug) -> + console.log("Controller: mixEdit") + app = require('app') + mix = new MixItem({id: slug}) + mix.fetch( + success: -> + app.contentRegion.show(new MixEditView(model: mix)) + ) + true + + user: (slug) -> + @showMixList('latest', {user: slug}) + + DssController \ No newline at end of file diff --git a/static/js/app/lib/controller.js b/static/js/app/lib/controller.js new file mode 100644 index 0000000..67bc2ad --- /dev/null +++ b/static/js/app/lib/controller.js @@ -0,0 +1,84 @@ +// Generated by CoffeeScript 1.6.2 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['app', 'marionette', 'models/mix/item', 'views/mix/list', 'views/mix/detail', 'views/mix/edit'], function(App, Marionette, MixItem, MixListView, MixDetailView, MixEditView) { + var DssController, _ref; + + DssController = (function(_super) { + __extends(DssController, _super); + + function DssController() { + _ref = DssController.__super__.constructor.apply(this, arguments); + return _ref; + } + + DssController.prototype.home = function() { + console.log("Controller: home"); + this.showMixList(); + return true; + }; + + DssController.prototype.showMixList = function(type, options) { + var app; + + console.log("Controller: showMixList"); + type = type || "latest"; + app = require('app'); + app.contentRegion.show(new MixListView($.extend({ + type: type + }, options)), 'drop'); + return true; + }; + + DssController.prototype.showMix = function(slug) { + var app, mix; + + console.log("Controller: showMix"); + app = require('app'); + mix = new MixItem({ + id: slug + }); + mix.fetch({ + success: function() { + app.contentRegion.show(new MixDetailView({ + model: mix + })); + return true; + } + }); + return true; + }; + + DssController.prototype.editMix = function(slug) { + var app, mix; + + console.log("Controller: mixEdit"); + app = require('app'); + mix = new MixItem({ + id: slug + }); + mix.fetch({ + success: function() { + return app.contentRegion.show(new MixEditView({ + model: mix + })); + } + }); + return true; + }; + + DssController.prototype.user = function(slug) { + return this.showMixList('latest', { + user: slug + }); + }; + + return DssController; + + })(Marionette.Controller); + return DssController; + }); + +}).call(this); diff --git a/static/js/app/lib/editableView.coffee b/static/js/app/lib/editableView.coffee new file mode 100644 index 0000000..c226a67 --- /dev/null +++ b/static/js/app/lib/editableView.coffee @@ -0,0 +1,98 @@ +define ["marionette"], +(Marionette) -> + class EditableView extends Marionette.ItemView + events: + "change input": "changed" + "change textarea": "changed" + + changeSelect: (evt) -> + changed = evt.currentTarget + if id + value = $(evt.currentTarget).val() + obj = "{\"" + changed.id + "\":\"" + value.replace(/\n/g, "
") + "\"}" + objInst = JSON.parse(obj) + @model.set objInst + + changed: (evt) -> + + #change handler for the form to update the model + #with the new values + return + changed = evt.currentTarget + + #$("#" + changed.id) + if changed.id + value = undefined + obj = undefined + if $(changed).is(":checkbox") + value = $(changed).is(":checked") + obj = "{\"" + changed.id + "\":" + value + "}" + else + value = $(changed).val() + obj = "{\"" + changed.id + "\":\"" + value.replace(/\n/g, "
") + "\"}" + objInst = JSON.parse(obj) + @model.set objInst + + _bakeForm: (el, lookups) -> + + #TODO extend lookups to be a list + #TODO this way we can initialise more than one lookup per page + model = @model + labels = undefined + mapped = undefined + $(".typeahead", el).typeahead + source: (query, process) -> + $.get "/ajax/lookup/" + lookups + "/", + query: query + , ((data) -> + labels = [] + mapped = {} + $.each data, (i, item) -> + mapped[item[1]] = item + labels.push item[1] + + process labels + ), "json" + + updater: (item) -> + @$element.val mapped[item][0] + model.set @$element.attr("id"), mapped[item][0] + item + + $(".datepicker", el).datepicker format: "dd/mm/yyyy" + $(".timepicker", el).timepicker() + $("textarea.tinymce", @el).tinymce + script_url: "/static/js/libs/tiny_mce/tiny_mce.js" + mode: "textareas" + theme: "advanced" + theme_advanced_toolbar_location: "top" + theme_advanced_toolbar_align: "left" + theme_advanced_buttons1: "fullscreen,media,tablecontrols,separator,link,unlink,anchor,separator,preview,separator,bold,italic,underline,strikethrough,separator,bullist,numlist,outdent,indent,separator,undo,redo,separator,image,cleanup,help,separator,code" + theme_advanced_buttons2: "" + theme_advanced_buttons3: "" + auto_cleanup_word: true + plugins: "media, table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,print,contextmenu,fullscreen,preview,searchreplace" + plugin_insertdate_dateFormat: "%m/%d/%Y" + plugin_insertdate_timeFormat: "%H:%M:%S" + extended_valid_elements: "a[name|href|target=_blank|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]" + fullscreen_settings: + theme_advanced_path_location: "top" + theme_advanced_buttons1: "fullscreen,media, separator,preview,separator,cut,copy,paste,separator,undo,redo,separator,search,replace,separator,code,separator,cleanup,separator,bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,help" + theme_advanced_buttons2: "removeformat,styleselect,formatselect,fontselect,fontsizeselect,separator,bullist,numlist,outdent,indent,separator,link,unlink,anchor" + theme_advanced_buttons3: "sub,sup,separator,image,insertdate,inserttime,separator,tablecontrols,separator,hr,advhr,visualaid,separator,charmap,emotions,iespell,flash,separator,print" + + + _saveChanges: -> + args = arguments + if not @model.isValid() + if @model.errors + for error of @model.errors + $("#group-" + error, @el).addClass "error" + $("#error-" + error, @el).text @model.errors[error] + else + @model.save null, + success: args[0].success + error: args[0].error + + + EditableView \ No newline at end of file diff --git a/static/js/app/lib/editableView.js b/static/js/app/lib/editableView.js new file mode 100644 index 0000000..357faab --- /dev/null +++ b/static/js/app/lib/editableView.js @@ -0,0 +1,134 @@ +// Generated by CoffeeScript 1.6.2 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(["marionette"], function(Marionette) { + var EditableView, _ref; + + EditableView = (function(_super) { + __extends(EditableView, _super); + + function EditableView() { + _ref = EditableView.__super__.constructor.apply(this, arguments); + return _ref; + } + + EditableView.prototype.events = { + "change input": "changed", + "change textarea": "changed" + }; + + EditableView.prototype.changeSelect = function(evt) { + var changed, obj, objInst, value; + + changed = evt.currentTarget; + if (id) { + value = $(evt.currentTarget).val(); + obj = "{\"" + changed.id + "\":\"" + value.replace(/\n/g, "
") + "\"}"; + objInst = JSON.parse(obj); + return this.model.set(objInst); + } + }; + + EditableView.prototype.changed = function(evt) { + var changed, obj, objInst, value; + + return; + changed = evt.currentTarget; + if (changed.id) { + value = void 0; + obj = void 0; + if ($(changed).is(":checkbox")) { + value = $(changed).is(":checked"); + obj = "{\"" + changed.id + "\":" + value + "}"; + } else { + value = $(changed).val(); + obj = "{\"" + changed.id + "\":\"" + value.replace(/\n/g, "
") + "\"}"; + } + objInst = JSON.parse(obj); + return this.model.set(objInst); + } + }; + + EditableView.prototype._bakeForm = function(el, lookups) { + var labels, mapped, model; + + model = this.model; + labels = void 0; + mapped = void 0; + $(".typeahead", el).typeahead({ + source: function(query, process) { + return $.get("/ajax/lookup/" + lookups + "/", { + query: query + }, (function(data) { + labels = []; + mapped = {}; + $.each(data, function(i, item) { + mapped[item[1]] = item; + return labels.push(item[1]); + }); + return process(labels); + }), "json"); + }, + updater: function(item) { + this.$element.val(mapped[item][0]); + model.set(this.$element.attr("id"), mapped[item][0]); + return item; + } + }); + $(".datepicker", el).datepicker({ + format: "dd/mm/yyyy" + }); + $(".timepicker", el).timepicker(); + return $("textarea.tinymce", this.el).tinymce({ + script_url: "/static/js/libs/tiny_mce/tiny_mce.js", + mode: "textareas", + theme: "advanced", + theme_advanced_toolbar_location: "top", + theme_advanced_toolbar_align: "left", + theme_advanced_buttons1: "fullscreen,media,tablecontrols,separator,link,unlink,anchor,separator,preview,separator,bold,italic,underline,strikethrough,separator,bullist,numlist,outdent,indent,separator,undo,redo,separator,image,cleanup,help,separator,code", + theme_advanced_buttons2: "", + theme_advanced_buttons3: "", + auto_cleanup_word: true, + plugins: "media, table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,print,contextmenu,fullscreen,preview,searchreplace", + plugin_insertdate_dateFormat: "%m/%d/%Y", + plugin_insertdate_timeFormat: "%H:%M:%S", + extended_valid_elements: "a[name|href|target=_blank|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]", + fullscreen_settings: { + theme_advanced_path_location: "top", + theme_advanced_buttons1: "fullscreen,media, separator,preview,separator,cut,copy,paste,separator,undo,redo,separator,search,replace,separator,code,separator,cleanup,separator,bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,help", + theme_advanced_buttons2: "removeformat,styleselect,formatselect,fontselect,fontsizeselect,separator,bullist,numlist,outdent,indent,separator,link,unlink,anchor", + theme_advanced_buttons3: "sub,sup,separator,image,insertdate,inserttime,separator,tablecontrols,separator,hr,advhr,visualaid,separator,charmap,emotions,iespell,flash,separator,print" + } + }); + }; + + EditableView.prototype._saveChanges = function() { + var args, error, _results; + + args = arguments; + if (!this.model.isValid()) { + if (this.model.errors) { + _results = []; + for (error in this.model.errors) { + $("#group-" + error, this.el).addClass("error"); + _results.push($("#error-" + error, this.el).text(this.model.errors[error])); + } + return _results; + } + } else { + return this.model.save(null, { + success: args[0].success, + error: args[0].error + }); + } + }; + + return EditableView; + + })(Marionette.ItemView); + return EditableView; + }); + +}).call(this); diff --git a/static/js/app/lib/eventAggregator.coffee b/static/js/app/lib/eventAggregator.coffee new file mode 100644 index 0000000..533cf9f --- /dev/null +++ b/static/js/app/lib/eventAggregator.coffee @@ -0,0 +1,5 @@ +define ['marionette'], +(Marionette) -> + class EventAggregator extends Marionette.Controller + + EventAggregator \ No newline at end of file diff --git a/static/js/app/lib/eventAggregator.js b/static/js/app/lib/eventAggregator.js new file mode 100644 index 0000000..f904048 --- /dev/null +++ b/static/js/app/lib/eventAggregator.js @@ -0,0 +1,22 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette'], function(Marionette) { + var EventAggregator; + EventAggregator = (function(_super) { + + __extends(EventAggregator, _super); + + function EventAggregator() { + return EventAggregator.__super__.constructor.apply(this, arguments); + } + + return EventAggregator; + + })(Marionette.Controller); + return EventAggregator; + }); + +}).call(this); diff --git a/static/js/app/lib/panningRegion.coffee b/static/js/app/lib/panningRegion.coffee new file mode 100644 index 0000000..6974f58 --- /dev/null +++ b/static/js/app/lib/panningRegion.coffee @@ -0,0 +1,107 @@ +define ['marionette'], +(Marionette) -> + + getPrefixedCssProp = (baseProp) -> + str = Modernizr.prefixed(baseProp) + str = str.replace(/([A-Z])/g, (str, m1) -> + "-" + m1.toLowerCase() + ).replace(/^ms-/, "-ms-") + str + + class PanningRegion extends Marionette.Region + el: "#content" + initialize: -> + transEndEventNames = + WebkitTransition: "webkitTransitionEnd" + MozTransition: "transitionend" + OTransition: "oTransitionEnd" + msTransition: "MSTransitionEnd" + transition: "transitionend" + + @transEndEventName = transEndEventNames[Modernizr.prefixed("transition")] + @transformPropName = getPrefixedCssProp("transform") + console.log @transEndEventName, @transformPropName + true + + # Very similar to show(), but uses css transition class between views + transitionToView: (newView, type) -> + self = this + + # Do we have a view currently? + view = @currentView + if not view or view.isClosed + @show newView + return + Marionette.triggerMethod.call this, "willTransition", view + + # Wait for the new view to render, then initialize a transition to + # show the new view while hiding the old. + newView.on "render", -> + + # clean up the old listeners, just to ensure we only have 1 active. + self.$el.off self.transEndEventName + + # Move the new view to an off-screen position using transformation matrix + translation = undefined + + # Determine the type of transition and build the css transformation. + if type is "slide" + translation = "translateX(100%)" + else if type is "rotate" + translation = "translateX(100%) translateY(100%) rotate(" + + ["20", "40", "60", "80", "90"][_.random(0, 4)] + "deg)" + else translation = "translateY(100%)" if type is "drop" + newView.$el.css self.transformPropName, translation + + # Add the new view to the dom + self.$el.append newView.el + + # Translate the container to show the new element + $background = jQuery("#world-bg") + + # Find the transformation matrix of each element. + worldContentMatrix = Matrix.initWithElem(self.$el) + worldBgMatrix = Matrix.initWithElem($background) + newViewMatrix = Matrix.initWithElem(newView.$el) + + # Turn on the css animations to enable the transition. We do this here, + # before the tranision instead of after the transition is complete + # because it causes less of a visual 'snap' as the pattern moves. + self.$el.addClass "animated" + $background.addClass "animated" + + # Given than we know the container has an identity matrix we can transition + # by simply inverting the matrix of the new view and appyling it to the parent. + self.$el.css self.transformPropName, newViewMatrix.clone().invert().toMatrixString() + + # Let's make sure the background moves to the same place. + $background.css self.transformPropName, newViewMatrix.clone().invert().toMatrixString() + + # after transition, clean up by removing the old view, then + # re-position everything back to a zero-point. There might be a problem + # relying on the transitionEnd event because there are cases where it + # does not fire. + self.$el.on self.transEndEventName, -> + self.$el.off self.transEndEventName + + # clean up the old view + self.close() + self.currentView = newView + + # clean up new view and place everything back + # to a sane starting position, ready for next transition. + self.$el.removeClass "animated" + $background.removeClass "animated" + self.$el.css self.transformPropName, (new Matrix()).toMatrixString() + newView.$el.css self.transformPropName, (new Matrix()).toMatrixString() + $background.css "webkit-transform", (new Matrix()).toMatrixString() + + # do the things show would normally do after showing a new view + Marionette.triggerMethod.call newView, "show" + Marionette.triggerMethod.call self, "show", newView + + + newView.render() + true + + PanningRegion \ No newline at end of file diff --git a/static/js/app/lib/panningRegion.js b/static/js/app/lib/panningRegion.js new file mode 100644 index 0000000..5638e1d --- /dev/null +++ b/static/js/app/lib/panningRegion.js @@ -0,0 +1,96 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette'], function(Marionette) { + var PanningRegion, getPrefixedCssProp; + getPrefixedCssProp = function(baseProp) { + var str; + str = Modernizr.prefixed(baseProp); + str = str.replace(/([A-Z])/g, function(str, m1) { + return "-" + m1.toLowerCase(); + }).replace(/^ms-/, "-ms-"); + return str; + }; + PanningRegion = (function(_super) { + + __extends(PanningRegion, _super); + + function PanningRegion() { + return PanningRegion.__super__.constructor.apply(this, arguments); + } + + PanningRegion.prototype.el = "#content"; + + PanningRegion.prototype.initialize = function() { + var transEndEventNames; + transEndEventNames = { + WebkitTransition: "webkitTransitionEnd", + MozTransition: "transitionend", + OTransition: "oTransitionEnd", + msTransition: "MSTransitionEnd", + transition: "transitionend" + }; + this.transEndEventName = transEndEventNames[Modernizr.prefixed("transition")]; + this.transformPropName = getPrefixedCssProp("transform"); + console.log(this.transEndEventName, this.transformPropName); + return true; + }; + + PanningRegion.prototype.transitionToView = function(newView, type) { + var self, view; + self = this; + view = this.currentView; + if (!view || view.isClosed) { + this.show(newView); + return; + } + Marionette.triggerMethod.call(this, "willTransition", view); + newView.on("render", function() { + var $background, newViewMatrix, translation, worldBgMatrix, worldContentMatrix; + self.$el.off(self.transEndEventName); + translation = void 0; + if (type === "slide") { + translation = "translateX(100%)"; + } else if (type === "rotate") { + translation = "translateX(100%) translateY(100%) rotate(" + ["20", "40", "60", "80", "90"][_.random(0, 4)] + "deg)"; + } else { + if (type === "drop") { + translation = "translateY(100%)"; + } + } + newView.$el.css(self.transformPropName, translation); + self.$el.append(newView.el); + $background = jQuery("#world-bg"); + worldContentMatrix = Matrix.initWithElem(self.$el); + worldBgMatrix = Matrix.initWithElem($background); + newViewMatrix = Matrix.initWithElem(newView.$el); + self.$el.addClass("animated"); + $background.addClass("animated"); + self.$el.css(self.transformPropName, newViewMatrix.clone().invert().toMatrixString()); + $background.css(self.transformPropName, newViewMatrix.clone().invert().toMatrixString()); + return self.$el.on(self.transEndEventName, function() { + self.$el.off(self.transEndEventName); + self.close(); + self.currentView = newView; + self.$el.removeClass("animated"); + $background.removeClass("animated"); + self.$el.css(self.transformPropName, (new Matrix()).toMatrixString()); + newView.$el.css(self.transformPropName, (new Matrix()).toMatrixString()); + $background.css("webkit-transform", (new Matrix()).toMatrixString()); + Marionette.triggerMethod.call(newView, "show"); + return Marionette.triggerMethod.call(self, "show", newView); + }); + }); + newView.render(); + return true; + }; + + return PanningRegion; + + })(Marionette.Region); + return PanningRegion; + }); + +}).call(this); diff --git a/static/js/app/lib/router.coffee b/static/js/app/lib/router.coffee new file mode 100644 index 0000000..b3e7889 --- /dev/null +++ b/static/js/app/lib/router.coffee @@ -0,0 +1,17 @@ +define ['marionette', 'app.lib/controller'], +(Marionette, Controller) -> + class DssRouter extends Marionette.AppRouter + controller: new Controller, + appRoutes: + "": "home", + "/": "home", + + "mixes": "showMixList", + "mixes/:type": "showMixList" + "mix/:slug": "showMix" + "mix/edit/:slug": "editMix", + + "user/:slug": "user" + + + diff --git a/static/js/app/lib/router.js b/static/js/app/lib/router.js new file mode 100644 index 0000000..aa4f781 --- /dev/null +++ b/static/js/app/lib/router.js @@ -0,0 +1,34 @@ +// Generated by CoffeeScript 1.6.2 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'app.lib/controller'], function(Marionette, Controller) { + var DssRouter, _ref; + + return DssRouter = (function(_super) { + __extends(DssRouter, _super); + + function DssRouter() { + _ref = DssRouter.__super__.constructor.apply(this, arguments); + return _ref; + } + + DssRouter.prototype.controller = new Controller; + + DssRouter.prototype.appRoutes = { + "": "home", + "/": "home", + "mixes": "showMixList", + "mixes/:type": "showMixList", + "mix/:slug": "showMix", + "mix/edit/:slug": "editMix", + "user/:slug": "user" + }; + + return DssRouter; + + })(Marionette.AppRouter); + }); + +}).call(this); diff --git a/static/js/app/models/activity/collection.coffee b/static/js/app/models/activity/collection.coffee new file mode 100644 index 0000000..9597421 --- /dev/null +++ b/static/js/app/models/activity/collection.coffee @@ -0,0 +1,7 @@ +define ['backbone', 'models/activity/item', 'app.lib/backbone.dss.model.collection'], \ + (Backbone, ActivityItem, DssCollection) -> + class ActivityCollection extends DssCollection + model: ActivityItem + url:com.podnoms.settings.urlRoot + "activity/" + + ActivityCollection \ No newline at end of file diff --git a/static/js/app/models/activity/collection.js b/static/js/app/models/activity/collection.js new file mode 100644 index 0000000..7b83f67 --- /dev/null +++ b/static/js/app/models/activity/collection.js @@ -0,0 +1,27 @@ +// Generated by CoffeeScript 1.6.2 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['backbone', 'models/activity/item', 'app.lib/backbone.dss.model.collection'], function(Backbone, ActivityItem, DssCollection) { + var ActivityCollection, _ref; + + ActivityCollection = (function(_super) { + __extends(ActivityCollection, _super); + + function ActivityCollection() { + _ref = ActivityCollection.__super__.constructor.apply(this, arguments); + return _ref; + } + + ActivityCollection.prototype.model = ActivityItem; + + ActivityCollection.prototype.url = com.podnoms.settings.urlRoot + "activity/"; + + return ActivityCollection; + + })(DssCollection); + return ActivityCollection; + }); + +}).call(this); diff --git a/static/js/app/models/activity/item.coffee b/static/js/app/models/activity/item.coffee new file mode 100644 index 0000000..0743cbf --- /dev/null +++ b/static/js/app/models/activity/item.coffee @@ -0,0 +1,5 @@ +define ['backbone'], \ + (Backbone) -> + class ActivityItem extends Backbone.Model + urlRoot: com.podnoms.settings.urlRoot + "activity/" + diff --git a/static/js/app/models/activity/item.js b/static/js/app/models/activity/item.js new file mode 100644 index 0000000..e95d107 --- /dev/null +++ b/static/js/app/models/activity/item.js @@ -0,0 +1,24 @@ +// Generated by CoffeeScript 1.6.2 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['backbone'], function(Backbone) { + var ActivityItem, _ref; + + return ActivityItem = (function(_super) { + __extends(ActivityItem, _super); + + function ActivityItem() { + _ref = ActivityItem.__super__.constructor.apply(this, arguments); + return _ref; + } + + ActivityItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "activity/"; + + return ActivityItem; + + })(Backbone.Model); + }); + +}).call(this); diff --git a/static/js/app/models/comments/collection.coffee b/static/js/app/models/comments/collection.coffee new file mode 100644 index 0000000..989a038 --- /dev/null +++ b/static/js/app/models/comments/collection.coffee @@ -0,0 +1,6 @@ +define ['backbone', 'models/comments/item', 'app.lib/backbone.dss.model.collection'], +(Backbone, CommentItem, DssCollection) -> + class CommentCollection extends DssCollection + model: CommentItem + + CommentCollection \ No newline at end of file diff --git a/static/js/app/models/comments/collection.js b/static/js/app/models/comments/collection.js new file mode 100644 index 0000000..4df79c6 --- /dev/null +++ b/static/js/app/models/comments/collection.js @@ -0,0 +1,24 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['backbone', 'models/comments/item', 'app.lib/backbone.dss.model.collection'], function(Backbone, CommentItem, DssCollection) { + var CommentCollection; + CommentCollection = (function(_super) { + + __extends(CommentCollection, _super); + + function CommentCollection() { + return CommentCollection.__super__.constructor.apply(this, arguments); + } + + CommentCollection.prototype.model = CommentItem; + + return CommentCollection; + + })(DssCollection); + return CommentCollection; + }); + +}).call(this); diff --git a/static/js/app/models/comments/item.coffee b/static/js/app/models/comments/item.coffee new file mode 100644 index 0000000..38271d6 --- /dev/null +++ b/static/js/app/models/comments/item.coffee @@ -0,0 +1,6 @@ +define ['backbone'], +(Backbone) -> + class CommentItem extends Backbone.Model + urlRoot:com.podnoms.settings.urlRoot + "comments/" + + CommentItem \ No newline at end of file diff --git a/static/js/app/models/comments/item.js b/static/js/app/models/comments/item.js new file mode 100644 index 0000000..cc00ec7 --- /dev/null +++ b/static/js/app/models/comments/item.js @@ -0,0 +1,25 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['backbone'], function(Backbone) { + var CommentItem; + CommentItem = (function(_super) { + + __extends(CommentItem, _super); + + function CommentItem() { + return CommentItem.__super__.constructor.apply(this, arguments); + } + + return CommentItem; + + })(Backbone.Model); + ({ + urlRoot: com.podnoms.settings.urlRoot + "comments/" + }); + return CommentItem; + }); + +}).call(this); diff --git a/static/js/app/models/mix/collection.coffee b/static/js/app/models/mix/collection.coffee new file mode 100644 index 0000000..8edd2f1 --- /dev/null +++ b/static/js/app/models/mix/collection.coffee @@ -0,0 +1,11 @@ +define ['backbone', 'models/mix/item', 'app.lib/backbone.dss.model.collection'], \ + (Backbone, MixItem, DssCollection) -> + class MixCollection extends DssCollection + model: MixItem + url:com.podnoms.settings.urlRoot + "mix/" + + _parse: (data) -> + console.log("MixCollection: parse") + + MixCollection + diff --git a/static/js/app/models/mix/collection.js b/static/js/app/models/mix/collection.js new file mode 100644 index 0000000..e9c90f0 --- /dev/null +++ b/static/js/app/models/mix/collection.js @@ -0,0 +1,30 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['backbone', 'models/mix/item', 'app.lib/backbone.dss.model.collection'], function(Backbone, MixItem, DssCollection) { + var MixCollection; + MixCollection = (function(_super) { + + __extends(MixCollection, _super); + + function MixCollection() { + return MixCollection.__super__.constructor.apply(this, arguments); + } + + MixCollection.prototype.model = MixItem; + + MixCollection.prototype.url = com.podnoms.settings.urlRoot + "mix/"; + + MixCollection.prototype._parse = function(data) { + return console.log("MixCollection: parse"); + }; + + return MixCollection; + + })(DssCollection); + return MixCollection; + }); + +}).call(this); diff --git a/static/js/app/models/mix/item.coffee b/static/js/app/models/mix/item.coffee new file mode 100644 index 0000000..a0be580 --- /dev/null +++ b/static/js/app/models/mix/item.coffee @@ -0,0 +1,6 @@ +define ['app.lib/backbone.dss.model'], \ + (DssModel) -> + class MixItem extends DssModel + urlRoot: com.podnoms.settings.urlRoot + "mix/" + + MixItem \ No newline at end of file diff --git a/static/js/app/models/mix/item.js b/static/js/app/models/mix/item.js new file mode 100644 index 0000000..73e945a --- /dev/null +++ b/static/js/app/models/mix/item.js @@ -0,0 +1,24 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['app.lib/backbone.dss.model'], function(DssModel) { + var MixItem; + MixItem = (function(_super) { + + __extends(MixItem, _super); + + function MixItem() { + return MixItem.__super__.constructor.apply(this, arguments); + } + + MixItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "mix/"; + + return MixItem; + + })(DssModel); + return MixItem; + }); + +}).call(this); diff --git a/static/js/app/site.js b/static/js/app/site.js index 631d853..3c5efb7 100644 --- a/static/js/app/site.js +++ b/static/js/app/site.js @@ -7,7 +7,6 @@ */ $(document).ready(function () { - $('#ajax-request').hide(); if (window.location.hash == '#_=_') { window.location.hash = ""; } @@ -16,20 +15,6 @@ $(document).ready(function () { } }); -if (com.podnoms.settings.isDebug) { - $(document).on({ - ajaxStart: function () { - $('#ajax-request').show(); - }, - ajaxStop: function () { - $('#ajax-request').hide(); - } - }); -}else{ - $('#ajax-request').hide(); -} - - $(document).ajaxSend(function (event, xhr, settings) { function getCookie(name) { var cookieValue = null; @@ -68,3 +53,15 @@ $(document).ajaxSend(function (event, xhr, settings) { xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); } }); + + +if (com.podnoms.settings.isDebug) { + $(document).on({ + ajaxStart: function () { + console.log("Site: ajax request starting"); + }, + ajaxStop: function () { + console.log("Site: ajax request finished"); + } + }); +} \ No newline at end of file diff --git a/static/js/app/social.js b/static/js/app/social.js index 1768c22..f43f5dc 100644 --- a/static/js/app/social.js +++ b/static/js/app/social.js @@ -6,52 +6,55 @@ Code provided under the BSD License: */ -postFacebookLike = function (mixId) { - //first off, find if the current user has allowed facebook likes - $.getJSON( - 'social/like/' + mixId + '/', - function (data) { - com.podnoms.utils.showAlert("Posted your like to facebook, you can stop this in your settings page.", "Cheers feen"); - } - ); -}; -postFacebookFavourite = function (mixId) { - -}; - -sharePageToTwitter = function (model) { -//We get the URL of the link - var loc = $(this).attr('href'); - -//We get the title of the link - var title = $(this).attr('title'); - -//We trigger a new window with the Twitter dialog, in the middle of the page - window.open( - 'http://twitter.com/share?url=' + 'http://' + window.location.host + "/" + model.get('item_url') + - '&text=' + model.get('title'), - 'twitterwindow', - 'height=450, width=550, top=' + ($(window).height() / 2 - 225) + - ', left=' + $(window).width() / 2 + - ', toolbar=0, location=0, menubar=0, directories=0, scrollbars=0'); -}; -sharePageToFacebook = function (model) { - FB.ui({ - method: 'feed', - name: 'Check out this mix on Deep South Sounds', - display: 'popup', - link: 'http://' + window.location.host + "/" + model.get('item_url'), - picture: model.get('mix_image'), - caption: model.get('title'), - description: model.get('description') - }, - function (response) { - if (response && response.post_id) { - com.podnoms.utils.showAlert("Success", "Post shared to facebook"); - } else { - com.podnoms.utils.showError("Error", "Failure sharing post"); +social = { + postFacebookLike: function (mixId) { + //first off, find if the current user has allowed facebook likes + $.getJSON( + 'social/like/' + mixId + '/', + function (data) { + com.podnoms.utils.showAlert("Posted your like to facebook, you can stop this in your settings page.", "Cheers feen"); } - } - ); + ); + }, + + postFacebookFavourite: function (mixId) { + + }, + + sharePageToTwitter: function (model) { + //We get the URL of the link + var loc = $(this).attr('href'); + + //We get the title of the link + var title = $(this).attr('title'); + + //We trigger a new window with the Twitter dialog, in the middle of the page + window.open( + 'http://twitter.com/share?url=' + 'http://' + window.location.host + "/" + model.get('item_url') + + '&text=' + model.get('title'), + 'twitterwindow', + 'height=450, width=550, top=' + ($(window).height() / 2 - 225) + + ', left=' + $(window).width() / 2 + + ', toolbar=0, location=0, menubar=0, directories=0, scrollbars=0'); + }, + sharePageToFacebook: function (model) { + FB.ui({ + method: 'feed', + name: 'Check out this mix on Deep South Sounds', + display: 'popup', + link: 'http://' + window.location.host + "/" + model.get('item_url'), + picture: model.get('mix_image'), + caption: model.get('title'), + description: model.get('description') + }, + function (response) { + if (response && response.post_id) { + com.podnoms.utils.showAlert("Success", "Post shared to facebook"); + } else { + com.podnoms.utils.showError("Error", "Failure sharing post"); + } + } + ); + } }; \ No newline at end of file diff --git a/static/js/app/views/activity/item.coffee b/static/js/app/views/activity/item.coffee new file mode 100644 index 0000000..08a0634 --- /dev/null +++ b/static/js/app/views/activity/item.coffee @@ -0,0 +1,6 @@ +define ['marionette', 'text!/tpl/ActivityListItemView'], +(Marionette, Template) -> + class ActivityItemView extends Marionette.ItemView + template: _.template(Template) + tagName: "li" + className: "media" \ No newline at end of file diff --git a/static/js/app/views/activity/item.js b/static/js/app/views/activity/item.js new file mode 100644 index 0000000..2ac89e6 --- /dev/null +++ b/static/js/app/views/activity/item.js @@ -0,0 +1,27 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'text!/tpl/ActivityListItemView'], function(Marionette, Template) { + var ActivityItemView; + return ActivityItemView = (function(_super) { + + __extends(ActivityItemView, _super); + + function ActivityItemView() { + return ActivityItemView.__super__.constructor.apply(this, arguments); + } + + ActivityItemView.prototype.template = _.template(Template); + + ActivityItemView.prototype.tagName = "li"; + + ActivityItemView.prototype.className = "media"; + + return ActivityItemView; + + })(Marionette.ItemView); + }); + +}).call(this); diff --git a/static/js/app/views/activity/list.coffee b/static/js/app/views/activity/list.coffee new file mode 100644 index 0000000..d897a32 --- /dev/null +++ b/static/js/app/views/activity/list.coffee @@ -0,0 +1,21 @@ +define ['marionette', 'models/activity/collection', 'views/activity/item', 'text!/tpl/ActivityListView'], +(Marionette, ActivityCollection, ActivityItemView, Template) -> + class ActivityListView extends Marionette.CompositeView + + template: _.template(Template) + tagName: "ul" + className: "activity-listing media-list" + itemView: ActivityItemView + itemViewContainer: "#activity-list-container-ul" + + initialize: -> + console.log "ActivityListView: initialize" + @collection = new ActivityCollection + @collection.fetch( + success: => + console.log "ActivityListView: Collection fetched" + return + ) + return + + ActivityListView diff --git a/static/js/app/views/activity/list.js b/static/js/app/views/activity/list.js new file mode 100644 index 0000000..5e0f473 --- /dev/null +++ b/static/js/app/views/activity/list.js @@ -0,0 +1,43 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'models/activity/collection', 'views/activity/item', 'text!/tpl/ActivityListView'], function(Marionette, ActivityCollection, ActivityItemView, Template) { + var ActivityListView; + ActivityListView = (function(_super) { + + __extends(ActivityListView, _super); + + function ActivityListView() { + return ActivityListView.__super__.constructor.apply(this, arguments); + } + + ActivityListView.prototype.template = _.template(Template); + + ActivityListView.prototype.tagName = "ul"; + + ActivityListView.prototype.className = "activity-listing media-list"; + + ActivityListView.prototype.itemView = ActivityItemView; + + ActivityListView.prototype.itemViewContainer = "#activity-list-container-ul"; + + ActivityListView.prototype.initialize = function() { + var _this = this; + console.log("ActivityListView: initialize"); + this.collection = new ActivityCollection; + this.collection.fetch({ + success: function() { + console.log("ActivityListView: Collection fetched"); + } + }); + }; + + return ActivityListView; + + })(Marionette.CompositeView); + return ActivityListView; + }); + +}).call(this); diff --git a/static/js/app/views/comments/item.coffee b/static/js/app/views/comments/item.coffee new file mode 100644 index 0000000..96fabba --- /dev/null +++ b/static/js/app/views/comments/item.coffee @@ -0,0 +1,6 @@ +define ['marionette', 'text!/tpl/CommentItemView'], +(Marionette, Template) -> + class CommentItemView extends Marionette.ItemView + template: _.template(Template) + + CommentItemView \ No newline at end of file diff --git a/static/js/app/views/comments/item.js b/static/js/app/views/comments/item.js new file mode 100644 index 0000000..c61b6d9 --- /dev/null +++ b/static/js/app/views/comments/item.js @@ -0,0 +1,24 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'text!/tpl/CommentItemView'], function(Marionette, Template) { + var CommentItemView; + CommentItemView = (function(_super) { + + __extends(CommentItemView, _super); + + function CommentItemView() { + return CommentItemView.__super__.constructor.apply(this, arguments); + } + + CommentItemView.prototype.template = _.template(Template); + + return CommentItemView; + + })(Marionette.ItemView); + return CommentItemView; + }); + +}).call(this); diff --git a/static/js/app/views/comments/list.coffee b/static/js/app/views/comments/list.coffee new file mode 100644 index 0000000..a08f2cd --- /dev/null +++ b/static/js/app/views/comments/list.coffee @@ -0,0 +1,14 @@ +define ['marionette', 'views/comments/item', 'text!/tpl/CommentListView'], +(Marionette, CommentItemView, Template) -> + class CommentListView extends Marionette.CompositeView + + template: _.template(Template) + tagName: "ul" + className: "activity-listing media-list" + itemView: CommentItemView + itemViewContainer: "#comment-list-container" + + initialize: -> + console.log "CommentListView: initialize" + + CommentListView diff --git a/static/js/app/views/comments/list.js b/static/js/app/views/comments/list.js new file mode 100644 index 0000000..84b9414 --- /dev/null +++ b/static/js/app/views/comments/list.js @@ -0,0 +1,36 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'views/comments/item', 'text!/tpl/CommentListView'], function(Marionette, CommentItemView, Template) { + var CommentListView; + CommentListView = (function(_super) { + + __extends(CommentListView, _super); + + function CommentListView() { + return CommentListView.__super__.constructor.apply(this, arguments); + } + + CommentListView.prototype.template = _.template(Template); + + CommentListView.prototype.tagName = "ul"; + + CommentListView.prototype.className = "activity-listing media-list"; + + CommentListView.prototype.itemView = CommentItemView; + + CommentListView.prototype.itemViewContainer = "#comment-list-container"; + + CommentListView.prototype.initialize = function() { + return console.log("CommentListView: initialize"); + }; + + return CommentListView; + + })(Marionette.CompositeView); + return CommentListView; + }); + +}).call(this); diff --git a/static/js/app/views/header.js b/static/js/app/views/header.js index 35a7e7a..b96709a 100644 --- a/static/js/app/views/header.js +++ b/static/js/app/views/header.js @@ -6,68 +6,72 @@ Code provided under the BSD License: */ -window.HeaderView = Backbone.View.extend({ - events:{ - "click #header-play-pause-button":"togglePlayState", - "click #header-login-button":"login", - "click #header-live-button":"playLive" - }, - initialize:function () { - this.render(); - _.bindAll(this, "trackChanged"); - _.bindAll(this, "trackPlaying"); - _.bindAll(this, "trackPaused"); - _eventAggregator.bind("track_changed", this.trackChanged); - _eventAggregator.bind("track_playing", this.trackPlaying); - _eventAggregator.bind("track_paused", this.trackPaused); - }, - login: function () { - com.podnoms.utils.modal('tpl/LoginView'); - }, - logout: function () { - com.podnoms.utils.showAlert("Success", "You are now logged out"); - }, - trackChanged:function (data) { - $(this.el).find('#track-description').text(data.title); - $(this.el).find('#track-description').attr("href", "#" + data.item_url); - }, - trackPlaying:function (data) { - $(this.el).find('#header-play-button-icon').removeClass('icon-play'); - $(this.el).find('#header-play-button-icon').addClass('icon-pause'); +define(['underscore', 'backbone', 'text!/tpl/HeaderView'], + function (_, Backbone, Template) { + return Backbone.View.extend({ + template: _.template(Template), + events: { + "click #header-play-pause-button": "togglePlayState", + "click #header-login-button": "login", + "click #header-live-button": "playLive" + }, + initialize: function () { + this.render(); + _.bindAll(this, "trackChanged"); + _.bindAll(this, "trackPlaying"); + _.bindAll(this, "trackPaused"); + window._eventAggregator.bind("track_changed", this.trackChanged); + _eventAggregator.bind("track_playing", this.trackPlaying); + _eventAggregator.bind("track_paused", this.trackPaused); + }, + login: function () { + com.podnoms.utils.modal('tpl/LoginView'); + }, + logout: function () { + com.podnoms.utils.showAlert("Success", "You are now logged out"); + }, + trackChanged: function (data) { + $(this.el).find('#track-description').text(data.title); + $(this.el).find('#track-description').attr("href", "#" + data.item_url); + }, + trackPlaying: function (data) { + $(this.el).find('#header-play-button-icon').removeClass('icon-play'); + $(this.el).find('#header-play-button-icon').addClass('icon-pause'); - }, - trackPaused:function (data) { - $(this.el).find('#header-play-button-icon').removeClass('icon-pause'); - $(this.el).find('#header-play-button-icon').addClass('icon-play'); - }, - render:function () { - $(this.el).html(this.template()); - return this; - }, - playLive:function () { - var ref = this; - dssSoundHandler.playLive(); - _eventAggregator.trigger("track_playing") - var button = $(this.el).find('#header-play-pause-button'); - button.data("mode", "pause"); - $.getJSON( - 'ajax/live_now_playing/', - function (data) { - alert(data.title); - $(ref.el).find('#live-now-playing').text(data.title); - }); - }, - togglePlayState:function () { - var button = $(this.el).find('#header-play-pause-button'); - var mode = button.data("mode"); - if (mode == "play") { - dssSoundHandler.resumeSound(); - _eventAggregator.trigger("track_playing"); - button.data("mode", "pause"); - } else { - dssSoundHandler.pauseSound(); - _eventAggregator.trigger("track_paused"); - button.data("mode", "play"); - } - } -}); \ No newline at end of file + }, + trackPaused: function (data) { + $(this.el).find('#header-play-button-icon').removeClass('icon-pause'); + $(this.el).find('#header-play-button-icon').addClass('icon-play'); + }, + render: function () { + $(this.el).html(this.template()); + return this; + }, + playLive: function () { + var ref = this; + dssSoundHandler.playLive(); + _eventAggregator.trigger("track_playing") + var button = $(this.el).find('#header-play-pause-button'); + button.data("mode", "pause"); + $.getJSON( + 'ajax/live_now_playing/', + function (data) { + alert(data.title); + $(ref.el).find('#live-now-playing').text(data.title); + }); + }, + togglePlayState: function () { + var button = $(this.el).find('#header-play-pause-button'); + var mode = button.data("mode"); + if (mode == "play") { + dssSoundHandler.resumeSound(); + _eventAggregator.trigger("track_playing"); + button.data("mode", "pause"); + } else { + dssSoundHandler.pauseSound(); + _eventAggregator.trigger("track_paused"); + button.data("mode", "play"); + } + } + }); + }); \ No newline at end of file diff --git a/static/js/app/views/mix.js b/static/js/app/views/mix.js index eb8ddcf..fb0b5d0 100644 --- a/static/js/app/views/mix.js +++ b/static/js/app/views/mix.js @@ -10,7 +10,7 @@ window.MixListItemView = DSSEditableView.extend({ tagName: "li", events: { "click .play-button-small-start": "startMix", - "click .play-button-small-resume": "resume", + "click .play-button-small-resume": "resumeMix", "click .play-button-small-pause": "pauseMix", "click .mix-link": "mixLink", "click .like-button a": "likeMix", @@ -130,10 +130,12 @@ window.MixListItemView = DSSEditableView.extend({ ); }, pauseMix: function () { + console.log("MixItemView: pauseMix") com.podnoms.player.pause(); _eventAggregator.trigger("track_paused"); }, - resume: function () { + resumeMix: function () { + console.log("MixItemView: resumeMix") _eventAggregator.trigger("track_playing"); com.podnoms.player.resume(); }, diff --git a/static/js/app/views/mix/detail.coffee b/static/js/app/views/mix/detail.coffee new file mode 100644 index 0000000..74d0b61 --- /dev/null +++ b/static/js/app/views/mix/detail.coffee @@ -0,0 +1,17 @@ +define ['marionette', 'models/mix/item', 'views/mix/item', 'text!/tpl/MixDetailView'], +(Marionette, MixItem, MixItemView, Template) -> + class MixDetailView extends Marionette.Layout + + template: _.template(Template) + regions:{ + mix: "#mix" + comments: "#comments" + } + + onRender: -> + view = new MixItemView({tagName: "div", className: "mix-listing audio-listing-single", model: @model}) + @mix.show(view) + view.renderComments() + true + + MixDetailView diff --git a/static/js/app/views/mix/detail.js b/static/js/app/views/mix/detail.js new file mode 100644 index 0000000..d9003aa --- /dev/null +++ b/static/js/app/views/mix/detail.js @@ -0,0 +1,41 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'models/mix/item', 'views/mix/item', 'text!/tpl/MixDetailView'], function(Marionette, MixItem, MixItemView, Template) { + var MixDetailView; + MixDetailView = (function(_super) { + + __extends(MixDetailView, _super); + + function MixDetailView() { + return MixDetailView.__super__.constructor.apply(this, arguments); + } + + MixDetailView.prototype.template = _.template(Template); + + MixDetailView.prototype.regions = { + mix: "#mix", + comments: "#comments" + }; + + MixDetailView.prototype.onRender = function() { + var view; + view = new MixItemView({ + tagName: "div", + className: "mix-listing audio-listing-single", + model: this.model + }); + this.mix.show(view); + view.renderComments(); + return true; + }; + + return MixDetailView; + + })(Marionette.Layout); + return MixDetailView; + }); + +}).call(this); diff --git a/static/js/app/views/mix/edit.coffee b/static/js/app/views/mix/edit.coffee new file mode 100644 index 0000000..ef64674 --- /dev/null +++ b/static/js/app/views/mix/edit.coffee @@ -0,0 +1,139 @@ +define ['app.lib/editableView', 'moment', 'libs/backbone/backbone.syphon', 'text!/tpl/MixEditView'], +(EditableView, moment, Syphon, Template) -> + class MixEditView extends EditableView + template: _.template(Template) + events: + "click #save-changes": "saveChanges" + "change #mix_image": "imageChanged" + + checkRedirect: -> + if @state is 2 + Backbone.history.navigate "/mix/" + @model.get("slug"), + trigger: true + + initialize: -> + @guid = com.podnoms.utils.generateGuid() + @state = 0 + + onRender: -> + console.log("MixEditView: onRender") + @sendImage = false + parent = this + if @model.id is 'undefined' + $("#mix-upload", @el).uploadifive( + uploadScript: "/ajax/upload_mix_file_handler/" + buttonText: "Select audio file (mp3 for now please)" + formData: + "upload-hash": @guid + sessionid: $.cookie("sessionid") + + onUploadFile: (file) -> + $(window).on "beforeunload", -> + alert "Go on outta that.." + + + onAddQueueItem: (file) -> + $("#upload-extension", @el).val file.name.split(".").pop() + $("#mix-details", @el).show() + + onProgress: (file, e) -> + + onUploadComplete: (file, data) -> + parent.state++ + parent.checkRedirect() + ) + $(".fileupload", @el).fileupload uploadtype: "image" + $("#mix-details", @el).hide() + $(".upload-hash", @el).val @guid + else + $("#div-upload-mix", @el).hide() + @state = 1 + + $("#image-form-proxy", @el).ajaxForm + beforeSubmit: -> + $("#results").html "Submitting..." + + success: (data) -> + $out = $("#results") + $out.html "Your results:" + $out.append "
" + data + "
" + + $("#genres", @el).select2 + placeholder: "Start typing and choose or press enter" + minimumInputLength: 1 + multiple: true + ajax: # instead of writing the function to execute the request we use Select2's convenient helper + url: "/ajax/lookup/genre/" + dataType: "json" + data: (term, page) -> + q: term + + results: (data, page) -> # parse the results into the format expected by Select2. + # since we are using custom formatting functions we do not need to alter remote JSON data + results: data + + initSelection: (element, callback) -> + result = [] + genres = parent.model.get("genre-list") + unless genres is `undefined` + $.each genres, (data) -> + result.push + id: @id + text: @text + + + callback result + + createSearchChoice: (term, data) -> + if $(data).filter(-> + @text.localeCompare(term) is 0 + ).length is 0 + id: term + text: term + + this + + saveChanges: => + console.log("MixEditView: saveChanges") + data = Syphon.serialize(this) + @model.set data + @model.set "upload-hash", @guid + @model.set "upload-extension", $("#upload-extension", @el).val() + @model.set "genre-list", $("#genres", @el).select2("data") + @model.set "mix_image", "DONOTSEND" unless @sendImage + @_saveChanges + success: => + if @sendImage + $.ajaxFileUpload + url: "/ajax/upload_image/" + @model.get("id") + "/" + secureuri: false + fileElementId: "mix_image" + success: (data, status) => + unless typeof (data.error) is "undefined" + unless data.error is "" + alert data.error + else + alert data.msg + else + $("#mix-details", @el).hide() + @state++ + @checkRedirect() + + error: (data, status, e) -> + alert e + + else + $("#mix-details", @el).hide() + @state++ + @checkRedirect() + true + error: (model, response) -> + com.podnoms.utils.showError "Error", "Something went wrong
Nerd stuff is: " + response + + false + + imageChanged: (evt) -> + @sendImage = true + true + + MixEditView \ No newline at end of file diff --git a/static/js/app/views/mix/edit.js b/static/js/app/views/mix/edit.js new file mode 100644 index 0000000..281b436 --- /dev/null +++ b/static/js/app/views/mix/edit.js @@ -0,0 +1,195 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['app.lib/editableView', 'moment', 'libs/backbone/backbone.syphon', 'text!/tpl/MixEditView'], function(EditableView, moment, Syphon, Template) { + var MixEditView; + return MixEditView = (function(_super) { + + __extends(MixEditView, _super); + + function MixEditView() { + this.saveChanges = __bind(this.saveChanges, this); + return MixEditView.__super__.constructor.apply(this, arguments); + } + + MixEditView.prototype.template = _.template(Template); + + MixEditView.prototype.events = { + "click #save-changes": "saveChanges", + "change #mix_image": "imageChanged" + }; + + MixEditView.prototype.checkRedirect = function() { + if (this.state === 2) { + return Backbone.history.navigate("/mix/" + this.model.get("slug"), { + trigger: true + }); + } + }; + + MixEditView.prototype.initialize = function() { + this.guid = com.podnoms.utils.generateGuid(); + return this.state = 0; + }; + + MixEditView.prototype.onRender = function() { + var parent; + console.log("MixEditView: onRender"); + this.sendImage = false; + parent = this; + if (this.model.id === 'undefined') { + $("#mix-upload", this.el).uploadifive({ + uploadScript: "/ajax/upload_mix_file_handler/", + buttonText: "Select audio file (mp3 for now please)", + formData: { + "upload-hash": this.guid, + sessionid: $.cookie("sessionid") + }, + onUploadFile: function(file) { + return $(window).on("beforeunload", function() { + return alert("Go on outta that.."); + }); + }, + onAddQueueItem: function(file) { + $("#upload-extension", this.el).val(file.name.split(".").pop()); + return $("#mix-details", this.el).show(); + }, + onProgress: function(file, e) {}, + onUploadComplete: function(file, data) { + parent.state++; + return parent.checkRedirect(); + } + }); + $(".fileupload", this.el).fileupload({ + uploadtype: "image" + }); + $("#mix-details", this.el).hide(); + $(".upload-hash", this.el).val(this.guid); + } else { + $("#div-upload-mix", this.el).hide(); + this.state = 1; + } + $("#image-form-proxy", this.el).ajaxForm({ + beforeSubmit: function() { + return $("#results").html("Submitting..."); + }, + success: function(data) { + var $out; + $out = $("#results"); + $out.html("Your results:"); + return $out.append("
" + data + "
"); + } + }); + $("#genres", this.el).select2({ + placeholder: "Start typing and choose or press enter", + minimumInputLength: 1, + multiple: true, + ajax: { + url: "/ajax/lookup/genre/", + dataType: "json", + data: function(term, page) { + return { + q: term + }; + }, + results: function(data, page) { + return { + results: data + }; + } + }, + initSelection: function(element, callback) { + var genres, result; + result = []; + genres = parent.model.get("genre-list"); + if (genres !== undefined) { + $.each(genres, function(data) { + return result.push({ + id: this.id, + text: this.text + }); + }); + } + return callback(result); + }, + createSearchChoice: function(term, data) { + if ($(data).filter(function() { + return this.text.localeCompare(term) === 0; + }).length === 0) { + return { + id: term, + text: term + }; + } + } + }); + return this; + }; + + MixEditView.prototype.saveChanges = function() { + var data, + _this = this; + console.log("MixEditView: saveChanges"); + data = Syphon.serialize(this); + this.model.set(data); + this.model.set("upload-hash", this.guid); + this.model.set("upload-extension", $("#upload-extension", this.el).val()); + this.model.set("genre-list", $("#genres", this.el).select2("data")); + if (!this.sendImage) { + this.model.set("mix_image", "DONOTSEND"); + } + this._saveChanges({ + success: function() { + if (_this.sendImage) { + $.ajaxFileUpload({ + url: "/ajax/upload_image/" + _this.model.get("id") + "/", + secureuri: false, + fileElementId: "mix_image", + success: function(data, status) { + if (typeof data.error !== "undefined") { + if (data.error !== "") { + return alert(data.error); + } else { + return alert(data.msg); + } + } else { + $("#mix-details", _this.el).hide(); + _this.state++; + return _this.checkRedirect(); + } + }, + error: function(data, status, e) { + return alert(e); + } + }); + } else { + $("#mix-details", _this.el).hide(); + _this.state++; + _this.checkRedirect(); + } + return true; + }, + error: function(model, response) { + return com.podnoms.utils.showError("Error", "Something went wrong
Nerd stuff is: " + response); + } + }); + return false; + }; + + MixEditView.prototype.imageChanged = function(evt) { + this.sendImage = true; + return true; + }; + + MixEditView; + + + return MixEditView; + + })(EditableView); + }); + +}).call(this); diff --git a/static/js/app/views/mix/item.coffee b/static/js/app/views/mix/item.coffee new file mode 100644 index 0000000..9e9de4f --- /dev/null +++ b/static/js/app/views/mix/item.coffee @@ -0,0 +1,104 @@ +define ['moment', 'app', 'marionette', 'models/comments/collection', 'views/comments/list', 'text!/tpl/MixListItemView'], +(moment, App, Marionette, CommentsCollection, CommentsListView, Template) -> + class MixItemView extends Marionette.ItemView + template: _.template(Template) + tagName: @tagName or "li" + className: @className or "" + + events: { + "click .play-button-small-start": "startMix", + "click .play-button-small-resume": "resumeMix", + "click .play-button-small-pause": "pauseMix", + "click .mix-link": "mixLink", + "click .like-button a": "likeMix", + "click .favourite-button a": "favouriteMix", + "click .share-button": "shareMix", + "click .download-button a": "downloadMix" + } + + initialize: => + @listenTo(@model, 'change:favourited', @render) + @listenTo(@model, 'change:liked', @render) + true + + + onRender: => + id = @model.get('id') + if @model.get('duration') + totalDuration = moment.duration(this.model.get('duration'), "seconds") + totalDurationText = if totalDuration.hours() != 0 then moment(totalDuration).format("HH:mm:ss") else moment(totalDuration).format("mm:ss"); + $('#player-duration-' + id, this.el).text(totalDurationText) + + @renderGenres() + return + + startMix: => + console.log("MixItemView: starting mix") + id = @model.get('id') + $.getJSON "/ajax/mix_stream_url/" + id + "/", (data) -> + com.podnoms.settings.setupPlayer(data, id) + com.podnoms.player.startPlaying + success: -> + window._eventAggregator.trigger "track_playing" + window._eventAggregator.trigger "track_changed", data + com.podnoms.utils.checkPlayCount() + return + error: -> + com.podnoms.utils.showWarning "Ooops", "Error playing mix. If you have a flash blocker, please disable it for this site. Otherwise, do please try again." + + com.podnoms.storage.setItem "now_playing", id + return + + pauseMix: -> + console.log("MixItemView: pauseMix") + com.podnoms.player.pause(); + @.trigger("mix:paused", @model); + true + + resumeMix: -> + console.log("MixItemView: resumeMix") + com.podnoms.player.resume(); + @trigger("mix:resumed", @model); + true + + renderGenres: => + el = @el + $.each @model.get("genre-list"), (data) -> + $("#genre-list", el).append '' + @text + '' + true + true + + renderComments: => + comments = new CommentsCollection() + comments.url = @model.get("resource_uri") + "comments/" + comments.mix_id = @model.id + comments.mix = @model.get("resource_uri") + comments.fetch success: (data) -> + console.log(data) + content = new CommentsListView(collection: comments).render() + $("#comments", @el).html content.el + $('#mix-tab a:first', @el).tab('show'); + true + + favouriteMix: -> + console.log("MixItemView: favouriteMix") + app = require('app') + app.vent.trigger("mix:favourite", @model) + true + + likeMix: -> + console.log("MixItemView: likeMix") + app = require('app') + app.vent.trigger("mix:like", @model) + true + + shareMix: (e) -> + console.log("MixItemView: shareMix") + mode = $(e.currentTarget).data("mode"); + console.log("MixItemView: "+ mode) + app = require('app') + app.vent.trigger("mix:share", mode, @model) + true + + + MixItemView diff --git a/static/js/app/views/mix/item.js b/static/js/app/views/mix/item.js new file mode 100644 index 0000000..8c60049 --- /dev/null +++ b/static/js/app/views/mix/item.js @@ -0,0 +1,156 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['moment', 'app', 'marionette', 'models/comments/collection', 'views/comments/list', 'text!/tpl/MixListItemView'], function(moment, App, Marionette, CommentsCollection, CommentsListView, Template) { + var MixItemView; + MixItemView = (function(_super) { + + __extends(MixItemView, _super); + + function MixItemView() { + this.renderComments = __bind(this.renderComments, this); + + this.renderGenres = __bind(this.renderGenres, this); + + this.startMix = __bind(this.startMix, this); + + this.onRender = __bind(this.onRender, this); + + this.initialize = __bind(this.initialize, this); + return MixItemView.__super__.constructor.apply(this, arguments); + } + + MixItemView.prototype.template = _.template(Template); + + MixItemView.prototype.tagName = MixItemView.tagName || "li"; + + MixItemView.prototype.className = MixItemView.className || ""; + + MixItemView.prototype.events = { + "click .play-button-small-start": "startMix", + "click .play-button-small-resume": "resumeMix", + "click .play-button-small-pause": "pauseMix", + "click .mix-link": "mixLink", + "click .like-button a": "likeMix", + "click .favourite-button a": "favouriteMix", + "click .share-button": "shareMix", + "click .download-button a": "downloadMix" + }; + + MixItemView.prototype.initialize = function() { + this.listenTo(this.model, 'change:favourited', this.render); + this.listenTo(this.model, 'change:liked', this.render); + return true; + }; + + MixItemView.prototype.onRender = function() { + var id, totalDuration, totalDurationText; + id = this.model.get('id'); + if (this.model.get('duration')) { + totalDuration = moment.duration(this.model.get('duration'), "seconds"); + totalDurationText = totalDuration.hours() !== 0 ? moment(totalDuration).format("HH:mm:ss") : moment(totalDuration).format("mm:ss"); + $('#player-duration-' + id, this.el).text(totalDurationText); + } + this.renderGenres(); + }; + + MixItemView.prototype.startMix = function() { + var id; + console.log("MixItemView: starting mix"); + id = this.model.get('id'); + $.getJSON("/ajax/mix_stream_url/" + id + "/", function(data) { + com.podnoms.settings.setupPlayer(data, id); + com.podnoms.player.startPlaying({ + success: function() { + window._eventAggregator.trigger("track_playing"); + window._eventAggregator.trigger("track_changed", data); + com.podnoms.utils.checkPlayCount(); + }, + error: function() { + return com.podnoms.utils.showWarning("Ooops", "Error playing mix. If you have a flash blocker, please disable it for this site. Otherwise, do please try again."); + } + }); + return com.podnoms.storage.setItem("now_playing", id); + }); + }; + + MixItemView.prototype.pauseMix = function() { + console.log("MixItemView: pauseMix"); + com.podnoms.player.pause(); + this.trigger("mix:paused", this.model); + return true; + }; + + MixItemView.prototype.resumeMix = function() { + console.log("MixItemView: resumeMix"); + com.podnoms.player.resume(); + this.trigger("mix:resumed", this.model); + return true; + }; + + MixItemView.prototype.renderGenres = function() { + var el; + el = this.el; + $.each(this.model.get("genre-list"), function(data) { + $("#genre-list", el).append('' + this.text + ''); + return true; + }); + return true; + }; + + MixItemView.prototype.renderComments = function() { + var comments; + comments = new CommentsCollection(); + comments.url = this.model.get("resource_uri") + "comments/"; + comments.mix_id = this.model.id; + comments.mix = this.model.get("resource_uri"); + comments.fetch({ + success: function(data) { + var content; + console.log(data); + content = new CommentsListView({ + collection: comments + }).render(); + $("#comments", this.el).html(content.el); + return $('#mix-tab a:first', this.el).tab('show'); + } + }); + return true; + }; + + MixItemView.prototype.favouriteMix = function() { + var app; + console.log("MixItemView: favouriteMix"); + app = require('app'); + app.vent.trigger("mix:favourite", this.model); + return true; + }; + + MixItemView.prototype.likeMix = function() { + var app; + console.log("MixItemView: likeMix"); + app = require('app'); + app.vent.trigger("mix:like", this.model); + return true; + }; + + MixItemView.prototype.shareMix = function(e) { + var app, mode; + console.log("MixItemView: shareMix"); + mode = $(e.currentTarget).data("mode"); + console.log("MixItemView: " + mode); + app = require('app'); + app.vent.trigger("mix:share", mode, this.model); + return true; + }; + + return MixItemView; + + })(Marionette.ItemView); + return MixItemView; + }); + +}).call(this); diff --git a/static/js/app/views/mix/list.coffee b/static/js/app/views/mix/list.coffee new file mode 100644 index 0000000..e6b134e --- /dev/null +++ b/static/js/app/views/mix/list.coffee @@ -0,0 +1,26 @@ +define ['marionette', 'models/mix/collection', 'views/mix/item', 'text!/tpl/MixListView'], +(Marionette, MixCollection, MixItemView, Template) -> + class MixListView extends Marionette.CompositeView + + template: _.template(Template) + className: "mix-listing audio-listing" + itemView: MixItemView + itemViewContainer: "#mix-list-container-ul" + + initialize: -> + console.log "MixListView: Before render" + @collection = new MixCollection() + @collection.fetch( + data: @options + success: => + console.log("MixListView: Collection fetched") + return + ) + return + + onRender: -> + $('#li-' + @options.type, @el).addClass('active') + true + + MixListView + diff --git a/static/js/app/views/mix/list.js b/static/js/app/views/mix/list.js new file mode 100644 index 0000000..56e893d --- /dev/null +++ b/static/js/app/views/mix/list.js @@ -0,0 +1,47 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['marionette', 'models/mix/collection', 'views/mix/item', 'text!/tpl/MixListView'], function(Marionette, MixCollection, MixItemView, Template) { + var MixListView; + MixListView = (function(_super) { + + __extends(MixListView, _super); + + function MixListView() { + return MixListView.__super__.constructor.apply(this, arguments); + } + + MixListView.prototype.template = _.template(Template); + + MixListView.prototype.className = "mix-listing audio-listing"; + + MixListView.prototype.itemView = MixItemView; + + MixListView.prototype.itemViewContainer = "#mix-list-container-ul"; + + MixListView.prototype.initialize = function() { + var _this = this; + console.log("MixListView: Before render"); + this.collection = new MixCollection(); + this.collection.fetch({ + data: this.options, + success: function() { + console.log("MixListView: Collection fetched"); + } + }); + }; + + MixListView.prototype.onRender = function() { + $('#li-' + this.options.type, this.el).addClass('active'); + return true; + }; + + return MixListView; + + })(Marionette.CompositeView); + return MixListView; + }); + +}).call(this); diff --git a/static/js/app/views/sidebar.js b/static/js/app/views/sidebar.js index 01acd11..1db56cb 100644 --- a/static/js/app/views/sidebar.js +++ b/static/js/app/views/sidebar.js @@ -7,83 +7,93 @@ */ -window.SidebarView = Backbone.View.extend({ - events: { - "click #sidebar-play-pause-button-small": "togglePlayState", - "click #sidebar-listen-live": "playLive" - }, - initialize: function () { - this.render(); - _.bindAll(this, "trackChanged"); - _.bindAll(this, "trackPlaying"); - _.bindAll(this, "trackPaused"); - _eventAggregator.bind("track_changed", this.trackChanged); - _eventAggregator.bind("track_playing", this.trackPlaying); - _eventAggregator.bind("track_paused", this.trackPaused); - $.getJSON( - 'ajax/live_now_playing/', - function (data) { - $("#live-now-playing", this.el).text(data.title); - }); - }, - render: function () { - $(this.el).html(this.template()); - var activity = new ActivityCollection(); - activity.fetch({ - success: function () { - var content = new ActivityListView({ - collection: activity - }).el; - $('#sidebar-content-activity', this.el).html(content); - } - }); - return this; - }, - togglePlayState: function () { +define(['marionette', 'views/activity/list', 'text!/tpl/SidebarView'], + function (Marionette, ActivityListView, Template) { - }, - trackChanged: function (data) { - $(this.el).find('#now-playing').text(data.title); - if (data.item_url != undefined) - $(this.el).find('#now-playing').attr("href", "#" + data.item_url); - }, - trackPlaying: function (data) { - $(this.el).find('#header-play-button-icon').removeClass('icon-play'); - $(this.el).find('#header-play-button-icon').addClass('icon-pause'); - }, - trackPaused: function (data) { - $(this.el).find('#header-play-button-icon').removeClass('icon-pause'); - $(this.el).find('#header-play-button-icon').addClass('icon-play'); - }, - playLive: function () { - var liveButton = $(this.el).find('#sidebar-listen-live'); - if ((liveButton).hasClass('btn-danger')) { - com.podnoms.player.stopPlaying(); - liveButton.removeClass('btn-danger').addClass('btn-success').text('Listen live'); - liveButton.blur(); - } else { - liveButton.button('loading'); - com.podnoms.player.playLive({ + return Marionette.View.extend({ + template: _.template(Template), + events: { + "click #sidebar-play-pause-button-small": "togglePlayState", + "click #sidebar-listen-live": "playLive" + }, + initialize: function () { + this.render(); + _.bindAll(this, "trackChanged"); + _.bindAll(this, "trackPlaying"); + _.bindAll(this, "trackPaused"); + window._eventAggregator.bind("track_changed", this.trackChanged); + window._eventAggregator.bind("track_playing", this.trackPlaying); + window._eventAggregator.bind("track_paused", this.trackPaused); + $.getJSON( + 'ajax/live_now_playing/', + function (data) { + $("#live-now-playing", this.el).text(data.title); + }); + }, + render: function () { + console.log("Sidebar: Render"); + $(this.el).html(this.template()); + var activityListView = new ActivityListView(); + $('#sidebar-content-activity', this.el).html(activityListView.el); + /* + var activity = new ActivityCollection(); + activity.fetch({ success: function () { - $.getJSON( - 'ajax/live_now_playing/', - function (data) { - $('#live-now-playing', el).text(data.title); - data.title += " (live)"; - _eventAggregator.trigger("track_changed", data); - liveButton.button('reset'); - liveButton.removeClass('btn-success').addClass('btn-danger').text('Stop listening'); - } - ); + var content = new ActivityListView({ + collection: activity + }).el; + $('#sidebar-content-activity', this.el).html(content); } }); + */ + return this; + }, + togglePlayState: function () { + + }, + trackChanged: function (data) { + $(this.el).find('#now-playing').text(data.title); + if (data.item_url != undefined) + $(this.el).find('#now-playing').attr("href", "#" + data.item_url); + }, + trackPlaying: function (data) { + $(this.el).find('#header-play-button-icon').removeClass('icon-play'); + $(this.el).find('#header-play-button-icon').addClass('icon-pause'); + }, + trackPaused: function (data) { + $(this.el).find('#header-play-button-icon').removeClass('icon-pause'); + $(this.el).find('#header-play-button-icon').addClass('icon-play'); + }, + playLive: function () { + var liveButton = $(this.el).find('#sidebar-listen-live'); + if ((liveButton).hasClass('btn-danger')) { + com.podnoms.player.stopPlaying(); + liveButton.removeClass('btn-danger').addClass('btn-success').text('Listen live'); + liveButton.blur(); + } else { + liveButton.button('loading'); + com.podnoms.player.playLive({ + success: function () { + $.getJSON( + 'ajax/live_now_playing/', + function (data) { + $('#live-now-playing', el).text(data.title); + data.title += " (live)"; + window._eventAggregator.trigger("track_changed", data); + liveButton.button('reset'); + liveButton.removeClass('btn-success').addClass('btn-danger').text('Stop listening'); + } + ); + } + }); + } + window._eventAggregator.trigger("track_playing") + var button = $(this.el).find('#sidebar-play-pause-button-small'); + var el = this.el; + button + .removeClass('play-button-small-start') + .removeClass('play-button-small-loading') + .addClass('play-button-small-pause'); } - _eventAggregator.trigger("track_playing") - var button = $(this.el).find('#sidebar-play-pause-button-small'); - var el = this.el; - button - .removeClass('play-button-smallstart') - .removeClass('play-button-small-loading') - .addClass('play-button-small-pause'); - } -}); \ No newline at end of file + }); +}); diff --git a/static/js/app/views/sidebar/sidebar.coffee b/static/js/app/views/sidebar/sidebar.coffee new file mode 100644 index 0000000..c45cb57 --- /dev/null +++ b/static/js/app/views/sidebar/sidebar.coffee @@ -0,0 +1,19 @@ +define ['underscore', 'backbone', 'marionette', 'views/activity/list', 'text!/tpl/SidebarView'], +(_, Backbone, Marionette, ActivityListView, Template) -> + class SidebarView extends Marionette.Layout + template: _.template(Template) + className: "tabbable" + regions: + topRegion: '#sidebar-top-content' + streamRegion: '#sidebar-stream-content' + + initialize: -> + console.log "SidebarView: initialize" + return + + onShow: -> + console.log "SidebarView: onShow" + #this.topRegion.show(new NowPlayingView()) + this.streamRegion.show(new ActivityListView()) + return + diff --git a/static/js/app/views/sidebar/sidebar.js b/static/js/app/views/sidebar/sidebar.js new file mode 100644 index 0000000..7a3a915 --- /dev/null +++ b/static/js/app/views/sidebar/sidebar.js @@ -0,0 +1,39 @@ +// Generated by CoffeeScript 1.3.3 +(function() { + var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + define(['underscore', 'backbone', 'marionette', 'views/activity/list', 'text!/tpl/SidebarView'], function(_, Backbone, Marionette, ActivityListView, Template) { + var SidebarView; + return SidebarView = (function(_super) { + + __extends(SidebarView, _super); + + function SidebarView() { + return SidebarView.__super__.constructor.apply(this, arguments); + } + + SidebarView.prototype.template = _.template(Template); + + SidebarView.prototype.className = "tabbable"; + + SidebarView.prototype.regions = { + topRegion: '#sidebar-top-content', + streamRegion: '#sidebar-stream-content' + }; + + SidebarView.prototype.initialize = function() { + console.log("SidebarView: initialize"); + }; + + SidebarView.prototype.onShow = function() { + console.log("SidebarView: onShow"); + this.streamRegion.show(new ActivityListView()); + }; + + return SidebarView; + + })(Marionette.Layout); + }); + +}).call(this); diff --git a/static/js/app/views/user/userItem.coffee b/static/js/app/views/user/userItem.coffee index 3b52e17..c4f378c 100644 --- a/static/js/app/views/user/userItem.coffee +++ b/static/js/app/views/user/userItem.coffee @@ -1,2 +1,4 @@ -class UserItemView extends Marionette.ItemView -> - itemView: UserItemView \ No newline at end of file +define ['marionette'], +(Marionette)-> + class UserItemView extends Marionette.ItemView + itemView: UserItemView \ No newline at end of file diff --git a/static/js/app/views/user/userItem.js b/static/js/app/views/user/userItem.js index af56fb6..2d9303b 100644 --- a/static/js/app/views/user/userItem.js +++ b/static/js/app/views/user/userItem.js @@ -1,23 +1,23 @@ // Generated by CoffeeScript 1.3.3 (function() { - var UserItemView, - __hasProp = {}.hasOwnProperty, + var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - UserItemView = (function(_super) { + define(['marionette'], function(Marionette) { + var UserItemView; + return UserItemView = (function(_super) { - __extends(UserItemView, _super); + __extends(UserItemView, _super); - function UserItemView() { - return UserItemView.__super__.constructor.apply(this, arguments); - } + function UserItemView() { + return UserItemView.__super__.constructor.apply(this, arguments); + } - return UserItemView; + UserItemView.prototype.itemView = UserItemView; - })(Marionette.ItemView(function() { - return { - itemView: UserItemView - }; - })); + return UserItemView; + + })(Marionette.ItemView); + }); }).call(this); diff --git a/static/js/app/views/user/userList.coffee b/static/js/app/views/user/userList.coffee index 857cedb..cdf4eb7 100644 --- a/static/js/app/views/user/userList.coffee +++ b/static/js/app/views/user/userList.coffee @@ -1,2 +1,13 @@ -class UserListView extends Marionette.CollectionView -> - \ No newline at end of file +define ['marionette', 'views/user/userItem'], +(Marionette, UserItemView) -> + + class UserListView extends Marionette.CompositeView + template: "

Hello Sailor + console.log "User list view initializing" + + return UserListView \ No newline at end of file diff --git a/static/js/app/views/user/userList.js b/static/js/app/views/user/userList.js index a2558c5..4b47e8f 100644 --- a/static/js/app/views/user/userList.js +++ b/static/js/app/views/user/userList.js @@ -1,19 +1,33 @@ -// Generated by CoffeeScript 1.3.3 +// Generated by CoffeeScript 1.6.2 (function() { - var UserListView, - __hasProp = {}.hasOwnProperty, + var __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - UserListView = (function(_super) { + define(['views/user/userItem'], function(UserItemView) { + var UserListView, _ref; - __extends(UserListView, _super); + return UserListView = (function(_super) { + __extends(UserListView, _super); - function UserListView() { - return UserListView.__super__.constructor.apply(this, arguments); - } + function UserListView() { + _ref = UserListView.__super__.constructor.apply(this, arguments); + return _ref; + } - return UserListView; + return UserListView; - })(Marionette.CollectionView(function() {})); + })(Marionette.CompositeView(function() { + ({ + template: "

Hello Sailor') + "\"}"; - var objInst = JSON.parse(obj); - this.model.set(objInst); - } - }, - changed: function (evt) { - //change handler for the form to update the model - //with the new values - return; - var changed = evt.currentTarget; - //$("#" + changed.id) - if (!com.podnoms.utils.isEmpty(changed.id)) { - var value, obj; - if ($(changed).is(':checkbox')) { - value = $(changed).is(':checked'); - obj = "{\"" + changed.id + "\":" + value + "}"; - } else { - value = $(changed).val(); - obj = "{\"" + changed.id + "\":\"" + value.replace(/\n/g, '
') + "\"}"; - } - var objInst = JSON.parse(obj); - this.model.set(objInst); - } - }, - _bakeForm: function (el, lookups) { - //TODO extend lookups to be a list - //TODO this way we can initialise more than one lookup per page - var model = this.model; - var labels, mapped; - $('.typeahead', el).typeahead({ - source: function (query, process) { - $.get( - '/ajax/lookup/' + lookups + '/', - { query: query }, - function (data) { - labels = [] - mapped = {} - $.each(data, function (i, item) { - mapped[item[1]] = item; - labels.push(item[1]); - }); - process(labels); - }, 'json'); - }, - updater: function (item) { - this.$element.val(mapped[item][0]); - model.set(this.$element.attr('id'), mapped[item][0]); - return item; - } - }); - $('.datepicker', el).datepicker( - { - 'format': 'dd/mm/yyyy' - } - ); - $('.timepicker', el).timepicker(); - $('textarea.tinymce', this.el).tinymce({ - script_url: "/static/js/libs/tiny_mce/tiny_mce.js", - mode: "textareas", - theme: "advanced", - theme_advanced_toolbar_location: "top", - theme_advanced_toolbar_align: "left", - theme_advanced_buttons1: "fullscreen,media,tablecontrols,separator,link,unlink,anchor,separator,preview,separator,bold,italic,underline,strikethrough,separator,bullist,numlist,outdent,indent,separator,undo,redo,separator,image,cleanup,help,separator,code", - theme_advanced_buttons2: "", - theme_advanced_buttons3: "", - auto_cleanup_word: true, - plugins: "media, table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,print,contextmenu,fullscreen,preview,searchreplace", - plugin_insertdate_dateFormat: "%m/%d/%Y", - plugin_insertdate_timeFormat: "%H:%M:%S", - extended_valid_elements: "a[name|href|target=_blank|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]", - fullscreen_settings: { - theme_advanced_path_location: "top", - theme_advanced_buttons1: "fullscreen,media, separator,preview,separator,cut,copy,paste,separator,undo,redo,separator,search,replace,separator,code,separator,cleanup,separator,bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,help", - theme_advanced_buttons2: "removeformat,styleselect,formatselect,fontselect,fontsizeselect,separator,bullist,numlist,outdent,indent,separator,link,unlink,anchor", - theme_advanced_buttons3: "sub,sup,separator,image,insertdate,inserttime,separator,tablecontrols,separator,hr,advhr,visualaid,separator,charmap,emotions,iespell,flash,separator,print" - } - }); - }, - _saveChanges: function () { - var args = arguments; - if (this.model.isValid() != "") { - if (this.model.errors) { - for (var error in this.model.errors) { - $('#group-' + error, this.el).addClass('error'); - $('#error-' + error, this.el).text(this.model.errors[error]); - } - } - } else { - this.model.save( - null, - { - success: args[0].success, - error: args[0].error - } - ); - } - } -}); diff --git a/static/js/libs/backbone/backbone.syphon.js b/static/js/libs/backbone/backbone.syphon.js index 95efe7f..8354dc9 100644 --- a/static/js/libs/backbone/backbone.syphon.js +++ b/static/js/libs/backbone/backbone.syphon.js @@ -2,4 +2,480 @@ // Copyright (c)2012 Derick Bailey, Muted Solutions, LLC. // Distributed under MIT license // http://github.com/derickbailey/backbone.syphon -Backbone.Syphon=function(a,b,c){var d={};d.ignoredTypes=["button","submit","reset","fieldset"],d.serialize=function(a,d){var g={},j=h(d),k=e(a,j);return c.each(k,function(a){var c=b(a),d=f(c),e=j.keyExtractors.get(d),h=e(c),k=j.inputReaders.get(d),l=k(c),m=j.keyAssignmentValidators.get(d);if(m(c,h,l)){var n=j.keySplitter(h);g=i(g,n,l)}}),g},d.deserialize=function(a,d,g){var i=h(g),k=e(a,i),l=j(i,d);c.each(k,function(a){var c=b(a),d=f(c),e=i.keyExtractors.get(d),g=e(c),h=i.inputWriters.get(d),j=l[g];h(c,j)})};var e=function(a,d){var e=g(a),h=e.elements;return h=c.reject(h,function(a){var e,g=f(a),h=d.keyExtractors.get(g),i=h(b(a)),j=c.include(d.ignoredTypes,g),k=c.include(d.include,i),l=c.include(d.exclude,i);return k?e=!1:d.include?e=!0:e=l||j,e}),h},f=function(a){var c,d=b(a),e=d[0].tagName,f=e;return e.toLowerCase()==="input"&&(c=d.attr("type"),c?f=c:f="text"),f.toLowerCase()},g=function(a){return c.isUndefined(a.$el)&&a.tagName.toLowerCase()==="form"?a:a.$el.is("form")?a.el:a.$("form")[0]},h=function(a){var b=c.clone(a)||{};return b.ignoredTypes=c.clone(d.ignoredTypes),b.inputReaders=b.inputReaders||d.InputReaders,b.inputWriters=b.inputWriters||d.InputWriters,b.keyExtractors=b.keyExtractors||d.KeyExtractors,b.keySplitter=b.keySplitter||d.KeySplitter,b.keyJoiner=b.keyJoiner||d.KeyJoiner,b.keyAssignmentValidators=b.keyAssignmentValidators||d.KeyAssignmentValidators,b},i=function(a,b,d){if(!b)return a;var e=b.shift();return a[e]||(a[e]=c.isArray(e)?[]:{}),b.length===0&&(c.isArray(a[e])?a[e].push(d):a[e]=d),b.length>0&&i(a[e],b,d),a},j=function(a,b,d){var e={};return c.each(b,function(b,f){var g={};d&&(f=a.keyJoiner(d,f)),c.isArray(b)?(f+="[]",g[f]=b):c.isObject(b)?g=j(a,b,f):g[f]=b,c.extend(e,g)}),e};return d}(Backbone,jQuery,_),Backbone.Syphon.TypeRegistry=function(){this.registeredTypes={}},Backbone.Syphon.TypeRegistry.extend=Backbone.Model.extend,_.extend(Backbone.Syphon.TypeRegistry.prototype,{get:function(a){var b=this.registeredTypes[a];return b||(b=this.registeredTypes["default"]),b},register:function(a,b){this.registeredTypes[a]=b},registerDefault:function(a){this.registeredTypes["default"]=a},unregister:function(a){this.registeredTypes[a]&&delete this.registeredTypes[a]}}),Backbone.Syphon.KeyExtractorSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.KeyExtractors=new Backbone.Syphon.KeyExtractorSet,Backbone.Syphon.KeyExtractors.registerDefault(function(a){return a.prop("name")}),Backbone.Syphon.InputReaderSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.InputReaders=new Backbone.Syphon.InputReaderSet,Backbone.Syphon.InputReaders.registerDefault(function(a){return a.val()}),Backbone.Syphon.InputReaders.register("checkbox",function(a){var b=a.prop("checked");return b}),Backbone.Syphon.InputWriterSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.InputWriters=new Backbone.Syphon.InputWriterSet,Backbone.Syphon.InputWriters.registerDefault(function(a,b){a.val(b)}),Backbone.Syphon.InputWriters.register("checkbox",function(a,b){a.prop("checked",b)}),Backbone.Syphon.InputWriters.register("radio",function(a,b){a.prop("checked",a.val()===b)}),Backbone.Syphon.KeyAssignmentValidatorSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.KeyAssignmentValidators=new Backbone.Syphon.KeyAssignmentValidatorSet,Backbone.Syphon.KeyAssignmentValidators.registerDefault(function(){return!0}),Backbone.Syphon.KeyAssignmentValidators.register("radio",function(a,b,c){return a.prop("checked")}),Backbone.Syphon.KeySplitter=function(a){var b=a.match(/[^\[\]]+/g);return a.indexOf("[]")===a.length-2&&(lastKey=b.pop(),b.push([lastKey])),b},Backbone.Syphon.KeyJoiner=function(a,b){return a+"["+b+"]"}; +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['underscore', "jquery", "backbone"], factory); + } +}(this, function (_, jQuery, Backbone) { + Backbone.Syphon = (function (Backbone, $, _) { + var Syphon = {}; + + // Ignore Element Types + // -------------------- + + // Tell Syphon to ignore all elements of these types. You can + // push new types to ignore directly in to this array. + Syphon.ignoredTypes = ["button", "submit", "reset", "fieldset"]; + + // Syphon + // ------ + + // Get a JSON object that represents + // all of the form inputs, in this view. + // Alternately, pass a form element directly + // in place of the view. + Syphon.serialize = function (view, options) { + var data = {}; + + // Build the configuration + var config = buildConfig(options); + + // Get all of the elements to process + var elements = getInputElements(view, config); + + // Process all of the elements + _.each(elements, function (el) { + var $el = $(el); + var type = getElementType($el); + + // Get the key for the input + var keyExtractor = config.keyExtractors.get(type); + var key = keyExtractor($el); + + // Get the value for the input + var inputReader = config.inputReaders.get(type); + var value = inputReader($el); + + // Get the key assignment validator and make sure + // it's valid before assigning the value to the key + var validKeyAssignment = config.keyAssignmentValidators.get(type); + if (validKeyAssignment($el, key, value)) { + var keychain = config.keySplitter(key); + data = assignKeyValue(data, keychain, value); + } + }); + + // Done; send back the results. + return data; + }; + + // Use the given JSON object to populate + // all of the form inputs, in this view. + // Alternately, pass a form element directly + // in place of the view. + Syphon.deserialize = function (view, data, options) { + // Build the configuration + var config = buildConfig(options); + + // Get all of the elements to process + var elements = getInputElements(view, config); + + // Flatten the data structure that we are deserializing + var flattenedData = flattenData(config, data); + + // Process all of the elements + _.each(elements, function (el) { + var $el = $(el); + var type = getElementType($el); + + // Get the key for the input + var keyExtractor = config.keyExtractors.get(type); + var key = keyExtractor($el); + + // Get the input writer and the value to write + var inputWriter = config.inputWriters.get(type); + var value = flattenedData[key]; + + // Write the value to the input + inputWriter($el, value); + }); + }; + + // Helpers + // ------- + + // Retrieve all of the form inputs + // from the form + var getInputElements = function (view, config) { + var form = getForm(view); + var elements = form.elements; + + elements = _.reject(elements, function (el) { + var reject; + var type = getElementType(el); + var extractor = config.keyExtractors.get(type); + var identifier = extractor($(el)); + + var foundInIgnored = _.include(config.ignoredTypes, type); + var foundInInclude = _.include(config.include, identifier); + var foundInExclude = _.include(config.exclude, identifier); + + if (foundInInclude) { + reject = false; + } else { + if (config.include) { + reject = true; + } else { + reject = (foundInExclude || foundInIgnored); + } + } + + return reject; + }); + + return elements; + }; + + // Determine what type of element this is. It + // will either return the `type` attribute of + // an `` element, or the `tagName` of + // the element when the element is not an ``. + var getElementType = function (el) { + var typeAttr; + var $el = $(el); + var tagName = $el[0].tagName; + var type = tagName; + + if (tagName.toLowerCase() === "input") { + typeAttr = $el.attr("type"); + if (typeAttr) { + type = typeAttr; + } else { + type = "text"; + } + } + + // Always return the type as lowercase + // so it can be matched to lowercase + // type registrations. + return type.toLowerCase(); + }; + + // If a form element is given, just return it. + // Otherwise, get the form element from the view. + var getForm = function (viewOrForm) { + if (_.isUndefined(viewOrForm.$el) && viewOrForm.tagName.toLowerCase() === 'form') { + return viewOrForm; + } else { + return viewOrForm.$el.is("form") ? viewOrForm.el : viewOrForm.$("form")[0]; + } + }; + + // Build a configuration object and initialize + // default values. + var buildConfig = function (options) { + var config = _.clone(options) || {}; + + config.ignoredTypes = _.clone(Syphon.ignoredTypes); + config.inputReaders = config.inputReaders || Syphon.InputReaders; + config.inputWriters = config.inputWriters || Syphon.InputWriters; + config.keyExtractors = config.keyExtractors || Syphon.KeyExtractors; + config.keySplitter = config.keySplitter || Syphon.KeySplitter; + config.keyJoiner = config.keyJoiner || Syphon.KeyJoiner; + config.keyAssignmentValidators = config.keyAssignmentValidators || Syphon.KeyAssignmentValidators; + + return config; + }; + + // Assigns `value` to a parsed JSON key. + // + // The first parameter is the object which will be + // modified to store the key/value pair. + // + // The second parameter accepts an array of keys as a + // string with an option array containing a + // single string as the last option. + // + // The third parameter is the value to be assigned. + // + // Examples: + // + // `["foo", "bar", "baz"] => {foo: {bar: {baz: "value"}}}` + // + // `["foo", "bar", ["baz"]] => {foo: {bar: {baz: ["value"]}}}` + // + // When the final value is an array with a string, the key + // becomes an array, and values are pushed in to the array, + // allowing multiple fields with the same name to be + // assigned to the array. + var assignKeyValue = function (obj, keychain, value) { + if (!keychain) { + return obj; + } + + var key = keychain.shift(); + + // build the current object we need to store data + if (!obj[key]) { + obj[key] = _.isArray(key) ? [] : {}; + } + + // if it's the last key in the chain, assign the value directly + if (keychain.length === 0) { + if (_.isArray(obj[key])) { + obj[key].push(value); + } else { + obj[key] = value; + } + } + + // recursive parsing of the array, depth-first + if (keychain.length > 0) { + assignKeyValue(obj[key], keychain, value); + } + + return obj; + }; + + // Flatten the data structure in to nested strings, using the + // provided `KeyJoiner` function. + // + // Example: + // + // This input: + // + // ```js + // { + // widget: "wombat", + // foo: { + // bar: "baz", + // baz: { + // quux: "qux" + // }, + // quux: ["foo", "bar"] + // } + // } + // ``` + // + // With a KeyJoiner that uses [ ] square brackets, + // should produce this output: + // + // ```js + // { + // "widget": "wombat", + // "foo[bar]": "baz", + // "foo[baz][quux]": "qux", + // "foo[quux]": ["foo", "bar"] + // } + // ``` + var flattenData = function (config, data, parentKey) { + var flatData = {}; + + _.each(data, function (value, keyName) { + var hash = {}; + + // If there is a parent key, join it with + // the current, child key. + if (parentKey) { + keyName = config.keyJoiner(parentKey, keyName); + } + + if (_.isArray(value)) { + keyName += "[]"; + hash[keyName] = value; + } else if (_.isObject(value)) { + hash = flattenData(config, value, keyName); + } else { + hash[keyName] = value; + } + + // Store the resulting key/value pairs in the + // final flattened data object + _.extend(flatData, hash); + }); + + return flatData; + }; + + return Syphon; + })(Backbone, jQuery, _); + + // Type Registry + // ------------- + + // Type Registries allow you to register something to + // an input type, and retrieve either the item registered + // for a specific type or the default registration + Backbone.Syphon.TypeRegistry = function () { + this.registeredTypes = {}; + }; + + // Borrow Backbone's `extend` keyword for our TypeRegistry + Backbone.Syphon.TypeRegistry.extend = Backbone.Model.extend; + + _.extend(Backbone.Syphon.TypeRegistry.prototype, { + + // Get the registered item by type. If nothing is + // found for the specified type, the default is + // returned. + get: function (type) { + var item = this.registeredTypes[type]; + + if (!item) { + item = this.registeredTypes["default"]; + } + + return item; + }, + + // Register a new item for a specified type + register: function (type, item) { + this.registeredTypes[type] = item; + }, + + // Register a default item to be used when no + // item for a specified type is found + registerDefault: function (item) { + this.registeredTypes["default"] = item; + }, + + // Remove an item from a given type registration + unregister: function (type) { + if (this.registeredTypes[type]) { + delete this.registeredTypes[type]; + } + } + }); + + + // Key Extractors + // -------------- + + // Key extractors produce the "key" in `{key: "value"}` + // pairs, when serializing. + Backbone.Syphon.KeyExtractorSet = Backbone.Syphon.TypeRegistry.extend(); + + // Built-in Key Extractors + Backbone.Syphon.KeyExtractors = new Backbone.Syphon.KeyExtractorSet(); + + // The default key extractor, which uses the + // input element's "id" attribute + Backbone.Syphon.KeyExtractors.registerDefault(function ($el) { + return $el.prop("name"); + }); + + + // Input Readers + // ------------- + + // Input Readers are used to extract the value from + // an input element, for the serialized object result + Backbone.Syphon.InputReaderSet = Backbone.Syphon.TypeRegistry.extend(); + + // Built-in Input Readers + Backbone.Syphon.InputReaders = new Backbone.Syphon.InputReaderSet(); + + // The default input reader, which uses an input + // element's "value" + Backbone.Syphon.InputReaders.registerDefault(function ($el) { + return $el.val(); + }); + + // Checkbox reader, returning a boolean value for + // whether or not the checkbox is checked. + Backbone.Syphon.InputReaders.register("checkbox", function ($el) { + var checked = $el.prop("checked"); + return checked; + }); + + + // Input Writers + // ------------- + + // Input Writers are used to insert a value from an + // object into an input element. + Backbone.Syphon.InputWriterSet = Backbone.Syphon.TypeRegistry.extend(); + + // Built-in Input Writers + Backbone.Syphon.InputWriters = new Backbone.Syphon.InputWriterSet(); + + // The default input writer, which sets an input + // element's "value" + Backbone.Syphon.InputWriters.registerDefault(function ($el, value) { + $el.val(value); + }); + + // Checkbox writer, set whether or not the checkbox is checked + // depending on the boolean value. + Backbone.Syphon.InputWriters.register("checkbox", function ($el, value) { + $el.prop("checked", value); + }); + + // Radio button writer, set whether or not the radio button is + // checked. The button should only be checked if it's value + // equals the given value. + Backbone.Syphon.InputWriters.register("radio", function ($el, value) { + $el.prop("checked", $el.val() === value); + }); + + // Key Assignment Validators + // ------------------------- + + // Key Assignment Validators are used to determine whether or not a + // key should be assigned to a value, after the key and value have been + // extracted from the element. This is the last opportunity to prevent + // bad data from getting serialized to your object. + + Backbone.Syphon.KeyAssignmentValidatorSet = Backbone.Syphon.TypeRegistry.extend(); + + // Build-in Key Assignment Validators + Backbone.Syphon.KeyAssignmentValidators = new Backbone.Syphon.KeyAssignmentValidatorSet(); + + // Everything is valid by default + Backbone.Syphon.KeyAssignmentValidators.registerDefault(function () { + return true; + }); + + // But only the "checked" radio button for a given + // radio button group is valid + Backbone.Syphon.KeyAssignmentValidators.register("radio", function ($el, key, value) { + return $el.prop("checked"); + }); + + + // Backbone.Syphon.KeySplitter + // --------------------------- + + // This function is used to split DOM element keys in to an array + // of parts, which are then used to create a nested result structure. + // returning `["foo", "bar"]` results in `{foo: { bar: "value" }}`. + // + // Override this method to use a custom key splitter, such as: + // ``, `return key.split(".")` + Backbone.Syphon.KeySplitter = function (key) { + var matches = key.match(/[^\[\]]+/g); + + if (key.indexOf("[]") === key.length - 2) { + lastKey = matches.pop(); + matches.push([lastKey]); + } + + return matches; + } + + + // Backbone.Syphon.KeyJoiner + // ------------------------- + + // Take two segments of a key and join them together, to create the + // de-normalized key name, when deserializing a data structure back + // in to a form. + // + // Example: + // + // With this data strucutre `{foo: { bar: {baz: "value", quux: "another"} } }`, + // the key joiner will be called with these parameters, and assuming the + // join happens with "[ ]" square brackets, the specified output: + // + // `KeyJoiner("foo", "bar")` //=> "foo[bar]" + // `KeyJoiner("foo[bar]", "baz")` //=> "foo[bar][baz]" + // `KeyJoiner("foo[bar]", "quux")` //=> "foo[bar][quux]" + + Backbone.Syphon.KeyJoiner = function (parentKey, childKey) { + return parentKey + "[" + childKey + "]"; + } + + + return Backbone.Syphon; +})); \ No newline at end of file diff --git a/static/js/libs/matrix.js b/static/js/libs/matrix.js new file mode 100644 index 0000000..fea6f86 --- /dev/null +++ b/static/js/libs/matrix.js @@ -0,0 +1,410 @@ + /** + * http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html + * + * A great resource: http://www.senocular.com/flash/tutorials/transformmatrix/ + * + * (a:Number = 1, b:Number = 0, c:Number = 0, d:Number = 1, tx:Number = 0, ty:Number = 0) + * + * @param int a + * @param int b + * @param int c + * @param int d + * @param int tx + * @param int ty + */ + + Matrix = function(a, b, c, d, tx, ty){ + + + /** + * @var int a The value that affects the positioning of pixels along the x + * axis when scaling or rotating an image. + */ + this.a = a || 1; + + + /** + * @var int b The value that affects the positioning of pixels + * along the y axis when rotating or skewing an image. + */ + this.b = b || 0; + + + /** + * @var int c The value that affects the positioning of pixels + * along the x axis when rotating or skewing an image. + */ + this.c = c || 0; + + /** + * @var int d The value that affects the positioning of + * pixels along the x axis when scaling or rotating an image. + */ + this.d = d || 1; + + /** + * @var int tx The distance by which to translate each point + * long the x axis. + */ + this.tx = tx || 0; + + /** + * @var int ty The distance by which to translate each point + * along the y axis. + */ + this.ty = ty || 0; + + }; + + /** + * @return {Matrix} A clone of this Matrix. + */ + Matrix.prototype.clone = function(){ + + return new Matrix(this.a, this.b, this.c, this.d, this.tx, this.ty); + + }; + + /** + * Concatenates a matrix with the current matrix, effectively combining the + * geometric effects of the two. + * + * http://en.wikipedia.org/wiki/Matrix_multiplication + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#concat()} + * + * @param {Matrix} m The matrix to contat with this matrix. + * + * @return void + */ + Matrix.prototype.concat = function(m) { + + var r = new Matrix(); + + // 1,1 + // (a,c,tx) * (a,b,0) + r.a = (this.a * m.a) + (this.c * m.b); + + // 1,2 + // (a,c,tx) * (c,d,0) + r.c = (this.a * m.c) + (this.c * m.d); + + // 1,3 + // (a,c,tx) * (tx,ty,1) + r.tx = (this.a * m.tx) + (this.c * m.ty) + this.tx; + + // 2,1 + // (b,d,ty) * (a,b,0) + r.b = (this.b * m.a) + (this.d * m.b); + + // 2,2 + //(b,d,ty) * (c,d,0) + r.d = (this.b * m.c) + (this.d * m.d); + + // 2,3 + // (b,d,ty) * (tx,ty,1); + r.ty = (this.b * m.tx) + (this.d * m.ty) + this.ty; + + this.a = r.a; + this.b = r.b; + this.c = r.c; + this.d = r.d; + this.tx = r.tx; + this.ty = r.ty; + + return this; + + }; + + /** + * Includes parameters for scaling, rotation, and translation. + * createBox(scaleX:Number, scaleY:Number, rotation:Number = 0, tx:Number = 0, + * ty:Number = 0):void + * + * @param float scaleX + * @param float scaleY + * @param float rotation + * @param float tx + * @param float ty + * + * @return void + */ + Matrix.prototype.createBox = function(scaleX, scaleY, rotation, tx, ty){ + this.identity(); + this.rotate(rotation); + this.scale(scaleX, scaleY); + this.translate(tx, ty); + }; + + /** + * Creates the specific style of matrix expected by the beginGradientFill() and + * lineGradientStyle() methods of the Graphics class. + * createGradientBox(width:Number, height:Number, rotation:Number = 0, tx:Number = + * 0, ty:Number = 0):void + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#createGradientBox()} + * + * @param float width + * @param float height + * @param float rotation + * @param float tx + * @param float ty + * + * @return void + */ + Matrix.prototype.createGradientBox = function(width, height, + rotation, tx, ty){ + + // does the graphics class have to be finished first? thinking yes. + + }; + + /** + * Given a point in the pretransform coordinate space, returns the coordinates + * of that point after the transformation occurs. + * deltaTransformPoint(point:Point):Point + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#deltaTransformPoint()} + * + * @param {Point} point + * + * @return {Point} + */ + Matrix.prototype.deltaTransformPoint = function(point){ + + var point = { + x : ( (this.a * point.x) + + (this.c * point.y) ), + y : ( (this.b * point.x) + + (this.d * point.y) ) + }; + + return new Point(point.x, point.y); + + + }; + + /** + * Sets each matrix property to a value that causes a null transformation. + * identity():void + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#identity()} + * + * @return void + */ + Matrix.prototype.identity = function(){ + + // 1 0 0 + // 0 1 0 + // 0 0 1 + + this.a = 1; + this.b = 0; + this.c = 0; + this.d = 1; + this.tx = 0; + this.ty = 0; + + }; + + + /** + * Performs the opposite transformation of the original matrix. invert():void + * + * Math below taken straight from Wikipedia: + * http://en.wikipedia.org/wiki/Matrix_inversion#Methods_of_matrix_inversion + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#invert()} + * + * @return void + */ + Matrix.prototype.invert = function(){ + + var determinant = this.a * this.d - this.b * this.c; + return new Matrix( + this.d / determinant, + -this.b / determinant, + -this.c / determinant, + this.a / determinant, + (this.c * this.ty - this.d * this.tx) / determinant, + (this.b * this.tx - this.a * this.ty) / determinant + ); + + // AA-1 = A-1A = I + // Flash Matrix -> Wikipedia Matrix -> Inverted Matrix + // a c tx -> a b c -> A D G + // b d ty -> d e f -> B E H + // 0 0 1 -> g h k -> C F K + + // Notice we do not need F or K + // C is necessary to test for invertability + var A = (this.d * 1) - (this.ty * 0), + B = (this.ty * 0) - (1 * this.b), + C = (this.b * 0) - (this.d_ * 0), + D = (this.tx * 0) - (this.c * 1), + E = (this.a * 1) - (this.tx * 0), + G = (this.c * this.ty) - (this.tx * this.d), + H = (this.tx * this.b) - (this.a * this.ty); + + // Z = a(ek − fh) + b(fg − kd) + c(dh − eg) + // Test to see if this Matrix is invertable + if(((this.a * A) + (this.c * B) + (this.tx * C)) <= 0) { // not invertable + return null; + } + + return new Matrix(A, B, D, E, G, H); + + }; + + /** + * Applies a rotation transformation to the Matrix object. + * rotate(angle:Number):void + * + * http://en.wikipedia.org/wiki/Rotation_matrix + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#rotate()} + * + * @return void + * + */ + Matrix.prototype.rotate = function(r){ + + var m = new Matrix(Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0); + this.concat(m); + + }; + + Matrix.prototype.getRotation = function(degrees) { + var scale = Math.sqrt(this.a*this.a + this.b*this.b); + + // arc sin, convert from radians to degrees, round + // DO NOT USE: see update below + var sin = this.b/scale; + + var radians = Math.asin(sin); + + if(degrees) { + return Math.round(radians * (180/Math.PI)); + } + return radians; + }; + + Matrix.prototype.degToRad = function(deg) { + return deg * (Math.PI / 180); + }; + + Matrix.prototype.radToDeg = function(rad) { + return rad * (180/Math.PI); + }; + + /** + * Applies a scaling transformation to the matrix. scale(sx:Number, + * sy:Number):void + * + * @link http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#scale()} + * + * @param float sx + * @param float sy + * + * @return void + * + */ + Matrix.prototype.scale = function(sx, sy){ + + var m = new Matrix(sx, 0, 0, sy, 0, 0); + this.concat(m); + + }; + + /** + * Returns a text value listing the properties of the Matrix object. + * toString():String + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#toString()} + * + * @return string + * + * TODO: need to test this override...see if it works. + */ + Matrix.prototype.toString = function(){ + + return this.a + ' ' + this.c + ' ' + this.tx + '\n' + + this.b + ' ' + this.d + ' ' + this.ty; + + }; + + + /** + * Returns the result of applying the geometric transformation represented by + * the Matrix object to the specified point. transformPoint(point:Point):Point + * + * Converts a local point to a world (matrix) point. + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#transformPoint()} + * + * @param {Point} point + * + * @return {Point} + * + */ + Matrix.prototype.transformPoint = function(point){ + + // WARNING: DOUBLE CHECK MATH!! been awhile since knocking these out + // in my linear algebra class + var point = { + x : ( (this.a * point.x) + + (this.c * point.y) + + (this.tx) ), + y : ( (this.b * point.x) + + (this.d * point.y) + + (this.ty) ) + }; + + return new Point(point.x, point.y); + + }; + + /** + * Translates the matrix along the x and y axes, as specified by the dx and dy + * parameters. translate(dx:Number, dy:Number):void + * + * @link {http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/geom/Matrix.html#translate()} + * + * @param float dx + * @param float dy + * + * @return void + * + */ + Matrix.prototype.translate = function(dx, dy){ + + this.tx += dx; + this.ty += dy; + + }; + + Matrix.prototype.toMatrixString = function () { + return 'matrix(' + this.a.toFixed(20) + ', ' + + this.b.toFixed(20) + ', ' + + this.c.toFixed(20) + ', ' + + this.d.toFixed(20) + ', ' + + this.tx.toFixed(20) + ', ' + + this.ty.toFixed(20) + ')'; + }; + + Matrix.initWithElem = function ($elem) { + var tr = $elem.css('-webkit-transform'); + var m = new Matrix(); + + try { + var v = tr.split('(')[1].split(')')[0].split(','); + m = new Matrix(Number(v[0]), + Number(v[1]), + Number(v[2]), + Number(v[3]), + Number(v[4]), + Number(v[5])); + } catch (e) {} + + return m; + }; \ No newline at end of file diff --git a/static/js/libs/modernizr.js b/static/js/libs/modernizr.js index b5958e9..db357e0 100644 --- a/static/js/libs/modernizr.js +++ b/static/js/libs/modernizr.js @@ -1,4 +1,950 @@ /* Modernizr 2.6.2 (Custom Build) | MIT & BSD - * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexbox_legacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load */ -;window.Modernizr=function(a,b,c){function C(a){j.cssText=a}function D(a,b){return C(n.join(a+";")+(b||""))}function E(a,b){return typeof a===b}function F(a,b){return!!~(""+a).indexOf(b)}function G(a,b){for(var d in a){var e=a[d];if(!F(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function H(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:E(f,"function")?f.bind(d||b):f}return!1}function I(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return E(b,"string")||E(b,"undefined")?G(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),H(e,b,c))}function J(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=E(e[d],"function"),E(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),A={}.hasOwnProperty,B;!E(A,"undefined")&&!E(A.call,"undefined")?B=function(a,b){return A.call(a,b)}:B=function(a,b){return b in a&&E(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return I("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!E(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!I("indexedDB",a)},s.hashchange=function(){return z("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return C("background-color:rgba(150,255,150,.5)"),F(j.backgroundColor,"rgba")},s.hsla=function(){return C("background-color:hsla(120,40%,100%,.5)"),F(j.backgroundColor,"rgba")||F(j.backgroundColor,"hsla")},s.multiplebgs=function(){return C("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return I("backgroundSize")},s.borderimage=function(){return I("borderImage")},s.borderradius=function(){return I("borderRadius")},s.boxshadow=function(){return I("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return D("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return I("animationName")},s.csscolumns=function(){return I("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return C((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),F(j.backgroundImage,"gradient")},s.cssreflections=function(){return I("boxReflect")},s.csstransforms=function(){return!!I("transform")},s.csstransforms3d=function(){var a=!!I("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return I("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var K in s)B(s,K)&&(x=K.toLowerCase(),e[x]=s[K](),v.push((e[x]?"":"no-")+x));return e.input||J(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)B(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},C(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.hasEvent=z,e.testProp=function(a){return G([a])},e.testAllProps=I,e.testStyles=y,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f', rule, ''].join(''); + div.id = mod; + (body ? div : fakeBody).innerHTML += style; + fakeBody.appendChild(div); + if (!body) { + fakeBody.style.background = ''; + fakeBody.style.overflow = 'hidden'; + docOverflow = docElement.style.overflow; + docElement.style.overflow = 'hidden'; + docElement.appendChild(fakeBody); + } + + ret = callback(div, rule); + if (!body) { + fakeBody.parentNode.removeChild(fakeBody); + docElement.style.overflow = docOverflow; + } else { + div.parentNode.removeChild(div); + } + + return !!ret; + + }, + + + isEventSupported = (function () { + + var TAGNAMES = { + 'select': 'input', 'change': 'input', + 'submit': 'form', 'reset': 'form', + 'error': 'img', 'load': 'img', 'abort': 'img' + }; + + function isEventSupported(eventName, element) { + + element = element || document.createElement(TAGNAMES[eventName] || 'div'); + eventName = 'on' + eventName; + + var isSupported = eventName in element; + + if (!isSupported) { + if (!element.setAttribute) { + element = document.createElement('div'); + } + if (element.setAttribute && element.removeAttribute) { + element.setAttribute(eventName, ''); + isSupported = is(element[eventName], 'function'); + + if (!is(element[eventName], 'undefined')) { + element[eventName] = undefined; + } + element.removeAttribute(eventName); + } + } + + element = null; + return isSupported; + } + + return isEventSupported; + })(), + + + _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp; + + if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) { + hasOwnProp = function (object, property) { + return _hasOwnProperty.call(object, property); + }; + } + else { + hasOwnProp = function (object, property) { + return ((property in object) && is(object.constructor.prototype[property], 'undefined')); + }; + } + + + if (!Function.prototype.bind) { + Function.prototype.bind = function bind(that) { + + var target = this; + + if (typeof target != "function") { + throw new TypeError(); + } + + var args = slice.call(arguments, 1), + bound = function () { + + if (this instanceof bound) { + + var F = function () { + }; + F.prototype = target.prototype; + var self = new F(); + + var result = target.apply( + self, + args.concat(slice.call(arguments)) + ); + if (Object(result) === result) { + return result; + } + return self; + + } else { + + return target.apply( + that, + args.concat(slice.call(arguments)) + ); + + } + + }; + + return bound; + }; + } + + function setCss(str) { + mStyle.cssText = str; + } + + function setCssAll(str1, str2) { + return setCss(prefixes.join(str1 + ';') + ( str2 || '' )); + } + + function is(obj, type) { + return typeof obj === type; + } + + function contains(str, substr) { + return !!~('' + str).indexOf(substr); + } + + function testProps(props, prefixed) { + for (var i in props) { + var prop = props[i]; + if (!contains(prop, "-") && mStyle[prop] !== undefined) { + return prefixed == 'pfx' ? prop : true; + } + } + return false; + } + + function testDOMProps(props, obj, elem) { + for (var i in props) { + var item = obj[props[i]]; + if (item !== undefined) { + + if (elem === false) return props[i]; + + if (is(item, 'function')) { + return item.bind(elem || obj); + } + + return item; + } + } + return false; + } + + function testPropsAll(prop, prefixed, elem) { + + var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), + props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); + + if (is(prefixed, "string") || is(prefixed, "undefined")) { + return testProps(props, prefixed); + + } else { + props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); + return testDOMProps(props, prefixed, elem); + } + } + + tests['flexbox'] = function () { + return testPropsAll('flexWrap'); + }; + + + tests['flexboxlegacy'] = function () { + return testPropsAll('boxDirection'); + }; + + + tests['canvas'] = function () { + var elem = document.createElement('canvas'); + return !!(elem.getContext && elem.getContext('2d')); + }; + + tests['canvastext'] = function () { + return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function')); + }; + + + tests['webgl'] = function () { + return !!window.WebGLRenderingContext; + }; + + + tests['touch'] = function () { + var bool; + + if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { + bool = true; + } else { + injectElementWithStyles(['@media (', prefixes.join('touch-enabled),('), mod, ')', '{#modernizr{top:9px;position:absolute}}'].join(''), function (node) { + bool = node.offsetTop === 9; + }); + } + + return bool; + }; + + + tests['geolocation'] = function () { + return 'geolocation' in navigator; + }; + + + tests['postmessage'] = function () { + return !!window.postMessage; + }; + + + tests['websqldatabase'] = function () { + return !!window.openDatabase; + }; + + tests['indexedDB'] = function () { + return !!testPropsAll("indexedDB", window); + }; + + tests['hashchange'] = function () { + return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7); + }; + + tests['history'] = function () { + return !!(window.history && history.pushState); + }; + + tests['draganddrop'] = function () { + var div = document.createElement('div'); + return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); + }; + + tests['websockets'] = function () { + return 'WebSocket' in window || 'MozWebSocket' in window; + }; + + + tests['rgba'] = function () { + setCss('background-color:rgba(150,255,150,.5)'); + + return contains(mStyle.backgroundColor, 'rgba'); + }; + + tests['hsla'] = function () { + setCss('background-color:hsla(120,40%,100%,.5)'); + + return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla'); + }; + + tests['multiplebgs'] = function () { + setCss('background:url(https://),url(https://),red url(https://)'); + + return (/(url\s*\(.*?){3}/).test(mStyle.background); + }; + tests['backgroundsize'] = function () { + return testPropsAll('backgroundSize'); + }; + + tests['borderimage'] = function () { + return testPropsAll('borderImage'); + }; + + + tests['borderradius'] = function () { + return testPropsAll('borderRadius'); + }; + + tests['boxshadow'] = function () { + return testPropsAll('boxShadow'); + }; + + tests['textshadow'] = function () { + return document.createElement('div').style.textShadow === ''; + }; + + + tests['opacity'] = function () { + setCssAll('opacity:.55'); + + return (/^0.55$/).test(mStyle.opacity); + }; + + + tests['cssanimations'] = function () { + return testPropsAll('animationName'); + }; + + + tests['csscolumns'] = function () { + return testPropsAll('columnCount'); + }; + + + tests['cssgradients'] = function () { + var str1 = 'background-image:', + str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));', + str3 = 'linear-gradient(left top,#9f9, white);'; + + setCss( + (str1 + '-webkit- '.split(' ').join(str2 + str1) + + prefixes.join(str3 + str1)).slice(0, -str1.length) + ); + + return contains(mStyle.backgroundImage, 'gradient'); + }; + + + tests['cssreflections'] = function () { + return testPropsAll('boxReflect'); + }; + + + tests['csstransforms'] = function () { + return !!testPropsAll('transform'); + }; + + + tests['csstransforms3d'] = function () { + + var ret = !!testPropsAll('perspective'); + + if (ret && 'webkitPerspective' in docElement.style) { + + injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) { + ret = node.offsetLeft === 9 && node.offsetHeight === 3; + }); + } + return ret; + }; + + + tests['csstransitions'] = function () { + return testPropsAll('transition'); + }; + + + tests['fontface'] = function () { + var bool; + + injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function (node, rule) { + var style = document.getElementById('smodernizr'), + sheet = style.sheet || style.styleSheet, + cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : ''; + + bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0; + }); + + return bool; + }; + + tests['generatedcontent'] = function () { + var bool; + + injectElementWithStyles(['#', mod, '{font:0/0 a}#', mod, ':after{content:"', smile, '";visibility:hidden;font:3px/1 a}'].join(''), function (node) { + bool = node.offsetHeight >= 3; + }); + + return bool; + }; + tests['video'] = function () { + var elem = document.createElement('video'), + bool = false; + + try { + if (bool = !!elem.canPlayType) { + bool = new Boolean(bool); + bool.ogg = elem.canPlayType('video/ogg; codecs="theora"').replace(/^no$/, ''); + + bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/, ''); + + bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/, ''); + } + + } catch (e) { + } + + return bool; + }; + + tests['audio'] = function () { + var elem = document.createElement('audio'), + bool = false; + + try { + if (bool = !!elem.canPlayType) { + bool = new Boolean(bool); + bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ''); + bool.mp3 = elem.canPlayType('audio/mpeg;').replace(/^no$/, ''); + + bool.wav = elem.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ''); + bool.m4a = ( elem.canPlayType('audio/x-m4a;') || + elem.canPlayType('audio/aac;')).replace(/^no$/, ''); + } + } catch (e) { + } + + return bool; + }; + + + tests['localstorage'] = function () { + try { + localStorage.setItem(mod, mod); + localStorage.removeItem(mod); + return true; + } catch (e) { + return false; + } + }; + + tests['sessionstorage'] = function () { + try { + sessionStorage.setItem(mod, mod); + sessionStorage.removeItem(mod); + return true; + } catch (e) { + return false; + } + }; + + + tests['webworkers'] = function () { + return !!window.Worker; + }; + + + tests['applicationcache'] = function () { + return !!window.applicationCache; + }; + + + tests['svg'] = function () { + return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect; + }; + + tests['inlinesvg'] = function () { + var div = document.createElement('div'); + div.innerHTML = ''; + return (div.firstChild && div.firstChild.namespaceURI) == ns.svg; + }; + + tests['smil'] = function () { + return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate'))); + }; + + + tests['svgclippaths'] = function () { + return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath'))); + }; + + function webforms() { + Modernizr['input'] = (function (props) { + for (var i = 0, len = props.length; i < len; i++) { + attrs[ props[i] ] = !!(props[i] in inputElem); + } + if (attrs.list) { + attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement); + } + return attrs; + })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' ')); + Modernizr['inputtypes'] = (function (props) { + + for (var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++) { + + inputElem.setAttribute('type', inputElemType = props[i]); + bool = inputElem.type !== 'text'; + + if (bool) { + + inputElem.value = smile; + inputElem.style.cssText = 'position:absolute;visibility:hidden;'; + + if (/^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined) { + + docElement.appendChild(inputElem); + defaultView = document.defaultView; + + bool = defaultView.getComputedStyle && + defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' && + (inputElem.offsetHeight !== 0); + + docElement.removeChild(inputElem); + + } else if (/^(search|tel)$/.test(inputElemType)) { + } else if (/^(url|email)$/.test(inputElemType)) { + bool = inputElem.checkValidity && inputElem.checkValidity() === false; + + } else { + bool = inputElem.value != smile; + } + } + + inputs[ props[i] ] = !!bool; + } + return inputs; + })('search tel url email datetime date month week time datetime-local number range color'.split(' ')); + } + + for (var feature in tests) { + if (hasOwnProp(tests, feature)) { + featureName = feature.toLowerCase(); + Modernizr[featureName] = tests[feature](); + + classes.push((Modernizr[featureName] ? '' : 'no-') + featureName); + } + } + + Modernizr.input || webforms(); + + + Modernizr.addTest = function (feature, test) { + if (typeof feature == 'object') { + for (var key in feature) { + if (hasOwnProp(feature, key)) { + Modernizr.addTest(key, feature[ key ]); + } + } + } else { + + feature = feature.toLowerCase(); + + if (Modernizr[feature] !== undefined) { + return Modernizr; + } + + test = typeof test == 'function' ? test() : test; + + if (typeof enableClasses !== "undefined" && enableClasses) { + docElement.className += ' ' + (test ? '' : 'no-') + feature; + } + Modernizr[feature] = test; + + } + + return Modernizr; + }; + + + setCss(''); + modElem = inputElem = null; + + ; + (function (window, document) { + var options = window.html5 || {}; + + var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i; + + var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i; + + var supportsHtml5Styles; + + var expando = '_html5shiv'; + + var expanID = 0; + + var expandoData = {}; + + var supportsUnknownElements; + + (function () { + try { + var a = document.createElement('a'); + a.innerHTML = ''; + supportsHtml5Styles = ('hidden' in a); + + supportsUnknownElements = a.childNodes.length == 1 || (function () { + (document.createElement)('a'); + var frag = document.createDocumentFragment(); + return ( + typeof frag.cloneNode == 'undefined' || + typeof frag.createDocumentFragment == 'undefined' || + typeof frag.createElement == 'undefined' + ); + }()); + } catch (e) { + supportsHtml5Styles = true; + supportsUnknownElements = true; + } + + }()); + function addStyleSheet(ownerDocument, cssText) { + var p = ownerDocument.createElement('p'), + parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement; + + p.innerHTML = 'x'; + return parent.insertBefore(p.lastChild, parent.firstChild); + } + + function getElements() { + var elements = html5.elements; + return typeof elements == 'string' ? elements.split(' ') : elements; + } + + function getExpandoData(ownerDocument) { + var data = expandoData[ownerDocument[expando]]; + if (!data) { + data = {}; + expanID++; + ownerDocument[expando] = expanID; + expandoData[expanID] = data; + } + return data; + } + + function createElement(nodeName, ownerDocument, data) { + if (!ownerDocument) { + ownerDocument = document; + } + if (supportsUnknownElements) { + return ownerDocument.createElement(nodeName); + } + if (!data) { + data = getExpandoData(ownerDocument); + } + var node; + + if (data.cache[nodeName]) { + node = data.cache[nodeName].cloneNode(); + } else if (saveClones.test(nodeName)) { + node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode(); + } else { + node = data.createElem(nodeName); + } + + return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node; + } + + function createDocumentFragment(ownerDocument, data) { + if (!ownerDocument) { + ownerDocument = document; + } + if (supportsUnknownElements) { + return ownerDocument.createDocumentFragment(); + } + data = data || getExpandoData(ownerDocument); + var clone = data.frag.cloneNode(), + i = 0, + elems = getElements(), + l = elems.length; + for (; i < l; i++) { + clone.createElement(elems[i]); + } + return clone; + } + + function shivMethods(ownerDocument, data) { + if (!data.cache) { + data.cache = {}; + data.createElem = ownerDocument.createElement; + data.createFrag = ownerDocument.createDocumentFragment; + data.frag = data.createFrag(); + } + + + ownerDocument.createElement = function (nodeName) { + if (!html5.shivMethods) { + return data.createElem(nodeName); + } + return createElement(nodeName, ownerDocument, data); + }; + + ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' + + 'var n=f.cloneNode(),c=n.createElement;' + + 'h.shivMethods&&(' + + getElements().join().replace(/\w+/g, function (nodeName) { + data.createElem(nodeName); + data.frag.createElement(nodeName); + return 'c("' + nodeName + '")'; + }) + + ');return n}' + )(html5, data.frag); + } + + function shivDocument(ownerDocument) { + if (!ownerDocument) { + ownerDocument = document; + } + var data = getExpandoData(ownerDocument); + + if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) { + data.hasCSS = !!addStyleSheet(ownerDocument, + 'article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}' + + 'mark{background:#FF0;color:#000}' + ); + } + if (!supportsUnknownElements) { + shivMethods(ownerDocument, data); + } + return ownerDocument; + } + + var html5 = { + + 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video', + + 'shivCSS': (options.shivCSS !== false), + + 'supportsUnknownElements': supportsUnknownElements, + + 'shivMethods': (options.shivMethods !== false), + + 'type': 'default', + + 'shivDocument': shivDocument, + + createElement: createElement, + + createDocumentFragment: createDocumentFragment + }; + window.html5 = html5; + + shivDocument(document); + + }(this, document)); + + Modernizr._version = version; + + Modernizr._prefixes = prefixes; + Modernizr._domPrefixes = domPrefixes; + Modernizr._cssomPrefixes = cssomPrefixes; + + + Modernizr.hasEvent = isEventSupported; + + Modernizr.testProp = function (prop) { + return testProps([prop]); + }; + + Modernizr.testAllProps = testPropsAll; + + + Modernizr.testStyles = injectElementWithStyles; + Modernizr.prefixed = function (prop, obj, elem) { + if (!obj) { + return testPropsAll(prop, 'pfx'); + } else { + return testPropsAll(prop, obj, elem); + } + }; + + + docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') + + + (enableClasses ? ' js ' + classes.join(' ') : ''); + + return Modernizr; + +})(this, this.document); +/*yepnope1.5.4|WTFPL*/ +(function (a, b, c) { + function d(a) { + return"[object Function]" == o.call(a) + } + + function e(a) { + return"string" == typeof a + } + + function f() { + } + + function g(a) { + return!a || "loaded" == a || "complete" == a || "uninitialized" == a + } + + function h() { + var a = p.shift(); + q = 1, a ? a.t ? m(function () { + ("c" == a.t ? B.injectCss : B.injectJs)(a.s, 0, a.a, a.x, a.e, 1) + }, 0) : (a(), h()) : q = 0 + } + + function i(a, c, d, e, f, i, j) { + function k(b) { + if (!o && g(l.readyState) && (u.r = o = 1, !q && h(), l.onload = l.onreadystatechange = null, b)) { + "img" != a && m(function () { + t.removeChild(l) + }, 50); + for (var d in y[c])y[c].hasOwnProperty(d) && y[c][d].onload() + } + } + + var j = j || B.errorTimeout, l = b.createElement(a), o = 0, r = 0, u = {t: d, s: c, e: f, a: i, x: j}; + 1 === y[c] && (r = 1, y[c] = []), "object" == a ? l.data = c : (l.src = c, l.type = a), l.width = l.height = "0", l.onerror = l.onload = l.onreadystatechange = function () { + k.call(this, r) + }, p.splice(e, 0, u), "img" != a && (r || 2 === y[c] ? (t.insertBefore(l, s ? null : n), m(k, j)) : y[c].push(l)) + } + + function j(a, b, c, d, f) { + return q = 0, b = b || "j", e(a) ? i("c" == b ? v : u, a, b, this.i++, c, d, f) : (p.splice(this.i++, 0, a), 1 == p.length && h()), this + } + + function k() { + var a = B; + return a.loader = {load: j, i: 0}, a + } + + var l = b.documentElement, m = a.setTimeout, n = b.getElementsByTagName("script")[0], o = {}.toString, p = [], q = 0, r = "MozAppearance"in l.style, s = r && !!b.createRange().compareNode, t = s ? l : n.parentNode, l = a.opera && "[object Opera]" == o.call(a.opera), l = !!b.attachEvent && !l, u = r ? "object" : l ? "script" : "img", v = l ? "script" : u, w = Array.isArray || function (a) { + return"[object Array]" == o.call(a) + }, x = [], y = {}, z = {timeout: function (a, b) { + return b.length && (a.timeout = b[0]), a + }}, A, B; + B = function (a) { + function b(a) { + var a = a.split("!"), b = x.length, c = a.pop(), d = a.length, c = {url: c, origUrl: c, prefixes: a}, e, f, g; + for (f = 0; f < d; f++)g = a[f].split("="), (e = z[g.shift()]) && (c = e(c, g)); + for (f = 0; f < b; f++)c = x[f](c); + return c + } + + function g(a, e, f, g, h) { + var i = b(a), j = i.autoCallback; + i.url.split(".").pop().split("?").shift(), i.bypass || (e && (e = d(e) ? e : e[a] || e[g] || e[a.split("/").pop().split("?")[0]]), i.instead ? i.instead(a, e, f, g, h) : (y[i.url] ? i.noexec = !0 : y[i.url] = 1, f.load(i.url, i.forceCSS || !i.forceJS && "css" == i.url.split(".").pop().split("?").shift() ? "c" : c, i.noexec, i.attrs, i.timeout), (d(e) || d(j)) && f.load(function () { + k(), e && e(i.origUrl, h, g), j && j(i.origUrl, h, g), y[i.url] = 2 + }))) + } + + function h(a, b) { + function c(a, c) { + if (a) { + if (e(a))c || (j = function () { + var a = [].slice.call(arguments); + k.apply(this, a), l() + }), g(a, j, b, 0, h); else if (Object(a) === a)for (n in m = function () { + var b = 0, c; + for (c in a)a.hasOwnProperty(c) && b++; + return b + }(), a)a.hasOwnProperty(n) && (!c && !--m && (d(j) ? j = function () { + var a = [].slice.call(arguments); + k.apply(this, a), l() + } : j[n] = function (a) { + return function () { + var b = [].slice.call(arguments); + a && a.apply(this, b), l() + } + }(k[n])), g(a[n], j, b, n, h)) + } else!c && l() + } + + var h = !!a.test, i = a.load || a.both, j = a.callback || f, k = j, l = a.complete || f, m, n; + c(h ? a.yep : a.nope, !!i), i && c(i) + } + + var i, j, l = this.yepnope.loader; + if (e(a))g(a, 0, l, 0); else if (w(a))for (i = 0; i < a.length; i++)j = a[i], e(j) ? g(j, 0, l, 0) : w(j) ? B(j) : Object(j) === j && h(j, l); else Object(a) === a && h(a, l) + }, B.addPrefix = function (a, b) { + z[a] = b + }, B.addFilter = function (a) { + x.push(a) + }, B.errorTimeout = 1e4, null == b.readyState && b.addEventListener && (b.readyState = "loading", b.addEventListener("DOMContentLoaded", A = function () { + b.removeEventListener("DOMContentLoaded", A, 0), b.readyState = "complete" + }, 0)), a.yepnope = k(), a.yepnope.executeStack = h, a.yepnope.injectJs = function (a, c, d, e, i, j) { + var k = b.createElement("script"), l, o, e = e || B.errorTimeout; + k.src = a; + for (o in d)k.setAttribute(o, d[o]); + c = j ? h : c || f, k.onreadystatechange = k.onload = function () { + !l && g(k.readyState) && (l = 1, c(), k.onload = k.onreadystatechange = null) + }, m(function () { + l || (l = 1, c(1)) + }, e), i ? k.onload() : n.parentNode.insertBefore(k, n) + }, a.yepnope.injectCss = function (a, c, d, e, g, i) { + var e = b.createElement("link"), j, c = i ? h : c || f; + e.href = a, e.rel = "stylesheet", e.type = "text/css"; + for (j in d)e.setAttribute(j, d[j]); + g || (n.parentNode.insertBefore(e, n), m(c, 0)) + } +})(this, document); +Modernizr.load = function () { + yepnope.apply(window, [].slice.call(arguments, 0)); +}; +; \ No newline at end of file diff --git a/static/js/libs/point.js b/static/js/libs/point.js new file mode 100644 index 0000000..e329949 --- /dev/null +++ b/static/js/libs/point.js @@ -0,0 +1,137 @@ +/** + * Adobe Docs: http://bit.ly/b2RieL + * + * // TODO: Reconstruct Point so we can inherit from it. Use .addProperties + * for getters and setters + * + * @constructor + * @param {number} x The x coordinate. + * @param {number} y The y coordinate. + */ +Point = Point = function (x, y) { + + this.x = x || 0; + this.y = y || 0; + +}; + +/** + * @this Point + * @return The length from {0,0}. + */ +Point.prototype.getLength = function () { + return Math.sqrt((this.x * this.x) + (this.y * this.y)); +}; + +Point.prototype.add = function (v) { + + return new Point(this.x + v.x, this.y + v.y); + +}; + +Point.prototype.clone = function () { + + return new Point(this.x, this.y); + +}; + +Point.prototype.distance = function (pt1, pt2) { + + var a = Math.abs(pt2.x - pt1.x), + b = Math.abs(pt2.y - pt1.y); + + return Math.sqrt((a * a) + b * b); + +}; + +Point.prototype.equals = function (toCompare) { + + return (this.x === toCompare.x) && (this.y === toCompare.y); + +}; + +/** + * interpolate(pt1:Point, pt2:Point, f:Number):Point + * [static] Determines a point between two specified points. + * + * @param {Point} pt1 Point to compare. + * @param {Point} pt2 Point to compare. + * @param {number} f position between points, from 0 to 1. + * + * @return {Point} A new point. + */ +Point.prototype.interpolate = function (pt1, pt2, f) { + + // http://en.wikipedia.org/wiki/Linear_interpolation + + var a = pt1.x + ((pt2.x - pt1.x) * f), + b = pt1.y + (a - pt1.x) * ((pt2.y - pt1.y) / (pt2.x - pt1.x)); + + return new Point(a, b); + +}; + +/** + * normalize(thickness:Number):void + * Scales line segment, between (0,0) and current point, to a set length. + */ +Point.prototype.normalize = function (thickness) { + + var n = (this.getLength() - thickness) / this.getLength(); + + //console.log('Thickness = ', thickness, ', length: ', this.getLength(), ', n: ', n); + + return new Point(this.x - (this.x * n), this.y - (this.y * n)); + +}; + +Point.prototype.offset = function (dx, dy) { + + this.x = this.x + dx; + this.y = this.y + dy; + +}; + +/** + * Wikipedia article on converting between polar and cartesian: + * http://bit.ly/cuZNzu + * + * polar(len:Number, angle:Number):Point + * [static] Converts a pair of polar coordinates to a + * Cartesian point coordinate. + * + * @param {number} len — The length coordinate of the polar pair. + * @param {number} angle — The angle, in radians, of the polar pair. + * + * @return {Point} a new point. + */ +Point.prototype.polar = function (len, angle) { + + // Convert cartesian to polar + /* + var a = this.length, + theta = Math.atan2(y, x); + + return new Point(a, theta); + */ + + var x = len * Math.cos(angle), + y = len * Math.sin(angle); + + return new Point(x, y); + +}; + +Point.prototype.subtract = function (v) { + + return new Point(this.x - v.x, this.y - v.y); + +}; + +Point.prototype.toString = function () { + + return '{x:' + this.x + + ', y:' + this.y + + ', length:' + this.getLength() + '}'; + +}; \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 507d9ca..f319296 100644 --- a/templates/base.html +++ b/templates/base.html @@ -11,8 +11,8 @@ - - + + @@ -25,6 +25,7 @@ {% endblock %} +{% include 'inc/facebook.html' %} {% include 'inc/analytics.html' %} {% include 'inc/ancient_browser.html' %} @@ -52,24 +53,32 @@ {% endif %} - + + + + + + + + + + +{% endcompress %} +{% comment %} + - - - - @@ -77,12 +86,7 @@ - - - - - @@ -94,7 +98,10 @@ + + + @@ -102,7 +109,7 @@ -{% endcompress %} +{% endcomment %} {% block footerscripts %} {% endblock %} diff --git a/templates/javascript/settings.js b/templates/javascript/settings.js index dc35151..053b94a 100644 --- a/templates/javascript/settings.js +++ b/templates/javascript/settings.js @@ -12,6 +12,7 @@ com.podnoms.settings = { smDebugMode: '{{ SM_DEBUG_MODE }}', isDebug: '{{ IS_DEBUG }}', drawTimelineOnMix: false, + staticUrl: '{{ STATIC_URL }}', currentUser: {{ CURRENT_USER_ID }}, /** simple helper to take an api JSON object and initialise a player item */ setupPlayer: function (data, id) { @@ -21,7 +22,6 @@ com.podnoms.settings = { waveFormEl: $('#waveform-' + id), playHeadEl: $('#playhead-player-' + id), loadingEl: $('#progress-player-' + id), - timeLineEl: $('#player-timeline-' + id), seekHeadEl: $('#player-seekhead'), playButtonEl: $('#play-pause-button-small-' + id), url: data.stream_url diff --git a/templates/views/ActivityListItemView.html b/templates/views/ActivityListItemView.html index 48095d1..0fbec61 100644 --- a/templates/views/ActivityListItemView.html +++ b/templates/views/ActivityListItemView.html @@ -1,16 +1,15 @@ {% load account_tags %}
- + -
- - <%= item.user_name %> + + <%= user_name %> - <%= item.verb %> <%= item.item_name %> -
<%= item.human_date %>
+ <%= verb %> <%= item_name %> +
<%= human_date %>
diff --git a/templates/views/ActivityListView.html b/templates/views/ActivityListView.html index 1891a71..a9762cf 100644 --- a/templates/views/ActivityListView.html +++ b/templates/views/ActivityListView.html @@ -1 +1,3 @@ -
+
+
    +
    diff --git a/templates/views/CommentItemView.html b/templates/views/CommentItemView.html new file mode 100644 index 0000000..b7be4b5 --- /dev/null +++ b/templates/views/CommentItemView.html @@ -0,0 +1,17 @@ +{% load account_tags %} + +
    + + + + +
    + + <%= user_name %> + +
    +

    <%= comment %>

    + <%= date_created %> +
    +
    +
    diff --git a/templates/views/CommentListItemView.html b/templates/views/CommentListItemView.html deleted file mode 100644 index bc61d8e..0000000 --- a/templates/views/CommentListItemView.html +++ /dev/null @@ -1,17 +0,0 @@ -{% load account_tags %} - -
    - - - - -
    - - <%= item.user_name %> - -
    -

    <%= item.comment %>

    - <%= item.date_created %> -
    -
    -
    diff --git a/templates/views/CommentListView.html b/templates/views/CommentListView.html index 26781dd..5b40f0b 100644 --- a/templates/views/CommentListView.html +++ b/templates/views/CommentListView.html @@ -1,12 +1,8 @@ -
    - {% if request.user.is_authenticated %} -
    +{% if request.user.is_authenticated %} +
    - {% else %} -

    Please login to add comments

    - {% endif %} -
    +{% endif %}

    Comments

    diff --git a/templates/views/HeaderView.html b/templates/views/HeaderView.html index cc1c5a1..08d78af 100644 --- a/templates/views/HeaderView.html +++ b/templates/views/HeaderView.html @@ -4,14 +4,16 @@ diff --git a/templates/views/MixDetailView.html b/templates/views/MixDetailView.html new file mode 100644 index 0000000..6673e26 --- /dev/null +++ b/templates/views/MixDetailView.html @@ -0,0 +1,18 @@ +
    +
      +
      + +
      + + +
      +
      +
      <%= description %>
      +
      +
      +
      +
      +
      \ No newline at end of file diff --git a/templates/views/MixCreateView.html b/templates/views/MixEditView.html similarity index 90% rename from templates/views/MixCreateView.html rename to templates/views/MixEditView.html index cffede3..09b255e 100644 --- a/templates/views/MixCreateView.html +++ b/templates/views/MixEditView.html @@ -1,4 +1,3 @@ -{% verbatim %}
      @@ -8,9 +7,7 @@
      -{% endverbatim %} {% csrf_token %} -{% verbatim %} Mix details @@ -19,7 +16,7 @@
      -
      @@ -29,14 +26,14 @@
      - +
      - +
      @@ -54,16 +51,12 @@ Remove
      -{% endverbatim %} {% if user.is_staff %} -{% verbatim %}
      + >Is featured?
      -{% endverbatim %} {% endif %} -{% verbatim %}
      @@ -82,4 +75,3 @@
      -{% endverbatim %} \ No newline at end of file diff --git a/templates/views/MixListView.html b/templates/views/MixListView.html index f3ca45c..dd0569e 100644 --- a/templates/views/MixListView.html +++ b/templates/views/MixListView.html @@ -1,12 +1,12 @@ -
      + +
        diff --git a/templates/views/MixView.html b/templates/views/MixView.html deleted file mode 100644 index 90feeea..0000000 --- a/templates/views/MixView.html +++ /dev/null @@ -1,19 +0,0 @@ -
        -
          -
          - - - -
          -
          -
          -
          
          -        
          -
          -
          -
          -
          -
          diff --git a/templates/views/SidebarHeaderView.html b/templates/views/SidebarHeaderView.html new file mode 100644 index 0000000..d67a0d2 --- /dev/null +++ b/templates/views/SidebarHeaderView.html @@ -0,0 +1 @@ +<%=label%> \ No newline at end of file diff --git a/templates/views/SidebarView.html b/templates/views/SidebarView.html index e64303f..b3a3e07 100644 --- a/templates/views/SidebarView.html +++ b/templates/views/SidebarView.html @@ -1,17 +1,3 @@ - -
          -
          - -
          -
          - {% include 'inc/side-player.html' %} - {% include 'inc/twitter.html' %} -
          -
          - {% include 'inc/chat.html' %} -
          -
          + + + diff --git a/templates/views/_MixItemInsert.html b/templates/views/_MixItemInsert.html index ab404f3..6e60279 100644 --- a/templates/views/_MixItemInsert.html +++ b/templates/views/_MixItemInsert.html @@ -2,23 +2,23 @@
          -
          +
          @@ -31,55 +31,50 @@
          -
          - - + + Audio waveform -
          -
          + src="<%= waveform_url %>"> +
          +
          -
          -
          -
            -
            -