From 895bb5e029460fcdb029f1acbb0090531803ee60 Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Sun, 2 Feb 2014 17:26:41 -0500 Subject: [PATCH 01/25] LMS: adding language selector to user dashboard (WIP) --- lms/static/sass/base/_mixins.scss | 20 +++ lms/static/sass/elements/_controls.scss | 26 +++- lms/static/sass/shared/_modal.scss | 39 ++++++ lms/templates/dashboard.html | 4 + .../dashboard/_dashboard_info_language.html | 17 +++ .../modal/_modal-settings-language.html | 117 ++++++++++++++++++ 6 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 lms/templates/dashboard/_dashboard_info_language.html create mode 100644 lms/templates/modal/_modal-settings-language.html diff --git a/lms/static/sass/base/_mixins.scss b/lms/static/sass/base/_mixins.scss index 22a1d96dbd..0205fe9875 100644 --- a/lms/static/sass/base/_mixins.scss +++ b/lms/static/sass/base/_mixins.scss @@ -97,6 +97,26 @@ %ui-depth4 { z-index: 10000; } %ui-depth5 { z-index: 100000; } +// extends - UI - utility - nth-type style clearing +%wipe-first-child { + + &:first-child { + margin-top: 0; + border-top: none; + padding-top: 0; + } +} + +// extends - UI - utility - nth-type style clearing +%wipe-last-child { + + &:last-child { + margin-bottom: 0; + border-bottom: none; + padding-bottom: 0; + } +} + // extends -hidden elems - screenreaders %text-sr { border: 0; diff --git a/lms/static/sass/elements/_controls.scss b/lms/static/sass/elements/_controls.scss index 30629537da..a7028efa22 100644 --- a/lms/static/sass/elements/_controls.scss +++ b/lms/static/sass/elements/_controls.scss @@ -231,11 +231,35 @@ cursor: default; pointer-events: none; box-shadow: none; - :hover, :focus { + + &:hover, &:focus { pointer-events: none; } } +// ==================== + +%btn-reset { + background: none; + border: none; + font-size: inherit; + box-shadow: none; + text-shadow: none; +} + +// button that appears visually as a link +%btn-link { + @extend %btn-reset; + color: $link-color; + text-decoration: none; + @include transition(all 0.1s linear 0s); + + &:hover, &:focus { + color: $link-color; + text-decoration: underline; + } +} + // ==================== // application: canned actions diff --git a/lms/static/sass/shared/_modal.scss b/lms/static/sass/shared/_modal.scss index f9c3027ddf..a6ce70251e 100644 --- a/lms/static/sass/shared/_modal.scss +++ b/lms/static/sass/shared/_modal.scss @@ -325,3 +325,42 @@ @extend .modal; } +// -------------------- + +// CASE: language settings +.modal-settings-language { + + // general reset + .list-input, .list-actions { + @extend %ui-no-list; + } + + .settings-language-select .select { + width: 100%; + } + + .list-input { + margin-bottom: $baseline; + } + + .list-actions { + + .action-item { + @extend %wipe-last-child; + display: inline-block; + vertical-align: middle; + margin-right: ($baseline/4); + } + + .action-submit { + color: $white; + padding-top: ($baseline/3); + padding-bottom: ($baseline/3); + } + + .action-cancel { + @extend %btn-link; + } + } +} + diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 47e2abd810..a19c07d3a7 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -193,6 +193,8 @@ ${ user.email | h } + <%include file='dashboard/_dashboard_info_language.html' /> + % if external_auth_map is None or 'shib' not in external_auth_map.external_domain:
  • ${_("Reset Password")}
    @@ -329,6 +331,8 @@ +<%include file='modal/_modal-settings-language.html' /> +
  • diff --git a/lms/templates/modal/_modal-settings-language.html b/lms/templates/modal/_modal-settings-language.html index 709e03a22a..c0858c711d 100644 --- a/lms/templates/modal/_modal-settings-language.html +++ b/lms/templates/modal/_modal-settings-language.html @@ -34,7 +34,7 @@ % for abbrv in language_options: % for language in settings.LANGUAGES: % if abbrv == language[0]: - % if abbrv == current_language['code']: + % if abbrv == current_language_code: % else: From a51ab4f1f42aeee72eea9b98372aa8a8bf26a777 Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Thu, 13 Feb 2014 15:32:44 -0500 Subject: [PATCH 14/25] LMS: adding iconography to language pref on dashboard UI --- lms/static/sass/multicourse/_dashboard.scss | 13 +++++++++++++ .../dashboard/_dashboard_info_language.html | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss index ef864cb392..e9d8663a59 100644 --- a/lms/static/sass/multicourse/_dashboard.scss +++ b/lms/static/sass/multicourse/_dashboard.scss @@ -854,6 +854,19 @@ } } + // status - language + .status-language { + + .icon, .title { + display: inline-block !important; // needed for LMS horrible specificity + vertical-align: middle; + } + + .icon { + margin-right: ($baseline/4); + } + } + // status - verification .status-verification { diff --git a/lms/templates/dashboard/_dashboard_info_language.html b/lms/templates/dashboard/_dashboard_info_language.html index 606895c763..912b55c18c 100644 --- a/lms/templates/dashboard/_dashboard_info_language.html +++ b/lms/templates/dashboard/_dashboard_info_language.html @@ -2,7 +2,8 @@ <%namespace name='static' file='../static_content.html'/> -
  • +
  • + ${_("Preferred Language")} (${_("edit")}) From d00a0f5b0890a4e9d24bccbad3a40ba13275e7db Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Thu, 13 Feb 2014 15:45:03 -0500 Subject: [PATCH 15/25] LMS: adding in supplemental 'volunteer to be a translator' action to language modal --- lms/static/sass/shared/_modal.scss | 15 +++++++++++++++ lms/templates/modal/_modal-settings-language.html | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/lms/static/sass/shared/_modal.scss b/lms/static/sass/shared/_modal.scss index f8c63775bb..b8a02d686d 100644 --- a/lms/static/sass/shared/_modal.scss +++ b/lms/static/sass/shared/_modal.scss @@ -342,5 +342,20 @@ .list-input { margin-bottom: $baseline; } + + .actions-supplemental { + padding: 0 ($baseline*2) $baseline ($baseline*2); + + .list-actions-item { + @extend %t-copy-sub1; + color: $base-font-color; + text-align: center; + } + + .action { + display: block; + margin-top: ($baseline/4); + } + } } diff --git a/lms/templates/modal/_modal-settings-language.html b/lms/templates/modal/_modal-settings-language.html index c0858c711d..3e2b488111 100644 --- a/lms/templates/modal/_modal-settings-language.html +++ b/lms/templates/modal/_modal-settings-language.html @@ -50,6 +50,12 @@ + +
      +
    • + ${_("Don't see your preferred language? {link_start}Volunteer to become a translator!{link_end}").format(link_start='', link_end="")} +
    • +
    From cb209fa0af0709ba1775413dbfe47ddcf92d7262 Mon Sep 17 00:00:00 2001 From: Brian Talbot Date: Thu, 13 Feb 2014 17:52:06 -0500 Subject: [PATCH 16/25] LMS: revising color of language icon --- lms/static/sass/multicourse/_dashboard.scss | 11 +++++++---- lms/templates/dashboard/_dashboard_info_language.html | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss index e9d8663a59..5172981661 100644 --- a/lms/static/sass/multicourse/_dashboard.scss +++ b/lms/static/sass/multicourse/_dashboard.scss @@ -857,13 +857,16 @@ // status - language .status-language { - .icon, .title { - display: inline-block !important; // needed for LMS horrible specificity + .icon { + @include font-size(17); + display: inline-block; vertical-align: middle; + margin-right: ($baseline/4); + color: $black; } - .icon { - margin-right: ($baseline/4); + .title .icon { + opacity: 0.75; // needed to overcome bad specificity elsewhere } } diff --git a/lms/templates/dashboard/_dashboard_info_language.html b/lms/templates/dashboard/_dashboard_info_language.html index 912b55c18c..80a6c0220e 100644 --- a/lms/templates/dashboard/_dashboard_info_language.html +++ b/lms/templates/dashboard/_dashboard_info_language.html @@ -3,8 +3,8 @@ <%namespace name='static' file='../static_content.html'/>
  • - + ${_("Preferred Language")} (${_("edit")}) From 48686793d794cd909092f07f90082f7e6e0a761f Mon Sep 17 00:00:00 2001 From: thedeadparrot Date: Fri, 14 Feb 2014 08:37:12 -0500 Subject: [PATCH 17/25] Clean up tests. --- common/djangoapps/student/views.py | 1 - common/djangoapps/user_api/models.py | 1 + .../user_api/tests/test_middleware.py | 3 +-- common/test/acceptance/tests/test_lms.py | 19 ++++++++++--------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index ead9c67db6..386fd1ae22 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -27,7 +27,6 @@ from django.http import (HttpResponse, HttpResponseBadRequest, HttpResponseForbi from django.shortcuts import redirect from django_future.csrf import ensure_csrf_cookie from django.utils.http import cookie_date, base36_to_int -from django.utils import translation from django.utils.translation import ugettext as _ from django.views.decorators.http import require_POST, require_GET diff --git a/common/djangoapps/user_api/models.py b/common/djangoapps/user_api/models.py index 91e0a77209..0207929fa1 100644 --- a/common/djangoapps/user_api/models.py +++ b/common/djangoapps/user_api/models.py @@ -1,6 +1,7 @@ from django.contrib.auth.models import User from django.db import models +# this is the UserPreference key for the user's preferred language LANGUAGE_KEY = 'pref-lang' diff --git a/common/djangoapps/user_api/tests/test_middleware.py b/common/djangoapps/user_api/tests/test_middleware.py index 36f59363b1..a3bbe8076b 100644 --- a/common/djangoapps/user_api/tests/test_middleware.py +++ b/common/djangoapps/user_api/tests/test_middleware.py @@ -14,10 +14,9 @@ class TestUserPreferenceMiddleware(TestCase): def setUp(self): self.middleware = UserPreferenceMiddleware() - self.request_factory = RequestFactory() self.session_middleware = SessionMiddleware() self.user = UserFactory.create() - self.request = self.request_factory.get('/somewhere') + self.request = RequestFactory().get('/somewhere') self.request.user = self.user self.session_middleware.process_request(self.request) diff --git a/common/test/acceptance/tests/test_lms.py b/common/test/acceptance/tests/test_lms.py index c12004a7b5..25e1a4b2d8 100644 --- a/common/test/acceptance/tests/test_lms.py +++ b/common/test/acceptance/tests/test_lms.py @@ -82,16 +82,18 @@ class LanguageTest(UniqueCourseTest): super(LanguageTest, self).setUp() self.dashboard_page = DashboardPage(self.browser) + self.test_new_lang = 'eo' + # This string is unicode for "ÇÜRRÉNT ÇØÜRSÉS", which should appear in our Dummy Esperanto page + self.current_courses_text = u"\xc7\xdcRR\xc9NT \xc7\xd8\xdcRS\xc9S" + def test_change_lang(self): AutoAuthPage(self.browser, course_id=self.course_id).visit() self.dashboard_page.visit() # Change language to Dummy Esperanto - self.dashboard_page.change_language("eo") + self.dashboard_page.change_language(self.test_new_lang) - # This string is unicode for "ÇÜRRÉNT ÇØÜRSÉS", which should appear in our Dummy Esperanto page - seektext = u"\xc7\xdcRR\xc9NT \xc7\xd8\xdcRS\xc9S" - self.browser.is_text_present(seektext) - self.assertTrue(self.browser.is_text_present(seektext)) + self.browser.is_text_present(self.current_courses_text) + self.assertTrue(self.browser.is_text_present(self.current_courses_text)) def test_language_persists(self): auto_auth_page = AutoAuthPage(self.browser, course_id=self.course_id) @@ -99,7 +101,7 @@ class LanguageTest(UniqueCourseTest): self.dashboard_page.visit() # Change language to Dummy Esperanto - self.dashboard_page.change_language("eo") + self.dashboard_page.change_language(self.test_new_lang) # destroy session self.browser._cookie_manager.delete() @@ -109,9 +111,8 @@ class LanguageTest(UniqueCourseTest): self.dashboard_page.visit() # This string is unicode for "ÇÜRRÉNT ÇØÜRSÉS", which should appear in our Dummy Esperanto page - seektext = u"\xc7\xdcRR\xc9NT \xc7\xd8\xdcRS\xc9S" - self.browser.is_text_present(seektext) - self.assertTrue(self.browser.is_text_present(seektext)) + self.browser.is_text_present(self.current_courses_text) + self.assertTrue(self.browser.is_text_present(self.current_courses_text)) class HighLevelTabTest(UniqueCourseTest): From 7e38c3ad6bffeaf9a8f5ac2cff0ae8e29b640394 Mon Sep 17 00:00:00 2001 From: thedeadparrot Date: Fri, 14 Feb 2014 08:50:36 -0500 Subject: [PATCH 18/25] Use a given default for getting a preference --- common/djangoapps/user_api/models.py | 6 +++--- common/djangoapps/user_api/tests/test_views.py | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/common/djangoapps/user_api/models.py b/common/djangoapps/user_api/models.py index 0207929fa1..ce3785fe1b 100644 --- a/common/djangoapps/user_api/models.py +++ b/common/djangoapps/user_api/models.py @@ -24,15 +24,15 @@ class UserPreference(models.Model): user_pref.save() @classmethod - def get_preference(cls, user, preference_key): + def get_preference(cls, user, preference_key, default=None): """ Gets the user preference value for a given key - Returns None if there isn't a preference for the given key + Returns the given default if there isn't a preference for the given key """ try: user_pref = cls.objects.get(user=user, key=preference_key) return user_pref.value except cls.DoesNotExist: - return None + return default diff --git a/common/djangoapps/user_api/tests/test_views.py b/common/djangoapps/user_api/tests/test_views.py index fbbe86a0d0..b7ac3c07d9 100644 --- a/common/djangoapps/user_api/tests/test_views.py +++ b/common/djangoapps/user_api/tests/test_views.py @@ -83,6 +83,10 @@ class ApiTestCase(TestCase): """Assert that the given response has the status code 403""" self.assertEqual(response.status_code, 403) + def assertHttpBadRequest(self, response): + """Assert that the given response has the status code 403""" + self.assertEqual(response.status_code, 400) + def assertHttpMethodNotAllowed(self, response): """Assert that the given response has the status code 405""" self.assertEqual(response.status_code, 405) @@ -358,7 +362,7 @@ class UserPreferenceViewSetTest(UserApiTestCase): ) -class TestLanguageSetting(TestCase): +class TestLanguageSetting(ApiTestCase): """ Test setting languages """ @@ -369,7 +373,7 @@ class TestLanguageSetting(TestCase): lang = 'en' response = self.client.post(reverse('user_api_set_language'), {'language': lang}) - self.assertEqual(response.status_code, 200) + self.assertHttpOK(response) user_pref = UserPreference.get_preference(user, LANGUAGE_KEY) self.assertEqual(user_pref, lang) @@ -379,6 +383,6 @@ class TestLanguageSetting(TestCase): response = self.client.post(reverse('user_api_set_language')) - self.assertEqual(response.status_code, 400) + self.assertHttpBadRequest(response) self.assertIsNone(UserPreference.get_preference(user, LANGUAGE_KEY)) From f6e14e62b5968a19ef2ab570fdecc55884e7bb7c Mon Sep 17 00:00:00 2001 From: thedeadparrot Date: Fri, 14 Feb 2014 09:02:53 -0500 Subject: [PATCH 19/25] Change setlang url --- common/djangoapps/user_api/urls.py | 2 +- lms/templates/dashboard.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/djangoapps/user_api/urls.py b/common/djangoapps/user_api/urls.py index 9dac1e31c0..b904ebc446 100644 --- a/common/djangoapps/user_api/urls.py +++ b/common/djangoapps/user_api/urls.py @@ -9,5 +9,5 @@ user_api_router.register(r'user_prefs', user_api_views.UserPreferenceViewSet) urlpatterns = patterns( '', url(r'^v1/', include(user_api_router.urls)), - url(r'^setlang/', 'user_api.views.set_language', name='user_api_set_language') + url(r'^v1/setlang/', 'user_api.views.set_language', name='user_api_set_language') ) diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 0db3c6a897..1e480770a2 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -85,7 +85,7 @@ $("#submit-lang").click(function(event, xhr) { event.preventDefault(); - $.post('/user_api/setlang/', + $.post('/user_api/v1/setlang/', {"language": $('#settings-language-value').val()}) .done( function(data){ From afdd8d68cbd99d66aad5c4bd1f91811b16be32cd Mon Sep 17 00:00:00 2001 From: thedeadparrot Date: Fri, 14 Feb 2014 10:19:29 -0500 Subject: [PATCH 20/25] Better dashboard display behavior * Don't show sidebar if only one language is present * only add in the default language code if it's not already present --- common/djangoapps/student/views.py | 3 ++- lms/templates/dashboard.html | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 386fd1ae22..d493608c5a 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -472,7 +472,8 @@ def dashboard(request): language_options = DarkLangConfig.current().released_languages_list - language_options.append(settings.LANGUAGE_CODE) + if settings.LANGUAGE_CODE not in language_options: + language_options.append(settings.LANGUAGE_CODE) cur_lang_code = UserPreference.get_preference(request.user, LANGUAGE_KEY) if cur_lang_code: diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 1e480770a2..b4b122f497 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -206,7 +206,9 @@ ${ user.email | h }
  • + %if len(language_options) > 1: <%include file='dashboard/_dashboard_info_language.html' /> + %endif % if external_auth_map is None or 'shib' not in external_auth_map.external_domain: