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
c45a6019
Commit
c45a6019
authored
Oct 15, 2015
by
Jonathan Piacenti
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Enable seamless use of steps that have no questions.
parent
c6e60602
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
115 additions
and
13 deletions
+115
-13
problem_builder/answer.py
+1
-0
problem_builder/public/js/mentoring_with_steps.js
+47
-12
problem_builder/public/js/step.js
+4
-0
problem_builder/questionnaire.py
+1
-0
problem_builder/step.py
+4
-0
problem_builder/templates/html/step.html
+1
-1
problem_builder/tests/integration/test_step_builder.py
+27
-0
problem_builder/tests/integration/xml_templates/step_builder.xml
+4
-0
problem_builder/tests/integration/xml_templates/step_builder_html_last.xml
+26
-0
No files found.
problem_builder/answer.py
View file @
c45a6019
...
...
@@ -125,6 +125,7 @@ class AnswerBlock(SubmittingXBlockMixin, AnswerMixin, QuestionMixin, StudioEdita
"""
CATEGORY
=
'pb-answer'
STUDIO_LABEL
=
_
(
u"Long Answer"
)
answerable
=
True
name
=
String
(
display_name
=
_
(
"Question ID (name)"
),
...
...
problem_builder/public/js/mentoring_with_steps.js
View file @
c45a6019
...
...
@@ -56,6 +56,15 @@ function MentoringWithStepsBlock(runtime, element) {
}
}
function
postUpdateStep
(
response
)
{
activeStep
=
response
.
active_step
;
if
(
activeStep
===
-
1
)
{
updateNumAttempts
();
}
else
{
updateControls
();
}
}
function
handleResults
(
response
)
{
showFeedback
(
response
);
...
...
@@ -64,14 +73,7 @@ function MentoringWithStepsBlock(runtime, element) {
// Otherwise, get UI ready for showing next step.
var
handlerUrl
=
runtime
.
handlerUrl
(
element
,
'update_active_step'
);
$
.
post
(
handlerUrl
,
JSON
.
stringify
(
activeStep
+
1
))
.
success
(
function
(
response
)
{
activeStep
=
response
.
active_step
;
if
(
activeStep
===
-
1
)
{
updateNumAttempts
();
}
else
{
updateControls
();
}
});
.
success
(
postUpdateStep
);
}
function
updateNumAttempts
()
{
...
...
@@ -138,6 +140,14 @@ function MentoringWithStepsBlock(runtime, element) {
step
.
submit
(
handleResults
);
}
function
markRead
()
{
var
handlerUrl
=
runtime
.
handlerUrl
(
element
,
'update_active_step'
);
$
.
post
(
handlerUrl
,
JSON
.
stringify
(
activeStep
+
1
)).
success
(
function
(
response
)
{
postUpdateStep
(
response
);
updateDisplay
();
});
}
function
getResults
()
{
var
step
=
steps
[
activeStep
];
step
.
getResults
(
handleReviewResults
);
...
...
@@ -195,9 +205,18 @@ function MentoringWithStepsBlock(runtime, element) {
showActiveStep
();
validateXBlock
();
updateNextLabel
();
nextDOM
.
attr
(
'disabled'
,
'disabled'
);
var
step
=
steps
[
activeStep
];
if
(
step
.
hasQuestion
())
{
nextDOM
.
attr
(
'disabled'
,
'disabled'
);
}
else
{
nextDOM
.
removeAttr
(
'disabled'
);
}
if
(
isLastStep
()
&&
reviewStep
)
{
reviewDOM
.
attr
(
'disabled'
,
'disabled'
);
if
(
step
.
hasQuestion
())
{
reviewDOM
.
attr
(
'disabled'
,
'disabled'
);
}
else
{
reviewDOM
.
removeAttr
(
'disabled'
)
}
reviewDOM
.
show
();
}
}
...
...
@@ -261,9 +280,14 @@ function MentoringWithStepsBlock(runtime, element) {
nextDOM
.
show
();
nextDOM
.
removeAttr
(
'disabled'
);
}
var
step
=
steps
[
activeStep
];
tryAgainDOM
.
hide
();
submitDOM
.
show
();
if
(
step
.
hasQuestion
())
{
submitDOM
.
show
();
}
else
{
submitDOM
.
hide
();
}
submitDOM
.
attr
(
'disabled'
,
'disabled'
);
reviewLinkDOM
.
show
();
...
...
@@ -302,8 +326,19 @@ function MentoringWithStepsBlock(runtime, element) {
}
else
{
submitDOM
.
removeAttr
(
'disabled'
);
}
if
(
isLastStep
())
{
if
(
isLastStep
()
&&
step
.
hasQuestion
()
)
{
nextDOM
.
hide
();
}
else
if
(
isLastStep
())
{
reviewDOM
.
one
(
'click'
,
markRead
);
reviewDOM
.
removeAttr
(
'disabled'
);
nextDOM
.
hide
()
}
else
if
(
!
step
.
hasQuestion
())
{
nextDOM
.
one
(
'click'
,
markRead
);
}
if
(
step
.
hasQuestion
())
{
submitDOM
.
show
();
}
else
{
submitDOM
.
hide
();
}
}
...
...
problem_builder/public/js/step.js
View file @
c45a6019
...
...
@@ -85,6 +85,10 @@ function MentoringStepBlock(runtime, element) {
getStepLabel
:
function
()
{
return
$
(
'.sb-step'
,
element
).
data
(
'next-button-label'
);
},
hasQuestion
:
function
()
{
return
$
(
'.sb-step'
,
element
).
data
(
'has-question'
)
}
};
...
...
problem_builder/questionnaire.py
View file @
c45a6019
...
...
@@ -90,6 +90,7 @@ class QuestionnaireAbstractBlock(
)
editable_fields
=
(
'question'
,
'message'
,
'weight'
,
'display_name'
,
'show_title'
)
has_children
=
True
answerable
=
True
@lazy
def
html_id
(
self
):
...
...
problem_builder/step.py
View file @
c45a6019
...
...
@@ -133,6 +133,10 @@ class MentoringStepBlock(
AnswerRecapBlock
,
MentoringTableBlock
,
]
@property
def
has_question
(
self
):
return
any
(
getattr
(
child
,
'answerable'
,
False
)
for
child
in
self
.
steps
)
@XBlock.json_handler
def
submit
(
self
,
submissions
,
suffix
=
''
):
log
.
info
(
u'Received submissions: {}'
.
format
(
submissions
))
...
...
problem_builder/templates/html/step.html
View file @
c45a6019
<div
class=
"sb-step"
data-next-button-label=
"{{ self.next_button_label }}"
>
<div
class=
"sb-step"
data-next-button-label=
"{{ self.next_button_label }}"
{%
if
self
.
has_question
%}
data-has-question=
"true"
{%
endif
%}
>
{% if show_title %}
<div
class=
"title"
>
<h3>
...
...
problem_builder/tests/integration/test_step_builder.py
View file @
c45a6019
...
...
@@ -211,6 +211,7 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
# It should be possible to visit the MRQ from here
self
.
wait_until_clickable
(
controls
.
next_question
)
controls
.
next_question
.
click
()
self
.
html_section
(
step_builder
,
controls
)
self
.
peek_at_multiple_response_question
(
None
,
step_builder
,
controls
,
extended_feedback
=
True
,
alternative_review
=
True
)
...
...
@@ -230,6 +231,24 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
self
.
expect_question_visible
(
None
,
step_builder
)
self
.
assertEqual
(
controls
.
next_question
.
get_attribute
(
'value'
),
"Next Challenge"
)
def
html_section
(
self
,
step_builder
,
controls
,
last
=
False
):
self
.
wait_until_hidden
(
controls
.
submit
)
target_control
=
controls
.
review
if
last
else
controls
.
next_question
self
.
wait_until_clickable
(
target_control
)
target_control
.
click
()
def
test_html_last
(
self
):
step_builder
,
controls
=
self
.
load_assessment_scenario
(
"step_builder_html_last.xml"
)
# Step 1
# Submit free-form answer, go to next step
self
.
freeform_answer
(
None
,
step_builder
,
controls
,
'This is the answer'
,
CORRECT
)
# Step 2
# Submit MCQ, go to next step
self
.
single_choice_question
(
None
,
step_builder
,
controls
,
'Maybe not'
,
INCORRECT
)
self
.
html_section
(
step_builder
,
controls
,
last
=
True
)
@data
(
{
"max_attempts"
:
0
,
"extended_feedback"
:
False
},
# Unlimited attempts, no extended feedback
{
"max_attempts"
:
1
,
"extended_feedback"
:
True
},
# Limited attempts, extended feedback
...
...
@@ -253,6 +272,9 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
# Submit rating, go to next step
self
.
rating_question
(
None
,
step_builder
,
controls
,
"5 - Extremely good"
,
CORRECT
)
# Step 4, html with no question.
self
.
html_section
(
step_builder
,
controls
)
# Last step
# Submit MRQ, go to review
with
patch
.
object
(
WorkbenchRuntime
,
'publish'
)
as
patched_method
:
...
...
@@ -308,6 +330,8 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
# Submit rating, go to next step
self
.
rating_question
(
None
,
step_builder
,
controls
,
"1 - Not good at all"
,
INCORRECT
)
# Step 4, read only. Go to next step.
self
.
html_section
(
step_builder
,
controls
)
# Last step
# Submit MRQ, go to review
user_selection
=
(
"Its elegance"
,
"Its beauty"
,
"Its gracefulness"
)
...
...
@@ -350,6 +374,7 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
self
.
freeform_answer
(
None
,
step_builder
,
controls
,
'This is the answer'
,
CORRECT
)
self
.
single_choice_question
(
None
,
step_builder
,
controls
,
'Maybe not'
,
INCORRECT
)
self
.
rating_question
(
None
,
step_builder
,
controls
,
"5 - Extremely good"
,
CORRECT
)
self
.
html_section
(
step_builder
,
controls
)
self
.
multiple_response_question
(
None
,
step_builder
,
controls
,
(
"Its beauty"
,),
PARTIAL
,
last
=
True
)
# The review tips for MCQ 2 and the MRQ should be shown:
...
...
@@ -374,6 +399,7 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
self
.
single_choice_question
(
None
,
step_builder
,
controls
,
'Yes'
,
CORRECT
)
self
.
rating_question
(
None
,
step_builder
,
controls
,
"5 - Extremely good"
,
CORRECT
)
user_selection
=
(
"Its elegance"
,
"Its beauty"
,
"Its gracefulness"
)
self
.
html_section
(
step_builder
,
controls
)
self
.
multiple_response_question
(
None
,
step_builder
,
controls
,
user_selection
,
CORRECT
,
last
=
True
)
# If attempts remain and student got all answers right, show "complete" message
...
...
@@ -390,6 +416,7 @@ class StepBuilderTest(MentoringAssessmentBaseTest):
)
self
.
single_choice_question
(
None
,
step_builder
,
controls
,
'Maybe not'
,
INCORRECT
)
self
.
rating_question
(
None
,
step_builder
,
controls
,
"1 - Not good at all"
,
INCORRECT
)
self
.
html_section
(
step_builder
,
controls
)
self
.
multiple_response_question
(
None
,
step_builder
,
controls
,
(
"Its beauty"
,),
PARTIAL
,
last
=
True
)
# The review tips will not be shown because no attempts remain:
...
...
problem_builder/tests/integration/xml_templates/step_builder.xml
View file @
c45a6019
...
...
@@ -36,6 +36,10 @@
</pb-rating>
</sb-step>
<sb-step
display_name=
"Fourth Step"
>
<html_demo>
Test test test
</html_demo>
</sb-step>
<sb-step
display_name=
"Last step"
>
<pb-mrq
name=
"mrq_1_1"
question=
"What do you like in this MRQ?"
required_choices=
'["gracefulness","elegance","beauty"]'
message=
"Question Feedback Message"
>
<pb-choice
value=
"elegance"
>
Its elegance
</pb-choice>
...
...
problem_builder/tests/integration/xml_templates/step_builder_html_last.xml
0 → 100644
View file @
c45a6019
<step-builder
url_name=
"step-builder"
display_name=
"Step Builder"
max_attempts=
"1"
extended_feedback=
"True"
>
<sb-step
display_name=
"First step"
next_button_label=
"Next Challenge"
>
<pb-answer
name=
"goal"
question=
"What is your goal?"
/>
</sb-step>
<sb-step
display_name=
"Second step"
next_button_label=
"Next Item"
>
<pb-mcq
name=
"mcq_1_1"
question=
"Do you like this MCQ?"
correct_choices=
'["yes"]'
>
<pb-choice
value=
"yes"
>
Yes
</pb-choice>
<pb-choice
value=
"maybenot"
>
Maybe not
</pb-choice>
<pb-choice
value=
"understand"
>
I don't understand
</pb-choice>
<pb-tip
values=
'["yes"]'
>
Great!
</pb-tip>
<pb-tip
values=
'["maybenot"]'
>
Ah, damn.
</pb-tip>
<pb-tip
values=
'["understand"]'
><div
id=
"test-custom-html"
>
Really?
</div></pb-tip>
</pb-mcq>
</sb-step>
<sb-step
display_name=
"Last HTML step"
>
<html_demo>
Bla bla bla
</html_demo>
</sb-step>
<sb-review-step
/>
</step-builder>
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