Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
problem-builder
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
problem-builder
Commits
30e9b3cd
Commit
30e9b3cd
authored
Jul 15, 2015
by
Braden MacDonald
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'clarifications' into fix-hgse-upgrade-merged
parents
caccfd1e
2bde5538
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
205 additions
and
15 deletions
+205
-15
problem_builder/mcq.py
+2
-6
problem_builder/mentoring.py
+7
-3
problem_builder/public/css/problem-builder-edit.css
+0
-0
problem_builder/public/css/problem-builder-tinymce-content.css
+15
-0
problem_builder/public/css/problem-builder.css
+8
-0
problem_builder/public/js/mentoring.js
+2
-0
problem_builder/public/js/mentoring_edit.js
+3
-0
problem_builder/public/js/questionnaire_edit.js
+4
-0
problem_builder/public/js/util.js
+40
-0
problem_builder/questionnaire.py
+9
-1
problem_builder/templates/html/ratingblock.html
+2
-2
problem_builder/templates/html/ratingblock_edit_preview.html
+3
-3
problem_builder/tests/integration/test_clarifications.py
+110
-0
No files found.
problem_builder/mcq.py
View file @
30e9b3cd
...
...
@@ -115,15 +115,13 @@ class MCQBlock(SubmittingXBlockMixin, QuestionnaireAbstractBlock):
log
.
debug
(
u'MCQ submission result:
%
s'
,
result
)
return
result
def
author_edit_view
(
self
,
context
):
def
get_author_edit_view_fragment
(
self
,
context
):
"""
The options for the 1-5 values of the Likert scale aren't child blocks but we want to
show them in the author edit view, for clarity.
"""
fragment
=
Fragment
(
u"<p>{}</p>"
.
format
(
self
.
question
))
self
.
render_children
(
context
,
fragment
,
can_reorder
=
True
,
can_add
=
False
)
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/questionnaire_add_buttons.html'
,
{}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/questionnaire-edit.css'
))
return
fragment
def
validate_field_data
(
self
,
validation
,
data
):
...
...
@@ -194,7 +192,7 @@ class RatingBlock(MCQBlock):
{
"display_name"
:
dn
,
"value"
:
val
}
for
val
,
dn
in
zip
(
self
.
FIXED_VALUES
,
display_names
)
]
+
super
(
RatingBlock
,
self
)
.
human_readable_choices
def
author_edit_view
(
self
,
context
):
def
get_author_edit_view_fragment
(
self
,
context
):
"""
The options for the 1-5 values of the Likert scale aren't child blocks but we want to
show them in the author edit view, for clarity.
...
...
@@ -207,6 +205,4 @@ class RatingBlock(MCQBlock):
'accepted_statuses'
:
[
None
]
+
[
self
.
describe_choice_correctness
(
c
)
for
c
in
"12345"
],
}))
self
.
render_children
(
context
,
fragment
,
can_reorder
=
True
,
can_add
=
False
)
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/questionnaire_add_buttons.html'
,
{}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/questionnaire-edit.css'
))
return
fragment
problem_builder/mentoring.py
View file @
30e9b3cd
...
...
@@ -314,8 +314,9 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
'child_content'
:
child_content
,
'missing_dependency_url'
:
self
.
has_missing_dependency
and
self
.
next_step_url
,
}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/
mentoring
.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/
problem-builder
.css'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/vendor/underscore-min.js'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/util.js'
))
js_file
=
'public/js/mentoring_{}_view.js'
.
format
(
'assessment'
if
self
.
is_assessment
else
'standard'
)
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
js_file
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/mentoring.js'
))
...
...
@@ -731,7 +732,7 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/mentoring_url_name.html'
,
{
"url_name"
:
self
.
url_name
}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/
mentoring_
edit.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/
problem-builder-
edit.css'
))
self
.
include_theme_files
(
fragment
)
return
fragment
...
...
@@ -746,7 +747,10 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/mentoring_url_name.html'
,
{
"url_name"
:
self
.
url_name
}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/mentoring_edit.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder-edit.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder-tinymce-content.css'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/util.js'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/mentoring_edit.js'
))
fragment
.
initialize_js
(
'MentoringEditComponents'
)
return
fragment
...
...
problem_builder/public/css/
mentoring_
edit.css
→
problem_builder/public/css/
problem-builder-
edit.css
View file @
30e9b3cd
File moved
problem_builder/public/css/problem-builder-tinymce-content.css
0 → 100644
View file @
30e9b3cd
/* Some styling to make clarifications stand out a bit in
studio HTML edit view. */
.mce-content-body
.pb-clarification
{
color
:
#999
;
font-size
:
0.75em
;
}
.mce-content-body
.pb-clarification
::before
{
content
:
"(?)["
}
.mce-content-body
.pb-clarification
::after
{
content
:
"]"
}
problem_builder/public/css/
mentoring
.css
→
problem_builder/public/css/
problem-builder
.css
View file @
30e9b3cd
...
...
@@ -173,3 +173,11 @@
float
:
right
;
display
:
none
;
}
.pb-clarification
span
.clarification
i
{
font-style
:
normal
;
}
.pb-clarification
span
.clarification
i
:hover
{
color
:
rgb
(
0
,
159
,
230
);
}
problem_builder/public/js/mentoring.js
View file @
30e9b3cd
...
...
@@ -113,6 +113,8 @@ function MentoringBlock(runtime, element) {
}
}
ProblemBuilderUtil
.
transformClarifications
(
element
);
if
(
data
.
mode
===
'standard'
)
{
MentoringStandardView
(
runtime
,
element
,
mentoring
);
}
...
...
problem_builder/public/js/mentoring_edit.js
View file @
30e9b3cd
...
...
@@ -17,5 +17,8 @@ function MentoringEditComponents(runtime, element) {
$
(
this
).
addClass
(
'disabled'
);
}
});
ProblemBuilderUtil
.
transformClarifications
(
element
);
runtime
.
listenTo
(
'deleted-child'
,
updateButtons
);
}
problem_builder/public/js/questionnaire_edit.js
0 → 100644
View file @
30e9b3cd
function
QuestionnaireEdit
(
runtime
,
element
)
{
'use strict'
;
ProblemBuilderUtil
.
transformClarifications
(
element
);
}
problem_builder/public/js/util.js
0 → 100644
View file @
30e9b3cd
window
.
ProblemBuilderUtil
=
{
transformClarifications
:
function
(
element
)
{
var
$element
=
$
(
element
);
var
transformExisting
=
function
(
node
)
{
$
(
'.pb-clarification'
,
node
).
each
(
function
()
{
var
item
=
$
(
this
);
var
content
=
item
.
html
();
var
clarification
=
$
(
'<span class="clarification" tabindex="0" role="note" aria-label="Clarification">'
+
'<i data-tooltip-show-on-click="true" class="fa fa-info-circle" aria-hidden="true"></i>'
+
'<span class="sr"></span>'
+
'</span>'
);
clarification
.
find
(
'i'
).
attr
(
'data-tooltip'
,
content
);
clarification
.
find
(
'span.sr'
).
html
(
content
);
item
.
empty
().
append
(
clarification
);
});
};
// Transform all span.pb-clarifications already existing inside the element.
transformExisting
(
$element
);
// Transform all future span.pb-clarifications using mutation observer.
// It's only needed in the Studio when editing xblock children because the
// block's JS init function isn't called after edits in the Studio.
if
(
window
.
MutationObserver
)
{
var
observer
=
new
MutationObserver
(
function
(
mutations
)
{
mutations
.
forEach
(
function
(
mutation
)
{
Array
.
prototype
.
forEach
.
call
(
mutation
.
addedNodes
,
function
(
node
)
{
transformExisting
(
node
);
});
})
});
observer
.
observe
(
$element
[
0
],
{
childList
:
true
,
subtree
:
true
});
}
}
};
problem_builder/questionnaire.py
View file @
30e9b3cd
...
...
@@ -167,13 +167,21 @@ class QuestionnaireAbstractBlock(StudioEditableXBlockMixin, StudioContainerXBloc
return
choice
.
content
return
submission
def
get_author_edit_view_fragment
(
self
,
context
):
fragment
=
super
(
QuestionnaireAbstractBlock
,
self
)
.
author_edit_view
(
context
)
return
fragment
def
author_edit_view
(
self
,
context
):
"""
Add some HTML to the author view that allows authors to add choices and tips.
"""
fragment
=
s
uper
(
QuestionnaireAbstractBlock
,
self
)
.
author_edit_view
(
context
)
fragment
=
s
elf
.
get_author_edit_view_fragment
(
context
)
fragment
.
add_content
(
loader
.
render_template
(
'templates/html/questionnaire_add_buttons.html'
,
{}))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/problem-builder.css'
))
fragment
.
add_css_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/css/questionnaire-edit.css'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/util.js'
))
fragment
.
add_javascript_url
(
self
.
runtime
.
local_resource_url
(
self
,
'public/js/questionnaire_edit.js'
))
fragment
.
initialize_js
(
'QuestionnaireEdit'
)
return
fragment
def
validate_field_data
(
self
,
validation
,
data
):
...
...
problem_builder/templates/html/ratingblock.html
View file @
30e9b3cd
...
...
@@ -15,8 +15,8 @@
</div>
<label
class=
"choice-label"
for=
"choice-{{ self.html_id }}-{{i}}"
>
{{i}}
{% if i == '1' %} - {{ self.low }}{% endif %}
{% if i == '5' %} - {{ self.high }}{% endif %}
{% if i == '1' %} - {{ self.low
|safe
}}{% endif %}
{% if i == '5' %} - {{ self.high
|safe
}}{% endif %}
</label>
<div
class=
"choice-tips-container"
>
<div
class=
"choice-tips"
></div>
...
...
problem_builder/templates/html/ratingblock_edit_preview.html
View file @
30e9b3cd
{% load i18n %}
<p>
{{ question }}
</p>
<p>
{{ question
|safe
}}
</p>
<h2>
{% trans "Built-in choices:" %}
</h2>
<ul>
<li>
Choice (1):
<strong>
1 - {{ low }}
</strong>
({{accepted_statuses.1}})
</li>
<li>
Choice (1):
<strong>
1 - {{ low
|safe
}}
</strong>
({{accepted_statuses.1}})
</li>
<li>
Choice (2):
<strong>
2
</strong>
({{accepted_statuses.2}})
</li>
<li>
Choice (3):
<strong>
3
</strong>
({{accepted_statuses.3}})
</li>
<li>
Choice (4):
<strong>
4
</strong>
({{accepted_statuses.4}})
</li>
<li>
Choice (5):
<strong>
5 - {{ high }}
</strong>
({{accepted_statuses.5}})
</li>
<li>
Choice (5):
<strong>
5 - {{ high
|safe
}}
</strong>
({{accepted_statuses.5}})
</li>
</ul>
<h2>
{% trans "Additional custom choices and tips:" %}
</h2>
problem_builder/tests/integration/test_clarifications.py
0 → 100644
View file @
30e9b3cd
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014-2015 Harvard, edX & OpenCraft
#
# This software's license gives you freedom; you can copy, convey,
# propagate, redistribute and/or modify this program under the terms of
# the GNU Affero General Public License (AGPL) as published by the Free
# Software Foundation (FSF), either version 3 of the License, or (at your
# option) any later version of the AGPL published by the FSF.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
# General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program in a file in the toplevel directory called
# "AGPLv3". If not, see <http://www.gnu.org/licenses/>.
#
"""
Test that <span class="pb-clarification"> elements are transformed into LMS-like tooltips.
"""
# Imports ###########################################################
import
ddt
from
cgi
import
escape
from
xblockutils.base_test
import
SeleniumXBlockTest
# Classes ###########################################################
@ddt.ddt
class
ClarificationTest
(
SeleniumXBlockTest
):
"""
Test that the content of span.pb-clarification elements is transformed into
tooltip elements.
"""
clarification_text
=
'Let me clarify...'
mcq_template
=
"""
<problem-builder>
<pb-mcq question="Who was your favorite character? {clarify_escaped}">
<pb-choice value="gaius">Gaius Baltar</pb-choice>
<pb-choice value="adama">Admiral William Adama {clarify}</pb-choice>
<pb-choice value="starbuck">Starbuck</pb-choice>
</pb-mcq>
</problem-builder>
"""
mrq_template
=
"""
<problem-builder>
<pb-mrq question="What makes a great {clarify_escaped} MRQ {clarify_escaped}?">
<pb-choice value="1">Lots of choices</pb-choice>
<pb-choice value="2">Funny{clarify} choices</pb-choice>
<pb-choice value="3">Not sure {clarify}</pb-choice>
</pb-mrq>
</problem-builder>
"""
rating_template
=
"""
<problem-builder>
<pb-rating name="rating_1_1" question="How do you rate {clarify_escaped} Battlestar Galactica?">
<pb-choice value="6">More than 5 stars {clarify}</pb-choice>
</pb-rating>
</problem-builder>
"""
long_answer_template
=
"""
<problem-builder>
<pb-answer question="What did you think {clarify_escaped} of the ending?" />
</problem-builder>
"""
html_block_template
=
"""
<problem-builder>
<html_demo><p>This is some raw {clarify} HTML code.</p></html_demo>
</problem-builder>
"""
def
prepare_xml_scenario
(
self
,
xml_template
):
span
=
'<span class="pb-clarification">{}</span>'
.
format
(
self
.
clarification_text
)
escaped_span
=
escape
(
span
,
quote
=
True
)
return
xml_template
.
format
(
clarify
=
span
,
clarify_escaped
=
escaped_span
)
@ddt.data
(
(
mcq_template
,
2
),
(
mrq_template
,
4
),
(
rating_template
,
2
),
(
long_answer_template
,
1
),
(
html_block_template
,
1
),
)
@ddt.unpack
def
test_title
(
self
,
xml_template
,
tooltip_count
):
self
.
set_scenario_xml
(
self
.
prepare_xml_scenario
(
xml_template
))
pb_element
=
self
.
go_to_view
()
clarifications
=
pb_element
.
find_elements_by_css_selector
(
'span.pb-clarification'
)
self
.
assertEqual
(
len
(
clarifications
),
tooltip_count
)
for
clarification
in
clarifications
:
tooltip
=
clarification
.
find_element_by_css_selector
(
'i[data-tooltip]'
)
self
.
assertEqual
(
tooltip
.
get_attribute
(
'data-tooltip'
),
self
.
clarification_text
)
sr
=
clarification
.
find_element_by_css_selector
(
'span.sr'
)
self
.
assertEqual
(
sr
.
text
,
self
.
clarification_text
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment