From 7e2a174eec98b38583022ba69d6c687d146c543e Mon Sep 17 00:00:00 2001 From: Andy Armstrong Date: Fri, 20 May 2016 23:08:32 -0400 Subject: [PATCH] Move discussion board to the Pattern Library TNL-4622 --- cms/static/sass/_base.scss | 2 +- .../view/discussion_thread_view_spec.coffee | 4 +- .../discussion/discussion-home.underscore | 2 +- .../templates/discussion/thread.underscore | 13 +- .../test/acceptance/pages/lms/discussion.py | 66 ++-- .../tests/discussion/test_discussion.py | 16 +- common/test/acceptance/tests/lms/test_lms.py | 46 ++- lms/djangoapps/courseware/testutils.py | 2 +- .../django_comment_client/forum/views.py | 8 +- .../teams/templates/team-profile.underscore | 6 +- lms/envs/common.py | 12 + lms/static/images/bg-texture.png | Bin 2092 -> 0 bytes lms/static/sass/_build-lms-v1.scss | 2 +- lms/static/sass/_build-lms-v2.scss | 3 + lms/static/sass/_developer.scss | 8 +- lms/static/sass/base/_base.scss | 2 +- lms/static/sass/base/_variables.scss | 3 +- lms/static/sass/course/base/_base.scss | 3 - .../sass/course/courseware/_sidebar.scss | 2 +- lms/static/sass/discussion/_build.scss | 39 ++ lms/static/sass/discussion/_discussion.scss | 129 ++---- lms/static/sass/discussion/_mixins.scss | 13 +- .../sass/discussion/elements/_actions.scss | 16 +- .../sass/discussion/elements/_editor.scss | 10 +- .../sass/discussion/elements/_navigation.scss | 39 +- .../discussion/lms-discussion-main-rtl.scss | 15 + .../sass/discussion/lms-discussion-main.scss | 15 + .../sass/discussion/utilities/_shame.scss | 2 +- .../utilities/_v1-compatibility.scss | 198 ++++++++++ .../discussion/utilities/_variables-v1.scss | 21 + .../discussion/utilities/_variables-v2.scss | 21 + .../sass/discussion/utilities/_variables.scss | 17 - .../discussion/views/_create-edit-post.scss | 36 +- lms/static/sass/discussion/views/_home.scss | 15 +- .../sass/discussion/views/_response.scss | 53 +-- lms/static/sass/discussion/views/_thread.scss | 83 ++-- lms/static/sass/elements/_program-card.scss | 14 +- lms/static/sass/shared-v2/_base.scss | 24 +- lms/static/sass/shared-v2/_components.scss | 49 +++ lms/static/sass/shared-v2/_footer.scss | 19 +- lms/static/sass/shared-v2/_header.scss | 197 ++++++---- lms/static/sass/shared-v2/_help-tab.scss | 16 +- lms/static/sass/shared-v2/_layouts.scss | 46 +++ lms/static/sass/shared-v2/_modal.scss | 44 +-- lms/static/sass/shared-v2/_navigation.scss | 2 +- lms/static/sass/shared-v2/_variables.scss | 7 + lms/static/sass/views/_program-list.scss | 24 +- lms/static/sass/views/_teams.scss | 367 +++++++++--------- .../courseware/course_navigation.html | 4 +- lms/templates/courseware/tabs.html | 9 +- .../_discussion_course_navigation.html | 5 +- .../discussion/_discussion_module.html | 9 +- lms/templates/discussion/index.html | 38 +- package.json | 2 +- screenshots/baseline/hinted-login-firefox.png | Bin 14521 -> 14512 bytes 55 files changed, 1091 insertions(+), 707 deletions(-) delete mode 100644 lms/static/images/bg-texture.png create mode 100644 lms/static/sass/discussion/_build.scss create mode 100644 lms/static/sass/discussion/lms-discussion-main-rtl.scss create mode 100644 lms/static/sass/discussion/lms-discussion-main.scss create mode 100644 lms/static/sass/discussion/utilities/_v1-compatibility.scss create mode 100644 lms/static/sass/discussion/utilities/_variables-v1.scss create mode 100644 lms/static/sass/discussion/utilities/_variables-v2.scss delete mode 100644 lms/static/sass/discussion/utilities/_variables.scss create mode 100644 lms/static/sass/shared-v2/_components.scss create mode 100644 lms/static/sass/shared-v2/_layouts.scss create mode 100644 lms/static/sass/shared-v2/_variables.scss diff --git a/cms/static/sass/_base.scss b/cms/static/sass/_base.scss index fc631e177a..a8fefa28d5 100644 --- a/cms/static/sass/_base.scss +++ b/cms/static/sass/_base.scss @@ -626,7 +626,7 @@ hr.divide { // ==================== // UI - semantically hide text -.sr { +.sr, .sr-only { @extend %cont-text-sr; } diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee index 510f896a9a..24970d6510 100644 --- a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee +++ b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee @@ -133,8 +133,8 @@ describe "DiscussionThreadView", -> checkVoteDisplay = (originallyClosed, mode) -> view = createDiscussionThreadView(originallyClosed, mode) - expect(view.$('.forum-thread-main-wrapper .action-vote').is(":visible")).toBe(not originallyClosed) - expect(view.$('.forum-thread-main-wrapper .display-vote').is(":visible")).toBe(originallyClosed) + expect(view.$('.thread-main-wrapper .action-vote').is(":visible")).toBe(not originallyClosed) + expect(view.$('.thread-main-wrapper .display-vote').is(":visible")).toBe(originallyClosed) view.$(".action-close").click() expect(view.$('.action-vote').is(":visible")).toBe(originallyClosed) expect(view.$('.display-vote').is(":visible")).toBe(not originallyClosed) diff --git a/common/static/common/templates/discussion/discussion-home.underscore b/common/static/common/templates/discussion/discussion-home.underscore index e07b7c49a8..3bd825a747 100644 --- a/common/static/common/templates/discussion/discussion-home.underscore +++ b/common/static/common/templates/discussion/discussion-home.underscore @@ -1,6 +1,6 @@
- <%- gettext("DISCUSSION HOME:") %> + <%- gettext("Discussion Home") %> <% if (window.courseName) { %>

<%- window.courseName %>

<% } %> diff --git a/common/static/common/templates/discussion/thread.underscore b/common/static/common/templates/discussion/thread.underscore index a21f07a8a4..d988824e30 100644 --- a/common/static/common/templates/discussion/thread.underscore +++ b/common/static/common/templates/discussion/thread.underscore @@ -1,21 +1,20 @@
-
+
    -
    -
    +
    <% if (!readOnly) { %>
    -
    <% } %> +
      <% if (can_create_comment && !readOnly) { %>
      -

      <%- gettext("Post a response:") %>

      +

      <%- gettext("Add a response:") %>

        diff --git a/common/test/acceptance/pages/lms/discussion.py b/common/test/acceptance/pages/lms/discussion.py index 3a666f09e1..ffb4d82b01 100644 --- a/common/test/acceptance/pages/lms/discussion.py +++ b/common/test/acceptance/pages/lms/discussion.py @@ -38,12 +38,22 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): text_list = self._find_within(selector).text return text_list[0] if text_list else None - def _is_element_visible(self, selector): + def is_element_visible(self, selector): + """ + Returns true if the element matching the specified selector is visible. + + Args: + selector (str): The CSS selector that matches the desired element. + + Returns: + bool: True if the element is visible. + + """ query = self._find_within(selector) return query.present and query.visible @contextmanager - def _secondary_action_menu_open(self, ancestor_selector): + def secondary_action_menu_open(self, ancestor_selector): """ Given the selector for an ancestor of a secondary menu, return a context manager that will open and close the menu @@ -51,14 +61,14 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): self.wait_for_ajax() self._find_within(ancestor_selector + " .action-more").click() EmptyPromise( - lambda: self._is_element_visible(ancestor_selector + " .actions-dropdown"), + lambda: self.is_element_visible(ancestor_selector + " .actions-dropdown"), "Secondary action menu opened" ).fulfill() yield - if self._is_element_visible(ancestor_selector + " .actions-dropdown"): + if self.is_element_visible(ancestor_selector + " .actions-dropdown"): self._find_within(ancestor_selector + " .action-more").click() EmptyPromise( - lambda: not self._is_element_visible(ancestor_selector + " .actions-dropdown"), + lambda: not self.is_element_visible(ancestor_selector + " .actions-dropdown"), "Secondary action menu closed" ).fulfill() @@ -96,7 +106,7 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): def has_add_response_button(self): """Returns true if the add response button is visible, false otherwise""" - return self._is_element_visible(".add-response-btn") + return self.is_element_visible(".add-response-btn") def click_add_response_button(self): """ @@ -112,11 +122,11 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): @wait_for_js def is_response_editor_visible(self, response_id): """Returns true if the response editor is present, false otherwise""" - return self._is_element_visible(".response_{} .edit-post-body".format(response_id)) + return self.is_element_visible(".response_{} .edit-post-body".format(response_id)) @wait_for_js def is_discussion_body_visible(self): - return self._is_element_visible(".post-body") + return self.is_element_visible(".post-body") def verify_mathjax_preview_available(self): """ Checks that MathJax Preview css class is present """ @@ -128,26 +138,26 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): def verify_mathjax_rendered(self): """ Checks that MathJax css class is present """ self.wait_for( - lambda: self._is_element_visible(".MathJax_SVG"), + lambda: self.is_element_visible(".MathJax_SVG"), description="MathJax Preview is rendered" ) def is_response_visible(self, comment_id): """Returns true if the response is viewable onscreen""" self.wait_for_ajax() - return self._is_element_visible(".response_{} .response-body".format(comment_id)) + return self.is_element_visible(".response_{} .response-body".format(comment_id)) def is_response_editable(self, response_id): """Returns true if the edit response button is present, false otherwise""" - with self._secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): - return self._is_element_visible(".response_{} .discussion-response .action-edit".format(response_id)) + with self.secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): + return self.is_element_visible(".response_{} .discussion-response .action-edit".format(response_id)) def get_response_body(self, response_id): return self._get_element_text(".response_{} .response-body".format(response_id)) def start_response_edit(self, response_id): """Click the edit button for the response, loading the editing view""" - with self._secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): + with self.secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): self._find_within(".response_{} .discussion-response .action-edit".format(response_id)).first.click() EmptyPromise( lambda: self.is_response_editor_visible(response_id), @@ -172,10 +182,10 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): ).fulfill() def is_response_reported(self, response_id): - return self._is_element_visible(".response_{} .discussion-response .post-label-reported".format(response_id)) + return self.is_element_visible(".response_{} .discussion-response .post-label-reported".format(response_id)) def report_response(self, response_id): - with self._secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): + with self.secondary_action_menu_open(".response_{} .discussion-response".format(response_id)): self._find_within(".response_{} .discussion-response .action-report".format(response_id)).first.click() self.wait_for_ajax() EmptyPromise( @@ -253,35 +263,35 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): def is_show_comments_visible(self, response_id): """Returns true if the "show comments" link is visible for a response""" - return self._is_element_visible(".response_{} .action-show-comments".format(response_id)) + return self.is_element_visible(".response_{} .action-show-comments".format(response_id)) def show_comments(self, response_id): """Click the "show comments" link for a response""" self._find_within(".response_{} .action-show-comments".format(response_id)).first.click() EmptyPromise( - lambda: self._is_element_visible(".response_{} .comments".format(response_id)), + lambda: self.is_element_visible(".response_{} .comments".format(response_id)), "Comments shown" ).fulfill() def is_add_comment_visible(self, response_id): """Returns true if the "add comment" form is visible for a response""" - return self._is_element_visible("#wmd-input-comment-body-{}".format(response_id)) + return self.is_element_visible("#wmd-input-comment-body-{}".format(response_id)) def is_comment_visible(self, comment_id): """Returns true if the comment is viewable onscreen""" - return self._is_element_visible("#comment_{} .response-body".format(comment_id)) + return self.is_element_visible("#comment_{} .response-body".format(comment_id)) def get_comment_body(self, comment_id): return self._get_element_text("#comment_{} .response-body".format(comment_id)) def is_comment_deletable(self, comment_id): """Returns true if the delete comment button is present, false otherwise""" - with self._secondary_action_menu_open("#comment_{}".format(comment_id)): - return self._is_element_visible("#comment_{} .action-delete".format(comment_id)) + with self.secondary_action_menu_open("#comment_{}".format(comment_id)): + return self.is_element_visible("#comment_{} .action-delete".format(comment_id)) def delete_comment(self, comment_id): with self.handle_alert(): - with self._secondary_action_menu_open("#comment_{}".format(comment_id)): + with self.secondary_action_menu_open("#comment_{}".format(comment_id)): self._find_within("#comment_{} .action-delete".format(comment_id)).first.click() EmptyPromise( lambda: not self.is_comment_visible(comment_id), @@ -290,12 +300,12 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): def is_comment_editable(self, comment_id): """Returns true if the edit comment button is present, false otherwise""" - with self._secondary_action_menu_open("#comment_{}".format(comment_id)): - return self._is_element_visible("#comment_{} .action-edit".format(comment_id)) + with self.secondary_action_menu_open("#comment_{}".format(comment_id)): + return self.is_element_visible("#comment_{} .action-edit".format(comment_id)) def is_comment_editor_visible(self, comment_id): """Returns true if the comment editor is present, false otherwise""" - return self._is_element_visible(".edit-comment-body[data-id='{}']".format(comment_id)) + return self.is_element_visible(".edit-comment-body[data-id='{}']".format(comment_id)) def _get_comment_editor_value(self, comment_id): return self._find_within("#wmd-input-edit-comment-body-{}".format(comment_id)).text[0] @@ -303,7 +313,7 @@ class DiscussionThreadPage(PageObject, DiscussionPageMixin): def start_comment_edit(self, comment_id): """Click the edit button for the comment, loading the editing view""" old_body = self.get_comment_body(comment_id) - with self._secondary_action_menu_open("#comment_{}".format(comment_id)): + with self.secondary_action_menu_open("#comment_{}".format(comment_id)): self._find_within("#comment_{} .action-edit".format(comment_id)).first.click() EmptyPromise( lambda: ( @@ -396,8 +406,8 @@ class DiscussionTabSingleThreadPage(CoursePage): return getattr(self.thread_page, name) def close_open_thread(self): - with self.thread_page._secondary_action_menu_open(".forum-thread-main-wrapper"): - self._find_within(".forum-thread-main-wrapper .action-close").first.click() + with self.thread_page.secondary_action_menu_open(".thread-main-wrapper"): + self._find_within(".thread-main-wrapper .action-close").first.click() def is_focused_on_element(self, selector): """ diff --git a/common/test/acceptance/tests/discussion/test_discussion.py b/common/test/acceptance/tests/discussion/test_discussion.py index a6e44091ff..0005e318ee 100644 --- a/common/test/acceptance/tests/discussion/test_discussion.py +++ b/common/test/acceptance/tests/discussion/test_discussion.py @@ -403,17 +403,17 @@ class DiscussionOpenClosedThreadTest(BaseDiscussionTestCase): def test_originally_open_thread_vote_display(self): page = self.setup_openclosed_thread_page() - self.assertFalse(page._is_element_visible('.forum-thread-main-wrapper .action-vote')) - self.assertTrue(page._is_element_visible('.forum-thread-main-wrapper .display-vote')) - self.assertFalse(page._is_element_visible('.response_response1 .action-vote')) - self.assertTrue(page._is_element_visible('.response_response1 .display-vote')) + self.assertFalse(page.is_element_visible('.thread-main-wrapper .action-vote')) + self.assertTrue(page.is_element_visible('.thread-main-wrapper .display-vote')) + self.assertFalse(page.is_element_visible('.response_response1 .action-vote')) + self.assertTrue(page.is_element_visible('.response_response1 .display-vote')) def test_originally_closed_thread_vote_display(self): page = self.setup_openclosed_thread_page(True) - self.assertTrue(page._is_element_visible('.forum-thread-main-wrapper .action-vote')) - self.assertFalse(page._is_element_visible('.forum-thread-main-wrapper .display-vote')) - self.assertTrue(page._is_element_visible('.response_response1 .action-vote')) - self.assertFalse(page._is_element_visible('.response_response1 .display-vote')) + self.assertTrue(page.is_element_visible('.thread-main-wrapper .action-vote')) + self.assertFalse(page.is_element_visible('.thread-main-wrapper .display-vote')) + self.assertTrue(page.is_element_visible('.response_response1 .action-vote')) + self.assertFalse(page.is_element_visible('.response_response1 .display-vote')) @attr('a11y') def test_page_accessibility(self): diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index ddfed9c6ff..fa62036db9 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -186,38 +186,44 @@ class LoginFromCombinedPageTest(UniqueCourseTest): course_names = self.dashboard_page.wait_for_page().available_courses self.assertIn(self.course_info["display_name"], course_names) - # Now logout and check that we can log back in instantly (because the account is linked): - LogoutPage(self.browser).visit() + try: + # Now logout and check that we can log back in instantly (because the account is linked): + LogoutPage(self.browser).visit() - self.login_page.visit() - self.login_page.click_third_party_dummy_provider() + self.login_page.visit() + self.login_page.click_third_party_dummy_provider() - self.dashboard_page.wait_for_page() - - self._unlink_dummy_account() + self.dashboard_page.wait_for_page() + finally: + self._unlink_dummy_account() def test_hinted_login(self): """ Test the login page when coming from course URL that specified which third party provider to use """ # Create a user account and link it to third party auth with the dummy provider: AutoAuthPage(self.browser, course_id=self.course_id).visit() self._link_dummy_account() - LogoutPage(self.browser).visit() + try: + LogoutPage(self.browser).visit() - # When not logged in, try to load a course URL that includes the provider hint ?tpa_hint=... - course_page = CoursewarePage(self.browser, self.course_id) - self.browser.get(course_page.url + '?tpa_hint=oa2-dummy') + # When not logged in, try to load a course URL that includes the provider hint ?tpa_hint=... + course_page = CoursewarePage(self.browser, self.course_id) + self.browser.get(course_page.url + '?tpa_hint=oa2-dummy') - # We should now be redirected to the login page - self.login_page.wait_for_page() - self.assertIn("Would you like to sign in using your Dummy credentials?", self.login_page.hinted_login_prompt) - # Baseline screen-shots are different for chrome and firefox. - self.assertScreenshot('#hinted-login-form', 'hinted-login-{}'.format(self.browser.name)) - self.login_page.click_third_party_dummy_provider() + # We should now be redirected to the login page + self.login_page.wait_for_page() + self.assertIn( + "Would you like to sign in using your Dummy credentials?", + self.login_page.hinted_login_prompt + ) - # We should now be redirected to the course page - course_page.wait_for_page() + # Baseline screen-shots are different for chrome and firefox. + self.assertScreenshot('#hinted-login-form', 'hinted-login-{}'.format(self.browser.name)) + self.login_page.click_third_party_dummy_provider() - self._unlink_dummy_account() + # We should now be redirected to the course page + course_page.wait_for_page() + finally: + self._unlink_dummy_account() def _link_dummy_account(self): """ Go to Account Settings page and link the user's account to the Dummy provider """ diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py index 194421d14b..a6618fef42 100644 --- a/lms/djangoapps/courseware/testutils.py +++ b/lms/djangoapps/courseware/testutils.py @@ -26,7 +26,7 @@ class RenderXBlockTestMixin(object): # DOM elements that appear in the LMS Courseware, # but are excluded from the xBlock-only rendering. COURSEWARE_CHROME_HTML_ELEMENTS = [ - '
        diff --git a/lms/envs/common.py b/lms/envs/common.py index 4c66a79245..3f7c85e75c 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1445,6 +1445,18 @@ PIPELINE_CSS = { ], 'output_filename': 'css/lms-style-student-notes.css', }, + 'style-discussion-main': { + 'source_filenames': [ + 'css/discussion/lms-discussion-main.css', + ], + 'output_filename': 'css/discussion/lms-discussion-main.css', + }, + 'style-discussion-main-rtl': { + 'source_filenames': [ + 'css/discussion/lms-discussion-main-rtl.css', + ], + 'output_filename': 'css/discussion/lms-discussion-main-rtl.css', + }, 'style-xmodule-annotations': { 'source_filenames': [ 'css/vendor/ova/annotator.css', diff --git a/lms/static/images/bg-texture.png b/lms/static/images/bg-texture.png deleted file mode 100644 index 8ca717fb916de4e77477111f31ba007b38afaa65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2092 zcmV+{2-Ek8P)gww2>+9_7?CtIC?(XjI@9*&N@bU5S^78WY^Ya8KRPg`+01k9gPE!C1 z6douuJx5VnW^j6hO4G0v000N0NklMdTrgl8MrEzC zeDaKCnv-J6!iDJ{RyOU^U^u(&+BpsIFzwS*`-qbivc+_!LL19+#a=13?o-&+meB(z zCpKj{GMO=uN1-RmD7Zub98r5v`|Qx3G3~~cfo9EpDrjw&Q~gwp+7#QZAXmYq7Su>` zMYFZBBL(BuHe-}0Zeu`5@%GdjEJ{v41v0ctZKXBsE)1le7`clm!C>Sm{dM4sL<7iTg}P{%!dBvQLkM;=V*PS9G*hu@=*h=zQD~q& zWe@D8X0zvjM&z@Ktj`Id#azZosL~%^;QIM!;u+a}nCCfxa{IE&?k>CINmbbxHNBM* zOkn&}T=s+GffAsp_0BT=1)NnL6E2RZZMHILn{q>Tpw-dEC$Kb-e|{>9k7tbv5m!%{G{;A999aam1&Aj%$9(WaAz}fjMb{m zY1KXrg#`8wrhUSZ%W!^du%Y2NO53Ja%vQ@*phRn9tQ&PyP@98k*XgL*=KeEL&)(kb z+DXK0yEJNgAGt0%&cf3pS0#RSjY!(2Qvk`M1CWBKpQ(%XcoJ)_eP|Hc#M(?>-nivX z*$sKJkcDj-yAORW1_gYmphNEm_3ZsI*Fxjxri70hc3JS}3t7w}RhB_*nj$2(v)E2G@iXD8avwmY#muVTg>>hz>O_dTHOg3f5 zNj8Pr5XgE{g+yA=u0ku4+Hmk(Nz}U^g?G0fwz^J#_ukfP`4)$cy2luQ5aW8?)cALt zFEz&ER&ezet+!qz5NUd(LiYBTtHq}eAsIo-~ z%sdIUAYENjf15)WrECmf#7HN4jH6A%xY~CeV+>`rGUQgb>S1ipXJ%@Bk*&XVXY1YY z#oXeq+nCv6THq-=`?Q$xIYm9~jd8V86M5WmS4mB=OH`QQMwn!94n?rnKY#(ODr2^I zg{NEt0?Gw=vb%-)rTSt~yK)&(67WE9v!$L1eo7X&sq0h;i(y)kBzh;U?l$tp31seX zF2^26>n(8li2~LaEZ?^c%lfZ4^6|O)o@IryV`7CEAT6e4Rn88IM|8&^w{ebgQtIkW z(hO76%*8q(D$ygFXYU$O)GIk{`TsB)*K5qd=Zb%Q$-bgEk~^|-$~cUA9AU z8!7+GBdhcNPFcU^2UH7M+QqbWbrs&zMoD{5sgn+wT`8sgtWvkrxD*;(YHD`<@L8{b zD6I&!D0<>@M~tUO&1k(r%l)D-m!I*bM=hM_a_mX$Z8PD>U^Z06w;NBntm2DJwtm~u z`~j)0XxsImb4idS*yP|QqpG1zyWQ^GnL;>&3fm5Y<%?6c%7+l|`kUijf1;zPy~F&t zjie);@%Ev1Jy_#U zdwPB9UR=4n>q?{0axO~0tq0dXnR`cl#GPzXIYxX#1+Ld>#eWXo*ULKY6A-MMUEJY) z5Lk~OQ|gFz8`-1{yC)eWoLzC-9d@_kmPI>ZY>h@;V77w@`%aL^JS~>|{+?fNO`Sht zmi5-u`D1LaugvK0YW?*tCI9#B(6ZGW-I8XureBY@CCt+>4QwvTM!vSmSe9-Rm8ygb zwWq+ES?Z1B3 zNblGRtlyANveR8KqB@Z}puUxbIcdf09d6WHJCd?KSr)uZPb?ZS<>>~>;g+$=pmHp} zz35)AG0~qpl=b>#{#OcF@5<-3lSF5ntnUfXuLY9poq6zICtbghy#DcsUN2+8Pu`fU zW8n<%oRI6SuVOyd8SCHlD?DFz$o1mQ(m#5$^^S1hXRET_oupdDdhd&sJ8@dyU5b50 z)2vjdPAV>fOjl1s-DP;mv{~Qh*k>A?enLwwixcLmgM~5ck2~x)7KZDOpP&7P<@gV4 Wg$vRHRNy`U0000 li { - border-top: 1px solid $gray-l4; + border-top: 1px solid $forum-color-border; padding: ($baseline/2) $baseline; } - blockquote { background: $gray-l4; border-radius: 3px; @@ -190,7 +159,7 @@ .comment-form-input { padding: ($baseline/4) ($baseline/2); - background-color: $white; + background-color: $forum-color-background; font-size: 14px; } diff --git a/lms/static/sass/discussion/views/_thread.scss b/lms/static/sass/discussion/views/_thread.scss index e75e747c6a..b2cce08d1e 100644 --- a/lms/static/sass/discussion/views/_thread.scss +++ b/lms/static/sass/discussion/views/_thread.scss @@ -14,9 +14,7 @@ body.discussion, .discussion-module { // post layout .discussion-post { - @include padding(($baseline*1.5), ($baseline*1.5), $baseline, ($baseline*1.5)); - @include border-radius(3px, 3px, 0, 0); - background-color: $white; + padding: 0 ($baseline/2); .wrapper-post-header { padding-bottom: 0; @@ -30,11 +28,25 @@ body.discussion, .discussion-module { .post-header-actions { @include float(right); - width: flex-grid(3,12); } - .posted-details { - color: $gray-d1; + .post-body { + width: flex-grid(10,12); + } + } + + .posted-details { + @extend %t-copy-sub2; + margin-top: ($baseline/5); + color: $gray-d1; + + .username { + @extend %t-strong; + display: inline; + } + + .timeago, .top-post-status { + color: inherit; } } @@ -52,7 +64,7 @@ body.discussion, .discussion-module { @include float(right); @include right($baseline); position: absolute; - top: ($baseline); + top: $baseline; } } @@ -73,18 +85,14 @@ body.discussion, .discussion-module { .comment-actions-list { @include float(right); } - - .posted-details { - margin-top: 0; - } } } // +thread - wrapper styling -.forum-thread-main-wrapper { - @include border-radius(3px, 3px, 0, 0); - border-bottom: 1px solid $white; // Prevent collapsing margins - background-color: $white; +.thread-wrapper { + .thread-main-wrapper { + padding-bottom: $baseline; + } } // +thread - elements - shared styles @@ -126,25 +134,9 @@ body.discussion { border-radius: 3px; } } - - // thread - header content details - .posted-details { - @extend %t-copy-sub2; - margin-top: ($baseline/5); - color: $gray-d1; - - .username { - @extend %t-strong; - display: inline; - } - - .timeago, .top-post-status { - color: inherit; - } - } } - .discussion-post .post-body, .discussion-response .response-body { + .discussion-response .response-body { @include padding-right($baseline); //ensures content doesn't overlap on post or response actions. } } @@ -179,11 +171,8 @@ body.view-in-course .discussion-article { @extend %t-copy-sub2; margin-top: $baseline; color: $gray-d1; - padding: ($baseline*0.75); - background-color: $gray-l6; - border-radius: 3px; - // CASE: no courseware context or cohort visiblity rules + // CASE: no courseware context or cohort visibility rules &:empty { display: none; } @@ -195,10 +184,22 @@ body.view-in-course .discussion-article { } } -// +post - answered question - collapsed comment area -body.discussion, .discussion-thread.expanded { - .forum-thread-main-wrapper { - box-shadow: 0 1px 3px $shadow; +// Layout control for discussion modules that does not apply to the discussion board +.discussion-module { + .discussion-thread { + .thread-main-wrapper, .thread-responses-wrapper { + padding: $baseline; + } + } + + .btn-brand { + @include blue-button; + display: inline-block; + padding-bottom: ($baseline/10); + height: 37px; + + &:hover, &:focus { + border-color: #222; + } } } - diff --git a/lms/static/sass/elements/_program-card.scss b/lms/static/sass/elements/_program-card.scss index fd2353eca5..044416ea86 100644 --- a/lms/static/sass/elements/_program-card.scss +++ b/lms/static/sass/elements/_program-card.scss @@ -10,7 +10,7 @@ @include span(12); border: 1px solid $border-color-l3; border-bottom: none; - margin-bottom: $baseline + px; + margin-bottom: $baseline; position: relative; @include susy-media($bp-screen-md) { @@ -58,7 +58,7 @@ } .text-section{ - padding: 40px $baseline + px $baseline + px; + padding: 40px $baseline $baseline; position: relative; margin-top: 156px; @@ -71,7 +71,7 @@ font-size: font-size(x-small); color: palette(grayscale, dark); position: absolute; - top: $baseline + px; + top: $baseline; width: calc(100% - 40px); } @@ -91,18 +91,18 @@ .xseries-icon{ @include float(right); - @include margin-right($baseline*0.25 + px); + @include margin-right($baseline*0.25); background: url('#{$static-path}/images/icon-sm-xseries-black.png') no-repeat; background-color: transparent; background-size: 100%; - width: ($baseline*0.7 + px); - height: ($baseline*0.7 + px); + width: ($baseline*0.7); + height: ($baseline*0.7); } } .hd-3 { color: palette(grayscale, x-dark); - min-height: ($baseline*3) + px; + min-height: ($baseline*3); line-height: 1; } diff --git a/lms/static/sass/shared-v2/_base.scss b/lms/static/sass/shared-v2/_base.scss index 12bba147e5..379cd0a176 100644 --- a/lms/static/sass/shared-v2/_base.scss +++ b/lms/static/sass/shared-v2/_base.scss @@ -1,11 +1,19 @@ // LMS base styles -.content-wrapper { - width: span(12); - margin: 0 auto; - background: palette(grayscale, white-t); - - @media print { - padding-bottom: 0; - } +.window-wrap { + background-color: $lms-background-color; +} + +.content-wrapper { + width: span(12); + margin: 0 auto; + + @media print { + padding-bottom: 0; + } +} + +// Support .sr as well as .sr-only for backward compatibility +.sr { + @extend .sr-only; } diff --git a/lms/static/sass/shared-v2/_components.scss b/lms/static/sass/shared-v2/_components.scss new file mode 100644 index 0000000000..6044de724a --- /dev/null +++ b/lms/static/sass/shared-v2/_components.scss @@ -0,0 +1,49 @@ +// TODO: tabs should be added to the Pattern Library +.tabs { + @include clearfix(); + @extend %reset-lists; + @include border-top-radius(4px); + padding: ($baseline*0.75) 0 ($baseline*0.75) 0; + + .tab { + @include float(left); + list-style: none; + margin-bottom: 0; + + &.prominent { + @include margin-right(16px); + background: rgba(255, 255, 255, 0.5); + border-radius: 3px; + } + + &.prominent + li { + @include border-left(1px solid $lms-border-color); + padding-left: $baseline*0.75; + } + + a, + a:visited { + padding: ($baseline/2) ($baseline*0.75) 13px ($baseline*0.75); + display: block; + text-align: center; + text-decoration: none; + border-style: solid; + border-width: 0 0 4px 0; + border-bottom-color: transparent; + color: $lms-label-color; + font-size: 14px; + + &:hover, + &:focus { + color: $lms-active-color; + border-bottom-color: $lms-active-color; + } + + &.active { + color: $lms-active-color; + border-bottom-color: $lms-active-color; + background-color: transparent; + } + } + } +} diff --git a/lms/static/sass/shared-v2/_footer.scss b/lms/static/sass/shared-v2/_footer.scss index f88e9190a2..bf68aa26fe 100644 --- a/lms/static/sass/shared-v2/_footer.scss +++ b/lms/static/sass/shared-v2/_footer.scss @@ -3,9 +3,10 @@ .wrapper-footer { @extend %ui-print-excluded; + margin-top: ($baseline*2); box-shadow: 0 -1px 5px 0 $shadow-l1; border-top: 1px solid tint(palette(grayscale, light), 50%); - padding: 25px ($baseline/2 + px) ($baseline*1.5 + px) ($baseline/2 + px); + padding: 25px ($baseline/2) ($baseline*1.5) ($baseline/2); background: $footer-bg; clear: both; @@ -46,9 +47,13 @@ @include clearfix(); margin: $footer_margin; + ol { + list-style: none; + } + li { @include float(left); - margin-right: ($baseline*0.75) + px; + margin-right: ($baseline*0.75); a { color: tint($black, 20%); @@ -79,8 +84,8 @@ p { @include float(left); @include span(9); - margin-left: $baseline + px; - padding-left: $baseline + px; + margin-left: $baseline; + padding-left: $baseline; font-size: font-size(small); background: transparent url(/static/images/bg-footer-divider.jpg) 0 0 no-repeat; } @@ -95,7 +100,7 @@ } .wrapper-logo { - margin: ($baseline*0.75) + px 0; + margin: ($baseline*0.75) 0; a { display: inline-block; @@ -124,7 +129,7 @@ .nav-legal-02 a { &:before { - @include margin-right(($baseline/4) + px); + @include margin-right(($baseline/4)); content: "-"; } } @@ -189,7 +194,7 @@ width: 960px; .colophon-about img { - margin-top: ($baseline*1.5) + px; + margin-top: ($baseline*1.5); } } } diff --git a/lms/static/sass/shared-v2/_header.scss b/lms/static/sass/shared-v2/_header.scss index 1cd5486125..4120da6825 100644 --- a/lms/static/sass/shared-v2/_header.scss +++ b/lms/static/sass/shared-v2/_header.scss @@ -1,96 +1,127 @@ // LMS header styles .header-global { - @extend %ui-depth1; - box-sizing: border-box; - position: relative; - width: 100%; - border-bottom: 1px solid $gray-l1; - box-shadow: 0 1px 5px 0 $shadow-l1; - background: $header-bg; - - .wrapper-header { - @include clearfix(); + @extend %ui-depth1; box-sizing: border-box; - height: 74px; - margin: 0 auto; - padding: 10px 10px 0; + position: relative; width: 100%; - max-width: 1180px; + border-bottom: 1px solid $gray-l1; + box-shadow: 0 1px 5px 0 $shadow-l1; + background: $header-bg; - .logo { - @include float(left); - @include margin-right(39px); - @include margin-left(10px); - margin-top: 4px; - margin-bottom: 0; - position: relative; - } + .wrapper-header { + @include clearfix(); + box-sizing: border-box; + height: 74px; + margin: 0 auto; + padding: 10px 10px 0; + width: 100%; + max-width: 1180px; - .left { - @include float(left); - } - - .right { - @include float(right); - } - - .wrapper-user-menu { - @include float(right); - margin-top: 4px; - width: auto; - } - - .dropdown-menu { - @include text-align(left); - top: inherit; - } - - .list-inline { - &.nav-global { - margin-top: 12px; - } - - &.nav-courseware { - margin-top: 5px; - } - - .item { - font-weight: font-weight(semi-bold); - text-transform: uppercase; - - &.active { - a { - text-decoration: none; - color: $link-color; - } + .left { + @include float(left); } - } - } - .tab-nav-item{ - @include float(left); - display: flex; - margin: 0; - justify-content: center; - - .tab-nav-link{ - font-size: font-size(base); - font-weight: font-weight(semi-bold); - color: palette(grayscale, dark); - padding: 5px 25px 23px; - display: inline-block; - - &:active, - &:focus, - &:hover { - border-bottom: 4px solid $courseware-border-bottom-color; + .right { + @include float(right); } - } - .active{ - border-bottom: 4px solid $black-t3 !important; - } + .logo { + @include float(left); + @include margin-left(10px); + @include margin-right(10px); + margin-top: 4px; + margin-bottom: 0; + position: relative; + } + + .course-header { + @include float(left); + @include margin(12px, 10px, 0px, 10px); + color: $lms-label-color; + } + + .wrapper-user-menu { + @include float(right); + margin-top: 4px; + width: auto; + } + + .dropdown-menu { + @include text-align(left); + top: inherit; + } + + .list-inline { + &.nav-global { + margin-top: 12px; + margin-bottom: 0; + } + + &.nav-courseware { + margin-top: 5px; + } + + .item { + font-weight: font-weight(semi-bold); + text-transform: uppercase; + + &.active { + a { + text-decoration: none; + color: $link-color; + } + } + } + } + + .tab-nav-item{ + @include float(left); + display: flex; + margin: 0; + justify-content: center; + + .tab-nav-link{ + font-size: font-size(base); + font-weight: font-weight(semi-bold); + color: palette(grayscale, dark); + padding: 5px 25px 23px; + display: inline-block; + + &:active, + &:focus, + &:hover { + border-bottom: 4px solid $lms-border-color; + } + } + + .active{ + border-bottom: 4px solid $black-t3 !important; + } + } + } + + // Style the courseware's slim version of the header + &.slim { + .wrapper-header { + height: 60px; + + .logo img { + margin-top: 4px; + height: 30px; + } + + .course-header { + margin-top: 10px; + } + + .list-inline.nav-global { + margin-top: 10px; + } + + .wrapper-user-menu { + margin-top: 0; + } + } } - } } diff --git a/lms/static/sass/shared-v2/_help-tab.scss b/lms/static/sass/shared-v2/_help-tab.scss index 90e4258415..c9278d0e93 100644 --- a/lms/static/sass/shared-v2/_help-tab.scss +++ b/lms/static/sass/shared-v2/_help-tab.scss @@ -9,9 +9,9 @@ a:link, a:visited { cursor: pointer; - border: 1px solid palette(grayscale, light); + border: 1px solid $lms-border-color; border-top-style: none; - border-radius: 0 0 ($baseline/2) + px ($baseline/2) + px; + border-radius: 0 0 ($baseline/2) ($baseline/2); background: transparentize(palette(grayscale, white-t), 0.25); color: transparentize(palette(grayscale-cool, x-dark), 0.25); font-weight: bold; @@ -28,25 +28,25 @@ } .help-buttons { - padding: ($baseline/2) + px ($baseline*2.5) + px; + padding: ($baseline/2) ($baseline*2.5); a:link, a:visited { - padding: ($baseline*0.75) + px 0; + padding: ($baseline*0.75) 0; text-align: center; cursor: pointer; background: palette(grayscale, white-t); text-decoration: none; display: block; - border: 1px solid palette(grayscale, light); + border: 1px solid $lms-border-color; &#feedback_link_problem { border-bottom-style: none; - border-radius: ($baseline/2) + px ($baseline/2) + px 0 0; + border-radius: ($baseline/2) ($baseline/2) 0 0; } &#feedback_link_question { border-top-style: none; - border-radius: 0 0 ($baseline/2) + px ($baseline/2) + px; + border-radius: 0 0 ($baseline/2) ($baseline/2); } &:hover, &:focus { @@ -72,6 +72,6 @@ #feedback_success_wrapper { p { - padding: 0 $baseline + px $baseline + px $baseline + px; + padding: 0 $baseline $baseline $baseline; } } diff --git a/lms/static/sass/shared-v2/_layouts.scss b/lms/static/sass/shared-v2/_layouts.scss new file mode 100644 index 0000000000..1001eaeb61 --- /dev/null +++ b/lms/static/sass/shared-v2/_layouts.scss @@ -0,0 +1,46 @@ +// LMS layouts + +.content-wrapper { + max-width: 1180px; + padding-top: 10px; + + .page-header { + @include clearfix(); + border-bottom: 1px solid $lms-border-color; + padding: $baseline $baseline ($baseline/2) $baseline; + + .page-title { + @extend %t-title4; + margin-bottom: ($baseline/4); + text-transform: none; + color: $black; + } + + .page-description { + @extend %t-copy-sub1; + margin-bottom: ($baseline/4); + color: $gray; + } + } + + .page-header.has-secondary { + + .page-header-main { + display: inline-block; + width: flex-grid(8,12); + } + + .page-header-secondary { + @include text-align(right); + display: inline-block; + width: flex-grid(4,12); + vertical-align: text-bottom; + } + } + + .container { + border: 1px solid #c8c8c8; + background-color: $lms-container-background-color; + padding: $baseline; + } +} diff --git a/lms/static/sass/shared-v2/_modal.scss b/lms/static/sass/shared-v2/_modal.scss index 7aa623f8fa..7d405b44b0 100644 --- a/lms/static/sass/shared-v2/_modal.scss +++ b/lms/static/sass/shared-v2/_modal.scss @@ -26,12 +26,12 @@ z-index: z-index(mid-front); background: $modal-bg-color; border-radius: 0; - border: 1px solid rgba(0, 0, 0, 0.9); + border: 1px solid $lms-border-color; box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.7); overflow: hidden; - padding-left: ($baseline/2) + px; - padding-right: ($baseline/2) + px; - padding-bottom: ($baseline/2) + px; + padding-left: ($baseline/2); + padding-right: ($baseline/2); + padding-bottom: ($baseline/2); position: relative; p { @@ -46,15 +46,11 @@ } } - .sr { - @extend .sr-only; - } - header { z-index: z-index(mid-front); - margin-bottom: ($baseline*1.5) + px; + margin-bottom: ($baseline*1.5); overflow: hidden; - padding: 28px $baseline + px 0; + padding: 28px $baseline 0; position: relative; &::before { @@ -115,7 +111,7 @@ border: 1px solid rgb(143, 14, 14); color: rgb(143, 14, 14); display: none; - margin-bottom: $baseline + px; + margin-bottom: $baseline; padding: 12px; } @@ -124,21 +120,21 @@ border: 1px solid darken($yellow, 60%); color: darken($yellow, 60%); display: none; - margin-bottom: $baseline + px; + margin-bottom: $baseline; padding: 12px; } .activation-message, .message { - padding: 0 ($baseline*2) + px ($baseline/2) + px; + padding: 0 ($baseline*2) ($baseline/2); p { - margin-bottom: ($baseline/2) + px; + margin-bottom: ($baseline/2); } } form { margin-bottom: 12px; - padding: 0 ($baseline*2) + px $baseline + px; + padding: 0 ($baseline*2) $baseline; position: relative; z-index: 2; @@ -146,8 +142,8 @@ @include clearfix(); border-bottom: 1px solid rgb(210,210,210); box-shadow: 0 1px 0 0 rgba(255,255,255, 0.6); - margin-bottom: ($baseline*1.5) + px; - padding-bottom: ($baseline/2) + px; + margin-bottom: ($baseline*1.5); + padding-bottom: ($baseline/2); } label { @@ -170,14 +166,14 @@ } input[type="checkbox"] { - margin-right: ($baseline/4) + px; + margin-right: ($baseline/4); } textarea { background: rgb(255,255,255); display: block; height: 45px; - margin-bottom: $baseline + px; + margin-bottom: $baseline; width: 100%; } @@ -187,12 +183,12 @@ background: rgb(255,255,255); display: block; height: 45px; - margin-bottom: $baseline + px; + margin-bottom: $baseline; width: 100%; } .submit { - padding-top: ($baseline/2) + px; + padding-top: ($baseline/2); input[type="submit"] { @extend .btn-brand; @@ -244,10 +240,10 @@ #help_wrapper, #feedback_form_wrapper, .discussion-alert-wrapper { - padding: 0 ($baseline*1.5) + px ($baseline*1.5) + px ($baseline*1.5) + px; + padding: 0 ($baseline*1.5) ($baseline*1.5) ($baseline*1.5); header { - margin-bottom: $baseline + px; + margin-bottom: $baseline; padding-right: 0; padding-left: 0; } @@ -258,7 +254,7 @@ family: $font-family-sans-serif; } line-height: 1.475; - margin-top: ($baseline/2) + px; + margin-top: ($baseline/2); color: $lighter-base-font-color; } } diff --git a/lms/static/sass/shared-v2/_navigation.scss b/lms/static/sass/shared-v2/_navigation.scss index 69abf46f34..cf604ab96a 100644 --- a/lms/static/sass/shared-v2/_navigation.scss +++ b/lms/static/sass/shared-v2/_navigation.scss @@ -9,7 +9,7 @@ top: -($baseline*30); overflow: hidden; background: $white; - border-bottom: 1px solid palette(grayscale, white); + border-bottom: 1px solid $lms-border-color; padding: ($baseline*0.75) ($baseline/2); &:focus, diff --git a/lms/static/sass/shared-v2/_variables.scss b/lms/static/sass/shared-v2/_variables.scss new file mode 100644 index 0000000000..00d0a7a101 --- /dev/null +++ b/lms/static/sass/shared-v2/_variables.scss @@ -0,0 +1,7 @@ +// LMS variables + +$lms-background-color: palette(grayscale, white); // Why is the Pattern Library default background different? +$lms-container-background-color: palette(grayscale, white-t); +$lms-border-color: palette(grayscale, light); +$lms-label-color: palette(grayscale, black); +$lms-active-color: palette(primary, base); diff --git a/lms/static/sass/views/_program-list.scss b/lms/static/sass/views/_program-list.scss index 63b0654ca2..2bf6d30bc6 100644 --- a/lms/static/sass/views/_program-list.scss +++ b/lms/static/sass/views/_program-list.scss @@ -1,5 +1,5 @@ .program-list-wrapper { - padding: $baseline + px; + padding: $baseline; } .program-cards-container { @@ -13,15 +13,15 @@ .sidebar { @include span(12); @include float(right); - margin-bottom: $baseline + px; + margin-bottom: $baseline; @include susy-media($bp-screen-md) { @include span(3); } .aside { - padding: $baseline + px; - margin-bottom: $baseline + px; + padding: $baseline; + margin-bottom: $baseline; background-color: $body-bg; box-sizing: border-box; border: 1px solid $border-color-l3; @@ -40,7 +40,7 @@ .advertise-message { font-size: font-size(x-small); color: palette(grayscale, black); - margin-bottom: $baseline + px; + margin-bottom: $baseline; } } @@ -48,11 +48,11 @@ .hd-6 { color: palette(grayscale, dark); font-weight: font-weight(normal); - margin-bottom: $baseline + px; + margin-bottom: $baseline; } .certificate-link { - padding-top: $baseline + px; + padding-top: $baseline; color: palette(primary, base); display: block; @@ -69,13 +69,13 @@ .empty-programs-message { border: 3px solid $gray-l4; background: $gray-l6; - padding: ($baseline*2) + px 0; + padding: ($baseline*2) 0; text-align: center; margin-bottom: 20px; .hd-3 { color: $black; - margin-bottom: $baseline + px; + margin-bottom: $baseline; } .find-xseries-programs { @@ -85,13 +85,13 @@ .action-xseries-icon { @include float(left); - @include margin-right($baseline*0.4 + px); + @include margin-right($baseline*0.4); display: inline; background: url('#{$static-path}/images/icon-sm-xseries-white.png') no-repeat; background-color: transparent; - width: ($baseline*1.1) + px; - height: ($baseline*1.1) + px; + width: ($baseline*1.1); + height: ($baseline*1.1); } &:active, diff --git a/lms/static/sass/views/_teams.scss b/lms/static/sass/views/_teams.scss index dda25316de..99627d6a6d 100644 --- a/lms/static/sass/views/_teams.scss +++ b/lms/static/sass/views/_teams.scss @@ -19,7 +19,7 @@ color: inherit; } -// layout + // layout .page-header { @include clearfix(); border-bottom: 1px solid $gray-l3; @@ -54,7 +54,7 @@ } } -// ui bits + // ui bits .breadcrumbs { @extend %t-copy-sub1; @@ -83,16 +83,16 @@ } .search-label { - @extend %text-sr; + @extend %text-sr; } .search-field { - transition: all $tmg-f2 ease-in-out; - border: 1px solid $gray-l4; - border-radius: 3px; - padding: ($baseline/4) ($baseline/2); - font-family: inherit; - color: $gray; + transition: all $tmg-f2 ease-in-out; + border: 1px solid $gray-l4; + border-radius: 3px; + padding: ($baseline/4) ($baseline/2); + font-family: inherit; + color: $gray; } .action-search { @@ -103,7 +103,7 @@ vertical-align: middle; .icon { - color: $white; + color: $white; } // STATE: hover and focus @@ -130,7 +130,7 @@ } } -// main content bits + // main content bits .page-content { padding: $baseline; } @@ -337,6 +337,11 @@ .team-profile { + .new-post-btn { + @include float(right); + @include blue-button; + } + .page-content-main { display: inline-block; width: flex-grid(8, 12); @@ -389,88 +394,88 @@ display: inline-block; @include tooltip-hover-style(-($baseline*2)); - } } + } } .create-team { legend { - @extend %t-title6; - @extend %t-weight4; - margin-bottom: ($baseline/4); + @extend %t-title6; + @extend %t-weight4; + margin-bottom: ($baseline/4); } .description { - @extend %t-copy-sub1; - margin-bottom: ($baseline/2); - color: $gray-l1; + @extend %t-copy-sub1; + margin-bottom: ($baseline/2); + color: $gray-l1; } .form-field { - margin: 0 0 ($baseline*0.75) 0; + margin: 0 0 ($baseline*0.75) 0; - .label { - display: block; - margin-bottom: ($baseline/4); + .label { + display: block; + margin-bottom: ($baseline/4); + } + + &.is-required { + @extend %t-weight4; + + .label:after { + @include margin-left($baseline/4); + content: "*"; } + } - &.is-required { - @extend %t-weight4; + .input-text { + @extend %t-copy-base; + transition: all $tmg-f2 ease-in-out 0s; + display: block; + width: 90%; + height: 100%; + margin-bottom: ($baseline/4); + border: 1px solid $gray-l2; + padding: ($baseline/2); + } - .label:after { - @include margin-left($baseline/4); - content: "*"; - } + .input-select { + @extend %t-copy-base; + width: 90%; + margin-bottom: ($baseline/4); + border: 1px solid $gray-l2; + } + + .input-text, + .input-select { + + &:focus { + border: 1px solid $blue; + + + .tip { + color: $blue; + } } + } - .input-text { - @extend %t-copy-base; - transition: all $tmg-f2 ease-in-out 0s; - display: block; - width: 90%; - height: 100%; - margin-bottom: ($baseline/4); - border: 1px solid $gray-l2; - padding: ($baseline/2); - } - - .input-select { - @extend %t-copy-base; - width: 90%; - margin-bottom: ($baseline/4); - border: 1px solid $gray-l2; - } + &.has-errors { .input-text, .input-select { + border: 1px solid $alert-color; - &:focus { - border: 1px solid $blue; - - + .tip { - color: $blue; - } - } + + .tip { + color: $alert-color; + } } + } - &.has-errors { - - .input-text, - .input-select { - border: 1px solid $alert-color; - - + .tip { - color: $alert-color; - } - } - } - - .tip { - @extend %t-copy-sub1; - display: block; - color: $gray-l1; - } + .tip { + @extend %t-copy-sub1; + display: block; + color: $gray-l1; + } } .required-wrapper { @@ -490,33 +495,33 @@ } .form-actions { - margin-top: $baseline; - } + margin-top: $baseline; + } - .action { - @extend %t-copy; - @extend %t-action2; - @include margin-right ($baseline/2); - padding: ($baseline/2) $baseline; - } + .action { + @extend %t-copy; + @extend %t-action2; + @include margin-right ($baseline/2); + padding: ($baseline/2) $baseline; + } - .action-primary { - @extend %btn-primary-blue; - display: inline-block; - text-shadow: none; - } + .action-primary { + @extend %btn-primary-blue; + display: inline-block; + text-shadow: none; + } - .action-cancel { - @extend %button-reset; - display: inline-block; - border: 1px solid transparent; - color: $gray; + .action-cancel { + @extend %button-reset; + display: inline-block; + border: 1px solid transparent; + color: $gray; - // STATE: hover and focus - &:hover, - &:focus { - border: 1px solid $link-color; - color: $link-color; + // STATE: hover and focus + &:hover, + &:focus { + border: 1px solid $link-color; + color: $link-color; } } @@ -569,107 +574,107 @@ width: 100%; @include clearfix(); - .team-required-fields { - @include float(left); - width: 55%; + .team-required-fields { + @include float(left); + width: 55%; - .u-field { - @include margin-right($baseline*2); + .u-field { + @include margin-right($baseline*2); + } + + .u-field.u-field-name { + padding-bottom: $baseline; + + .u-field-value { + width: 100%; + + input { + border-radius: ($baseline/5); + height: ($baseline*2); + } + } + + .u-field-message { + @include padding-left(0); + padding-top: ($baseline/4); + width: 100%; + } + } + + .u-field.u-field-description { + + .u-field-value { + width: 100%; + + textarea { + width: 100%; + height: ($baseline*5); + border-radius: ($baseline/5) + } + } + + .u-field-footer { + + .u-field-message { + display: block; + @extend %t-copy-sub1; + @include padding-left(0); + margin-top: ($baseline/4); + color: $gray-l1; + width: 100%; + } + } + } + + .u-field-title { + padding-bottom: ($baseline/4); + color: $base-font-color; + width: 100%; + } } - .u-field.u-field-name { - padding-bottom: $baseline; + .team-optional-fields { + @include float(left); + @include margin-left($baseline*2); + width: 40%; - .u-field-value { - width: 100%; + .u-field.u-field-optional_description { + margin-bottom: ($baseline/2); - input { - border-radius: ($baseline/5); - height: ($baseline*2); + .u-field-title { + color: $base-font-color; + font-weight: $font-semibold; + margin-bottom: ($baseline/5); } + + .u-field-value { + display: none; + } + } + + .u-field.u-field-language { + margin-bottom: ($baseline/5); + } + + .u-field-value-display { + display: none; + } + + .u-field-title { + color: $base-font-color; } .u-field-message { @include padding-left(0); - padding-top: ($baseline/4); + } + + .u-field-title, .u-field-value, .u-field-message { width: 100%; } } - .u-field.u-field-description { - - .u-field-value { - width: 100%; - - textarea { - width: 100%; - height: ($baseline*5); - border-radius: ($baseline/5) - } - } - - .u-field-footer { - - .u-field-message { - display: block; - @extend %t-copy-sub1; - @include padding-left(0); - margin-top: ($baseline/4); - color: $gray-l1; - width: 100%; - } - } - } - - .u-field-title { - padding-bottom: ($baseline/4); - color: $base-font-color; - width: 100%; - } } - .team-optional-fields { - @include float(left); - @include margin-left($baseline*2); - width: 40%; - - .u-field.u-field-optional_description { - margin-bottom: ($baseline/2); - - .u-field-title { - color: $base-font-color; - font-weight: $font-semibold; - margin-bottom: ($baseline/5); - } - - .u-field-value { - display: none; - } - } - - .u-field.u-field-language { - margin-bottom: ($baseline/5); - } - - .u-field-value-display { - display: none; - } - - .u-field-title { - color: $base-font-color; - } - - .u-field-message { - @include padding-left(0); - } - - .u-field-title, .u-field-value, .u-field-message { - width: 100%; - } - } - - } - .u-field { padding: 0; } @@ -692,10 +697,10 @@ // vertical line between required and optional fields .vertical-line:after { - height: 100%; - border-left: 2px solid $gray-l4; - content: ""; - position: absolute; + height: 100%; + border-left: 2px solid $gray-l4; + content: ""; + position: absolute; } .form-instructions { diff --git a/lms/templates/courseware/course_navigation.html b/lms/templates/courseware/course_navigation.html index 9b3a5afae3..b14ead5ff2 100644 --- a/lms/templates/courseware/course_navigation.html +++ b/lms/templates/courseware/course_navigation.html @@ -1,4 +1,5 @@ ## mako +<%page args="active_page=None" expression_filter="h" /> <%namespace name='static' file='/static_content.html'/> <%! from django.utils.translation import ugettext as _ @@ -10,7 +11,6 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json from openedx.core.djangolib.markup import HTML, Text from student.models import CourseEnrollment %> -<%page args="active_page=None" expression_filter="h" /> <% if active_page is None and active_page_context is not UNDEFINED: @@ -88,7 +88,7 @@ include_special_exams = settings.FEATURES.get('ENABLE_SPECIAL_EXAMS', False) and tab_list = get_course_tab_list(request, course) tabs_tmpl = static.get_template_path('/courseware/tabs.html') %> -
          +
            <%include file="${tabs_tmpl}" args="tab_list=tab_list,active_page=active_page,default_tab=default_tab,tab_image=tab_image" /> <%block name="extratabs" />
          diff --git a/lms/templates/courseware/tabs.html b/lms/templates/courseware/tabs.html index 0959355302..bf68f8baad 100644 --- a/lms/templates/courseware/tabs.html +++ b/lms/templates/courseware/tabs.html @@ -1,10 +1,11 @@ ## mako + <%namespace name='static' file='/static_content.html'/> <%! from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse %> -<%page args="tab_list, active_page, default_tab, tab_image" /> +<%page args="tab_list, active_page, default_tab, tab_image" expression_filter="h" /> <% def url_class(is_active): @@ -17,9 +18,9 @@ def url_class(is_active): tab_is_active = tab.tab_id in (active_page, default_tab) tab_class = url_class(tab_is_active) %> -
        1. - - ${_(tab.name) | h} +
        2. + + ${_(tab.name)} % if tab_is_active: , current location %endif diff --git a/lms/templates/discussion/_discussion_course_navigation.html b/lms/templates/discussion/_discussion_course_navigation.html index a84154c550..1cc1a98655 100644 --- a/lms/templates/discussion/_discussion_course_navigation.html +++ b/lms/templates/discussion/_discussion_course_navigation.html @@ -1,3 +1,4 @@ +<%page expression_filter="h"/> <%inherit file="../courseware/course_navigation.html" /> <%! from django.utils.translation import ugettext as _ @@ -6,6 +7,8 @@ from django_comment_client.permissions import has_permission <%block name="extratabs"> % if has_permission(user, 'create_thread', course.id): -
        3. ${_("New Post")}
        4. +
        5. + +
        6. % endif diff --git a/lms/templates/discussion/_discussion_module.html b/lms/templates/discussion/_discussion_module.html index ba6d1c88e9..6a8cb9785a 100644 --- a/lms/templates/discussion/_discussion_module.html +++ b/lms/templates/discussion/_discussion_module.html @@ -1,11 +1,14 @@ +<%page expression_filter="h"/> <%include file="_underscore_templates.html" /> <%! from django.utils.translation import ugettext as _ %> -
          - ${_("Show Discussion")} +
          + + ${_("Show Discussion")} + % if can_create_thread: - ${_("New Post")} + % endif
          diff --git a/lms/templates/discussion/index.html b/lms/templates/discussion/index.html index 82a21da5b9..6e0ca8e363 100644 --- a/lms/templates/discussion/index.html +++ b/lms/templates/discussion/index.html @@ -1,3 +1,8 @@ +## mako + +<%! main_css = "style-discussion-main" %> + +<%page expression_filter="h"/> <%inherit file="../main.html" /> <%namespace name='static' file='../static_content.html'/> <%! @@ -7,12 +12,9 @@ from django.core.urlresolvers import reverse %> <%block name="bodyclass">discussion -<%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default) | h} +<%block name="pagetitle">${_("Discussion - {course_number}").format(course_number=course.display_number_with_default)} <%block name="headextra"> -<%static:css group='style-course-vendor'/> -<%static:css group='style-course'/> - <%include file="_js_head_dependencies.html" /> @@ -24,21 +26,22 @@ from django.core.urlresolvers import reverse <%include file="_discussion_course_navigation.html" args="active_page='discussion'" /> +<%block name="content">
          + data-threads="${threads}" + data-thread-pages="${thread_pages}" + data-content-info="${annotated_content_info}" + data-sort-preference="${sort_preference}" + data-flag-moderator="${flag_moderator}" + data-user-cohort-id="${user_cohort}" + data-course-settings="${course_settings}">
          @@ -49,6 +52,7 @@ from django.core.urlresolvers import reverse
          + <%include file="_underscore_templates.html" /> <%include file="_thread_list_template.html" /> diff --git a/package.json b/package.json index 6c4d9b6639..59a4da30b6 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "dependencies": { "backbone": "~1.3.2", "coffee-script": "1.6.1", - "edx-pattern-library": "~0.12.4", + "edx-pattern-library": "0.13.0", "edx-ui-toolkit": "~1.1.0", "jquery": "~2.2.0", "jquery-migrate": "^1.4.1", diff --git a/screenshots/baseline/hinted-login-firefox.png b/screenshots/baseline/hinted-login-firefox.png index e5ea1f8fbde458a50f2f27fb65292e5246b4b6aa..dad617e3be05e911ebd8b60f9559be4a9e224bd5 100644 GIT binary patch literal 14512 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 E0H-L~U;qFB literal 14521 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 J0{Y?8e*qHZ%JBdI