diff --git a/dss/settings.py b/dss/settings.py index fbc97f6..39bccd8 100755 --- a/dss/settings.py +++ b/dss/settings.py @@ -49,13 +49,6 @@ s = True SITE_ROOT = here('') -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', - 'LOCATION': '127.0.0.1:11211', - } -} - ADMIN_MEDIA_PREFIX = STATIC_URL + "grappelli/" TINYMCE_JS_URL = os.path.join(STATIC_ROOT, "js/libs/tiny_mce/tiny_mce.js") @@ -98,12 +91,6 @@ STATICFILES_DIRS = ( here('static'), ) -TEMPLATE_LOADERS = ( - ('django.template.loaders.cached.Loader', ( - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - )), -) TEMPLATE_CONTEXT_PROCESSORS = global_settings.TEMPLATE_CONTEXT_PROCESSORS + ( 'django_facebook.context_processors.facebook', 'django.core.context_processors.request', diff --git a/dss/urls.py b/dss/urls.py index e41f0c2..d8e2fec 100755 --- a/dss/urls.py +++ b/dss/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import patterns, include, url from django.contrib import admin -from django.views.generic import TemplateView +from django.views.generic import TemplateView, RedirectView from dss import settings @@ -10,19 +10,20 @@ admin.autodiscover() # from django.contrib import admin # admin.autodiscover() -urlpatterns = patterns('', - url(r'^admin/', include(admin.site.urls)), - #(r'^favicon\.ico$', 'django.views.generic.simple.redirect_to', {'url': '/static/img/favicon.ico'}), - (r'^channel\.html$', TemplateView.as_view(template_name='boiler/fb_channel.html')), - (r'^privacy\.html$', TemplateView.as_view(template_name='boiler/privacy.html')), - (r'^robots\.txt', TemplateView.as_view(template_name='boiler/robots.txt')), - (r'^tos\.html$', TemplateView.as_view(template_name='boiler/tos.html')), - (r'^test\.html$', TemplateView.as_view(template_name='boiler/test.html')), - (r'^500', 'django.views.defaults.server_error'), - (r'^grappelli/', include('grappelli.urls')), - url(r'^accounts/', include('allauth.urls')), - (r'^avatar/', include('avatar.urls')), - url(r'^', include('spa.urls')), +urlpatterns = patterns( + '', + url(r'^favicon\.ico$', RedirectView.as_view(url='/static/img/favicon.ico')), + url(r'^admin/', include(admin.site.urls)), + (r'^channel\.html$', TemplateView.as_view(template_name='boiler/fb_channel.html')), + (r'^privacy\.html$', TemplateView.as_view(template_name='boiler/privacy.html')), + (r'^robots\.txt', TemplateView.as_view(template_name='boiler/robots.txt')), + (r'^tos\.html$', TemplateView.as_view(template_name='boiler/tos.html')), + (r'^test\.html$', TemplateView.as_view(template_name='boiler/test.html')), + (r'^500', 'django.views.defaults.server_error'), + (r'^grappelli/', include('grappelli.urls')), + url(r'^accounts/', include('allauth.urls')), + (r'^avatar/', include('avatar.urls')), + url(r'^', include('spa.urls')), ) handler500 = 'spa.views.debug_500' diff --git a/requirements.txt b/requirements.txt index 480d136..1e379fb 100755 --- a/requirements.txt +++ b/requirements.txt @@ -50,3 +50,4 @@ pyyaml ua-parser user-agents django-user-agents +nginx_signing diff --git a/spa/api/v1/MixResource.py b/spa/api/v1/MixResource.py index 5d425e4..a527fe4 100755 --- a/spa/api/v1/MixResource.py +++ b/spa/api/v1/MixResource.py @@ -16,6 +16,7 @@ from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource from spa.api.v1.CommentResource import CommentResource from spa.api.v1.ActivityResource import ActivityResource from spa.models.mix import Mix +from spa.models.show import Show class MixResource(BackboneCompatibleResource): @@ -158,6 +159,9 @@ class MixResource(BackboneCompatibleResource): ) semi_filtered = semi_filtered.filter( user__in=request.user.get_profile().following.all()) + if request.GET.get('for_show'): + semi_filtered = semi_filtered.filter(show__isnull=True) + if f_user is not None: semi_filtered = semi_filtered.filter(user__slug=f_user) diff --git a/spa/api/v1/ShowResource.py b/spa/api/v1/ShowResource.py index 6a85e05..51f827f 100644 --- a/spa/api/v1/ShowResource.py +++ b/spa/api/v1/ShowResource.py @@ -1,3 +1,4 @@ +from tastypie import fields from tastypie.authorization import Authorization from tastypie.exceptions import ImmediateHttpResponse from tastypie.http import HttpBadRequest @@ -11,10 +12,14 @@ DATE_FORMAT = '%d/%m/%Y %H:%M:%S' class ShowResource(BackboneCompatibleResource): + mix = fields.ToOneField('spa.api.v1.MixResource.MixResource', + 'mix', null=False, full=False) + class Meta: queryset = Show.objects.all() authorization = Authorization() - resource_name = 'schedules' + resource_name = 'show' + always_return_data = True def obj_create(self, bundle, **kwargs): try: @@ -23,4 +28,8 @@ class ShowResource(BackboneCompatibleResource): raise ImmediateHttpResponse( HttpBadRequest("This event overlaps with an existing event") ) + except Exception, ex: + raise ImmediateHttpResponse( + HttpBadRequest(ex.message) + ) diff --git a/spa/migrations/0050_auto__add_field_show_mix.py b/spa/migrations/0050_auto__add_field_show_mix.py new file mode 100644 index 0000000..73e8375 --- /dev/null +++ b/spa/migrations/0050_auto__add_field_show_mix.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as 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 'Show.mix' + db.add_column(u'spa_show', 'mix', + self.gf('django.db.models.fields.related.ForeignKey')(default=3, related_name='show', to=orm['spa.Mix']), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Show.mix' + db.delete_column(u'spa_show', 'mix_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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + 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', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + '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'}) + }, + 'schedule.calendar': { + 'Meta': {'object_name': 'Calendar'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '200'}) + }, + 'schedule.event': { + 'Meta': {'object_name': 'Event'}, + 'calendar': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Calendar']", 'null': 'True', 'blank': 'True'}), + 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'creator'", 'null': 'True', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'end': ('django.db.models.fields.DateTimeField', [], {}), + 'end_recurring_period': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'rule': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['schedule.Rule']", 'null': 'True', 'blank': 'True'}), + 'start': ('django.db.models.fields.DateTimeField', [], {}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'updated_on': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}) + }, + 'schedule.rule': { + 'Meta': {'object_name': 'Rule'}, + 'description': ('django.db.models.fields.TextField', [], {}), + 'frequency': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '32'}), + 'params': ('django.db.models.fields.TextField', [], {'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.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'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['spa.UserProfile']", 'null': 'True', 'blank': 'True'}) + }, + 'spa.activitycomment': { + 'Meta': {'object_name': 'ActivityComment', '_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': "'activity_comments'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activitydownload': { + 'Meta': {'object_name': 'ActivityDownload', '_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': "'activity_downloads'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityfavourite': { + 'Meta': {'object_name': 'ActivityFavourite', '_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': "'activity_favourites'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityfollow': { + 'Meta': {'object_name': 'ActivityFollow', '_ormbases': ['spa.Activity']}, + u'activity_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['spa.Activity']", 'unique': 'True', 'primary_key': 'True'}), + 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_follow'", 'to': "orm['spa.UserProfile']"}) + }, + 'spa.activitylike': { + 'Meta': {'object_name': 'ActivityLike', '_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': "'activity_likes'", 'to': "orm['spa.Mix']"}) + }, + 'spa.activityplay': { + 'Meta': {'object_name': 'ActivityPlay', '_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': "'activity_plays'", 'to': "orm['spa.Mix']"}) + }, + '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', [], {'default': '0'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': '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'}), + 'duration': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}), + 'favourites': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'favourites'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + 'filetype': ('django.db.models.fields.CharField', [], {'default': "'mp3'", 'max_length': '10'}), + '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'}), + 'likes': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'likes'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + 'mix_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '1024', 'blank': 'True'}), + 'mp3tags_updated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + '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(2014, 5, 9, 0, 0)'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'mixes'", 'to': "orm['spa.UserProfile']"}), + 'waveform_generated': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'spa.notification': { + 'Meta': {'object_name': 'Notification'}, + 'accepted_date': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'from_user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'notifications'", 'null': 'True', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'notification_html': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'notification_text': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), + 'notification_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True'}), + 'target': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}), + 'to_user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'to_notications'", 'to': "orm['spa.UserProfile']"}), + 'verb': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}) + }, + '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(2014, 5, 9, 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'}), + 'release': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'release_audio'", 'null': 'True', 'to': "orm['spa.Release']"}) + }, + 'spa.show': { + 'Meta': {'object_name': 'Show', '_ormbases': ['schedule.Event']}, + u'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['schedule.Event']", 'unique': 'True', 'primary_key': 'True'}), + 'mix': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'show'", 'to': "orm['spa.Mix']"}) + }, + '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': '1024', 'blank': 'True'}), + 'avatar_type': ('django.db.models.fields.CharField', [], {'default': "'social'", 'max_length': '15'}), + 'city': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'country': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'blank': 'True'}), + 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '35', 'blank': 'True'}), + 'following': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'followers'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['spa.UserProfile']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_known_session': ('django.db.models.fields.CharField', [], {'max_length': '250', 'null': 'True', 'blank': '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'] diff --git a/spa/models/show.py b/spa/models/show.py index 1650cec..9bba8a6 100644 --- a/spa/models/show.py +++ b/spa/models/show.py @@ -1,10 +1,15 @@ -from django.db.models import Q +from django.db.models import Q, ForeignKey from schedule.models import Event +from spa.models import Mix + class ShowOverlapException(Exception): pass + class Show(Event): + mix = ForeignKey(Mix, related_name='show') + class Meta: app_label = 'spa' @@ -13,7 +18,6 @@ class Show(Event): """ throw an exception if event overlaps with another event """ - import ipdb; ipdb.set_trace() overlaps = Show.objects.filter( Q(start__gte=self.start, end__lte=self.start) | Q(start__gte=self.end, end__lte=self.end) diff --git a/spa/urls.py b/spa/urls.py index 172c675..74a87b5 100755 --- a/spa/urls.py +++ b/spa/urls.py @@ -7,7 +7,6 @@ from spa.api.v1.NotificationResource import NotificationResource from spa.audio import AudioHandler from spa.api.v1.ChatResource import ChatResource from spa.api.v1.CommentResource import CommentResource -#from spa.api.v1.EventResource import EventResource from spa.api.v1.MixResource import MixResource from spa.api.v1.ReleaseAudioResource import ReleaseAudioResource from spa.api.v1.ReleaseResource import ReleaseResource @@ -21,7 +20,6 @@ api.register(CommentResource()) api.register(MixResource()) api.register(ReleaseResource()) api.register(ReleaseAudioResource()) -#api.register(EventResource()) api.register(UserResource()) api.register(ActivityResource()) api.register(NotificationResource()) @@ -34,7 +32,7 @@ audio = AudioHandler() urlpatterns = patterns( '', url(r'^$', 'spa.views.app', name='home'), - url(r'^tpl/(?P\w+)/$', 'spa.templates.get_template'), + url(r'^tpl/(?P\w+)', 'spa.templates.get_template'), url(r'^dlg/(?P\w+)/$', 'spa.templates.get_dialog'), url(r'^dlg/embed/(?P[\w\d_.-]+)/$', 'spa.templates.get_embed_codes_dialog'), url(r'^js/(?P\w+)/$', 'spa.templates.get_javascript'), diff --git a/static/js/app/appv2.coffee b/static/js/app/appv2.coffee index 6ad06be..e86203a 100755 --- a/static/js/app/appv2.coffee +++ b/static/js/app/appv2.coffee @@ -25,6 +25,7 @@ define ['backbone', 'marionette', 'vent', 'utils', 'underscore', App.addRegions headerRegion: "#header" + fullContentRegion: "#full-content" contentRegion: selector: "#content" footerRegion: "#footer" diff --git a/static/js/app/appv2.js b/static/js/app/appv2.js index a2fd0ef..74e1aea 100755 --- a/static/js/app/appv2.js +++ b/static/js/app/appv2.js @@ -18,6 +18,7 @@ }); App.addRegions({ headerRegion: "#header", + fullContentRegion: "#full-content", contentRegion: { selector: "#content" }, diff --git a/static/js/app/lib/controller.coffee b/static/js/app/lib/controller.coffee index a1cad1a..b416fd4 100755 --- a/static/js/app/lib/controller.coffee +++ b/static/js/app/lib/controller.coffee @@ -1,11 +1,11 @@ define ['app', 'marionette', 'vent', 'utils', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', - 'views/schedule/scheduleView', + 'views/show/scheduleShowLayout', 'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView', 'models/mix/mixCollection', 'models/mix/mixItem', 'models/user/userItem'], (App, Marionette, vent, utils, MixListLayout, MixListView, MixDetailView, - ScheduleView, + ScheduleShowLayout, MixEditView, UserProfileView, UserListView, UserEditView, MixCollection, MixItem, UserItem)-> class DssController extends Marionette.Controller @@ -22,8 +22,8 @@ define ['app', 'marionette', 'vent', 'utils', showSchedule: -> app = require('app') - app.contentRegion.show(new ScheduleView()) - vent.trigger('schedule:show') + app.contentRegion.show(new ScheduleShowLayout()) + vent.trigger('show:schedule:show') showMixList: (options, emptyTemplate) -> app = require('app') diff --git a/static/js/app/lib/controller.js b/static/js/app/lib/controller.js index 0207e52..a47ad6d 100755 --- a/static/js/app/lib/controller.js +++ b/static/js/app/lib/controller.js @@ -3,7 +3,7 @@ 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', 'vent', 'utils', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', 'views/schedule/scheduleView', 'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView', 'models/mix/mixCollection', 'models/mix/mixItem', 'models/user/userItem'], function(App, Marionette, vent, utils, MixListLayout, MixListView, MixDetailView, ScheduleView, MixEditView, UserProfileView, UserListView, UserEditView, MixCollection, MixItem, UserItem) { + define(['app', 'marionette', 'vent', 'utils', 'views/mix/mixListLayout', 'views/mix/mixListView', 'views/mix/mixDetailView', 'views/show/scheduleShowLayout', 'views/mix/mixEditView', 'views/user/userProfileView', 'views/user/userListView', 'views/user/userEditView', 'models/mix/mixCollection', 'models/mix/mixItem', 'models/user/userItem'], function(App, Marionette, vent, utils, MixListLayout, MixListView, MixDetailView, ScheduleShowLayout, MixEditView, UserProfileView, UserListView, UserEditView, MixCollection, MixItem, UserItem) { var DssController; DssController = (function(_super) { @@ -29,8 +29,8 @@ DssController.prototype.showSchedule = function() { var app; app = require('app'); - app.contentRegion.show(new ScheduleView()); - return vent.trigger('schedule:show'); + app.contentRegion.show(new ScheduleShowLayout()); + return vent.trigger('show:schedule:show'); }; DssController.prototype.showMixList = function(options, emptyTemplate) { diff --git a/static/js/app/models/show/showCollection.coffee b/static/js/app/models/show/showCollection.coffee new file mode 100644 index 0000000..3946352 --- /dev/null +++ b/static/js/app/models/show/showCollection.coffee @@ -0,0 +1,15 @@ +define ['backbone', 'models/show/showItem', 'app.lib/backbone.dss.model.collection'], +(Backbone, ShowItem, DssCollection) -> + class ScheduleCollection extends DssCollection + model: ShowItem + page: 0 + limit: 20 + url: -> + com.podnoms.settings.urlRoot + "show/?limit=" + @limit + "&offset=" + Math.max(@page-1, 0) * @limit + + initialize: -> + if not ShowItem + @model = require('models/show/showItem') + + ScheduleCollection + diff --git a/static/js/app/models/show/showCollection.js b/static/js/app/models/show/showCollection.js new file mode 100644 index 0000000..680d053 --- /dev/null +++ b/static/js/app/models/show/showCollection.js @@ -0,0 +1,38 @@ +// Generated by CoffeeScript 1.4.0 +(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/show/showItem', 'app.lib/backbone.dss.model.collection'], function(Backbone, ShowItem, DssCollection) { + var ScheduleCollection; + ScheduleCollection = (function(_super) { + + __extends(ScheduleCollection, _super); + + function ScheduleCollection() { + return ScheduleCollection.__super__.constructor.apply(this, arguments); + } + + ScheduleCollection.prototype.model = ShowItem; + + ScheduleCollection.prototype.page = 0; + + ScheduleCollection.prototype.limit = 20; + + ScheduleCollection.prototype.url = function() { + return com.podnoms.settings.urlRoot + "show/?limit=" + this.limit + "&offset=" + Math.max(this.page - 1, 0) * this.limit; + }; + + ScheduleCollection.prototype.initialize = function() { + if (!ShowItem) { + return this.model = require('models/show/showItem'); + } + }; + + return ScheduleCollection; + + })(DssCollection); + return ScheduleCollection; + }); + +}).call(this); diff --git a/static/js/app/models/show/showItem.coffee b/static/js/app/models/show/showItem.coffee new file mode 100644 index 0000000..166bd54 --- /dev/null +++ b/static/js/app/models/show/showItem.coffee @@ -0,0 +1,5 @@ +define ['app.lib/backbone.dss.model'], +(DssModel) -> + class ShowItem extends DssModel + urlRoot: com.podnoms.settings.urlRoot + "show/" + ShowItem \ No newline at end of file diff --git a/static/js/app/models/show/showItem.js b/static/js/app/models/show/showItem.js new file mode 100644 index 0000000..2f790d7 --- /dev/null +++ b/static/js/app/models/show/showItem.js @@ -0,0 +1,24 @@ +// Generated by CoffeeScript 1.4.0 +(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 ShowItem; + ShowItem = (function(_super) { + + __extends(ShowItem, _super); + + function ShowItem() { + return ShowItem.__super__.constructor.apply(this, arguments); + } + + ShowItem.prototype.urlRoot = com.podnoms.settings.urlRoot + "show/"; + + return ShowItem; + + })(DssModel); + return ShowItem; + }); + +}).call(this); diff --git a/static/js/app/models/user/userCollection.coffee b/static/js/app/models/user/userCollection.coffee index c454744..97c7a16 100755 --- a/static/js/app/models/user/userCollection.coffee +++ b/static/js/app/models/user/userCollection.coffee @@ -7,7 +7,6 @@ define ['backbone', 'models/user/userItem', 'app.lib/backbone.dss.model.collecti url: -> com.podnoms.settings.urlRoot + "user/?limit=" + @limit + "&offset=" + Math.max(@page-1, 0) * @limit initialize: -> - console.clear() if not UserItem @model = require('models/user/userItem') diff --git a/static/js/app/models/user/userCollection.js b/static/js/app/models/user/userCollection.js index 625931f..c92f000 100755 --- a/static/js/app/models/user/userCollection.js +++ b/static/js/app/models/user/userCollection.js @@ -24,7 +24,6 @@ }; UserCollection.prototype.initialize = function() { - console.clear(); if (!UserItem) { return this.model = require('models/user/userItem'); } diff --git a/static/js/app/views/schedule/scheduleView.coffee b/static/js/app/views/schedule/scheduleView.coffee deleted file mode 100644 index 20b6574..0000000 --- a/static/js/app/views/schedule/scheduleView.coffee +++ /dev/null @@ -1,130 +0,0 @@ -define ['app', 'vent', 'marionette', 'fullcalendar', 'text!/tpl/ScheduleView'], -(App, vent, Marionette, fullcalendar, Template)-> - class ScheduleView extends Marionette.ItemView - template: _.template(Template) - - onShow: -> - - $("#external-events div.external-event").each -> - - # create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/) - # it doesn't need to have a start or end - eventObject = - title: $.trim($(this).text()) # use the element's text as the event title - - # store the Event Object in the DOM element so we can get to it later - $(this).data "eventObject", eventObject - - # make the event draggable using jQuery UI - $(this).draggable - zIndex: 999 - revert: true # will cause the event to go back to its - revertDuration: 0 # original position after the drag - - return - - date = new Date() - d = date.getDate() - m = date.getMonth() - y = date.getFullYear() - calendar = $("#calendar").fullCalendar( - #isRTL: true, - buttonText: - prev: "" - next: "" - - header: - left: "prev,next today" - center: "title" - right: "month,agendaWeek,agendaDay" - - events: [ - { - title: "All Day Event" - start: new Date(y, m, 1) - className: "label-important" - } - { - title: "Long Event" - start: new Date(y, m, d - 5) - end: new Date(y, m, d - 2) - className: "label-success" - } - { - title: "Some Event" - start: new Date(y, m, d - 3, 16, 0) - allDay: false - } - ] - editable: true - droppable: true # this allows things to be dropped onto the calendar !!! - drop: (date, allDay) -> # this function is called when something is dropped - - # retrieve the dropped element's stored Event Object - originalEventObject = $(this).data("eventObject") - $extraEventClass = $(this).attr("data-class") - - # we need to copy it, so that multiple events don't have a reference to the same object - copiedEventObject = $.extend({}, originalEventObject) - - # assign it the date that was reported - copiedEventObject.start = date - copiedEventObject.allDay = allDay - copiedEventObject["className"] = [$extraEventClass] if $extraEventClass - - # render the event on the calendar - # the last `true` argument determines if the event "sticks" (http://arshaw.com/fullcalendar/docs/event_rendering/renderEvent/) - $("#calendar").fullCalendar "renderEvent", copiedEventObject, true - - # is the "remove after drop" checkbox checked? - - # if so, remove the element from the "Draggable Events" list - $(this).remove() if $("#drop-remove").is(":checked") - return - - selectable: true - selectHelper: true - select: (start, end, allDay) -> - bootbox.prompt "New Event Title:", (title) -> - if title isnt null - calendar.fullCalendar "renderEvent", - title: title - start: start - end: end - allDay: allDay - , true # make the event "stick" - return - - calendar.fullCalendar "unselect" - return - - eventClick: (calEvent, jsEvent, view) -> - - #display a modal - modal = "
\t\t\t
\t\t\t
\t\t\t\t
\t\t\t\t \t\t\t\t
\t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t
\t\t\t\t
\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t
\t\t\t
\t\t\t
" - modal = $(modal).appendTo("body") - modal.find("form").on "submit", (ev) -> - ev.preventDefault() - calEvent.title = $(this).find("input[type=text]").val() - calendar.fullCalendar "updateEvent", calEvent - modal.modal "hide" - return - - modal.find("button[data-action=delete]").on "click", -> - calendar.fullCalendar "removeEvents", (ev) -> - ev._id is calEvent._id - - modal.modal "hide" - return - - modal.modal("show").on "hidden", -> - modal.remove() - return - - return - ) - true - - ScheduleView - - diff --git a/static/js/app/views/schedule/scheduleView.js b/static/js/app/views/schedule/scheduleView.js deleted file mode 100644 index b18b899..0000000 --- a/static/js/app/views/schedule/scheduleView.js +++ /dev/null @@ -1,125 +0,0 @@ -// Generated by CoffeeScript 1.4.0 -(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', 'vent', 'marionette', 'fullcalendar', 'text!/tpl/ScheduleView'], function(App, vent, Marionette, fullcalendar, Template) { - var ScheduleView; - ScheduleView = (function(_super) { - - __extends(ScheduleView, _super); - - function ScheduleView() { - return ScheduleView.__super__.constructor.apply(this, arguments); - } - - ScheduleView.prototype.template = _.template(Template); - - ScheduleView.prototype.onShow = function() { - var calendar, d, date, m, y; - $("#external-events div.external-event").each(function() { - var eventObject; - eventObject = { - title: $.trim($(this).text()) - }; - $(this).data("eventObject", eventObject); - $(this).draggable({ - zIndex: 999, - revert: true, - revertDuration: 0 - }); - }); - date = new Date(); - d = date.getDate(); - m = date.getMonth(); - y = date.getFullYear(); - return calendar = $("#calendar").fullCalendar({ - buttonText: { - prev: "", - next: "" - }, - header: { - left: "prev,next today", - center: "title", - right: "month,agendaWeek,agendaDay" - }, - events: [ - { - title: "All Day Event", - start: new Date(y, m, 1), - className: "label-important" - }, { - title: "Long Event", - start: new Date(y, m, d - 5), - end: new Date(y, m, d - 2), - className: "label-success" - }, { - title: "Some Event", - start: new Date(y, m, d - 3, 16, 0), - allDay: false - } - ], - editable: true, - droppable: true, - drop: function(date, allDay) { - var $extraEventClass, copiedEventObject, originalEventObject; - originalEventObject = $(this).data("eventObject"); - $extraEventClass = $(this).attr("data-class"); - copiedEventObject = $.extend({}, originalEventObject); - copiedEventObject.start = date; - copiedEventObject.allDay = allDay; - if ($extraEventClass) { - copiedEventObject["className"] = [$extraEventClass]; - } - $("#calendar").fullCalendar("renderEvent", copiedEventObject, true); - if ($("#drop-remove").is(":checked")) { - $(this).remove(); - } - }, - selectable: true, - selectHelper: true, - select: function(start, end, allDay) { - bootbox.prompt("New Event Title:", function(title) { - if (title !== null) { - calendar.fullCalendar("renderEvent", { - title: title, - start: start, - end: end, - allDay: allDay - }, true); - } - }); - calendar.fullCalendar("unselect"); - }, - eventClick: function(calEvent, jsEvent, view) { - var modal; - modal = "
\t\t\t
\t\t\t
\t\t\t\t
\t\t\t\t \t\t\t\t
\t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t
\t\t\t\t
\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t
\t\t\t
\t\t\t
"; - modal = $(modal).appendTo("body"); - modal.find("form").on("submit", function(ev) { - ev.preventDefault(); - calEvent.title = $(this).find("input[type=text]").val(); - calendar.fullCalendar("updateEvent", calEvent); - modal.modal("hide"); - }); - modal.find("button[data-action=delete]").on("click", function() { - calendar.fullCalendar("removeEvents", function(ev) { - return ev._id === calEvent._id; - }); - modal.modal("hide"); - }); - modal.modal("show").on("hidden", function() { - modal.remove(); - }); - } - }); - }; - - true; - - return ScheduleView; - - })(Marionette.ItemView); - return ScheduleView; - }); - -}).call(this); diff --git a/static/js/app/views/show/scheduleShowLayout.coffee b/static/js/app/views/show/scheduleShowLayout.coffee new file mode 100644 index 0000000..c3fdc63 --- /dev/null +++ b/static/js/app/views/show/scheduleShowLayout.coffee @@ -0,0 +1,108 @@ +define ['app', 'vent', 'utils', 'marionette', 'fullcalendar', + 'views/show/scheduleShowMixListView', + 'models/show/showCollection', 'models/show/showItem', + 'models/mix/mixCollection', + 'text!/tpl/ShowScheduleLayout'], +(App, vent, utils, Marionette, fullcalendar, + ScheduleShowMixList, + ShowCollection, ShowItem, + MixCollection, + Template)-> + class ScheduleShowLayout extends Marionette.Layout + template: _.template(Template) + regions: + availableMixes: "#external-events" + + initialize: (options)-> + @collection = new ShowCollection() + @options = options + + @mixCollection = new MixCollection() + @mixCollection.fetch + data: {for_show: true, order_by: 'latest'} + success: (collection)=> + @availableMixes.show(new ScheduleShowMixList({collection: collection})) + return + + onShow: => + @calendar = $("#calendar").fullCalendar( + editable: true + droppable: true + selectable: true + selectHelper: true + defaultView: "agendaDay" + + buttonText: + prev: "" + next: "" + + header: + left: "prev,next today" + center: "title" + right: "month,agendaWeek,agendaDay" + + drop: (date, allDay, jsEvent, ui) => + s = new ShowItem( + mix: com.podnoms.settings.urlRoot + jsEvent.target.id + start: date + end: date + description: $(jsEvent.toElement).text().trim() + ) + s.save null, + success: (model, response) => + @collection.add(model) + @_renderEvent(model) + $(this).remove() # if $("#drop-remove").is(":checked") + error: (model, response) => + utils.showError(response.responseText) + return + + eventClick: (calEvent, jsEvent, view) -> + + #display a modal + modal = "
\t\t\t
\t\t\t
\t\t\t\t
\t\t\t\t \t\t\t\t
\t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t
\t\t\t\t
\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t
\t\t\t
\t\t\t
" + modal = $(modal).appendTo("body") + modal.find("form").on "submit", (ev) -> + ev.preventDefault() + calEvent.title = $(this).find("input[type=text]").val() + calendar.fullCalendar "updateEvent", calEvent + modal.modal "hide" + return + + modal.find("button[data-action=delete]").on "click", -> + calendar.fullCalendar "removeEvents", (ev) -> + ev._id is calEvent._id + + modal.modal "hide" + return + + modal.modal("show").on "hidden", -> + modal.remove() + return + + return + ) + @_fetchEvents() + + _fetchEvents: -> + @collection.fetch( + data: @options + success: => + console.log("ScheduleView: Collection fetched") + @collection.each (model) => + @_renderEvent(model) + return + ) + + _renderEvent: (model) -> + $("#calendar").fullCalendar("renderEvent", { + title: model.get("description").substring(0, 15), + start: model.get("start"), + end: model.get("end"), + allDay: false, + className: "label-important" + }) + true + ScheduleShowLayout + + diff --git a/static/js/app/views/show/scheduleShowLayout.js b/static/js/app/views/show/scheduleShowLayout.js new file mode 100644 index 0000000..b939739 --- /dev/null +++ b/static/js/app/views/show/scheduleShowLayout.js @@ -0,0 +1,133 @@ +// Generated by CoffeeScript 1.4.0 +(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', 'vent', 'utils', 'marionette', 'fullcalendar', 'views/show/scheduleShowMixListView', 'models/show/showCollection', 'models/show/showItem', 'models/mix/mixCollection', 'text!/tpl/ShowScheduleLayout'], function(App, vent, utils, Marionette, fullcalendar, ScheduleShowMixList, ShowCollection, ShowItem, MixCollection, Template) { + var ScheduleShowLayout; + ScheduleShowLayout = (function(_super) { + + __extends(ScheduleShowLayout, _super); + + function ScheduleShowLayout() { + this.onShow = __bind(this.onShow, this); + return ScheduleShowLayout.__super__.constructor.apply(this, arguments); + } + + ScheduleShowLayout.prototype.template = _.template(Template); + + ScheduleShowLayout.prototype.regions = { + availableMixes: "#external-events" + }; + + ScheduleShowLayout.prototype.initialize = function(options) { + var _this = this; + this.collection = new ShowCollection(); + this.options = options; + this.mixCollection = new MixCollection(); + this.mixCollection.fetch({ + data: { + for_show: true, + order_by: 'latest' + }, + success: function(collection) { + return _this.availableMixes.show(new ScheduleShowMixList({ + collection: collection + })); + } + }); + }; + + ScheduleShowLayout.prototype.onShow = function() { + var _this = this; + this.calendar = $("#calendar").fullCalendar({ + editable: true, + droppable: true, + selectable: true, + selectHelper: true, + defaultView: "agendaDay", + buttonText: { + prev: "", + next: "" + }, + header: { + left: "prev,next today", + center: "title", + right: "month,agendaWeek,agendaDay" + }, + drop: function(date, allDay, jsEvent, ui) { + var s; + s = new ShowItem({ + mix: com.podnoms.settings.urlRoot + jsEvent.target.id, + start: date, + end: date, + description: $(jsEvent.toElement).text().trim() + }); + s.save(null, { + success: function(model, response) { + _this.collection.add(model); + _this._renderEvent(model); + return $(_this).remove(); + }, + error: function(model, response) { + return utils.showError(response.responseText); + } + }); + }, + eventClick: function(calEvent, jsEvent, view) { + var modal; + modal = "
\t\t\t
\t\t\t
\t\t\t\t
\t\t\t\t \t\t\t\t
\t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t
\t\t\t\t
\t\t\t\t
\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\t\t\t
\t\t\t
\t\t\t
"; + modal = $(modal).appendTo("body"); + modal.find("form").on("submit", function(ev) { + ev.preventDefault(); + calEvent.title = $(this).find("input[type=text]").val(); + calendar.fullCalendar("updateEvent", calEvent); + modal.modal("hide"); + }); + modal.find("button[data-action=delete]").on("click", function() { + calendar.fullCalendar("removeEvents", function(ev) { + return ev._id === calEvent._id; + }); + modal.modal("hide"); + }); + modal.modal("show").on("hidden", function() { + modal.remove(); + }); + } + }); + return this._fetchEvents(); + }; + + ScheduleShowLayout.prototype._fetchEvents = function() { + var _this = this; + return this.collection.fetch({ + data: this.options, + success: function() { + console.log("ScheduleView: Collection fetched"); + _this.collection.each(function(model) { + return _this._renderEvent(model); + }); + } + }); + }; + + ScheduleShowLayout.prototype._renderEvent = function(model) { + return $("#calendar").fullCalendar("renderEvent", { + title: model.get("description").substring(0, 15), + start: model.get("start"), + end: model.get("end"), + allDay: false, + className: "label-important" + }); + }; + + true; + + return ScheduleShowLayout; + + })(Marionette.Layout); + return ScheduleShowLayout; + }); + +}).call(this); diff --git a/static/js/app/views/show/scheduleShowMixListView.coffee b/static/js/app/views/show/scheduleShowMixListView.coffee new file mode 100644 index 0000000..79cee3d --- /dev/null +++ b/static/js/app/views/show/scheduleShowMixListView.coffee @@ -0,0 +1,30 @@ +define ['app', 'vent', 'marionette', 'fullcalendar', + 'models/show/showCollection', + 'models/mix/mixCollection', + 'text!/tpl/ShowScheduleMixItem'], +(App, vent, Marionette, fullcalendar, + ScheduleCollection, MixCollection, + Template)-> + + class ScheduleShowMixItem extends Marionette.ItemView + template: _.template(Template) + + class ScheduleShowMixList extends Marionette.CollectionView + itemView: ScheduleShowMixItem + + initialize: (options)-> + console.log("ScheduleShowMixList: initialize") + true + + onShow: -> + $("#external-events div.external-event").each -> + $(this).draggable + zIndex: 999 + revert: true # will cause the event to go back to its + revertDuration: 0 # original position after the drag + + return + true + ScheduleShowMixList + + diff --git a/static/js/app/views/show/scheduleShowMixListView.js b/static/js/app/views/show/scheduleShowMixListView.js new file mode 100644 index 0000000..d24c05e --- /dev/null +++ b/static/js/app/views/show/scheduleShowMixListView.js @@ -0,0 +1,54 @@ +// Generated by CoffeeScript 1.4.0 +(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', 'vent', 'marionette', 'fullcalendar', 'models/show/showCollection', 'models/mix/mixCollection', 'text!/tpl/ShowScheduleMixItem'], function(App, vent, Marionette, fullcalendar, ScheduleCollection, MixCollection, Template) { + var ScheduleShowMixItem, ScheduleShowMixList; + ScheduleShowMixItem = (function(_super) { + + __extends(ScheduleShowMixItem, _super); + + function ScheduleShowMixItem() { + return ScheduleShowMixItem.__super__.constructor.apply(this, arguments); + } + + ScheduleShowMixItem.prototype.template = _.template(Template); + + return ScheduleShowMixItem; + + })(Marionette.ItemView); + ScheduleShowMixList = (function(_super) { + + __extends(ScheduleShowMixList, _super); + + function ScheduleShowMixList() { + return ScheduleShowMixList.__super__.constructor.apply(this, arguments); + } + + ScheduleShowMixList.prototype.itemView = ScheduleShowMixItem; + + ScheduleShowMixList.prototype.initialize = function(options) { + console.log("ScheduleShowMixList: initialize"); + return true; + }; + + ScheduleShowMixList.prototype.onShow = function() { + return $("#external-events div.external-event").each(function() { + $(this).draggable({ + zIndex: 999, + revert: true, + revertDuration: 0 + }); + }); + }; + + true; + + return ScheduleShowMixList; + + })(Marionette.CollectionView); + return ScheduleShowMixList; + }); + +}).call(this); diff --git a/templates/base.html b/templates/base.html index 37f6049..751f660 100755 --- a/templates/base.html +++ b/templates/base.html @@ -40,21 +40,23 @@ {% include 'inc/analytics.html' %}
-
-
-
{{ ua_html|safe }}
+
+
+
+
{{ ua_html|safe }}
+
+
+
+
+ {% block content %} + {% endblock %}
-
-
+
+ {% block sidecontent %} + {% endblock %} + +
- {% block content %} - {% endblock %} -
-
- {% block sidecontent %} - {% endblock %} - -
diff --git a/templates/views/ScheduleView.html b/templates/views/ScheduleView.html deleted file mode 100644 index c0653ed..0000000 --- a/templates/views/ScheduleView.html +++ /dev/null @@ -1,61 +0,0 @@ -
-
-
- -
-
- -
-
-
-

Draggable events

-
- -
-
-
-
- - My Event 1 -
- -
- - My Event 2 -
- -
- - My Event 3 -
- -
- - My Event 4 -
- -
- - My Event 5 -
- -
- - My Event 6 -
- -
- - My Event 7 -
- - -
-
-
-
-
-
\ No newline at end of file diff --git a/templates/views/ShowScheduleLayout.html b/templates/views/ShowScheduleLayout.html new file mode 100644 index 0000000..4ff1012 --- /dev/null +++ b/templates/views/ShowScheduleLayout.html @@ -0,0 +1,20 @@ +
+
+
+ +
+
+
+
+
+

Schedule shows

+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/templates/views/ShowScheduleMixItem.html b/templates/views/ShowScheduleMixItem.html new file mode 100644 index 0000000..e41f9ca --- /dev/null +++ b/templates/views/ShowScheduleMixItem.html @@ -0,0 +1,4 @@ +
+ + <%= title %> +
\ No newline at end of file