From a0e52300b3f3991d141f3d2df29de4fe5c71cdeb Mon Sep 17 00:00:00 2001 From: Charles Connell Date: Mon, 31 Mar 2014 21:06:51 -0400 Subject: [PATCH] Account pages, about page, fix note/user associations --- karmaworld/apps/document_upload/views.py | 4 +- karmaworld/apps/notes/models.py | 5 +- .../apps/users/templatetags/__init__.py | 1 + .../users/templatetags/social_account_list.py | 30 ++++ karmaworld/apps/users/views.py | 4 - karmaworld/assets/css/about.css | 27 +-- karmaworld/assets/css/dashboard.css | 61 +++++++ karmaworld/assets/css/global.css | 40 ++++- karmaworld/assets/js/jquery.metadata.js | 116 ------------ karmaworld/assets/js/note-detail.js | 2 - karmaworld/templates/about.html | 27 +-- karmaworld/templates/base.html | 2 +- karmaworld/templates/control_panel.html | 18 -- karmaworld/templates/header.html | 4 +- karmaworld/templates/notes/note_detail.html | 83 ++++----- karmaworld/templates/user_profile.html | 167 +++++++++++------- karmaworld/urls.py | 3 - 17 files changed, 287 insertions(+), 307 deletions(-) create mode 100644 karmaworld/apps/users/templatetags/__init__.py create mode 100644 karmaworld/apps/users/templatetags/social_account_list.py delete mode 100755 karmaworld/assets/js/jquery.metadata.js delete mode 100644 karmaworld/templates/control_panel.html diff --git a/karmaworld/apps/document_upload/views.py b/karmaworld/apps/document_upload/views.py index a8c85b2..98b21e4 100644 --- a/karmaworld/apps/document_upload/views.py +++ b/karmaworld/apps/document_upload/views.py @@ -24,7 +24,7 @@ def save_fp_upload(request): # note that .save() has the side-effect of kicking of a celery processing task if request.user.is_authenticated(): - raw_document.save(user=request.user) + raw_document.save() else: anonymous_upload_urls = request.session.get(ANONYMOUS_UPLOAD_URLS, []) anonymous_upload_urls.append(request.POST['fp_file']) @@ -36,7 +36,7 @@ def save_fp_upload(request): r_d_f.save_m2m() # Proccess document after the tags are saved so that it isn't converted # to a note before the tags are attached to the document - raw_document.process_document() + raw_document.process_document(user=request.user) return HttpResponse({'success'}) else: diff --git a/karmaworld/apps/notes/models.py b/karmaworld/apps/notes/models.py index dc25b96..84caec8 100644 --- a/karmaworld/apps/notes/models.py +++ b/karmaworld/apps/notes/models.py @@ -435,7 +435,10 @@ def update_note_counts(note_instance): else: # course exists note_instance.course.update_note_count() - note_instance.course.school.update_note_count() + if note_instance.course.school: + note_instance.course.school.update_note_count() + elif note_instance.course.department.school: + note_instance.course.department.school.update_note_count() @receiver(pre_save, sender=Note, weak=False) def note_pre_save_receiver(sender, **kwargs): diff --git a/karmaworld/apps/users/templatetags/__init__.py b/karmaworld/apps/users/templatetags/__init__.py new file mode 100644 index 0000000..8be6577 --- /dev/null +++ b/karmaworld/apps/users/templatetags/__init__.py @@ -0,0 +1 @@ +__author__ = 'charles' diff --git a/karmaworld/apps/users/templatetags/social_account_list.py b/karmaworld/apps/users/templatetags/social_account_list.py new file mode 100644 index 0000000..80cea1a --- /dev/null +++ b/karmaworld/apps/users/templatetags/social_account_list.py @@ -0,0 +1,30 @@ +from allauth.socialaccount.models import SocialAccount +from django import template + +register = template.Library() + + +class SocialAccountListNode(template.Node): + def __init__(self, user): + self.user_string = template.Variable(user) + + def render(self, context): + try: + user = self.user_string.resolve(context) + accounts = [account.provider.title() for account in user.socialaccount_set.all()] + accounts_string = ', '.join(accounts) + return accounts_string + except template.VariableDoesNotExist: + return '' + + +def do_social_account_list(parser, token): + try: + # split_contents() knows not to split quoted strings. + tag_name, user = token.split_contents() + except ValueError: + raise template.TemplateSyntaxError("social_account_list tag requires a single argument") + return SocialAccountListNode(user) + +register.tag('social_account_list', do_social_account_list) + diff --git a/karmaworld/apps/users/views.py b/karmaworld/apps/users/views.py index b2f17b6..611920b 100644 --- a/karmaworld/apps/users/views.py +++ b/karmaworld/apps/users/views.py @@ -30,7 +30,3 @@ class ProfileView(TemplateView, MultipleObjectMixin): kwargs['badge'] = self.request.user.get_profile().get_badge() return super(ProfileView, self).get_context_data(**kwargs) - -class ControlView(TemplateView): - template_name = 'control_panel.html' - diff --git a/karmaworld/assets/css/about.css b/karmaworld/assets/css/about.css index 2308557..3a5b4b9 100644 --- a/karmaworld/assets/css/about.css +++ b/karmaworld/assets/css/about.css @@ -18,28 +18,12 @@ background: url(../img/team_crop.jpg); } -#hero_image_caption_container -{ - position: absolute; - z-index: 5; - bottom: 20px; -} - -#hero_image_caption -{ - font-family: "MuseoSlab-700"; - font-size: 17px; - color: #FFF; - line-height: 150%; -} - /* COPY */ #about_copy_header { padding-top: 40px; color: #f05a28; - font-family: "MuseoSlab-700"; font-size: 38px; } @@ -50,7 +34,6 @@ #about_copy_body p { - font-family: "MuseoSlab-500"; font-size: 17px; margin: 20px 0 0; line-height: 150%; @@ -79,14 +62,12 @@ #donate_copy_header { - font-family: "MuseoSlab-700"; font-size: 40px; color: #3a3a3a; } #donate_copy_body { - font-family: "MuseoSlab-700"; font-size: 20px; color: #3a3a3a; padding-top: 10px; @@ -99,8 +80,8 @@ #donate_button { - font-family: "MuseoSlab-900"; } + #amazon-donate-form { margin: 1em 1em 0; } @@ -113,13 +94,11 @@ #leaderboard_header { padding-top: 75px; - font-family: "MuseoSlab-700"; font-size: 25px; } #leaderboard_copy { - font-family: "MuseoSlab-500"; font-size: 17px; padding-top: 3px; padding-bottom: 30px; @@ -145,20 +124,16 @@ .leaderboard_rank { - font-family: "MuseoSans-900"; font-size: 14px; - /*width: 20px!important;*/ padding-top: 4px; } .leaderboard_school, .leaderboard_score { - font-family: "MuseoSlab-500"; font-size: 19px; } .bullets li { - font-family: "MuseoSlab-500"; font-size: 17px; } diff --git a/karmaworld/assets/css/dashboard.css b/karmaworld/assets/css/dashboard.css index e69de29..78413ed 100644 --- a/karmaworld/assets/css/dashboard.css +++ b/karmaworld/assets/css/dashboard.css @@ -0,0 +1,61 @@ +#stats-container { + margin: 20px 0 20px 0; +} + +#user-name { + font-size: 1.5em; +} + +.stat-count { + font-size: 2.5em; +} + +div.stat-container { + border-left: solid 1px #dfdfdf; +} + +.activity_item { + margin: 15px 0 15px 0; +} + +.activity_timestamp { + font-size: 0.7em; +} + +.activity_details_action { + margin: 10px 0 5px 0; +} + +.activity_details_object { + margin: 5px 0 5px 0; +} + +.activity_details_points_positive, +.activity_details_points_negative { + background: #f1592a; + padding: 0px 5px 0 5px; + border-radius: 2px; + color: #ffffff; +} + +.account_settings_row { + padding: 15px 0 15px 0; + border-bottom: 1px solid #f0f0f0; +} + +.account_settings_category { + text-align: right; + font-weight: normal; +} + +.account_settings_edit { + text-align: right; + font: 0.8em 'museo700'; +} + +@media only screen and (max-width: 40.063em) { + .account_settings_category, + .account_settings_edit { + text-align: left; + } +} /* medium screens and down */ diff --git a/karmaworld/assets/css/global.css b/karmaworld/assets/css/global.css index 422329d..1e25aa6 100644 --- a/karmaworld/assets/css/global.css +++ b/karmaworld/assets/css/global.css @@ -1,5 +1,6 @@ body { font-family: 'adelle-sans'; + font-weight: lighter; } .museo300 { @@ -8,12 +9,21 @@ body { .museo700 { font-family: 'museo700'; + font-weight: normal; } .adelle-sans { font-family: 'adelle-sans'; } +h1, h2, h3, h4, h5 { + font-family: 'museo700'; +} + +p { + font-weight: inherit; +} + .nav-list ul { list-style-type: none; margin: 0; @@ -166,10 +176,10 @@ table.dataTable div.data-table-entry { margin: 20px 0 20px 0; } -table.dataTable tr.even { +.even { background: #fafafa; - border-top: 2px solid #f0f0f0; - border-bottom: 2px solid #f0f0f0; + border-top: 1px solid #f0f0f0; + border-bottom: 1px solid #f0f0f0; } ul.ui-autocomplete { @@ -191,3 +201,27 @@ ul.ui-autocomplete { border: none; } +dl.tabs dd.active { + border-radius: 3px; +} + +dl.tabs dd { + margin: 0 10px 0px 10px; + border: 1px solid #dfdfdf; + border-bottom: none; +} + +dl.tabs dd, +dl.tabs dd a { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} + +dl.tabs dd a { + padding: 5px 10px 5px 10px; +} + +div.tabs-content { + margin-top: -1px; + border-top: 1px solid #dfdfdf; +} \ No newline at end of file diff --git a/karmaworld/assets/js/jquery.metadata.js b/karmaworld/assets/js/jquery.metadata.js deleted file mode 100755 index dc4538e..0000000 --- a/karmaworld/assets/js/jquery.metadata.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Metadata - jQuery plugin for parsing metadata from elements - * - * Copyright (c) 2006 John Resig, Yehuda Katz, Jörn Zaefferer, Paul McLanahan - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - */ - -/** - * Sets the type of metadata to use. Metadata is encoded in JSON, and each property - * in the JSON will become a property of the element itself. - * - * There are three supported types of metadata storage: - * - * attr: Inside an attribute. The name parameter indicates *which* attribute. - * - * class: Inside the class attribute, wrapped in curly braces: { } - * - * elem: Inside a child element (e.g. a script tag). The - * name parameter indicates *which* element. - * - * The metadata for an element is loaded the first time the element is accessed via jQuery. - * - * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements - * matched by expr, then redefine the metadata type and run another $(expr) for other elements. - * - * @name $.metadata.setType - * - * @example

