diff --git a/pinry/api/api.py b/pinry/api/api.py index 04ad3e0..36655d2 100644 --- a/pinry/api/api.py +++ b/pinry/api/api.py @@ -11,7 +11,7 @@ class UserResource(ModelResource): class Meta: queryset = User.objects.all() resource_name = 'user' - excludes = ['email', 'password', 'is_superuser', 'first_name', + excludes = ['password', 'is_superuser', 'first_name', 'last_name', 'is_active', 'is_staff', 'last_login', 'date_joined'] include_resource_uri = False diff --git a/pinry/core/forms.py b/pinry/core/forms.py new file mode 100644 index 0000000..6fe0770 --- /dev/null +++ b/pinry/core/forms.py @@ -0,0 +1,38 @@ +from django import forms +from django.utils.translation import ugettext, ugettext_lazy as _ +from django.contrib.auth.models import User + + +class UserCreationForm(forms.ModelForm): + """ + A form that creates a user, with no privileges, from the given username, + email, and password. + """ + error_messages = { + 'duplicate_username': _("A user with that username already exists."), + } + username = forms.RegexField(label=_("Username"), max_length=30, + regex=r'^[\w-]+$') + password = forms.CharField(label=_("Password"), + widget=forms.PasswordInput) + + class Meta: + model = User + fields = ("username", "email") + + def clean_username(self): + # Since User.username is unique, this check is redundant, + # but it sets a nicer error message than the ORM. See #13147. + username = self.cleaned_data["username"] + try: + User._default_manager.get(username=username) + except User.DoesNotExist: + return username + raise forms.ValidationError(self.error_messages['duplicate_username']) + + def save(self, commit=True): + user = super(UserCreationForm, self).save(commit=False) + user.set_password(self.cleaned_data["password"]) + if commit: + user.save() + return user diff --git a/pinry/core/static/core/css/pinry.css b/pinry/core/static/core/css/pinry.css index 609981b..387e21f 100644 --- a/pinry/core/static/core/css/pinry.css +++ b/pinry/core/static/core/css/pinry.css @@ -66,15 +66,6 @@ body { text-align: center; } - -.tags { - padding: 13px 0; -} - - .tag { - cursor: pointer; - } - #pins { top: 70px; } @@ -83,14 +74,43 @@ body { background: #fff; width: 200px; box-shadow: 0 1px 3px #bbb; - padding: 20px; + -moz-box-shadow: 0 1px 3px #bbb; + -webkit-box-shadow: 0 1px 3px #bbb; + padding: 15px; position: absolute; } + .pin .editable { + border: 2px solid rgba(255, 255, 255, 0.4); + background: rgba(255, 255, 255, 0.4); + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + position: absolute; + right: 23px; + top: 23px; + display: none; + } + + .pin:hover .editable { + display: block; + } + + .pin .editable .borderable { + padding: 7px 8px 5px; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + background: rgba(0, 0, 0, 0.8); + cursor: pointer; + } + .pin img { width: 200px; padding: 0; margin: 0; + cursor: -webkit-zoom-in; + cursor: -moz-zoom-in; } .pin p { @@ -103,6 +123,36 @@ body { font-weight: normal; } + .pin-footer { + background-color: #eee; + font-weight: bold; + margin: 0 -15px -15px -15px; + padding: 15px; + margin-top: 15px; + color: #777; + font-size: 12px; + cursor: default; + } + + .pin-footer .dim { + font-weight: normal; + color: #999; + } + + .pin-footer .avatar { + width: 30px; + height: 30px; + background-color: #555; + border-radius: 4px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + } + + .pin-footer .text { + width: 155px; + margin-top: -3px; + } + .pin-options { margin: 5px; display: none; diff --git a/pinry/core/static/core/js/pinry.js b/pinry/core/static/core/js/pinry.js index 4e7187c..e5e29d3 100644 --- a/pinry/core/static/core/js/pinry.js +++ b/pinry/core/static/core/js/pinry.js @@ -11,7 +11,7 @@ $(window).load(function() { var blocks = blockContainer.children('.pin'); // Size of blocks/pins and the spacing between them - var blockMargin = 20; + var blockMargin = 15; var blockWidth = 240; // How many items we can fit in a row and our array for the row heights @@ -67,6 +67,10 @@ $(window).load(function() { // Fetch our pins from the api using our current offset $.get('/api/v1/pin/?format=json&offset='+String(offset), function(pins) { + // Set which items are editable by the current user + for (var i=0; i < pins.objects.length; i++) + pins.objects[i].editable = (pins.objects[i].submitter.username == currentUser); + // Use the fetched pins as our context for our pins template var template = Handlebars.compile($('#pins-template').html()); var html = template({pins: pins.objects}); diff --git a/pinry/core/templates/core/base.html b/pinry/core/templates/core/base.html index 648500f..d7b28c8 100644 --- a/pinry/core/templates/core/base.html +++ b/pinry/core/templates/core/base.html @@ -51,8 +51,7 @@ {% compress js inline %} {% endcompress %} diff --git a/pinry/core/views.py b/pinry/core/views.py index ac65812..b1c6e1b 100644 --- a/pinry/core/views.py +++ b/pinry/core/views.py @@ -3,10 +3,11 @@ from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required from django.contrib.auth import logout -from django.contrib.auth.forms import UserCreationForm from django.contrib import messages from django.conf import settings +from .forms import UserCreationForm + def home(request): return HttpResponseRedirect(reverse('pins:recent-pins')) diff --git a/pinry/pins/templates/pins/recent_pins.html b/pinry/pins/templates/pins/recent_pins.html index 6000f22..41578f6 100644 --- a/pinry/pins/templates/pins/recent_pins.html +++ b/pinry/pins/templates/pins/recent_pins.html @@ -20,19 +20,29 @@ {{#each pins}}
{{description}}
{{/if}} - {{#if tags}} -+