diff --git a/cms/static/sass/_build-v1.scss b/cms/static/sass/_build-v1.scss index b2d56c57ec..94cec810c8 100644 --- a/cms/static/sass/_build-v1.scss +++ b/cms/static/sass/_build-v1.scss @@ -87,3 +87,7 @@ // +CodeMirror Overrides // ==================== @import 'elements/codemirror-overrides'; + +// CAPA Problem Feedback +@import 'edx-pattern-library-shims/buttons'; + diff --git a/cms/static/sass/edx-pattern-library-shims b/cms/static/sass/edx-pattern-library-shims new file mode 120000 index 0000000000..eae51650c7 --- /dev/null +++ b/cms/static/sass/edx-pattern-library-shims @@ -0,0 +1 @@ +../../../common/static/sass/edx-pattern-library-shims \ No newline at end of file diff --git a/cms/static/sass/elements/_system-feedback.scss b/cms/static/sass/elements/_system-feedback.scss index 44510875eb..2bdcc879c0 100644 --- a/cms/static/sass/elements/_system-feedback.scss +++ b/cms/static/sass/elements/_system-feedback.scss @@ -399,7 +399,6 @@ margin: 0 auto; width: flex-grid(12); max-width: $fg-max-width; - min-width: $fg-min-width; strong { @extend %t-strong; diff --git a/cms/static/sass/elements/_xblocks.scss b/cms/static/sass/elements/_xblocks.scss index e702861075..ed77384405 100644 --- a/cms/static/sass/elements/_xblocks.scss +++ b/cms/static/sass/elements/_xblocks.scss @@ -248,15 +248,7 @@ color: $color-visibility-set; } } - - .action { - - .save { - // taking styles from LMS for these Save buttons to maintain consistency - // there is no studio-specific style for these LMS-styled buttons - @extend %btn-lms-style; - } - } + } // +Messaging - Xblocks diff --git a/cms/static/sass/xmodule/_headings.scss b/cms/static/sass/xmodule/_headings.scss index e44d31ec2d..c58fba2f3e 100644 --- a/cms/static/sass/xmodule/_headings.scss +++ b/cms/static/sass/xmodule/_headings.scss @@ -32,9 +32,8 @@ $headings-base-color: $gray-d2; %hd-2 { - margin-bottom: 1em; - font-size: 1.5em; - font-weight: $headings-font-weight-normal; + font-size: 1.1125em; + font-weight: $headings-font-weight-bold; line-height: 1.4em; } diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 548ccd43da..be6c8549ec 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -376,7 +376,7 @@ class LoncapaProblem(object): def grade_answers(self, answers): """ - Grade student responses. Called by capa_module.check_problem. + Grade student responses. Called by capa_module.submit_problem. `answers` is a dict of all the entries from request.POST, but with the first part of each key removed (the string before the first "_"). @@ -496,6 +496,7 @@ class LoncapaProblem(object): choice-level explanations shown to a student after submission. Does nothing if there is no targeted-feedback attribute. """ + _ = self.capa_system.i18n.ugettext # Note that the modifications has been done, avoiding problems if called twice. if hasattr(self, 'has_targeted'): return @@ -515,9 +516,12 @@ class LoncapaProblem(object): # Keep track of the explanation-id that corresponds to the student's answer # Also, keep track of the solution-id solution_id = None + choice_correctness_for_student_answer = _('Incorrect') for choice in choices_list: if choice.get('name') == student_answer: expl_id_for_student_answer = choice.get('explanation-id') + if choice.get('correct') == 'true': + choice_correctness_for_student_answer = _('Correct') if choice.get('correct') == 'true': solution_id = choice.get('explanation-id') @@ -527,7 +531,15 @@ class LoncapaProblem(object): if len(targetedfeedbackset) != 0: targetedfeedbackset = targetedfeedbackset[0] targetedfeedbacks = targetedfeedbackset.xpath('./targetedfeedback') + # find the legend by id in choicegroup.html for aria-describedby + problem_legend_id = str(choicegroup.get('id')) + '-legend' for targetedfeedback in targetedfeedbacks: + screenreadertext = etree.Element("span") + targetedfeedback.insert(0, screenreadertext) + screenreadertext.set('class', 'sr') + screenreadertext.text = choice_correctness_for_student_answer + targetedfeedback.set('role', 'group') + targetedfeedback.set('aria-describedby', problem_legend_id) # Don't show targeted feedback if the student hasn't answer the problem # or if the target feedback doesn't match the student's (incorrect) answer if not self.done or targetedfeedback.get('explanation-id') != expl_id_for_student_answer: @@ -561,6 +573,7 @@ class LoncapaProblem(object): # Add our solution instead to the targetedfeedbackset and change its tag name solution_element.tag = 'targetedfeedback' + targetedfeedbackset.append(solution_element) def get_html(self): diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index 161f04155e..7482ca72a2 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -51,6 +51,7 @@ from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautifu import capa.xqueue_interface as xqueue_interface import capa.safe_exec as safe_exec +from openedx.core.djangolib.markup import HTML, Text log = logging.getLogger(__name__) @@ -352,9 +353,9 @@ class LoncapaResponse(object): # Tricky: label None means output defaults, while '' means output empty label if label is None: if correct: - label = _(u'Correct') + label = _(u'Correct:') else: - label = _(u'Incorrect') + label = _(u'Incorrect:') # self.runtime.track_function('get_demand_hint', event_info) # This this "feedback hint" event @@ -372,15 +373,23 @@ class LoncapaResponse(object): self.capa_module.runtime.track_function('edx.problem.hint.feedback_displayed', event_info) # Form the div-wrapped hint texts - hints_wrap = u''.join( - [u'
- ${value|h} - - ${status.display_name} + ${value|h} + ${status.display_name}
diff --git a/common/lib/capa/capa/templates/choicegroup.html b/common/lib/capa/capa/templates/choicegroup.html index bcad73897a..259ea37373 100644 --- a/common/lib/capa/capa/templates/choicegroup.html +++ b/common/lib/capa/capa/templates/choicegroup.html @@ -15,7 +15,7 @@${description_text}
% endfor % for choice_id, choice_label in choices: -- ${status.display_name} + ${status.display_name}
% if msg: - ${msg|n} + ${HTML(msg)} % endif % if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']: diff --git a/common/lib/capa/capa/templates/designprotein2dinput.html b/common/lib/capa/capa/templates/designprotein2dinput.html index bb3490f5af..3cdce1c97a 100644 --- a/common/lib/capa/capa/templates/designprotein2dinput.html +++ b/common/lib/capa/capa/templates/designprotein2dinput.html @@ -11,7 +11,7 @@- ${status.display_name} + ${status.display_name}
diff --git a/common/lib/capa/capa/templates/drag_and_drop_input.html b/common/lib/capa/capa/templates/drag_and_drop_input.html index 57803bf909..b18d9ed1dd 100644 --- a/common/lib/capa/capa/templates/drag_and_drop_input.html +++ b/common/lib/capa/capa/templates/drag_and_drop_input.html @@ -17,14 +17,14 @@ -- ${status.display_name} +
+ ${status.display_name}
% if msg: - ${HTML(msg)} + ${HTML(msg)} % endif % if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']: diff --git a/common/lib/capa/capa/templates/editageneinput.html b/common/lib/capa/capa/templates/editageneinput.html index 11c947a955..4ae36cb964 100644 --- a/common/lib/capa/capa/templates/editageneinput.html +++ b/common/lib/capa/capa/templates/editageneinput.html @@ -12,7 +12,7 @@- ${status.display_name} + ${status.display_name}
diff --git a/common/lib/capa/capa/templates/editamolecule.html b/common/lib/capa/capa/templates/editamolecule.html index c51101dc9d..633bff4c05 100644 --- a/common/lib/capa/capa/templates/editamolecule.html +++ b/common/lib/capa/capa/templates/editamolecule.html @@ -17,9 +17,8 @@- ${status.display_name} + ${status.display_name}
-${description_text}
@@ -18,7 +18,7 @@ /> ${trailing_text} - + ${status.display_tooltip} @@ -33,6 +33,6 @@ % if msg: - ${HTML(msg)} + ${HTML(msg)} % endif- ${status.display_name} + ${status.display_name}
-- ${status.display_name} +
+ ${status.display_name}
% if msg: - ${HTML(msg)} + ${HTML(msg)} % endif % if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:tags. + wrapped in
-
- -processing
+processing
+Correctexcellent
Yepcorrect
Incorrectno, try again
' spyOn($, 'postWithPrefix').and.callFake (url, answers, callback) -> - callback(success: 'incorrect', contents: 'Incorrect') + callback(success: 'incorrect', contents: contents) promise = always: (callable) -> callable() done: (callable) -> callable() - @problem.check() - expect(@problem.el.html()).toEqual 'Incorrect' - expect(window.SR.readElts).toHaveBeenCalled() + @problem.submit() + expect(@problem.el).toHaveHtml contents + expect(window.SR.readTexts).toHaveBeenCalledWith ['no, try again'] - it 'tests if all the capa buttons are disabled while checking', (done)-> + it 'tests if all the capa buttons are disabled while submitting', (done)-> deferred = $.Deferred() self = this @@ -230,7 +245,7 @@ describe 'Problem', -> done: (callable) -> callable() spyOn @problem, 'enableAllButtons' - @problem.check() + @problem.submit() expect(@problem.enableAllButtons).toHaveBeenCalledWith false, true if jQuery.active == 0 deferred.resolve() @@ -241,7 +256,7 @@ describe 'Problem', -> return ).always done - it 'tests the expected change in text of check button', (done) -> + it 'tests the expected change in text of submit button', (done) -> deferred = $.Deferred() self = this @@ -253,31 +268,35 @@ describe 'Problem', -> callable() done: (callable) -> callable() - spyOn @problem.checkButtonLabel, 'text' - @problem.check() - expect(@problem.checkButtonLabel.text).toHaveBeenCalledWith 'Checking...' + spyOn @problem.submitButtonLabel, 'text' + @problem.submit() + expect(@problem.submitButtonLabel.text).toHaveBeenCalledWith 'Submitting' if jQuery.active == 0 deferred.resolve() deferred.promise() runs.call(self).then(-> - expect(self.problem.checkButtonLabel.text).toHaveBeenCalledWith 'Check' + expect(self.problem.submitButtonLabel.text).toHaveBeenCalledWith 'Submit' return ).always done - describe 'check button on problems', -> + describe 'submit button on problems', -> beforeEach -> @problem = new Problem($('.xblock-student_view')) - @checkDisabled = (v) -> expect(@problem.checkButton.hasClass('is-disabled')).toBe(v) + @submitDisabled = (disabled) => + if disabled + expect(@problem.submitButton).toHaveAttr('disabled') + else + expect(@problem.submitButton).not.toHaveAttr('disabled') - describe 'some basic tests for check button', -> + describe 'some basic tests for submit button', -> it 'should become enabled after a value is entered into the text box', -> $('#input_example_1').val('test').trigger('input') - @checkDisabled false + @submitDisabled false $('#input_example_1').val('').trigger('input') - @checkDisabled true + @submitDisabled true - describe 'some advanced tests for check button', -> + describe 'some advanced tests for submit button', -> it 'should become enabled after a checkbox is checked', -> html = '''Answer: One
', 'Answer: Two
'] - - it 'toggle the show answer button, answers are elements', -> - answer1 = '' + gettext('Answer:') + ' ' + value + '
') - else - answer = @$("#answer_#{key}, #solution_#{key}") - answer.html(value) - Collapsible.setCollapsibles(answer) + Logger.log 'problem_show', problem: @id + $.postWithPrefix "#{@url}/problem_show", (response) => + answers = response.answers + $.each answers, (key, value) => + if $.isArray(value) + for choice in value + @$("label[for='input_#{key}_#{choice}']").attr correct_answer: 'true' + else + answer = @$("#answer_#{key}, #solution_#{key}") + edx.HtmlUtils.setHtml(answer, edx.HtmlUtils.HTML(value)) + Collapsible.setCollapsibles(answer) - # Sometimes, `value` is just a string containing a MathJax formula. - # If this is the case, jQuery will throw an error in some corner cases - # because of an incorrect selector. We setup a try..catch so that - # the script doesn't break in such cases. - # - # We will fallback to the second `if statement` below, if an - # error is thrown by jQuery. - try - solution = $(value).find('.detailed-solution') - catch e - solution = {} - if solution.length - answer_text.push(solution) - else - answer_text.push('' + gettext('Answer:') + ' ' + value + '
') + # Sometimes, `value` is just a string containing a MathJax formula. + # If this is the case, jQuery will throw an error in some corner cases + # because of an incorrect selector. We setup a try..catch so that + # the script doesn't break in such cases. + # + # We will fallback to the second `if statement` below, if an + # error is thrown by jQuery. + try + solution = $(value).find('.detailed-solution') + catch e + solution = {} - # TODO remove the above once everything is extracted into its own - # inputtype functions. - - @el.find(".capa_inputtype").each (index, inputtype) => - classes = $(inputtype).attr('class').split(' ') - for cls in classes - display = @inputtypeDisplays[$(inputtype).attr('id')] - showMethod = @inputtypeShowAnswerMethods[cls] - showMethod(inputtype, display, answers) if showMethod? - - if MathJax? - @el.find('.problem > div').each (index, element) => - MathJax.Hub.Queue ["Typeset", MathJax.Hub, element] - - `// Translators: the word Answer here refers to the answer to a problem the student must solve.` - @$('.show-label').text gettext('Hide Answer') - @el.addClass 'showed' - @updateProgress response - window.SR.readElts(answer_text) - else - @$('[id^=answer_], [id^=solution_]').text '' - @$('[correct_answer]').attr correct_answer: null - @el.removeClass 'showed' - `// Translators: the word Answer here refers to the answer to a problem the student must solve.` - @$('.show-label').text gettext('Show Answer') - window.SR.readText(gettext('Answer hidden')) + # TODO remove the above once everything is extracted into its own + # inputtype functions. @el.find(".capa_inputtype").each (index, inputtype) => - display = @inputtypeDisplays[$(inputtype).attr('id')] classes = $(inputtype).attr('class').split(' ') for cls in classes - hideMethod = @inputtypeHideAnswerMethods[cls] - hideMethod(inputtype, display) if hideMethod? + display = @inputtypeDisplays[$(inputtype).attr('id')] + showMethod = @inputtypeShowAnswerMethods[cls] + showMethod(inputtype, display, answers) if showMethod? + + if MathJax? + @el.find('.problem > div').each (index, element) => + MathJax.Hub.Queue ["Typeset", MathJax.Hub, element] + + @el.find('.show').attr('disabled', 'disabled') + @updateProgress response + window.SR.readText(gettext('Answers to this problem are now shown. Navigate through the problem to review it with answers inline.')) + @scroll_to_problem_meta() + + clear_all_notifications: => + @submitNotification.remove() + @gentleAlertNotification.hide() + @saveNotification.hide() gentle_alert: (msg) => - if @el.find('.capa_alert').length - @el.find('.capa_alert').remove() - alert_elem = "Simple Text
'); + }); + + it('supports the setting of an array of text', function() { + window.SR.readTexts(['One', 'Two']); + expect(getSRText()).toContain('One
\nTwo
'); + }); + + it('supports setting an array of elements', function() { + window.SR.readElts($('.status')); + expect(getSRText()).toContain( + 'Yes!Your answer is correct!
\nNo!Your answer is wrong!
' + ); + }); + }); + }); diff --git a/common/static/js/src/accessibility_tools.js b/common/static/js/src/accessibility_tools.js index 52a8a06282..a593c65a3e 100644 --- a/common/static/js/src/accessibility_tools.js +++ b/common/static/js/src/accessibility_tools.js @@ -147,28 +147,52 @@ $(function() { SRAlert = (function() { function SRAlert() { - $('body').append(''); - this.el = $('#reader-feedback'); + // This initialization sometimes gets done twice, so take to only create a single reader-feedback div. + var readerFeedbackID = 'reader-feedback', + $readerFeedbackSelector = $('#' + readerFeedbackID); + + if ($readerFeedbackSelector.length === 0) { + edx.HtmlUtils.append( + $('body'), + edx.HtmlUtils.interpolateHtml( + edx.HtmlUtils.HTML(''), + {readerFeedbackID: readerFeedbackID} + ) + ); + } + this.el = $('#' + readerFeedbackID); } SRAlert.prototype.clear = function() { - return this.el.html(' '); + edx.HtmlUtils.setHtml(this.el, ''); }; SRAlert.prototype.readElts = function(elts) { - var feedback = ''; + var texts = []; $.each(elts, function(idx, value) { - return feedback += '' + $(value).html() + '
\n'; + texts.push($(value).html()); }); - return this.el.html(feedback); + return this.readTexts(texts); }; SRAlert.prototype.readText = function(text) { - return this.el.text(text); + return this.readTexts([text]); + }; + + SRAlert.prototype.readTexts = function(texts) { + var htmlFeedback = edx.HtmlUtils.HTML(''); + $.each(texts, function(idx, value) { + htmlFeedback = edx.HtmlUtils.interpolateHtml( + edx.HtmlUtils.HTML('{previous_feedback}{value}
\n'), + // "value" may be HTML, if an element is being passed + {previous_feedback: htmlFeedback, value: edx.HtmlUtils.HTML(value)} + ); + }); + edx.HtmlUtils.setHtml(this.el, htmlFeedback); }; return SRAlert; })(); - window.SR = new SRAlert; + window.SR = new SRAlert(); }); diff --git a/common/static/sass/edx-pattern-library-shims/_buttons.scss b/common/static/sass/edx-pattern-library-shims/_buttons.scss new file mode 100644 index 0000000000..0f290713bb --- /dev/null +++ b/common/static/sass/edx-pattern-library-shims/_buttons.scss @@ -0,0 +1,119 @@ +// ------------------------------ +// LMS Problem Feedback Revamp styling +// Mirror styles from the Pattern Library + +@import 'base/variables'; + + +// ---------------------------- +// #GLOBALS +// ---------------------------- +%btn { + display: inline-block; + border-style: $btn-border-style; + border-radius: $btn-border-radius; + border-width: $btn-border-size; + box-shadow: none; + padding: 0.625rem 1.25rem; + font-size: 16px; + font-weight: normal; + text-shadow: none; + text-transform: capitalize; + + // Display: block, one button per line, full width + &.block { + display: block; + width: 100%; + } + + // STATE: is disabled + &:disabled, + &.is-disabled { + @extend %state-disabled; + } + + .icon { + display: inline-block; + vertical-align: baseline; + + &:only-child, + .sr-only + & { + @include margin-right(0); + } + } + &.btn-small { + @extend %btn-small; + } +} + +// ---------------------------- +// #DEFAULT +// ---------------------------- +.btn-default { + @extend %btn; + border-color: $btn-default-border-color; + background: $btn-default-background; + color: $btn-default-color; + + // STATE: hover and focus + &:hover, + &.is-hovered, + &:focus, + &.is-focused { + border-color: $btn-default-focus-border-color; + background-color: $btn-default-background; + color: $btn-default-focus-color; + } + + // STATE: is pressed or active + &:active, + &.is-pressed, + &.is-active { + border-color: $btn-default-active-border-color; + color: $btn-default-active-color; + } + + // STATE: is disabled + &:disabled, + &.is-disabled { + border-color: $btn-disabled-border-color; + color: $btn-disabled-color; + } +} + +// ---------------------------- +// #BRAND +// ---------------------------- +.btn-brand { + @extend %btn; + border-color: $btn-brand-border-color; + background: $btn-brand-background; + color: $btn-brand-color; + + // STATE: hover and focus + &:hover, + &.is-hovered, + &:focus, + &.is-focused { + border-color: $btn-brand-focus-border-color; + background-color: $btn-brand-focus-background; + color: $btn-brand-focus-color; + } + + // STATE: is pressed or active + &:active, + &.is-pressed, + &.is-active { + border-color: $btn-brand-active-border-color; + background: $btn-brand-active-background; + } + + // STATE: is disabled + &:disabled, + &.is-disabled { + border-color: $btn-disabled-border-color; + background: $btn-brand-disabled-background; + color: $btn-brand-disabled-color; + } +} + diff --git a/common/static/sass/edx-pattern-library-shims/base/_variables.scss b/common/static/sass/edx-pattern-library-shims/base/_variables.scss new file mode 100644 index 0000000000..def96c46c2 --- /dev/null +++ b/common/static/sass/edx-pattern-library-shims/base/_variables.scss @@ -0,0 +1,222 @@ +// COLORS +$light-gray1: rgb(221, 221, 221); + + +// Font Sizes in em +$small-font-size: 0.85em !default; +$medium-font-size: 0.9em !default; +$base-font-size: 1em !default; + +// Line height +$base-line-height: 1.5em !default; + + +$component-border-radius: 3px !default; + +// grid - breakpoints +$bp-screen-sm: 480px !default; +$bp-screen-md: 768px !default; +$bp-screen-lg: 1024px !default; +$bp-screen-xl: 1280px !default; + + +// #SPACING +// ---------------------------- +// spacing - baseline +$baseline: 20px !default; + +// vertical spacing +$baseline-vertical: ($baseline*2) !default; + +$spacing-vertical: ( + base: $baseline-vertical, + mid-small: ($baseline-vertical*0.75), + small: ($baseline-vertical/2), + x-small: ($baseline-vertical/4), + xx-small: ($baseline-vertical/8), + xxx-small: ($baseline-vertical/10), + mid-large: ($baseline-vertical*1.5), + large: ($baseline-vertical*2), + x-large: ($baseline-vertical*4) +); + +// horizontal spacing +$baseline-horizontal: $baseline !default; + +$spacing-horizontal: ( + base: $baseline-horizontal, + mid-small: ($baseline-horizontal*0.75), + small: ($baseline-horizontal/2), + x-small: ($baseline-horizontal/4), + xx-small: ($baseline-horizontal/8), + mid-large: ($baseline-horizontal*1.5), + large: ($baseline-horizontal*2), + x-large: ($baseline-horizontal*4) +); + +// get vertical spacings from defined map values +@function spacing-vertical($key) { + @if map-has-key($spacing-vertical, $key) { + @return rem(map-get($spacing-vertical, $key)); + } + + @warn "Unknown `#{$key}` in $spacing-vertical."; + @return null; +} + +// get horizontal spacings from defined map values +@function spacing-horizontal($key) { + @if map-has-key($spacing-horizontal, $key) { + @return rem(map-get($spacing-horizontal, $key)); + } + + @warn "Unknown `#{$key}` in $spacing-horizontal."; + @return null; +} + +// typography: weights +$font-weights: ( + normal: 400, + light: 300, + x-light: 200, + semi-bold: 600, + bold: 700 +); + +// typography: sizes +$font-sizes: ( + xxxx-large: 38, + xxx-large: 28, + xx-large: 24, + x-large: 21, + large: 18, + base: 16, + small: 14, + x-small: 12, + xx-small: 11, + xxx-small: 10, +); + +// get font sizes from defined map values +@function font-size($key) { + @if map-has-key($font-sizes, $key) { + @return rem(map-get($font-sizes, $key)); + } + + @warn "Unknown `#{$key}` in $font-sizes."; + @return null; +} + +// get font weight from defined map values +@function font-weight($key) { + @if map-has-key($font-weights, $key) { + @return map-get($font-weights, $key); + } + + @warn "Unknown `#{$key}` in $font-weights."; + @return null; +} + + +// visual disabled +%state-disabled { + pointer-events: none; + outline: none; + cursor: not-allowed; +} + +// +Colors - UXPL new pattern library colors +// ==================== +$uxpl-blue-base: rgba(0, 116, 180, 1); // wcag2a compliant +$uxpl-blue-hover-active: darken($uxpl-blue-base, 7%); // wcag2a compliant + +$uxpl-green-base: rgba(0, 129, 0, 1); // wcag2a compliant +$uxpl-green-hover-active: lighten($uxpl-green-base, 7%); // wcag2a compliant + +$uxpl-gray-dark: rgb(17, 17, 17); +$uxpl-gray-base: rgb(65, 65, 65); +$uxpl-gray-background: rgb(217, 217, 217); + + +// Alert styles +$error-color: rgb(203, 7, 18) !default; +$success-color: rgb(0, 155, 0) !default; +$warning-color: rgb(255, 192, 31) !default; +$warning-color-accent: rgb(255, 252, 221) !default; + +// BUTTONS + +// disabled button +$btn-disabled-border-color: #d2d0d0 !default; +$btn-disabled-color: #6b6969 !default; + +// base button +$btn-default-border-color: transparent !default; +$btn-default-background: transparent !default; +$btn-default-color: $uxpl-blue-base !default; +$btn-default-focus-border-color: $uxpl-blue-base !default; +$btn-default-focus-color: $uxpl-blue-base !default; +$btn-default-active-border-color: $uxpl-blue-base !default; +$btn-default-active-color: $uxpl-blue-base !default; + +// brand button +$btn-brand-border-color: $uxpl-blue-base !default; +$btn-brand-background: $uxpl-blue-base !default; +$btn-brand-color: #fcfcfc !default; +$btn-brand-focus-color: $btn-brand-color !default; +$btn-brand-focus-border-color: $uxpl-blue-hover-active !default; +$btn-brand-focus-background: $uxpl-blue-hover-active !default; +$btn-brand-active-border-color: $uxpl-blue-base !default; +$btn-brand-active-background: $uxpl-blue-base !default; +$btn-brand-disabled-background: #f2f3f3 !default; +$btn-brand-disabled-color: #676666 !default; + +// ---------------------------- +// #SETTINGS +// ---------------------------- +$btn-border-style: solid !default; +$btn-border-size: 1px !default; +$btn-shadow: 3px !default; +$btn-font-weight: font-weight(semi-bold) !default; +$btn-border-radius: $component-border-radius !default; + +// sizes +$btn-large-padding-vertical: spacing-vertical(small); +$btn-large-padding-horizontal: spacing-horizontal(mid-large); + + +$btn-base-padding-vertical: spacing-vertical(x-small); +$btn-base-padding-horizontal: spacing-horizontal(base); +$btn-base-font-size: font-size(base); + +$btn-small-padding-vertical: spacing-vertical(x-small); +$btn-small-padding-horizontal: spacing-horizontal(small); + + +// ---------------------------- +// #SIZES +// ---------------------------- +// large +%btn-large { + padding: 1.25rem 1.875rem; + font-size: font-size(large); +} + +// small +%btn-small { + padding: 0.625rem 0.625rem; + font-size: 14px; +} + +// ---------------------------- +// Problem Notifications +// ---------------------------- + +@mixin notification-by-type($color) { + border-top: 3px solid $color; + .icon { + @include margin-right(3 * $baseline/ 4); + color: $color; + } +} + diff --git a/common/test/acceptance/pages/lms/annotation_component.py b/common/test/acceptance/pages/lms/annotation_component.py index ec8ef3906c..ca6223cd9e 100644 --- a/common/test/acceptance/pages/lms/annotation_component.py +++ b/common/test/acceptance/pages/lms/annotation_component.py @@ -72,7 +72,7 @@ class AnnotationComponentPage(PageObject): # Wait for the click to take effect, which is after the class is applied. self.wait_for(lambda: 'selected' in self.q(css=answer_css).attrs('class')[0], description='answer selected') # Click the "Check" button. - self.q(css=self.active_problem_selector('.check')).click() + self.q(css=self.active_problem_selector('.submit')).click() # This will trigger a POST to problem_check so wait until the response is returned. self.wait_for_ajax() diff --git a/common/test/acceptance/pages/lms/problem.py b/common/test/acceptance/pages/lms/problem.py index 02f885db53..7ffbd19005 100644 --- a/common/test/acceptance/pages/lms/problem.py +++ b/common/test/acceptance/pages/lms/problem.py @@ -2,6 +2,8 @@ Problem Page. """ from bok_choy.page_object import PageObject +from common.test.acceptance.pages.common.utils import click_css +from selenium.webdriver.common.keys import Keys class ProblemPage(PageObject): @@ -20,6 +22,7 @@ class ProblemPage(PageObject): """ Return the current problem name. """ + self.wait_for_element_visibility(self.CSS_PROBLEM_HEADER, 'wait for problem header') return self.q(css='.problem-header').text[0] @property @@ -48,14 +51,15 @@ class ProblemPage(PageObject): """ Return the "hint" text of the problem from html """ - return self.q(css="div.problem div.problem-hint").html[0].split(' <', 1)[0] + hints_html = self.q(css="div.problem .notification-hint .notification-message li").html + return [hint_html.split('Which piece of furniture is built for sitting?
Which of the following are musical instruments?
Choose Yes.