Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-ora2
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
edx
edx-ora2
Commits
043e493b
Commit
043e493b
authored
Aug 06, 2014
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement leaderboard authoring
parent
25412f9e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
180 additions
and
78 deletions
+180
-78
openassessment/templates/openassessmentblock/edit/oa_edit.html
+15
-1
openassessment/xblock/openassessmentblock.py
+2
-1
openassessment/xblock/schema.py
+1
-0
openassessment/xblock/static/js/fixtures/templates.json
+2
-0
openassessment/xblock/static/js/openassessment-lms.min.js
+0
-0
openassessment/xblock/static/js/openassessment-studio.min.js
+0
-0
openassessment/xblock/static/js/spec/oa_server.js
+6
-2
openassessment/xblock/static/js/spec/studio/oa_edit.js
+2
-0
openassessment/xblock/static/js/spec/studio/oa_edit_settings.js
+34
-0
openassessment/xblock/static/js/src/oa_server.js
+3
-1
openassessment/xblock/static/js/src/studio/oa_edit.js
+1
-0
openassessment/xblock/static/js/src/studio/oa_edit_settings.js
+30
-1
openassessment/xblock/studio_mixin.py
+3
-0
openassessment/xblock/test/data/invalid_update_xblock.json
+27
-0
openassessment/xblock/test/data/update_from_xml_error.json
+0
-63
openassessment/xblock/test/data/update_xblock.json
+4
-0
openassessment/xblock/test/test_studio.py
+16
-0
openassessment/xblock/test/test_validation.py
+28
-0
openassessment/xblock/validation.py
+6
-1
openassessment/xblock/xml.py
+0
-8
No files found.
openassessment/templates/openassessmentblock/edit/oa_edit.html
View file @
043e493b
...
...
@@ -99,7 +99,7 @@
</div>
<p
class=
"setting-help"
>
{% trans "The date and time when students can no longer submit responses." %}
</p>
</li>
<li
id=
"openassessment_su
mb
ission_image_wrapper"
class=
"field comp-setting-entry"
>
<li
id=
"openassessment_su
bm
ission_image_wrapper"
class=
"field comp-setting-entry"
>
<div
class=
"wrapper-comp-setting"
>
<label
for=
"openassessment_submission_image_editor"
class=
"setting-label"
>
{% trans "Allow Image Responses"%}
</label>
<select
id=
"openassessment_submission_image_editor"
class=
"input setting-input"
name=
"image submission"
>
...
...
@@ -109,6 +109,20 @@
</div>
<p
class=
"setting-help"
>
{% trans "Specify whether students can submit an image file along with their text response." %}
</p>
</li>
<li
id=
"openassessment_leaderboard_wrapper"
class=
"field comp-setting-entry"
>
<div
class=
"wrapper-comp-setting"
>
<label
for=
"openassessment_leaderboard_editor"
class=
"setting-label"
>
{% trans "Number of Leaderboard Scores" %}
</label>
<input
id=
"openassessment_leaderboard_editor"
class=
"input setting-input"
type=
"number"
value=
"{{ leaderboard_show }}"
min=
"0"
max=
"99"
/>
</div>
<p
class=
"setting-help"
>
{% trans "Set the number of scores to display on the leaderboard. If set to 0, the leaderboard will not be shown." %}
</p>
</li>
<li>
</ul>
<p
class=
"openassessment_description"
id=
"openassessment_step_select_description"
>
...
...
openassessment/xblock/openassessmentblock.py
View file @
043e493b
...
...
@@ -380,7 +380,8 @@ class OpenAssessmentBlock(
create_rubric_dict
(
config
[
'prompt'
],
config
[
'rubric_criteria'
]),
config
[
'rubric_assessments'
],
submission_start
=
config
[
'submission_start'
],
submission_due
=
config
[
'submission_due'
]
submission_due
=
config
[
'submission_due'
],
leaderboard_show
=
config
[
'leaderboard_show'
]
)
block
.
rubric_criteria
=
config
[
'rubric_criteria'
]
...
...
openassessment/xblock/schema.py
View file @
043e493b
...
...
@@ -72,6 +72,7 @@ EDITOR_UPDATE_SCHEMA = Schema({
Required
(
'submission_start'
):
Any
(
datetime_validator
,
None
),
Required
(
'submission_due'
):
Any
(
datetime_validator
,
None
),
Required
(
'allow_file_upload'
):
bool
,
Required
(
'leaderboard_show'
):
int
,
Required
(
'assessments'
):
[
Schema
({
Required
(
'name'
):
All
(
utf8_validator
,
In
(
VALID_ASSESSMENT_TYPES
)),
...
...
openassessment/xblock/static/js/fixtures/templates.json
View file @
043e493b
...
...
@@ -402,6 +402,7 @@
"title"
:
"The most important of all questions."
,
"submission_start"
:
"2014-01-02T12:15"
,
"submission_due"
:
"2014-10-01T04:53"
,
"leaderboard_show"
:
12
,
"criteria"
:
[
{
"name"
:
"criterion_1"
,
...
...
@@ -482,6 +483,7 @@
"title"
:
"Test title"
,
"submission_start"
:
"2014-01-1T10:00:00"
,
"submission_due"
:
"2014-10-1T10:00:00"
,
"leaderboard_show"
:
12
,
"criteria"
:
[
{
"name"
:
"criterion_with_two_options"
,
...
...
openassessment/xblock/static/js/openassessment-lms.min.js
View file @
043e493b
This diff is collapsed.
Click to expand it.
openassessment/xblock/static/js/openassessment-studio.min.js
View file @
043e493b
This diff is collapsed.
Click to expand it.
openassessment/xblock/static/js/spec/oa_server.js
View file @
043e493b
...
...
@@ -239,7 +239,9 @@ describe("OpenAssessment.Server", function() {
submissionDue
:
SUBMISSION_DUE
,
criteria
:
CRITERIA
,
assessments
:
ASSESSMENTS
,
editorAssessmentsOrder
:
EDITOR_ASSESSMENTS_ORDER
editorAssessmentsOrder
:
EDITOR_ASSESSMENTS_ORDER
,
imageSubmissionEnabled
:
true
,
leaderboardNum
:
15
});
expect
(
$
.
ajax
).
toHaveBeenCalledWith
({
type
:
"POST"
,
url
:
'/update_editor_context'
,
...
...
@@ -251,7 +253,9 @@ describe("OpenAssessment.Server", function() {
submission_due
:
SUBMISSION_DUE
,
criteria
:
CRITERIA
,
assessments
:
ASSESSMENTS
,
editor_assessments_order
:
EDITOR_ASSESSMENTS_ORDER
editor_assessments_order
:
EDITOR_ASSESSMENTS_ORDER
,
allow_file_upload
:
true
,
leaderboard_show
:
15
})
});
});
...
...
openassessment/xblock/static/js/spec/studio/oa_edit.js
View file @
043e493b
...
...
@@ -48,6 +48,7 @@ describe("OpenAssessment.StudioView", function() {
submissionStart
:
"2014-01-02T12:15"
,
submissionDue
:
"2014-10-01T04:53"
,
imageSubmissionEnabled
:
false
,
leaderboardNum
:
12
,
criteria
:
[
{
order_num
:
0
,
...
...
@@ -149,6 +150,7 @@ describe("OpenAssessment.StudioView", function() {
expect
(
server
.
receivedData
.
submissionStart
).
toEqual
(
EXPECTED_SERVER_DATA
.
submissionStart
);
expect
(
server
.
receivedData
.
submissionDue
).
toEqual
(
EXPECTED_SERVER_DATA
.
submissionDue
);
expect
(
server
.
receivedData
.
imageSubmissionEnabled
).
toEqual
(
EXPECTED_SERVER_DATA
.
imageSubmissionEnabled
);
expect
(
server
.
receivedData
.
leaderboardNum
).
toEqual
(
EXPECTED_SERVER_DATA
.
leaderboardNum
);
// Criteria
for
(
var
criterion_idx
=
0
;
criterion_idx
<
EXPECTED_SERVER_DATA
.
criteria
.
length
;
criterion_idx
++
)
{
...
...
openassessment/xblock/static/js/spec/studio/oa_edit_settings.js
View file @
043e493b
...
...
@@ -91,6 +91,14 @@ describe("OpenAssessment.EditSettingsView", function() {
expect
(
view
.
imageSubmissionEnabled
()).
toBe
(
false
);
});
it
(
"sets and loads the leaderboard number"
,
function
()
{
view
.
leaderboardNum
(
18
);
expect
(
view
.
leaderboardNum
()).
toEqual
(
18
);
view
.
leaderboardNum
(
0
);
expect
(
view
.
leaderboardNum
()).
toEqual
(
0
);
});
it
(
"builds a description of enabled assessments"
,
function
()
{
// Depends on the template having an original order
// of training --> peer --> self --> ai
...
...
@@ -157,6 +165,32 @@ describe("OpenAssessment.EditSettingsView", function() {
);
});
it
(
"validates the leaderboard number field"
,
function
()
{
// Valid value for the leaderboard number
view
.
leaderboardNum
(
0
);
expect
(
view
.
validate
()).
toBe
(
true
);
expect
(
view
.
validationErrors
()).
toEqual
([]);
// Below the minimum
view
.
leaderboardNum
(
-
1
);
expect
(
view
.
validate
()).
toBe
(
false
);
expect
(
view
.
validationErrors
()).
toContain
(
"Leaderboard number is invalid"
);
// Clear validation errors
view
.
clearValidationErrors
();
expect
(
view
.
validationErrors
()).
toEqual
([]);
// Valid, near the maximum
view
.
leaderboardNum
(
100
);
expect
(
view
.
validate
()).
toBe
(
true
);
// Above the maximum
view
.
leaderboardNum
(
101
);
expect
(
view
.
validate
()).
toBe
(
false
);
});
it
(
"validates assessment views"
,
function
()
{
// Simulate one of the assessment views being invalid
assessmentViews
[
PEER
].
isValid
=
false
;
...
...
openassessment/xblock/static/js/src/oa_server.js
View file @
043e493b
...
...
@@ -418,6 +418,7 @@ if (typeof OpenAssessment.Server == "undefined" || !OpenAssessment.Server) {
criteria (list of object literals): The rubric criteria.
assessments (list of object literals): The assessments the student will be evaluated on.
imageSubmissionEnabled (boolean): TRUE if image attachments are allowed.
leaderboardNum (int): The number of scores to show in the leaderboard.
Returns:
A JQuery promise, which resolves with no arguments
...
...
@@ -435,7 +436,8 @@ if (typeof OpenAssessment.Server == "undefined" || !OpenAssessment.Server) {
criteria
:
kwargs
.
criteria
,
assessments
:
kwargs
.
assessments
,
editor_assessments_order
:
kwargs
.
editorAssessmentsOrder
,
allow_file_upload
:
kwargs
.
imageSubmissionEnabled
allow_file_upload
:
kwargs
.
imageSubmissionEnabled
,
leaderboard_show
:
kwargs
.
leaderboardNum
});
return
$
.
Deferred
(
function
(
defer
)
{
$
.
ajax
({
...
...
openassessment/xblock/static/js/src/studio/oa_edit.js
View file @
043e493b
...
...
@@ -193,6 +193,7 @@ OpenAssessment.StudioView.prototype = {
submissionDue
:
view
.
settingsView
.
submissionDue
(),
assessments
:
view
.
settingsView
.
assessmentsDescription
(),
imageSubmissionEnabled
:
view
.
settingsView
.
imageSubmissionEnabled
(),
leaderboardNum
:
view
.
settingsView
.
leaderboardNum
(),
editorAssessmentsOrder
:
view
.
settingsView
.
editorAssessmentsOrder
()
}).
done
(
// Notify the client-side runtime that we finished saving
...
...
openassessment/xblock/static/js/src/studio/oa_edit_settings.js
View file @
043e493b
...
...
@@ -27,6 +27,11 @@ OpenAssessment.EditSettingsView = function(element, assessmentViews) {
"#openassessment_submission_due_time"
).
install
();
this
.
leaderboardIntField
=
new
OpenAssessment
.
IntField
(
$
(
"#openassessment_leaderboard_editor"
,
this
.
element
),
{
min
:
0
,
max
:
100
}
);
this
.
initializeSortableAssessments
();
};
...
...
@@ -128,7 +133,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
imageSubmissionEnabled
:
function
(
isEnabled
)
{
var
sel
=
$
(
"#openassessment_submission_image_editor"
,
this
.
settingsElement
);
if
(
typeof
(
isEnabled
)
!==
"undefined"
)
{
if
(
isEnabled
!==
undefined
)
{
if
(
isEnabled
)
{
sel
.
val
(
1
);
}
else
{
sel
.
val
(
0
);
}
}
...
...
@@ -136,6 +141,24 @@ OpenAssessment.EditSettingsView.prototype = {
},
/**
Get or set the number of scores to show in the leaderboard.
If set to 0, the leaderboard will not be shown.
Args:
num (int, optional)
Returns:
int
**/
leaderboardNum
:
function
(
num
)
{
if
(
num
!==
undefined
)
{
this
.
leaderboardIntField
.
set
(
num
);
}
return
this
.
leaderboardIntField
.
get
(
num
);
},
/**
Construct a list of enabled assessments and their properties.
...
...
@@ -212,6 +235,7 @@ OpenAssessment.EditSettingsView.prototype = {
isValid
=
(
this
.
startDatetimeControl
.
validate
()
&&
isValid
);
isValid
=
(
this
.
dueDatetimeControl
.
validate
()
&&
isValid
);
isValid
=
(
this
.
leaderboardIntField
.
validate
()
&&
isValid
);
// Validate each of the *enabled* assessment views
$
.
each
(
this
.
assessmentViews
,
function
()
{
...
...
@@ -240,10 +264,14 @@ OpenAssessment.EditSettingsView.prototype = {
if
(
this
.
dueDatetimeControl
.
validationErrors
().
length
>
0
)
{
errors
.
push
(
"Submission due is invalid"
);
}
if
(
this
.
leaderboardIntField
.
validationErrors
().
length
>
0
)
{
errors
.
push
(
"Leaderboard number is invalid"
);
}
$
.
each
(
this
.
assessmentViews
,
function
()
{
errors
=
errors
.
concat
(
this
.
validationErrors
());
});
return
errors
;
},
...
...
@@ -253,6 +281,7 @@ OpenAssessment.EditSettingsView.prototype = {
clearValidationErrors
:
function
()
{
this
.
startDatetimeControl
.
clearValidationErrors
();
this
.
dueDatetimeControl
.
clearValidationErrors
();
this
.
leaderboardIntField
.
clearValidationErrors
();
$
.
each
(
this
.
assessmentViews
,
function
()
{
this
.
clearValidationErrors
();
});
...
...
openassessment/xblock/studio_mixin.py
View file @
043e493b
...
...
@@ -114,6 +114,7 @@ class StudioMixin(object):
'criteria'
:
criteria
,
'feedbackprompt'
:
self
.
rubric_feedback_prompt
,
'allow_file_upload'
:
self
.
allow_file_upload
,
'leaderboard_show'
:
self
.
leaderboard_show
,
'editor_assessments_order'
:
[
make_django_template_key
(
asmnt
)
for
asmnt
in
editor_assessments_order
...
...
@@ -187,6 +188,7 @@ class StudioMixin(object):
data
[
'assessments'
],
submission_start
=
data
[
'submission_start'
],
submission_due
=
data
[
'submission_due'
],
leaderboard_show
=
data
[
'leaderboard_show'
]
)
if
not
success
:
return
{
'success'
:
False
,
'msg'
:
self
.
_
(
'Validation error: {error}'
)
.
format
(
error
=
msg
)}
...
...
@@ -203,6 +205,7 @@ class StudioMixin(object):
self
.
submission_start
=
data
[
'submission_start'
]
self
.
submission_due
=
data
[
'submission_due'
]
self
.
allow_file_upload
=
bool
(
data
[
'allow_file_upload'
])
self
.
leaderboard_show
=
data
[
'leaderboard_show'
]
return
{
'success'
:
True
,
'msg'
:
self
.
_
(
u'Successfully updated OpenAssessment XBlock'
)}
...
...
openassessment/xblock/test/data/invalid_update_xblock.json
View file @
043e493b
...
...
@@ -4,6 +4,7 @@
"title"
:
"My new title."
,
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -26,6 +27,7 @@
"no_prompt"
:
{
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -74,6 +76,7 @@
"no_feedback_prompt"
:
{
"prompt"
:
"Test prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -123,6 +126,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -171,6 +175,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -221,6 +226,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -271,6 +277,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
"Hello"
,
...
...
@@ -313,6 +320,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -354,6 +362,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"prompty"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
[]
],
...
...
@@ -374,6 +383,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -415,6 +425,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -442,6 +453,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -478,6 +490,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -519,6 +532,7 @@
"feedback_prompt"
:
"Feedback prompt"
,
"prompt"
:
"Test Prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -669,6 +683,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -723,6 +738,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -775,6 +791,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -830,6 +847,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -885,6 +903,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -934,6 +953,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -990,6 +1010,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -1038,6 +1059,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -1087,6 +1109,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -1112,6 +1135,7 @@
"prompt"
:
"Test Prompt"
,
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -1160,6 +1184,7 @@
"prompt"
:
"Test Prompt"
,
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -1208,6 +1233,7 @@
"prompt"
:
"Test Prompt"
,
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
@@ -1279,6 +1305,7 @@
"prompt"
:
"Test Prompt"
,
"feedback_prompt"
:
"Feedback prompt"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"criteria"
:
[
{
"order_num"
:
0
,
...
...
openassessment/xblock/test/data/update_from_xml_error.json
View file @
043e493b
...
...
@@ -452,69 +452,6 @@
]
},
"leaderboard_num_zero"
:
{
"xml"
:
[
"<openassessment leaderboard_show=
\"
0
\"
>"
,
"<title>Foo</title>"
,
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
start=
\"
2014-02-27T09:46:28
\"
due=
\"
2014-03-01T00:00:00
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
/>"
,
"</assessments>"
,
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
,
"</openassessment>"
]
},
"leaderboard_num_negative"
:
{
"xml"
:
[
"<openassessment leaderboard_show=
\"
-1
\"
>"
,
"<title>Foo</title>"
,
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
start=
\"
2014-02-27T09:46:28
\"
due=
\"
2014-03-01T00:00:00
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
/>"
,
"</assessments>"
,
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
,
"</openassessment>"
]
},
"leaderboard_num_too_high"
:
{
"xml"
:
[
"<openassessment leaderboard_show=
\"
101
\"
>"
,
"<title>Foo</title>"
,
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
start=
\"
2014-02-27T09:46:28
\"
due=
\"
2014-03-01T00:00:00
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
/>"
,
"</assessments>"
,
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
,
"</openassessment>"
]
},
"leaderboard_num_not_integer"
:
{
"xml"
:
[
"<openassessment leaderboard_show=
\"
not_an_int
\"
>"
,
...
...
openassessment/xblock/test/data/update_xblock.json
View file @
043e493b
...
...
@@ -31,6 +31,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -80,6 +81,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"ɯʎ uǝʍ ʇıʇןǝ"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
...
...
@@ -129,6 +131,7 @@
"submission_start"
:
"4014-02-10T09:46"
,
"title"
:
"My new title."
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"assessments"
:
[
{
"name"
:
"student-training"
,
...
...
@@ -189,6 +192,7 @@
"submission_due"
:
"4014-02-27T09:46"
,
"submission_start"
:
"4014-02-10T09:46"
,
"allow_file_upload"
:
false
,
"leaderboard_show"
:
0
,
"title"
:
"My new title."
,
"assessments"
:
[
{
...
...
openassessment/xblock/test/test_studio.py
View file @
043e493b
...
...
@@ -22,6 +22,7 @@ class StudioViewTest(XBlockHandlerTestCase):
"submission_start"
:
"4014-02-10T09:46"
,
"submission_due"
:
"4014-02-27T09:46"
,
"allow_file_upload"
:
False
,
"leaderboard_show"
:
4
,
"assessments"
:
[{
"name"
:
"self-assessment"
}],
"editor_assessments_order"
:
[
"student-training"
,
...
...
@@ -127,6 +128,11 @@ class StudioViewTest(XBlockHandlerTestCase):
self
.
assertTrue
(
resp
[
'success'
],
msg
=
resp
.
get
(
'msg'
))
@scenario
(
'data/basic_scenario.xml'
)
def
test_include_leaderboard_in_editor
(
self
,
xblock
):
xblock
.
leaderboard_show
=
15
self
.
assertEqual
(
xblock
.
editor_context
()[
'leaderboard_show'
],
15
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_editor_context_saves_assessment_order
(
self
,
xblock
):
# Update the XBlock with a different editor assessment order
data
=
copy
.
deepcopy
(
self
.
UPDATE_EDITOR_DATA
)
...
...
@@ -140,6 +146,7 @@ class StudioViewTest(XBlockHandlerTestCase):
self
.
assertTrue
(
resp
[
'success'
],
msg
=
resp
.
get
(
'msg'
))
self
.
assertEqual
(
xblock
.
editor_assessments_order
,
data
[
'editor_assessments_order'
])
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_editor_context_saves_assessment_order_with_ai
(
self
,
xblock
):
# Update the XBlock with a different editor assessment order
...
...
@@ -159,6 +166,15 @@ class StudioViewTest(XBlockHandlerTestCase):
self
.
assertTrue
(
resp
[
'success'
],
msg
=
resp
.
get
(
'msg'
))
self
.
assertEqual
(
xblock
.
editor_assessments_order
,
data
[
'editor_assessments_order'
])
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_editor_context_saves_leaderboard
(
self
,
xblock
):
data
=
copy
.
deepcopy
(
self
.
UPDATE_EDITOR_DATA
)
data
[
'leaderboard_show'
]
=
42
xblock
.
published_date
=
None
resp
=
self
.
request
(
xblock
,
'update_editor_context'
,
json
.
dumps
(
data
),
response_format
=
'json'
)
self
.
assertTrue
(
resp
[
'success'
],
msg
=
resp
.
get
(
'msg'
))
self
.
assertEqual
(
xblock
.
leaderboard_show
,
42
)
@file_data
(
'data/invalid_update_xblock.json'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_context_invalid_request_data
(
self
,
xblock
,
data
):
...
...
openassessment/xblock/test/test_validation.py
View file @
043e493b
...
...
@@ -334,3 +334,31 @@ class ValidationIntegrationTest(TestCase):
is_valid
,
msg
=
self
.
validator
(
mutated_rubric
,
no_example_based
)
self
.
assertTrue
(
is_valid
)
self
.
assertEqual
(
msg
,
u''
)
def
test_leaderboard_num_validation
(
self
):
self
.
_assert_leaderboard_num_valid
(
-
1
,
False
)
self
.
_assert_leaderboard_num_valid
(
0
,
True
)
self
.
_assert_leaderboard_num_valid
(
1
,
True
)
self
.
_assert_leaderboard_num_valid
(
100
,
True
)
self
.
_assert_leaderboard_num_valid
(
101
,
False
)
self
.
_assert_leaderboard_num_valid
(
102
,
False
)
def
_assert_leaderboard_num_valid
(
self
,
num
,
expected_is_valid
):
"""
Check that the leaderboard number is either valid or invalid.
Args:
num (int): The leaderboard number to check
expected_is_valid (bool): Whether the number is valid or invalid.
Raises:
AssertionError
"""
is_valid
,
msg
=
self
.
validator
(
self
.
RUBRIC
,
self
.
ASSESSMENTS
,
num
)
if
expected_is_valid
:
self
.
assertTrue
(
is_valid
,
msg
=
"Leaderboard num {num} should be valid"
.
format
(
num
=
num
))
self
.
assertEqual
(
msg
,
''
)
else
:
self
.
assertFalse
(
is_valid
,
msg
=
"Leaderboard num {num} should be invalid"
.
format
(
num
=
num
))
self
.
assertEqual
(
msg
,
'Leaderboard number is invalid.'
)
openassessment/xblock/validation.py
View file @
043e493b
...
...
@@ -2,6 +2,7 @@
Validate changes to an XBlock before it is updated.
"""
from
collections
import
Counter
from
submissions.api
import
MAX_TOP_SUBMISSIONS
from
openassessment.assessment.serializers
import
rubric_from_dict
,
InvalidRubric
from
openassessment.assessment.api.student_training
import
validate_training_examples
from
openassessment.xblock.resolve_dates
import
resolve_dates
,
DateValidationError
,
InvalidDateFormat
...
...
@@ -316,7 +317,7 @@ def validator(oa_block, _, strict_post_release=True):
callable, of a form that can be passed to `update_from_xml`.
"""
def
_inner
(
rubric_dict
,
assessments
,
submission_start
=
None
,
submission_due
=
None
):
def
_inner
(
rubric_dict
,
assessments
,
leaderboard_show
=
0
,
submission_start
=
None
,
submission_due
=
None
):
is_released
=
strict_post_release
and
oa_block
.
is_released
()
...
...
@@ -348,6 +349,10 @@ def validator(oa_block, _, strict_post_release=True):
if
not
success
:
return
(
False
,
msg
)
# Leaderboard
if
leaderboard_show
<
0
or
leaderboard_show
>
MAX_TOP_SUBMISSIONS
:
return
(
False
,
_
(
"Leaderboard number is invalid."
))
# Success!
return
(
True
,
u''
)
...
...
openassessment/xblock/xml.py
View file @
043e493b
...
...
@@ -6,7 +6,6 @@ import lxml.etree as etree
import
pytz
import
dateutil.parser
import
defusedxml.ElementTree
as
safe_etree
from
submissions.api
import
MAX_TOP_SUBMISSIONS
class
UpdateFromXmlError
(
Exception
):
...
...
@@ -755,13 +754,6 @@ def parse_from_xml(root):
if
'leaderboard_show'
in
root
.
attrib
:
try
:
leaderboard_show
=
int
(
root
.
attrib
[
'leaderboard_show'
])
if
leaderboard_show
<
1
:
raise
UpdateFromXmlError
(
'The leaderboard must have a positive integer value.'
)
if
leaderboard_show
>
MAX_TOP_SUBMISSIONS
:
msg
=
'The number of leaderboard scores must be less than {max_num}'
.
format
(
max_num
=
MAX_TOP_SUBMISSIONS
)
raise
UpdateFromXmlError
(
msg
)
except
(
TypeError
,
ValueError
):
raise
UpdateFromXmlError
(
'The leaderboard must have an integer value.'
)
...
...
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