This is a p

- * @before $.metadata.setType("class") - * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" - * @desc Reads metadata from the class attribute - * - * @example

This is a p

- * @before $.metadata.setType("attr", "data") - * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" - * @desc Reads metadata from a "data" attribute - * - * @example

This is a p

- * @before $.metadata.setType("elem", "script") - * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label" - * @desc Reads metadata from a nested script element - * - * @param String type The encoding type - * @param String name The name of the attribute to be used to get metadata (optional) - * @cat Plugins/Metadata - * @descr Sets the type of encoding to be used when loading metadata for the first time - * @type undefined - * @see metadata() - */ - -(function($) { - -$.extend({ - metadata : { - defaults : { - type: 'class', - name: 'metadata', - cre: /(\{.*\})/, - single: 'metadata' - }, - setType: function( type, name ){ - this.defaults.type = type; - this.defaults.name = name; - }, - get: function( elem, opts ){ - var data, m, e, attr, - settings = $.extend({},this.defaults,opts); - // check for empty string in single property - if ( !settings.single.length ) { settings.single = 'metadata'; } - - data = $.data(elem, settings.single); - // returned cached data if it already exists - if ( data ) { return data; } - - data = "{}"; - - if ( settings.type === "class" ) { - m = settings.cre.exec( elem.className ); - if ( m ) { data = m[1]; } - } else if ( settings.type === "elem" ) { - if( !elem.getElementsByTagName ) { return undefined; } - e = elem.getElementsByTagName(settings.name); - if ( e.length ) { data = $.trim(e[0].innerHTML); } - } else if ( elem.getAttribute !== undefined ) { - attr = elem.getAttribute( settings.name ); - if ( attr ) { data = attr; } - } - - if ( data.indexOf( '{' ) <0 ) { data = "{" + data + "}"; } - - data = eval("(" + data + ")"); - - $.data( elem, settings.single, data ); - return data; - } - } -}); - -/** - * Returns the metadata object for the first member of the jQuery object. - * - * @name metadata - * @descr Returns element's metadata object - * @param Object opts An object contianing settings to override the defaults - * @type jQuery - * @cat Plugins/Metadata - */ -$.fn.metadata = function( opts ){ - return $.metadata.get( this[0], opts ); -}; - -})(jQuery); \ No newline at end of file diff --git a/karmaworld/assets/js/note-detail.js b/karmaworld/assets/js/note-detail.js index 67da534..a178320 100644 --- a/karmaworld/assets/js/note-detail.js +++ b/karmaworld/assets/js/note-detail.js @@ -73,8 +73,6 @@ function writeNoteFrame(contents) { $(function() { - $("#tabs").tabs(); - $("#thank-button").click(function(event) { event.preventDefault(); diff --git a/karmaworld/templates/about.html b/karmaworld/templates/about.html index b08d05f..08d72b5 100644 --- a/karmaworld/templates/about.html +++ b/karmaworld/templates/about.html @@ -14,17 +14,6 @@
- {% comment %} -
-
-
-
- -
-
-
-
- {% endcomment %}
@@ -32,20 +21,18 @@
-
+
Help us spread the academic wealth.
-
+

KarmaNotes empowers college students to share course notes, study guides, and other digital learning resources online. By exchanging knowledge on KarmaNotes, everyone benefits from access to a growing database of knowledge.

All content on KarmaNotes is licensed Creative Commons and all code is free and open source. We also maintain full compliance with the Digital Millennium Copyright Act.

Beyond the ivory tower, KarmaNotes is a network with the potential to digitize education, one lecture at a time. Like a give-a-penny jar, KarmaNotes collects knowledge for the common good. Best of all, our capacity is practically limitless, and withdrawals are entirely free.

KarmaNotes is improving access to learning resources thanks to support from the William and Flora Hewlett Foundation and generous scholars like you. Want to get involved or learn more? Please contact us or support our mission with a tax-deductible charitable donation to the FinalsClub Foundation.

- -
@@ -53,7 +40,7 @@