From 9ff641c11d4e2f215e6e6d5a0ca63ee2c0917dca Mon Sep 17 00:00:00 2001 From: Fergal Moran Date: Mon, 29 Apr 2013 11:25:19 +0100 Subject: [PATCH] Various changes to user profile editing --- .gitignore | 2 +- spa/ajax.py | 8 +- spa/api/v1/ActivityResource.py | 2 + spa/api/v1/CommentResource.py | 2 + spa/api/v1/UserResource.py | 121 +- spa/management/commands/deletefailed.py | 20 +- spa/management/commands/deleteorphanmp3.py | 28 +- spa/middleware/stripwhitespace.py | 78 +- .../0006_auto__chg_field_userprofile_user.py | 219 ++ spa/models/UserProfile.py | 10 +- spa/models/managers/__init__.py | 2 +- spa/templates.py | 4 + static/css/bootstrap-timepicker.css | 182 +- static/css/deepsouthsounds.css | 11 + static/js/app/app.js | 8 +- static/js/app/models/activity.js | 36 +- static/js/app/models/user.js | 11 +- static/js/app/views/mix.js | 2 +- static/js/app/views/user.js | 116 +- static/js/libs/ICanHaz.js | 1039 +++---- .../js/libs/backbone/backbone.marionette.js | 2388 +++++++++++++++++ static/js/libs/backbone/backbone.mine.js | 5 +- static/js/libs/backbone/backbone.syphon.js | 471 ++++ static/js/libs/backbone/underscore.js | 1239 ++++++++- templates/base.html | 3 +- templates/boiler/robots.txt | 8 +- templates/boiler/test.html | 42 +- templates/boiler/test2.html | 42 +- templates/inc/activity.html | 30 +- templates/javascript/settings.js | 1 + templates/views/UserView.html | 157 +- 31 files changed, 5344 insertions(+), 943 deletions(-) create mode 100755 spa/migrations/0006_auto__chg_field_userprofile_user.py create mode 100755 static/js/libs/backbone/backbone.marionette.js create mode 100755 static/js/libs/backbone/backbone.syphon.js diff --git a/.gitignore b/.gitignore index 2f152b7..6f838f1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ tags .tags_sorted_by_file .idea *.pyc +*.swp media/* build/* _working/* @@ -13,4 +14,3 @@ dss.conf dss/debugsettings.py mysql test.py - diff --git a/spa/ajax.py b/spa/ajax.py index d459dd7..653d5d9 100644 --- a/spa/ajax.py +++ b/spa/ajax.py @@ -209,7 +209,7 @@ def upload_release_image(request, release_id): release.save() return HttpResponse(_get_json("Success")) except Exception, ex: - logger.exception("Error uploading avatar") + logger.exception("Error uploading release image") return HttpResponse(_get_json("Failed")) @@ -223,17 +223,17 @@ def upload_image(request, mix_id): mix.save() return HttpResponse(_get_json("Success")) except Exception, ex: - logger.exception("Error uploading avatar") + logger.exception("Error uploading image") return HttpResponse(_get_json("Failed")) @csrf_exempt def upload_avatar_image(request): try: - if 'Filedata' in request.FILES: + if 'avatar_image' in request.FILES: profile = request.user.get_profile() if profile: - profile.avatar_image = request.FILES['Filedata'] + profile.avatar_image = request.FILES['avatar_image'] profile.save() return HttpResponse(_get_json("Success")) except Exception, ex: diff --git a/spa/api/v1/ActivityResource.py b/spa/api/v1/ActivityResource.py index d8f88c7..ca11c05 100644 --- a/spa/api/v1/ActivityResource.py +++ b/spa/api/v1/ActivityResource.py @@ -49,5 +49,7 @@ class ActivityResource(BackboneCompatibleResource): return [i for i in data['objects'] if i is not None and i.obj.user is not None and i.obj.get_object_name is not None and i.obj.get_object_url is not None] """ + """ def dehydrate_date(self, bundle): return self.humanize_date(bundle.obj.date) + """ \ No newline at end of file diff --git a/spa/api/v1/CommentResource.py b/spa/api/v1/CommentResource.py index 6be427d..1784db4 100644 --- a/spa/api/v1/CommentResource.py +++ b/spa/api/v1/CommentResource.py @@ -22,8 +22,10 @@ class CommentResource(BackboneCompatibleResource): bundle.data['user'] = {'pk': request.user.pk} return super(CommentResource, self).obj_create(bundle, request, user=request.user) + """ def dehydrate_date_created(self, bundle): return self.humanize_date(bundle.obj.date_created) + """ def dehydrate(self, bundle): bundle.data['avatar_image'] = bundle.obj.user.get_profile().get_small_profile_image() diff --git a/spa/api/v1/UserResource.py b/spa/api/v1/UserResource.py index a2096ce..5ac4313 100644 --- a/spa/api/v1/UserResource.py +++ b/spa/api/v1/UserResource.py @@ -1,71 +1,88 @@ -from django.conf.urls import url +from django.contrib.auth.models import User +from tastypie import fields from tastypie.authentication import Authentication -from tastypie.authorization import Authorization -from tastypie.constants import ALL, ALL_WITH_RELATIONS +from tastypie.authorization import DjangoAuthorization from spa.api.v1.BackboneCompatibleResource import BackboneCompatibleResource from spa.models import UserProfile -class UserResource(BackboneCompatibleResource): +class UserProfileResource(BackboneCompatibleResource): class Meta: queryset = UserProfile.objects.all() - excludes = [] - authorization = Authorization() - authentication = Authentication() + resource_name = 'profile' + include_resource_uri = False + include_absolute_url = False always_return_data = True - filtering = { - 'user': ALL_WITH_RELATIONS, - 'username': ALL, - 'id': ALL, - } + authorization = DjangoAuthorization() + authentication = Authentication() - 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"), - ] + def _hydrateBitmapOption(self, source, comparator): + return "checked" if (source & comparator) != 0 else "" - def authorized_read_list(self, object_list, bundle): - return object_list.filter(user_id=bundle.request.user.id) - def authorized_read_detail(self, object_list, bundle): - return object_list.only('description') + def hydrate(self, bundle): + if 'activity_sharing_likes' in bundle.data: + likes = UserProfile.ACTIVITY_SHARE_LIKES if bundle.data['activity_sharing_likes'] else 0 + favourites = UserProfile.ACTIVITY_SHARE_FAVOURITES if bundle.data['activity_sharing_favourites'] else 0 + comments = UserProfile.ACTIVITY_SHARE_COMMENTS if bundle.data['activity_sharing_comments'] else 0 + bundle.data['activity_sharing'] = (likes | favourites | comments) + del bundle.data['activity_sharing_likes'] + del bundle.data['activity_sharing_favourites'] + del bundle.data['activity_sharing_comments'] + + if 'activity_sharing_networks_facebook' in bundle.data: + facebook = UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK if bundle.data['activity_sharing_networks_facebook'] else 0 + twitter = UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER if bundle.data['activity_sharing_networks_twitter'] else 0 + bundle.data['activity_sharing_networks'] = (facebook | twitter) + del bundle.data['activity_sharing_networks_facebook'] + del bundle.data['activity_sharing_networks_twitter'] + + return bundle + + def obj_update(self, bundle, skip_errors=False, **kwargs): + """ + This feels extremely hacky - but for some reason, deleting from the bundle + in hydrate is not preventing the fields from being serialized at the ORM + """ + if 'activity_sharing_networks_facebook' in kwargs: del kwargs['activity_sharing_networks_facebook'] + if 'activity_sharing_networks_twitter' in kwargs: del kwargs['activity_sharing_networks_twitter'] + if 'activity_sharing_likes' in kwargs: del kwargs['activity_sharing_likes'] + if 'activity_sharing_favourites' in kwargs: del kwargs['activity_sharing_favourites'] + if 'activity_sharing_comments' in kwargs: del kwargs['activity_sharing_comments'] + + return super(UserProfileResource, self).obj_update(bundle, skip_errors, **kwargs) def dehydrate(self, bundle): - - #set the "me" user only properties + del bundle.data['activity_sharing'] + del bundle.data['activity_sharing_networks'] if bundle.obj.user.id == bundle.request.user.id: - bundle.data['email'] = bundle.obj.email - if bundle.obj.activity_sharing is not None: - bundle.data['activity_share_likes'] = \ - (bundle.obj.activity_sharing & UserProfile.ACTIVITY_SHARE_LIKES) != 0 - bundle.data['activity_share_favourites'] = \ - (bundle.obj.activity_sharing & UserProfile.ACTIVITY_SHARE_FAVOURITES) != 0 - bundle.data['activity_share_comments'] = \ - (bundle.obj.activity_sharing & UserProfile.ACTIVITY_SHARE_COMMENTS) != 0 - else: - bundle.data['activity_share_likes'] = 0 - bundle.data['activity_share_favourites'] = 0 - bundle.data['activity_share_comments'] = 0 + bundle.data['activity_sharing_likes'] = \ + self._hydrateBitmapOption(bundle.obj.activity_sharing, UserProfile.ACTIVITY_SHARE_LIKES) + bundle.data['activity_sharing_favourites'] = \ + self._hydrateBitmapOption(bundle.obj.activity_sharing, UserProfile.ACTIVITY_SHARE_FAVOURITES) + bundle.data['activity_sharing_comments'] = \ + self._hydrateBitmapOption(bundle.obj.activity_sharing, UserProfile.ACTIVITY_SHARE_COMMENTS) - if bundle.obj.activity_sharing_networks is not None: - bundle.data['activity_share_networks_facebook'] = \ - (bundle.obj.activity_sharing_networks & UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK) != 0 - bundle.data['activity_share_networks_twitter'] = \ - (bundle.obj.activity_sharing_networks & UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER) != 0 - else: - bundle.data['activity_share_networks_facebook'] = 0 - bundle.data['activity_share_networks_facebook'] = 0 - else: - del bundle.data['activity_sharing'] - del bundle.data['activity_sharing_networks'] - - bundle.data['first_name'] = bundle.obj.first_name - bundle.data['last_name'] = bundle.obj.last_name + bundle.data['activity_sharing_networks_facebook'] = \ + self._hydrateBitmapOption(bundle.obj.activity_sharing_networks, UserProfile.ACTIVITY_SHARE_NETWORK_FACEBOOK) + bundle.data['activity_sharing_networks_twitter'] = \ + self._hydrateBitmapOption(bundle.obj.activity_sharing_networks, UserProfile.ACTIVITY_SHARE_NETWORK_TWITTER) return bundle - def hydrate_slug(self, bundle): - if bundle.data['slug'] == '': - bundle.data['slug'] = None - return bundle +class UserResource(BackboneCompatibleResource): + profile = fields.ToOneField(UserProfileResource, attribute='userprofile', related_name='user', full=True) + class Meta: + queryset = User.objects.all() + resource_name = 'user' + excludes = ['is_active', 'is_staff', 'is_superuser', 'password'] + authorization = DjangoAuthorization() + authentication = Authentication() + + def dehydrate(self, bundle): + if bundle.obj.id != bundle.request.user.id: + del bundle.data['email'] + del bundle.data['username'] + + return bundle diff --git a/spa/management/commands/deletefailed.py b/spa/management/commands/deletefailed.py index 609509e..7db8534 100644 --- a/spa/management/commands/deletefailed.py +++ b/spa/management/commands/deletefailed.py @@ -1,10 +1,10 @@ -from django.core.management.base import NoArgsCommand -from spa.models import Mix - - -class Command(NoArgsCommand): - def handle(self, *args, **options): - candidates = Mix.objects.filter(waveform_generated=False) - for mix in candidates: - print "Deleting: %s" % mix.title - mix.delete() +from django.core.management.base import NoArgsCommand +from spa.models import Mix + + +class Command(NoArgsCommand): + def handle(self, *args, **options): + candidates = Mix.objects.filter(waveform_generated=False) + for mix in candidates: + print "Deleting: %s" % mix.title + mix.delete() diff --git a/spa/management/commands/deleteorphanmp3.py b/spa/management/commands/deleteorphanmp3.py index 50cc744..32c1084 100644 --- a/spa/management/commands/deleteorphanmp3.py +++ b/spa/management/commands/deleteorphanmp3.py @@ -1,14 +1,14 @@ -import os -import shutil -from django.core.management.base import NoArgsCommand -from spa.models import Mix - - -class Command(NoArgsCommand): - def handle(self, *args, **options): - candidates = Mix.objects.all() - for mix in candidates: - file = mix.get_absolute_path(prefix="expired/") - if os.path.exists(file): - new = mix.get_absolute_path() - shutil.move(file, new) +import os +import shutil +from django.core.management.base import NoArgsCommand +from spa.models import Mix + + +class Command(NoArgsCommand): + def handle(self, *args, **options): + candidates = Mix.objects.all() + for mix in candidates: + file = mix.get_absolute_path(prefix="expired/") + if os.path.exists(file): + new = mix.get_absolute_path() + shutil.move(file, new) diff --git a/spa/middleware/stripwhitespace.py b/spa/middleware/stripwhitespace.py index f1450a8..18c765a 100644 --- a/spa/middleware/stripwhitespace.py +++ b/spa/middleware/stripwhitespace.py @@ -1,39 +1,39 @@ -""" -Tightens up response content by removed superflous line breaks and whitespace. -By Doug Van Horn - ----- CHANGES ---- -v1.1 - 31st May 2011 -Cal Leeming [Simplicity Media Ltd] -Modified regex to strip leading/trailing white space from every line, not just those with blank \n. - ----- TODO ---- -* Ensure whitespace isn't stripped from within
 or  or 
-                        Tell us a bit about yourself.
+                        

+

Tell us a bit about yourself.
+

+
-
Share this activity
-
    -
  • -
    Likes
    - -
  • -
  • -
    Favourites
    - -
  • -
  • -
    Comments
    - -
  • -
-
-
-
On these networks
-
    -
  • -
    Facebook
    - -
  • -
  • -
    Twitter
    - -
  • -
+

+

What can we share about you?
+

+
+
Share this activity
+ + + + + + + + + + + + + +
LikesFavouritesComments
+ + + + + +
+
+
+
On these networks
+ + + + + + + + + + + +
FacebookTwitter
+ + + +
+
@@ -124,4 +148,5 @@ - \ No newline at end of file + +{% endverbatim %}