Improving login experience
authorCharles Connell <charles@connells.org>
Sat, 11 Jan 2014 17:47:53 +0000 (12:47 -0500)
committerCharles Connell <charles@connells.org>
Sat, 11 Jan 2014 17:47:53 +0000 (12:47 -0500)
16 files changed:
karmaworld/apps/notes/migrations/0013_auto__chg_field_note_user.py
karmaworld/apps/notes/models.py
karmaworld/apps/users/models.py
karmaworld/assets/css/accounts.css
karmaworld/assets/css/global.css
karmaworld/assets/img/facebook.png
karmaworld/assets/img/google.png [new file with mode: 0644]
karmaworld/assets/img/twitter.png [new file with mode: 0644]
karmaworld/settings/common.py
karmaworld/templates/account/base.html
karmaworld/templates/account/login.html
karmaworld/templates/courses/course_detail.html
karmaworld/templates/partial/filepicker.html
karmaworld/templates/socialaccount/connections.html
karmaworld/templates/socialaccount/snippets/provider_list.html
karmaworld/templates/user_profile.html

index 3eb44dba5d16b4514fa154a17d4e7f00fe87fafa..03d512668cfc99e2db0b0a4afb2fb44ecc2684e4 100644 (file)
@@ -114,12 +114,12 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '80'})
         },
         'notes.note': {
-            'Meta': {'ordering': "['-uploaded_at']", 'object_name': 'Note'},
+            'Meta': {'ordering': "['-uploaded_at']", 'unique_together': "(('fp_file', 'upstream_link'),)", 'object_name': 'Note'},
             'course': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['courses.Course']"}),
             'file_type': ('django.db.models.fields.CharField', [], {'default': "'???'", 'max_length': '15', 'null': 'True', 'blank': 'True'}),
             'flags': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
             'fp_file': ('django_filepicker.models.FPFileField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
-            'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'gdrive_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
             'html': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
             'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
             'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
@@ -133,7 +133,7 @@ class Migration(SchemaMigration):
             'thanks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
             'tweeted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
             'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.utcnow', 'null': 'True'}),
-            'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
+            'upstream_link': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
             'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}),
             'year': ('django.db.models.fields.IntegerField', [], {'default': '2014', 'null': 'True', 'blank': 'True'})
         },
index f9f281aefe3dba074770b85a5094debc42b69297..d284977020f30a4353fbfd06b6279676016b04f9 100644 (file)
@@ -189,6 +189,7 @@ class Note(Document):
 
     class Meta:
         unique_together = ('fp_file', 'upstream_link')
+        ordering = ['-uploaded_at']
 
     def __unicode__(self):
         return u"Note at {0} (from {1})".format(self.fp_file, self.upstream_link)
index 42d97042e979bf5717770b3c048bc5fcb31ea0ce..53106dc31556bcfd7f710c2ceeae47c932a561c1 100644 (file)
@@ -1,9 +1,11 @@
 #!/usr/bin/env python
 # -*- coding:utf8 -*-
 # Copyright (C) 2013  FinalsClub Foundation
+import random
 from allauth.account.signals import user_logged_in
 from django.contrib.auth.models import User
-from django.db.models.signals import post_save
+from django.core.exceptions import ObjectDoesNotExist
+from django.db.models.signals import post_save, pre_save
 from django.dispatch import receiver
 from django.db import models
 from karmaworld.apps.courses.models import School
@@ -19,6 +21,31 @@ class UserProfile(models.Model):
     def __unicode__(self):
         return self.user.__unicode__()
 
+def user_display_name(user):
+    """Return the best way to display a user's
+    name to them on the site."""
+    if user.first_name or user.last_name:
+        return user.first_name + ' ' + user.last_name
+    else:
+        return user.username
+
+
+@receiver(pre_save, sender=User, weak=True)
+def assign_username(sender, instance, **kwargs):
+    # If a user does not have a username, they need
+    # one before we save to the database
+    if not instance.username:
+        if instance.email:
+            try:
+                # See if any other users have this email address
+                others = User.objects.get(email=instance.email)
+            except ObjectDoesNotExist:
+                instance.username = instance.email
+            else:
+                instance.username = 'user' + str(random.randint(10000, 100000))
+        else:
+            instance.username = 'user' + str(random.randint(10000, 100000))
+
 
 @receiver(post_save, sender=User, weak=True)
 def create_user_profile(sender, instance, created, **kwargs):
index 2d70e5c81ef3a1db7bff02c783d82ae1b41217c1..ebb026d03d07e55bb2029e92ec10a675866899b0 100644 (file)
@@ -24,16 +24,6 @@ ul
   list-style-type: none;
 }
 
