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
c3161007
Commit
c3161007
authored
Jun 06, 2014
by
gradyward
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added UI functionality to allow Three Tab OA Creation
parent
9355cc55
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
314 additions
and
83 deletions
+314
-83
AUTHORS
+2
-0
apps/openassessment/templates/openassessmentblock/oa_edit.html
+39
-2
apps/openassessment/xblock/openassessmentblock.py
+1
-1
apps/openassessment/xblock/static/css/openassessment.css
+42
-0
apps/openassessment/xblock/static/js/openassessment.min.js
+0
-0
apps/openassessment/xblock/static/js/src/oa_edit.js
+93
-59
apps/openassessment/xblock/static/js/src/oa_server.js
+9
-3
apps/openassessment/xblock/static/sass/oa/utilities/_developer.scss
+70
-2
apps/openassessment/xblock/studio_mixin.py
+58
-16
apps/openassessment/xblock/xml.py
+0
-0
No files found.
AUTHORS
View file @
c3161007
...
...
@@ -7,3 +7,4 @@ Brian Talbot <btalbot@edx.org>
Mark Hoeber <hoeber@edx.org>
Sylvia Pearce <spearce@edx.org>
Ned Batchelder <ned@nedbatchelder.com>
Grady Ward <gward@brandeis.edu>
\ No newline at end of file
apps/openassessment/templates/openassessmentblock/oa_edit.html
View file @
c3161007
{% load i18n %}
<div
id=
"openassessment-edit"
class=
"editor-with-buttons"
>
<textarea
class=
"openassessment-editor"
></textarea>
<div
id=
"openassessment-editor"
class=
"editor-with-buttons editor-with-tabs"
>
<div
class=
"openassessment-editor-content-and-tabs"
>
<div
class=
"openassessment-editor-header"
>
<h6
id=
"oa-editor-window-title"
class=
"title modal-window-title"
>
Editing: Open Assessment
</h6>
<ul
class=
"editor-modes action-list action-modes editor-tabs"
>
<li
class=
"view-button oa-editor-tab"
><a
href=
"#oa-settings-editor-wrapper"
>
{% trans "Settings" %}
</a></li>
<li
class=
"view-button oa-editor-tab"
><a
href=
"#oa-rubric-editor-wrapper"
>
{% trans "Rubric" %}
</a></li>
<li
class=
"view-button oa-editor-tab"
><a
href=
"#oa-prompt-editor-wrapper"
>
{% trans "Prompt" %}
</a></li>
</ul>
</div>
<div
id =
"oa-prompt-editor-wrapper"
class=
"oa-editor-content-wrapper"
>
<h2>
Prompt Editor
</h2>
<textarea
class=
"openassessment-prompt-editor"
></textarea>
</div>
<div
id=
"oa-rubric-editor-wrapper"
class=
"oa-editor-content-wrapper"
>
<h2>
Rubric Editor
</h2>
<textarea
class=
"openassessment-rubric-editor"
></textarea>
</div>
<div
id=
"oa-settings-editor-wrapper"
class=
"oa-editor-content-wrapper"
>
<div
id=
"oa-settings-editor-text-fields"
>
<h2>
Settings Editor
</h2>
<h2>
Title:
</h2>
<input
type=
"text"
name=
"title"
class=
"openassessment-title-editor"
>
<h2>
Submission Start Date:
</h2>
<input
type=
"text"
name=
"start_date"
class=
"openassessment-submission-start-editor"
>
<h2>
Submission Due Date:
</h2>
<input
type=
"text"
name=
"due_date"
class=
"openassessment-submission-due-editor"
>
</div>
<div
id=
"oa-settings-assessments"
>
XML For Assessments:
<textarea
class=
"openassessment-assessments-editor"
></textarea>
</div>
</div>
</div>
<div
class=
"xblock-actions"
>
<h3
class=
"sr"
>
Actions
</h3>
<ul>
...
...
apps/openassessment/xblock/openassessmentblock.py
View file @
c3161007
...
...
@@ -22,7 +22,7 @@ from openassessment.xblock.lms_mixin import LmsCompatibilityMixin
from
openassessment.xblock.self_assessment_mixin
import
SelfAssessmentMixin
from
openassessment.xblock.submission_mixin
import
SubmissionMixin
from
openassessment.xblock.studio_mixin
import
StudioMixin
from
openassessment.xblock.xml
import
update_from_xml
,
serialize_content_to_xml
from
openassessment.xblock.xml
import
serialize_content_to_xml
from
openassessment.xblock.staff_info_mixin
import
StaffInfoMixin
from
openassessment.xblock.workflow_mixin
import
WorkflowMixin
from
openassessment.workflow
import
api
as
workflow_api
...
...
apps/openassessment/xblock/static/css/openassessment.css
View file @
c3161007
...
...
@@ -2133,6 +2133,48 @@ hr.divider,
.step--student-training
.message--incorrect.is--hidden
.step__header
{
border-bottom
:
none
;
}
#openassessment-editor
.openassessment-editor-content-and-tabs
{
width
:
100%
;
height
:
370px
;
}
#openassessment-editor
.openassessment-editor-header
{
background-color
:
#e5e5e5
;
width
:
100%
;
top
:
0
;
}
#openassessment-editor
#oa-editor-window-title
{
float
:
left
;
}
#openassessment-editor
.oa-editor-tab
{
float
:
right
;
padding
:
2.5px
5px
;
margin
:
2.5px
5px
;
}
#openassessment-editor
.oa-editor-content-wrapper
{
height
:
100%
;
width
:
100%
;
padding
:
5px
10px
;
}
#openassessment-editor
.openassessment-prompt-editor
{
width
:
100%
;
height
:
100%
;
resize
:
none
;
}
#openassessment-editor
.openassessment-rubric-editor
{
width
:
100%
;
height
:
100%
;
}
#openassessment-editor
.openassessment-assessments-editor
{
width
:
100%
;
}
#openassessment-editor
#oa-settings-editor-text-fields
{
float
:
left
;
width
:
30%
;
}
#openassessment-editor
#oa-settings-assessments
{
float
:
right
;
width
:
70%
;
height
:
100%
;
}
#openassessment-editor
.xblock-actions
{
background-color
:
#e5e5e5
;
position
:
absolute
;
width
:
100%
;
bottom
:
0
;
}
.modal-content
{
height
:
500px
!important
;
}
.openassessment
.self-assessment__display__header
,
.openassessment
.peer-assessment__display__header
,
.openassessment
.step__header
{
margin-bottom
:
0
!important
;
border-radius
:
0
!important
;
...
...
apps/openassessment/xblock/static/js/openassessment.min.js
View file @
c3161007
This diff is collapsed.
Click to expand it.
apps/openassessment/xblock/static/js/src/oa_edit.js
View file @
c3161007
/**
Interface for editing view in Studio.
The constructor initializes the DOM for editing.
Interface for editing view in Studio.
The constructor initializes the DOM for editing.
Args:
runtime (Runtime): an XBlock runtime instance.
element (DOM element): The DOM element representing this XBlock.
server (OpenAssessment.Server): The interface to the XBlock server.
Args:
runtime (Runtime): an XBlock runtime instance.
element (DOM element): The DOM element representing this XBlock.
server (OpenAssessment.Server): The interface to the XBlock server.
Returns:
OpenAssessment.StudioView
**/
Returns:
OpenAssessment.StudioView
**/
OpenAssessment
.
StudioView
=
function
(
runtime
,
element
,
server
)
{
this
.
runtime
=
runtime
;
this
.
server
=
server
;
// Initialize the code box
this
.
codeBox
=
CodeMirror
.
fromTextArea
(
$
(
element
).
find
(
'.openassessment-editor'
).
first
().
get
(
0
),
this
.
promptBox
=
$
(
'.openassessment-prompt-editor'
).
first
().
get
(
0
);
this
.
rubricXmlBox
=
CodeMirror
.
fromTextArea
(
$
(
element
).
find
(
'.openassessment-rubric-editor'
).
first
().
get
(
0
),
{
mode
:
"xml"
,
lineNumbers
:
true
,
lineWrapping
:
true
}
);
this
.
titleField
=
$
(
element
).
find
(
'.openassessment-title-editor'
);
this
.
submissionStartField
=
$
(
element
).
find
(
'.openassessment-submission-start-editor'
).
first
().
get
(
0
);
this
.
submissionDueField
=
$
(
element
).
find
(
'.openassessment-submission-due-editor'
).
first
().
get
(
0
);
this
.
assessmentsXmlBox
=
CodeMirror
.
fromTextArea
(
$
(
element
).
find
(
'.openassessment-assessments-editor'
).
first
().
get
(
0
),
{
mode
:
"xml"
,
lineNumbers
:
true
,
lineWrapping
:
true
}
);
// Install click handlers
var
view
=
this
;
$
(
element
).
find
(
'.openassessment-save-button'
).
click
(
function
(
eventData
)
{
function
(
eventData
)
{
view
.
save
();
});
});
$
(
element
).
find
(
'.openassessment-cancel-button'
).
click
(
function
(
eventData
)
{
function
(
eventData
)
{
view
.
cancel
();
});
};
});
$
(
'.openassessment-editor-content-and-tabs'
).
tabs
();
};
OpenAssessment
.
StudioView
.
prototype
=
{
/**
Load the XBlock XML definition from the server and display it in the view.
**/
load
:
function
()
{
Load the XBlock XML definition from the server and display it in the view.
**/
load
:
function
()
{
var
view
=
this
;
this
.
server
.
loadXml
().
done
(
function
(
xml
)
{
view
.
codeBox
.
setValue
(
xml
);
}).
fail
(
function
(
msg
)
{
function
(
prompt
,
rubricXml
,
settings
)
{
view
.
rubricXmlBox
.
setValue
(
rubricXml
);
view
.
assessmentsXmlBox
.
setValue
(
settings
.
assessments
);
view
.
submissionStartField
.
value
=
settings
.
submission_start
;
view
.
submissionDueField
.
value
=
settings
.
submission_due
;
view
.
promptBox
.
value
=
prompt
;
view
.
titleField
.
value
=
settings
.
title
;
}).
fail
(
function
(
msg
)
{
view
.
showError
(
msg
);
}
);
},
/**
Save the problem's XML definition to the server.
If the problem has been released, make the user confirm the save.
**/
save
:
function
()
{
Save the problem's XML definition to the server.
If the problem has been released, make the user confirm the save.
**/
save
:
function
()
{
var
view
=
this
;
// Check whether the problem has been released; if not,
// warn the user and allow them to cancel.
this
.
server
.
checkReleased
().
done
(
function
(
isReleased
)
{
if
(
isReleased
)
{
view
.
confirmPostReleaseUpdate
(
$
.
proxy
(
view
.
updateXml
,
view
));
}
else
{
view
.
updateXml
();
}
function
(
isReleased
)
{
if
(
isReleased
)
{
view
.
confirmPostReleaseUpdate
(
$
.
proxy
(
view
.
updateXml
,
view
));
}
else
{
view
.
updateXml
();
}
}
).
fail
(
function
(
errMsg
)
{
view
.
showError
(
msg
);
});
).
fail
(
function
(
errMsg
)
{
view
.
showError
(
msg
);
});
},
/**
Make the user confirm that he/she wants to update a problem
that has already been released.
Args:
onConfirm (function): A function that accepts no arguments,
executed if the user confirms the update.
**/
confirmPostReleaseUpdate
:
function
(
onConfirm
)
{
Make the user confirm that he/she wants to update a problem
that has already been released.
Args:
onConfirm (function): A function that accepts no arguments,
executed if the user confirms the update.
**/
confirmPostReleaseUpdate
:
function
(
onConfirm
)
{
var
msg
=
gettext
(
"This problem has already been released. Any changes will apply only to future assessments."
);
// TODO: classier confirm dialog
if
(
confirm
(
msg
))
{
onConfirm
();
}
if
(
confirm
(
msg
))
{
onConfirm
();
}
},
/**
Save the updated XML definition to the server.
**/
updateXml
:
function
()
{
Save the updated XML definition to the server.
**/
updateXml
:
function
()
{
// Notify the client-side runtime that we are starting
// to save so it can show the "Saving..." notification
this
.
runtime
.
notify
(
'save'
,
{
state
:
'start'
});
// Send the updated XML to the server
var
xml
=
this
.
codeBox
.
getValue
();
var
prompt
=
this
.
promptBox
.
value
;
var
rubricXml
=
this
.
rubricXmlBox
.
getValue
();
var
title
=
this
.
titleField
.
value
;
var
sub_start
=
this
.
submissionStartField
.
value
;
var
sub_due
=
this
.
submissionDueField
.
value
;
var
assessmentsXml
=
this
.
assessmentsXmlBox
.
getValue
();
var
view
=
this
;
this
.
server
.
updateXml
(
xml
).
done
(
function
()
{
this
.
server
.
updateXml
(
prompt
,
rubricXml
,
title
,
sub_start
,
sub_due
,
assessmentsXml
).
done
(
function
()
{
// Notify the client-side runtime that we finished saving
// so it can hide the "Saving..." notification.
view
.
runtime
.
notify
(
'save'
,
{
state
:
'end'
});
// Reload the XML definition in the editor
view
.
load
();
}).
fail
(
function
(
msg
)
{
}).
fail
(
function
(
msg
)
{
view
.
showError
(
msg
);
});
},
/**
Cancel editing.
**/
cancel
:
function
()
{
Cancel editing.
**/
cancel
:
function
()
{
// Notify the client-side runtime so it will close the editing modal.
this
.
runtime
.
notify
(
'cancel'
,
{});
},
/**
Display an error message to the user.
Display an error message to the user.
Args:
errorMsg (string): The error message to display.
**/
showError
:
function
(
errorMsg
)
{
Args:
errorMsg (string): The error message to display.
**/
showError
:
function
(
errorMsg
)
{
this
.
runtime
.
notify
(
'error'
,
{
msg
:
errorMsg
});
}
};
...
...
@@ -130,11 +163,11 @@ OpenAssessment.StudioView.prototype = {
function
OpenAssessmentEditor
(
runtime
,
element
)
{
/**
Initialize the editing interface on page load.
**/
$
(
function
(
$
)
{
Initialize the editing interface on page load.
**/
$
(
function
(
$
)
{
var
server
=
new
OpenAssessment
.
Server
(
runtime
,
element
);
var
view
=
new
OpenAssessment
.
StudioView
(
runtime
,
element
,
server
);
view
.
load
();
});
}
}
;
\ No newline at end of file
apps/openassessment/xblock/static/js/src/oa_server.js
View file @
c3161007
...
...
@@ -356,7 +356,7 @@ OpenAssessment.Server.prototype = {
$
.
ajax
({
type
:
"POST"
,
url
:
url
,
data
:
"
\"\"
"
}).
done
(
function
(
data
)
{
if
(
data
.
success
)
{
defer
.
resolveWith
(
this
,
[
data
.
xml
]);
}
if
(
data
.
success
)
{
defer
.
resolveWith
(
this
,
[
data
.
prompt
,
data
.
rubric
,
data
.
settings
]);
}
else
{
defer
.
rejectWith
(
this
,
[
data
.
msg
]);
}
}).
fail
(
function
(
data
)
{
defer
.
rejectWith
(
this
,
[
gettext
(
'This problem could not be loaded.'
)]);
...
...
@@ -378,9 +378,15 @@ OpenAssessment.Server.prototype = {
function(err) { console.log(err); }
);
**/
updateXml
:
function
(
x
ml
)
{
updateXml
:
function
(
prompt
,
rubricXml
,
title
,
sub_start
,
sub_due
,
assessmentsX
ml
)
{
var
url
=
this
.
url
(
'update_xml'
);
var
payload
=
JSON
.
stringify
({
xml
:
xml
});
var
settings
=
{
'title'
:
title
,
'submission_start'
:
sub_start
,
'submission_due'
:
sub_due
,
'assessments'
:
assessmentsXml
};
var
payload
=
JSON
.
stringify
({
'prompt'
:
prompt
,
'rubric'
:
rubricXml
,
'settings'
:
settings
});
return
$
.
Deferred
(
function
(
defer
)
{
$
.
ajax
({
type
:
"POST"
,
url
:
url
,
data
:
payload
...
...
apps/openassessment/xblock/static/sass/oa/utilities/_developer.scss
View file @
c3161007
...
...
@@ -57,8 +57,8 @@
}
.openassessment__student-info_list
{
list-style-type
:
none
;
}
list-style-type
:
none
;
}
.value
{
width
:
$max-width
/
2
;
...
...
@@ -165,6 +165,74 @@
}
}
}
}
// --------------------
// Developer Styles for Studio Editing of OA problems
// --------------------
#openassessment-editor
{
.openassessment-editor-content-and-tabs
{
width
:
100%
;
height
:
370px
;
}
.openassessment-editor-header
{
background-color
:
#e5e5e5
;
width
:
100%
;
top
:
0
;
}
#oa-editor-window-title
{
float
:
left
;
}
.oa-editor-tab
{
float
:
right
;
padding
:
(
$baseline-v
/
8
)
(
$baseline-h
/
8
);
margin
:
(
$baseline-v
/
8
)
(
$baseline-h
/
8
);
}
.oa-editor-content-wrapper
{
height
:
100%
;
width
:
100%
;
padding
:
(
$baseline-v
/
4
)
(
$baseline-h
/
4
);
}
.openassessment-prompt-editor
{
width
:
100%
;
height
:
100%
;
resize
:
none
;
}
.openassessment-rubric-editor
{
width
:
100%
;
height
:
100%
;
}
.openassessment-assessments-editor
{
width
:
100%
;
}
#oa-settings-editor-text-fields
{
float
:
left
;
width
:
30%
;
}
#oa-settings-assessments
{
float
:
right
;
width
:
70%
;
height
:
100%
;
}
.xblock-actions
{
background-color
:
#e5e5e5
;
position
:
absolute
;
width
:
100%
;
bottom
:
0
;
}
}
.modal-content
{
height
:
500px
!
important
;
}
apps/openassessment/xblock/studio_mixin.py
View file @
c3161007
...
...
@@ -8,7 +8,11 @@ from django.template.loader import get_template
from
django.utils.translation
import
ugettext
as
_
from
xblock.core
import
XBlock
from
xblock.fragment
import
Fragment
from
openassessment.xblock.xml
import
serialize_content
,
update_from_xml_str
,
ValidationError
,
UpdateFromXmlError
from
openassessment.xblock.xml
import
(
serialize_content
,
parse_rubric_xml
,
parse_assessments_xml
,
UpdateFromXmlError
,
serialize_rubric_to_xml_str
,
serialize_assessments_to_xml_str
)
from
openassessment.xblock.validation
import
validator
...
...
@@ -51,21 +55,52 @@ class StudioMixin(object):
Returns:
dict with keys 'success' (bool) and 'msg' (str)
"""
if
'xml'
in
data
:
try
:
update_from_xml_str
(
self
,
data
[
'xml'
],
validator
=
validator
(
self
))
if
'rubric'
not
in
data
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Must specify "rubric" in request JSON dict.'
)}
except
ValidationError
as
ex
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Validation error: {error}'
)
.
format
(
error
=
ex
)}
if
'settings'
not
in
data
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Must specify "settings" in request JSON dict.'
)}
except
UpdateFromXmlError
as
ex
:
return
{
'success'
:
False
,
'msg'
:
_
(
'An error occurred while saving: {error}'
)
.
format
(
error
=
ex
)}
if
'prompt'
not
in
data
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Must specify "prompt" in request JSON dict.'
)}
else
:
return
{
'success'
:
True
,
'msg'
:
_
(
'Successfully updated OpenAssessment XBlock'
)}
settings
=
data
[
'settings'
]
try
:
rubric
=
parse_rubric_xml
(
data
[
'rubric'
])
assessments
=
parse_assessments_xml
(
settings
[
'assessments'
])
submission_due
=
settings
[
"submission_due"
]
except
UpdateFromXmlError
as
ex
:
return
{
'success'
:
False
,
'msg'
:
_
(
'An error occurred while saving: {error}'
)
.
format
(
error
=
ex
)}
xblock_validator
=
validator
(
self
)
success
,
msg
=
xblock_validator
(
rubric
,
{
'due'
:
submission_due
},
assessments
)
if
not
success
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Validation error: {error}'
)
.
format
(
error
=
msg
)}
self
.
update
(
rubric
,
assessments
,
settings
[
"submission_due"
],
settings
[
"submission_start"
],
settings
[
"title"
],
data
[
'prompt'
]
)
return
{
'success'
:
True
,
'msg'
:
_
(
'Successfully updated OpenAssessment XBlock'
)}
def
update
(
self
,
rubric
,
assessments
,
submission_due
,
submission_start
,
title
,
prompt
):
"""
Given a dictionary of properties, update the XBlock
else
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Must specify "xml" in request JSON dict.'
)}
"""
# If we've gotten this far, then we've successfully parsed the XML
# and validated the contents. At long last, we can safely update the XBlock.
self
.
title
=
title
self
.
prompt
=
prompt
self
.
rubric_criteria
=
rubric
[
'criteria'
]
self
.
rubric_assessments
=
assessments
self
.
rubric_feedback_prompt
=
rubric
[
'feedback_prompt'
]
self
.
submission_start
=
submission_start
self
.
submission_due
=
submission_due
@XBlock.json_handler
def
xml
(
self
,
data
,
suffix
=
''
):
...
...
@@ -82,8 +117,14 @@ class StudioMixin(object):
dict with keys 'success' (bool), 'message' (unicode), and 'xml' (unicode)
"""
try
:
xml
=
serialize_content
(
self
)
rubric
=
serialize_rubric_to_xml_str
(
self
)
prompt
=
self
.
prompt
settings
=
{
'title'
:
self
.
title
,
'submission_start'
:
self
.
submission_start
,
'submission_due'
:
self
.
submission_due
,
'assessments'
:
serialize_assessments_to_xml_str
(
self
)
}
# We do not expect `serialize_content` to raise an exception,
# but if it does, handle it gracefully.
except
Exception
as
ex
:
...
...
@@ -91,7 +132,7 @@ class StudioMixin(object):
logger
.
error
(
msg
)
return
{
'success'
:
False
,
'msg'
:
msg
,
'xml'
:
u''
}
else
:
return
{
'success'
:
True
,
'msg'
:
''
,
'
xml'
:
xml
}
return
{
'success'
:
True
,
'msg'
:
''
,
'
prompt'
:
prompt
,
'rubric'
:
rubric
,
'settings'
:
settings
}
@XBlock.json_handler
def
check_released
(
self
,
data
,
suffix
=
''
):
...
...
@@ -112,4 +153,4 @@ class StudioMixin(object):
return
{
'success'
:
True
,
'msg'
:
u''
,
'is_released'
:
self
.
is_released
()
}
}
\ No newline at end of file
apps/openassessment/xblock/xml.py
View file @
c3161007
This diff is collapsed.
Click to expand it.
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