-button,
-button:hover
-{
-  border: none;
-  background-color: white;
-  color: #f05a28;
-  cursor: pointer;
-  font: 30px/1.2em "MuseoSlab-300", serif;
-  margin: 1px;
-  text-align: center;
-  text-transform: uppercase;
+.errorlist {
+  color: #c60f13
 }
-
index 502ef733707844618d660bc10c90d06133b67c2a..962c1126c13f83b7b41f3a6ffddc6df02ea21a5c 100644 (file)
@@ -857,7 +857,9 @@ legend
 
 /* Social account integration */
 
-.facebook-login-btn
-{
-  content: url(../img/facebook.png);
+ul.socialaccount_providers li {
+  list-style: none;
+  margin: 10px 0 5px 0;
 }
+
+
index a9e2d57bd5618cdeaf3be13fbc97c05d8b301cda..8d0d202c68465148e12b10fef21c56c5df0630fa 100644 (file)
Binary files a/karmaworld/assets/img/facebook.png and b/karmaworld/assets/img/facebook.png differ
diff --git a/karmaworld/assets/img/google.png b/karmaworld/assets/img/google.png
new file mode 100644 (file)
index 0000000..a284559
Binary files /dev/null and b/karmaworld/assets/img/google.png differ
diff --git a/karmaworld/assets/img/twitter.png b/karmaworld/assets/img/twitter.png
new file mode 100644 (file)
index 0000000..c2822dc
Binary files /dev/null and b/karmaworld/assets/img/twitter.png differ
index e7d55f7eefa5b95dd65f0727aeea9deebe6f1594..4b20c2f6d2c5e01843058872adce6680661597d2 100644 (file)
@@ -217,7 +217,6 @@ THIRD_PARTY_APPS = (
     # ... include the providers you want to enable:
     'allauth.socialaccount.providers.facebook',
     'allauth.socialaccount.providers.google',
-    'allauth.socialaccount.providers.openid',
     'allauth.socialaccount.providers.twitter',
 )
 
@@ -255,13 +254,9 @@ ACCOUNT_USER_MODEL_EMAIL_FIELD = "email"
 ACCOUNT_USERNAME_REQUIRED = False
 SOCIALACCOUNT_EMAIL_REQUIRED = True
 SOCIALACCOUNT_EMAIL_VERIFICATION = "optional"
+ACCOUNT_USER_DISPLAY = 'karmaworld.apps.users.models.user_display_name'
 
-# You can't log in with a username,
-# you must use an authenitcation provider
-ACCOUNT_USER_MODEL_USERNAME_FIELD = None
-ACCOUNT_USER_MODEL_EMAIL_FIELD = None
-
-AUTH_PROFILE_MODULE = 'accounts.UserProfile'
+AUTH_PROFILE_MODULE = 'users.UserProfile'
 
 ######### END AUTHENTICATION
 
index d9e59dc7471dd0538fc7e802461a42e194333271..ab64a015414524d7bb54f830bfc6f55e0251cc2e 100644 (file)
@@ -44,7 +44,7 @@
 
 <section id="account_content">
   <div class="row">
-    <div class="small-12 columns center">
+    <div class="small-12 large-6 columns small-centered center">
       {% block content %}
       {% endblock %}
     </div>
index 83cf27984a86bd6462093e642eeb435b26182c12..6857607d5409bf5865a5fdf24eae1845db0b2144 100644 (file)
@@ -11,9 +11,8 @@
 <h1>{% trans "Sign In" %}</h1>
 
 {% if socialaccount.providers  %}
-<p>{% blocktrans with site.name as site_name %}Please sign in with one
-of your existing third party accounts. Or, <a href="{{ signup_url }}">sign up</a>
-for a {{site_name}} account and sign in below:{% endblocktrans %}</p>
+<p>You can sign in to KarmaNotes with any of the existing accounts you might have below.
+Or, <a href="{{ signup_url }}">sign up</a> for a KarmaNotes account and sign in below.</p>
 
 <div class="socialaccount_ballot">
 
@@ -25,8 +24,6 @@ for a {{site_name}} account and sign in below:{% endblocktrans %}</p>
 
 </div>
 
-{% include "socialaccount/snippets/login_extra.html" %}
-
 {% else %}
 <p>{% blocktrans %}If you have not created an account yet, then please
 <a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p>
index c5a1443000b7b988029a3a0a337372b56744f3fe..410d4374f0f5b2beec9d00050efd4d3b6743741b 100644 (file)
 
     {% include 'partial/filepicker.html' %}
 
-
-    {% if request.GET.thankyou == '' %}
-    <div id=thankyou-wrapper class="row">
-      <div class="small-8 columns small-offset-2">
-        <div id="thankyou">
-          <p>
-            Thank you for uploading
-            <a href="{{ request.GET.url }}">{{ request.GET.name }}</a>.
-            Share another or take a
-            <a href="https://docs.google.com/a/finalsclub.org/spreadsheet/viewform?usp=sharing&formkey=dFg1WnI2cUVfckZyYnJpZ0ExQmUxSnc6MQ#gid=0" target="_blank">quick survey</a> to help us make KarmaNotes even better.
-          </p>
-          <script>
-          // when showing the thankyou button, flash it orangered first
-          $(function() {
-            $("#thankyou").effect("highlight", {'color': '#f05a28'}, 3000);
-          });
-          </script>
-
-        </div><!-- /thankyou -->
-      </div>
-    </div> <!-- .row -->
-    {% endif %}
-
-
     <div class="row">
       <div class="small-10 columns small-offset-1"> <hr/> </div>
     </div>
 
-
-
     <div id="course_container">
       <div class="row">
         <div class="small-12 columns large-10 large-offset-1">
-
           {% for note in note_set %}
             {% include 'notes/note_list_entry.html' with note=note %}
           {% endfor %}
index d675074390fcae064cc92190541a2cde80ae55ec..c4580cc49a5dfc4597928d4173f94ee89c086444 100644 (file)
@@ -3,7 +3,7 @@
 <section id=filepicker-form class="extend-form">
 <!-- Javascript -->
 <script type="text/javascript" src="//api.filepicker.io/v1/filepicker.js"></script>
-  <div class="row" id="">
+  <div class="row" id="filepicker_row">
     <div class="small-8 small-offset-1 columns large-10">
         <input id="filepicker-file-upload"
           type="filepicker-dragdrop"
         {% if not request.user.is_authenticated %}
           <p>We'd love to have you sign up so you can claim the notes you just uploaded, and
           build a reputation for uploading great notes.</p>
-          <p><a href='{% provider_login_url "facebook" %}'>
-            <span class="facebook-login-btn"></span>
-            </a></p>
+          <div class="socialaccount_ballot">
+            <ul class="socialaccount_providers">
+              {% include "socialaccount/snippets/provider_list.html" with process="login" %}
+            </ul>
+            <a href="{{ signup_url }}">Sign up for a traditional account</a>
+          </div>
         {% endif %}
       </div>
     </div>
                 }
                 $('#success').show();
                 $('#save-btn').hide();
+                $('#filepicker_row').hide();
                 $('#forms_container .inline-form').remove();
                 if (document.location.host === 'www.karmanotes.org' ||
                   document.location.host === 'karmanotes.org') {
index def62e18e1d6dd4e7fd5e9a9cc984c09905a7202..d24cf00d7bacc8fb21fe69b423da8515dda772bf 100644 (file)
@@ -50,6 +50,4 @@
 {% include "socialaccount/snippets/provider_list.html" with process="connect" %}
 </ul>
 
-{% include "socialaccount/snippets/login_extra.html" %}
-
 {% endblock %}
index 202c5c2dc4bf0eeb063dae9501ada212402e3caa..4fd1ba865b3948a68ea354baf17d86c61c8648dd 100644 (file)
@@ -7,13 +7,13 @@
   <a title="{{brand.name}}" 
      class="socialaccount_provider {{provider.id}} {{brand.id}}" 
      href="{% provider_login_url provider.id openid=brand.openid_url process=process %}"
-     >{{brand.name}}</a>
+     ><img src="{{STATIC_URL}}img/{{brand.name|lower}}.png"></a>
 </li>
 {% endfor %}
 {% endif %}
 <li>
   <a title="{{provider.name}}" class="socialaccount_provider {{provider.id}}" 
-     href="{% provider_login_url provider.id process=process %}">{{provider.name}}</a>
+     href="{% provider_login_url provider.id process=process %}"><img src="{{STATIC_URL}}img/{{provider.name|lower}}.png"></a>
 </li>
 {% endfor %}
 
index 219a70b07c16e16f57235cbde01d467af8e11b9b..39654aa401edf9cb7da23c575ddd6a2f9dc75ea2 100644 (file)
@@ -7,20 +7,11 @@
 {% endblock %}
 
 {% block content %}
-  <section id="account_content">
-
-    <div class="row">
-      <div class="small-12 columns">
-        <h1>Hello there, {% user_display user %}.</h1>
-        <p>Here are the notes that you've uploaded:</p>
-        <ul>
-          {% for note in user.note_set.all %}
-            <li><a href="{{ note.get_absolute_url }}">{{ note.name }}</a></li>
-          {% endfor %}
-        </ul>
-      </div>
-    </div>
-
-
-  </section><!--/about_content-->
+  <h1>Hello there,<br/>{% user_display user %}.</h1>
+  <p>Here are the notes that you've uploaded:</p>
+  <ul>
+    {% for note in user.note_set.all %}
+      <li><a href="{{ note.get_absolute_url }}">{{ note.name }}</a></li>
+    {% endfor %}
+  </ul>
 {% endblock %}